LC_MAIN Hijacking
Adversaries may hijack the LC_MAIN Mach-O load command in macOS binaries to redirect initial execution flow to malicious code before returning control to the legitimate entry point. The LC_MAIN header, introduced in OS X 10.8, defines the entry point offset for a Mach-O executable. By patching this offset to point at an injected code section or cave, an attacker can execute arbitrary code under the identity of a trusted binary, bypassing application whitelisting controls that validate only the file path or name. This technique has been deprecated in the MITRE ATT&CK framework but remains relevant for forensic analysis of older macOS malware samples and legacy systems.
// Part 1: Detect use of Mach-O binary inspection and manipulation tools with suspicious flags
let MachOInspectionTools = dynamic(["otool", "jtool", "jtool2", "vtool", "MachOView", "install_name_tool", "lipo"]);
let SuspiciousLoadCmdFlags = dynamic(["-l", "--load-commands", "LC_MAIN", "LC_THREAD", "LC_UNIXTHREAD", "entryoff", "stacksize"]);
let SensitivePaths = dynamic(["/Applications/", "/usr/bin/", "/usr/local/bin/", "/usr/sbin/", "/bin/", "/sbin/", "/opt/"]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ (MachOInspectionTools)
| where ProcessCommandLine has_any (SuspiciousLoadCmdFlags)
| where ProcessCommandLine has_any (SensitivePaths)
| extend TargetBinary = extract(@"(?:/Applications/[^\s]+\.app/Contents/MacOS/[^\s]+|/usr/(?:bin|local/bin|sbin)/[^\s]+|/bin/[^\s]+|/opt/[^\s]+)", 0, ProcessCommandLine)
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, TargetBinary,
InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
// Part 2: Detect writes to Mach-O executable locations by non-system processes
// Run separately or union with above
// DeviceFileEvents
// | where Timestamp > ago(24h)
// | where ActionType in ("FileModified", "FileCreated", "FileRenamed")
// | where FolderPath matches regex @"/Applications/[^/]+\.app/Contents/MacOS"
// or FolderPath startswith "/usr/bin/"
// or FolderPath startswith "/usr/local/bin/"
// or FolderPath startswith "/usr/sbin/"
// | where not(InitiatingProcessFileName in~ ("Installer", "softwareupdate", "pkgutil", "MRT", "XProtect", "trustd"))
// | project Timestamp, DeviceName, AccountName, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessCommandLine Data Sources
Required Tables
False Positives
- Security researchers and reverse engineers routinely use otool, jtool, and vtool with -l flags to inspect Mach-O load commands for legitimate analysis
- Software build pipelines (Xcode, CMake, conan) invoke install_name_tool and lipo against application binaries during compilation and packaging
- macOS application notarization and code signing workflows use codesign and related tools against .app bundle executables
- Third-party software managers (Homebrew, MacPorts) legitimately write to /usr/local/bin and /opt/ during package installation and upgrades
- System software updates via softwareupdate and MRT modify binaries in protected system paths
References (9)
- https://attack.mitre.org/techniques/T1149/
- https://assets.documentcloud.org/documents/2459197/bit9-carbon-black-threat-research-report-2015.pdf
- https://www.virusbulletin.com/uploads/pdf/conference/vb2014/VB2014-Wardle.pdf
- https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html
- https://github.com/aidansteele/osx-abi-macho-file-format-reference
- https://redcanary.com/blog/mac-malware-2021/
- https://objective-see.org/blog.html
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1149/T1149.md
- https://www.sentinelone.com/labs/20-common-tools-techniques-used-by-macos-threat-actors-malware/
Unlock Pro Content
Get the full detection package for T1149 including response playbook, investigation guide, and atomic red team tests.