Entitlements are an important part of Apple Security architecture. They allow Apple to limit an OS feature to be only available to Apple-approved processes. Nowadays, even with System Integrity Protection disabled, the AMFI Kernel Extension and
amfid process dueto will always kill any process at execution with restricted Entitlements not signed by Apple or with a properly Apple-approved embedded provisioning profile.
Unrestricted Entitlements are available to all signed binaries, even ad-hoc (some examples of this are the Sandbox entitlements
com.apple.security.* or the application identifier one
com.apple.application-identifier) but they do no give any special capability to the process, on the contrary, they limit its reach.
To allow any Entitlements, even the more interesting Restricted ones, for a Developer ID signed binary we have to modificate the
amfid process (to allow adhoc signatures too we would have to patch the AMFI Kernel Extension or its underlying dependencies which I didn’t try).
To patch a system daemon, we have to disable macOS System Integrity Protection. After some reverse engineering, it seems one of the main decisions in the
amfid flow is in the address offset
Knowing that we can change the following two instructions from:
test %r14, %r14 je loc_100003531
mov %r14, %r15 jno loc_100003531
This way the flow will always jump to
%r14 will become null (
%r15 is always null in this point), so every Developer ID signed process will be validated even without a provisioning profile allowing its Entitlements.
To achieve this modification we can go the hard way by modifing the binary in situ (it is located at
/usr/libexec/amfid) or the soft way: patching
amfid memory at runtime. I preferred the second option so I could restart the unpatched
amfid code by simply killing it.
To do it I ported to Python 3 a wrapper for Mach VM APIs called pymach and added a new function to get the ASRL Slice Offset of the process: PyMach for Python 3. With that I wrote this script for macOS 10.12.2. To use it simply run:
$ sudo ./amfid_patch.py
yes when asked if you want to patch the process. Voilà! Now any Developer ID signed binaries will be executed even with restricted Entitlements.
You can set any Entitlement you want, like
com.apple.private.appleaccount.app-hidden-from-icloud-settings with an arbitrary iCloud container. For a complete list of private Entitlements used by Apple you can go to Jonathan Levin’s Entitlements Database.