
Educational deep dive into macOS app bundles, plist files, and launchd process behavior, with offensive security notes on packaging payloads as .app files and evading process-tree monitoring.
Transitioning to macOS from Linux or Windows can feel like walking in a strange new land. Since Linux is open-source and Windows is well-documented and very popular (and macOS is neither, exactly), macOS can be challenging at times. In this blogpost, I intend to discuss some of the first things you might notice on macOS - Apps, Apps everywhere!
Coming from a Windows or Linux background, the concept of Apps might seem weird. We all know threads are "units of execution" and processes are containers for threads with their own address space -- what more is there to it? Well, processes are rarely deployed in single files. On both Windows and Linux there are many things code might need to function, some of them are:
.dll, .so). For example, the C runtime library (msvcr<version>.dll on Windows, libc-<version>.so) as well as other depndencies.PE, which has directories - one of them is the resource directory (even kind of documented here that might contain resources (images, strings and others). Resources could also be loaded from disk dynamically, of course.PE file itself (read here) or in catalogue files (i.e., externally).xml, ini, json) and the Windows Registry.Well, macOS puts heavy emphasis on Application Bundles. The idea is to package (almost) everything required for the program to run in a directory structure - including resources, localization information, etc.. Of course, not evertything could be nicely packaged (like the C runtime library, for instance) - but it still means that things are bundled together nicely - no need to navigate a huge Registry or to read manual pages for obscure configuration file locations. Application bundles are just directories ending with .app - even though the UI hides the .app extension (and the fact it's a directory).
From an attacker's perspective this is interesting - since an Application Bundle can have arbitrary icons and hides the .app extension - delivering malware could be achieved by fooling an unsuspecting user to click such an app. For example, think about a Resume.app file with a PDF icon.
The directory structure for an Application Bundle can be easily examined, obviously by the builtin Calculator App:
jbo@McJbo ~ % cd /System/Applications/Calculator.app
jbo@McJbo Calculator.app % ll
total 0
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 .
drwxr-xr-x 43 root wheel 1376 Mar 17 21:34 ..
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 Contents
jbo@McJbo Calculator.app % cd Contents
jbo@McJbo Contents % ll
total 16
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 .
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 ..
-rw-r--r-- 1 root wheel 2147 Mar 17 21:34 Info.plist
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 MacOS
-rw-r--r-- 204 root wheel 8 Mar 17 21:34 PkgInfo
drwxr-xr-x 4 root wheel 128 Mar 17 21:34 PlugIns
drwxr-xr-x 54 root wheel 1728 Mar 17 21:34 Resources
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 _CodeSignature
-rw-r--r-- 1 root wheel 461 Mar 17 21:34 version.plist
jbo@McJbo Contents % cd MacOS
jbo@McJbo MacOS % ll
total 344
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 .
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 ..
-rwxr-xr-x 1 root wheel 540912 Mar 17 21:34 Calculator
jbo@McJbo MacOS %
As you can see, Calculator.app is a directory. Under it there is a single item - another directory called Contents.
Under Contents there are multiple items:
Info.plist - contains metadata on the App. More on that later.MacOS - contains the main executable of the App (as can be seen in the 3rd directory listing).PkgInfo - non-mandatory. A binary file that contains package information.PlugIns - non-mandatory. A directory that might contain plugins for the App. Calculator has two - one for "Basic and Scientific" and one for "Hexadecimal" (I really don't know why they made that separation, nor do I care).Resources - non-mandatory. As the name suggests, contains resources. You might find several items there, including .icns file with Icons, as well as directories with the .lprroj suffix that are related to localization._CodeSignature - non mandatory. As the name suggests - contains code signing information.version.plist - non-mandatory, contains verison information.Note there are very few items that are officially required. In fact, we can create our own first App without even compiling anything!
But first we must discuss that Info.plist file.
The more you look at macOS, the more you'll find those strange files. Those are nothing more than glorified configuration files.
They will always have a .plist extension, which is just a short way of calling their formal name: Property list files.
Unfortunately, there are 3 different plist formats maintained by Appled:
xml format, readable by humans.json format, not widely used.bplist as magic.Luckily, there is a utility called plutil that supports all formats. To output a plist file, simply use plutil -p. For example:
jbo@McJbo Contents % plutil -p Info.plist | head -n 20
{
"BuildMachineOSBuild" => "22A380007"
"CFBundleDevelopmentRegion" => "English"
"CFBundleExecutable" => "Calculator"
"CFBundleGetInfoString" => "10.14, Copyright © 2000-2018, Apple Inc."
"CFBundleHelpBookFolder" => "Calculator.help"
"CFBundleHelpBookName" => "com.apple.Calculator.help"
"CFBundleIconFile" => "AppIcon"
"CFBundleIconName" => "AppIcon"
"CFBundleIdentifier" => "com.apple.calculator"
"CFBundleInfoDictionaryVersion" => "6.0"
"CFBundleName" => "Calculator"
"CFBundlePackageType" => "APPL"
"CFBundleShortVersionString" => "10.16"
"CFBundleSignature" => "????"
"CFBundleSupportedPlatforms" => [
0 => "MacOSX"
]
"CFBundleVersion" => "223"
"CTIgnoreUserFonts" => 1
jbo@McJbo Contents %
There are also conversion functionalities built into plutil - we won't demonstrate those right now.
Apple documents several requirements in an App's Info.plist, but there are very little fields that are actually mandatory. Here are some interesting fields:
CFBundleExecutable - the name of the main executable, expected to be under the MacOS directory.CFBundleIconFile - the name of the icon file. Non-mandatory.CFBundleIdentifier - an identifier for the App Bundle. Apple recommends using a reverse DNS notation (e.g. com.apple.calculator).CFBundleName - the bundle name.With that in mind, we can create our own first awesome app, without even coding! Take a look:
#!/bin/zsh
# Create Bundle structure
mkdir -p ./MyApp.app/Contents/MacOS