MachO Execution Shims - containermanagerd - iOS

A development technique colloquially known as “shims” is a small binary / library / service which acts like a bridge between operations or processes. Program execution shims – shims which help facilitate the actual execution of code – are an extremely important concept for Apple Operating Systems reverse engineering, internals, vulnerability research, and incident response.

Apple’s XNU kernel does not have the ability to ‘exec’ a framework directly, so most frameworks are imported and used as pieces within existing MachO executables. In many cases, purpose built small executables are made with the sole intention of facilitating the ability to execute code embedded within frameworks. We are going to examine one such example to understand execution shims in iOS.

/usr/libexec/containermangerd
PROGRAM:containermanagerd
PROJECT:MobileContainerManager-685

The containermanagerd executable is an extremely simple entry point shim to allow controlled execution of a framework. The entire pseudocode for this program looks like the following:

This standalone executable acts as a bridge to call upon the ContainerManagerCommon[1] service while passing the "User" flag. This framework will then pivot to use other frameworks based on the provided "User" argument (or will it?). 

This is a great example of an entry point shim due to how simple and straightforward it is while emphasizing why shims exist:

  1. Allows for direct execution of the framework. 

  2. This shim contains all the entitlements required to communicate with the ContainerManager frameworks. Calling on this executable directly from other services allows for enhanced security (since those services do not need to contain the additional entitlements themselves – making it harder for attackers to pivot if they can break into those services).

  3. The service acts as a code monolith. If the ContainerManager frameworks must be framework and update arguments, entitlements, etc… We would only need to update this one since binary in such a scenario.

  4. The ‘User’ argument should (theoretically – more on this later) be interpreted by the called framework to enforce non-root execution of the code as the mobile user, thus decreasing the ambiguity in execution environment.

[1] - Which is stored in the dyld shared cache/System/Library/PrivateFrameworks/ContainerManagerCommon.framework/ContainerManagerCommon

“User”?

The containermanagerd executable issues a call containing the “User” argument while the containermanagerd_system executable found in in the same directory issues the same call but instead uses the “System” argument:

__containermanagerd_main(self, _cmd, "System");

Although the “User” argument is passed it is not even used by the framework! The void __containermanagerd_main() function within the ContainerManagerCommon framework does not actually accept any arguments, nor does it accept any command line arguments as the call in containermanagerd might infer.

This is a prime example of vestigal (forgotten non-functional) code. At one point this argument must have made some real impact (otherwise it would never have been written) but with iterations of the framework being updated at some point a patch was made to ignore all input and set the execution based on introspection of the environment. The framework checks its own UID and initializes user mode if the UID is not equal to “0” (the root UID). It will then look for specific entitlements to define capabilities (See Appendix A. and B. for a list of entitlements in containermanagerd and containermanagerd_system).

Arguments?

This program does not support any command line arguments. While it does accept them, in actuality if you run it with arguments, they will be forwarded to the framework which will simply ignore them.

Appendix A. Containermanagerd Entitlements

com.apple.mkb.usersession.info
true
com.apple.private.MobileContainerManager.allowed
true
com.apple.private.MobileContainerManager.proxy
true
com.apple.private.MobileContainerManager.repair
true
com.apple.private.apfs.space-attribution
true
com.apple.private.memorystatus
true
com.apple.private.sandbox.profile:embedded
- containermanagerd
com.apple.private.security.container-manager
true
com.apple.private.security.storage.AppDataContainers
true
com.apple.private.security.storage.MobileContainerManager
true
com.apple.private.vfs.allow-low-space-writes
true
com.apple.runningboard.terminateprocess
true
com.apple.security.enterprise-volume-access
true
com.apple.usermanagerd.persona.fetch
true
com.apple.usermanagerd.persona.fetchbundle
true
com.apple.usermanagerd.persona.grantSandboxExtension
true
com.apple.usermanagerd.persona.observer
true

Appendix B. Containermanagerd_system Entitlements

com.apple.private.apfs.space-attribution
true
com.apple.private.memorystatus
true
com.apple.private.sandbox.profile:embedded
- containermanagerd
com.apple.private.security.container-manager
true
com.apple.private.security.storage.AppBundles
true
com.apple.private.security.storage.DiagnosticReports
true
com.apple.private.security.storage.ManagedConfiguration
true
com.apple.private.security.storage.MobileContainerManager
true
com.apple.private.vfs.allow-low-space-writes
true
com.apple.security.exception.iokit-user-client-class
- AppleAPFSUserClient

Nicholas Dubois

Nicholas Dubois is a digital forensic examiner and educational content writer. Nicholas has spoken at several conferences on forensic findings and the offensive security of educational institutions including HTCIA, DFRWS, and NCCC.

Next
Next

New Lumyx Essentials Course at Hexordia