Identify the battle ground.
Architecture of a normal Mac OS application. MacOS Applications are suppose to work on MacOS (OSX) platform. They are bundled into “Application Bundles” with the “.app” as the extension. These applications consist of bundled hierarchy that contains actual executable and the resources required by the same. Below is architecture “Books” application bundle on MacOS
Bundle contains some important files to look into.
Info.plistis a property list file stored at a location that identifies a directory hierarchy as a bundle. For a list of
Information Property List. This is used to analyze what all permissions does the application have. What all resources can it access.
Code content is either executable code, like a helper tool, or another bundle that contains executable code, like an app extension. In this context, executable code means a Mach-O image. It doesn’t include things like shell scripts, Python scripts, and AppleScripts (unless you save the AppleScript as an application). Although you execute a script, it has no place to hold a code signature, so you treat it as a resource.
Resources are everything that’s not code.
Security Protections which are already in place.
- SIP : System Integrity Protection. System Integrity Protection (SIP) is a security technology in macOS that safeguards certain system directories from unauthorized access, even for the root user. It prevents modifications to these directories, including creation, alteration, or deletion of files. The main directories that SIP protects are:
SIP needs to be either bypassed (tough task) or disabled.
# To check status of SIP
# To disable SIP
#To keep SIP enabled, but just not prevent debugging.
csrutil enable --without debug
2. Notarization: Developers need to submit the application. Then application is sent to Apple Notary Service, where rigorous tests are made to scrutinize the software against malicious content. Also against code-signing. Notarization ticket is created, which is attached to the software. Gatekeeper looks for this ticket.
3. Gatekeeper: Checks if user runs only trusted software. Prevents running application directly as an application, by first opening it as installer package. It checks if the downloaded software is signed by the recognized developer. It checks if it is already Notarized by the Apple. It prompts user to approve before running the application.
4. Quarantine files: Files from non trusted source have Quarantine flag set.
5. Sandbox: Limits running application inside a Sandboxed environment, where only access to resources mentioned in Info.plist is given. Sandbox profile will contain access to the resources. App runs with a sandbox profile.
6. TCC (Transparency, Consent, and Control): is a mechanism in macOS to limit and control application access to certain features, usually from a privacy perspective. This can include things such as location services, contacts, photos, microphone, camera, accessibility, full disk access, and a bunch more.
What to look for. From here starts our approach.
Logs: All the applications log their data somewhere. These may be debug logs, error logs, system logs, access logs etc. A lot of information can be gained looking into the logs. The debug logs also can define, what is the flow of application, as in what was tried to be accessed after and before.
The Logs can be UNIFIED Logs and can be hidden. This is when a <private> tag is attached to the logs.
2. Entitlements: Key-value pairs that grant an executable permission to use a service or technology.
#To look for the entitlements on the app.
codesign -d --entitlements :- /System/Applications/Books.app
3. Verify if the content of app is modified.
Codesign --verify --verbose /Application/Books.app
4. Get the real signer of the binary. You can also resign the binary. This is required when you want to copy the binary from expected path to intended path.
# To get signer details
codesign --v -d /bin/ls 2?&1 | grep -E "Authority|TeamIdentifier"
#To sign a binary
codesign -s <cert-keychain-name> abcd
#"Where abcd is app'
5. You need to see if (lib) and (bin) are both signed by same certs. In this case
com.apple.security.cs.disable_library_validation entitlements can be bypassed
# Check if the signature is valid
spctl --assess --verbose /Applications/Books.app
6. If the language used is Objective-C you need to look for “objc_msgsend()” function. And play with parameters. Similarly if the language is Swift, you need to look for __Swift prefix in the module.
7. ObjDump : You can list the dynamically linked libraries using tool. You can get the header of the binary. You can see if Symbol Table exists. You can disassemble the binary.
De compile/Disassemble the Application
- Hopper : UI tool to de compile, disassemble the Mac Os Application.
- Otool: De compile the application. Dynamically linked libraries can be listed as well.
Process Abuse. In this section we will mention the ways in which processes on mac Os can be manipulated to execute our code.
- Library Injection :
2. Function Hooking
Frida Dynamic Instrumentation
Dyld injection via Environment Variables
Dylib process injection
Debugger — lldb
3. IPC Communication Abuse
Thread injection via task port
XPC Connecting process check
Approach for the two Hijacking techniques
What not like windows on Mac OS :
a. MacOS Binaries indicate full path. So no NAME NOT FOUND type.
b. Mac OS never searches the folder of $PATH Variable.
Different commands used to load libraries and loopholes. Look into
Imageloader.cpp inside ImageLoader::recursiveLoadLibraries
a. LC_LOAD_DYLIB: contains path for specific libraries to load. Look for several
@rpaths . Abuse the paths with missing libraries.
b. LC_LOAD_WEAK_DYLIB: Look for missing weak linked libraries. Place dylib where expected. For this
lib -> required is
You can do a quick check using “Dylib Hijack Scanner”
To do this, different search order paths are followed, which you need to trace down. One example is as follows.
- CWD (if unrestricted process)
Look at the architecture of Application first.
- Universal Mach O Binary
Approach as follows.
- Of course SIP disabled or bypassed is step numro uno.
2. Look for PT_DENY_ATTACH to be not present.
If it is present. We need to disable it. For that we need to do
ptrace detection. If ptrace is present. You need to potentially inspect and undo
ptrace call. It would look like
ptrace(PT_DENY_ATTACH,0,0,0) You need to find this, p_lflag and change the value to disable PT_DENY_ATTACH.
3. Finally attach (LLDB) — and run command. You can find list of commands here.
Few more key take aways
- VM detection can be ON.
hw.modelis used to check if mac or not.
- Malwares may also detect VM using MAC Address pattern.
- We need to see if debugging is disabled.
if(P_TRACED == (info.kp_proc_p_flag & P_TRACED)