macOS Dylib Hijacking Detection via Endpoint Security
A DEF CON 34 talk details how macOS dylib hijacking and dylib-based malware evade process-level security tools, and how Endpoint Security mmap events can detect and block them.
This Objective-See blog post recaps a DEF CON 34 talk examining dylib-based attacks on macOS, arguing that despite mitigations up through macOS 26, dylib hijacking remains possible in limited forms. The author reviews historical and real-world examples of dylib abuse: Flashback malware injecting via DYLD_INSERT_LIBRARIES into Safari for ad fraud, evidence suggesting Equation Group's OS X implant supported a dylib-loaded variant, the 3CX supply chain attack which trojanized libffmpeg.dylib to download second-stage payloads, and a SIP-bypass exploit (documented by researcher CodeColorist) that abused a vulnerable dylib lookup path (DEVELOPER_DIR) in an Apple-signed sampling tool holding the com.apple.system-task-ports entitlement. The core thesis is that macOS security decisions (entitlements, TCC, Endpoint Security attribution, firewall rules) are made at the process level, so malicious code loaded as a dylib inherits a host process's trust while remaining invisible to tools like LuLu or eslogger, which attribute all activity to the host application (e.g., Photoshop) rather than the injected library.
The post then details defensive techniques: static enumeration of Mach-O LC_LOAD_DYLIB dependencies (as used in the open-source Dylib Hijack Scanner) to spot duplicate @rpath dependencies indicating a hijack; runtime enumeration of loaded libraries in a remote process via proc_pidinfo with PROC_PIDREGIONPATHINFO, which avoids the now-restricted task_for_pid approach; and load-time monitoring/blocking using Apple's Endpoint Security ES_EVENT_TYPE_AUTH_MMAP event, which allows a security tool to inspect and deny malicious executable mappings before they load, effectively preventing dylib hijacking and other dylib-based payloads. Limitations are noted, including incomplete visibility into the dyld shared cache, potential TOCTOU issues between mapped memory and on-disk files, and the need to also watch ES_EVENT_TYPE_AUTH_MPROTECT for more exotic in-memory techniques. The article is defensive research and detection guidance, not a report of a new active campaign.
Mentioned in this report
Detection guidance
Process Launched with DYLD_INSERT_LIBRARIES Environment Variable
Detects process execution with the DYLD_INSERT_LIBRARIES environment variable set, the classic dynamic linker hijacking technique used by Flashback and similar dylib-injection malware to force a target process to load an attacker-controlled library. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: Process Launched with DYLD_INSERT_LIBRARIES Environment Variable
description: Detects a process launched with DYLD_INSERT_LIBRARIES set in its environment,
which forces the dynamic linker to load an attacker-supplied dylib into the process
address space before normal execution. Generalises on the environment variable itself
rather than any specific dylib path or malware family.
tags:
- attack.defense-evasion
- attack.persistence
- attack.t1574.006
logsource:
category: process_creation
product: macos
detection:
selection:
Environment|contains: DYLD_INSERT_LIBRARIES=
filter_dev_tools:
Image|contains:
- /Xcode.app/
- /Applications/Xcode.app
condition: selection and not filter_dev_tools
falsepositives:
- Developers using DYLD_INSERT_LIBRARIES for legitimate debugging, profiling, or interposing
during local development
- QA/security tooling that intentionally injects instrumentation libraries during
testing
level: high
id: 163901e2-5b2e-5d72-a476-42ba9d19c561
status: experimental
author: Vorant
Process Launched with Non-Standard DEVELOPER_DIR Environment Variable
Detects execution of a process with the DEVELOPER_DIR environment variable pointing outside the standard Xcode install path, matching the dylib search-path hijack technique used to abuse a vulnerable Apple-signed sampling tool and bypass SIP. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: Process Launched with Non-Standard DEVELOPER_DIR Environment Variable
description: Detects processes launched with a DEVELOPER_DIR environment variable
that does not point to the standard Xcode.app path. Some Apple-signed developer
tools resolve helper dylibs relative to DEVELOPER_DIR, and pointing it at an attacker-controlled
directory can hijack that dylib lookup to gain code execution with the host binary's
entitlements (e.g. com.apple.system-task-ports), as documented in the CodeColorist
SIP-bypass case. Generalises on the abnormal environment variable value rather than
a specific tool or exploit path.
tags:
- attack.defense-evasion
- attack.privilege-escalation
- attack.t1574.004
logsource:
category: process_creation
product: macos
detection:
selection:
Environment|contains: DEVELOPER_DIR=
filter_standard_xcode:
Environment|contains:
- DEVELOPER_DIR=/Applications/Xcode.app
- DEVELOPER_DIR=/Library/Developer/CommandLineTools
condition: selection and not filter_standard_xcode
falsepositives:
- Developers switching Xcode versions with xcode-select using a custom but legitimate
install location
- CI/build pipelines that set DEVELOPER_DIR to a pinned Xcode beta path on the build
host
level: medium
id: 694ae591-089b-58bc-8227-46d4f36de215
status: experimental
author: Vorant
Dylib Loaded from Non-Bundle Writable Path by Signed Application
Detects a running application loading a dynamic library from a user-writable location outside its own app bundle or standard system library paths, consistent with dylib hijacking via duplicate @rpath dependencies that let a malicious library ride on a trusted host process's entitlements. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: Dylib Loaded from Non-Bundle Writable Path by Signed Application
description: Detects an application process loading a dylib from a path outside its
own .app bundle Frameworks/PlugIns directory and outside standard system library
directories, e.g. from /tmp, /var/tmp, ~/Library/Caches, or Downloads. This matches
the dylib hijacking pattern where an attacker plants a same-named library earlier
in the @rpath search order so a trusted, code-signed host process (and its entitlements/TCC
grants) loads attacker code invisibly to process-level security tooling. Generalises
on the load location relative to the host bundle, not on any specific library name
from a known campaign (e.g. libffmpeg.dylib in the 3CX incident).
tags:
- attack.defense-evasion
- attack.persistence
- attack.t1574.004
- attack.t1055.001
- attack.t1055
logsource:
category: image_load
product: macos
detection:
selection:
ImageLoaded|endswith: .dylib
ImageLoaded|contains:
- /tmp/
- /var/tmp/
- /Library/Caches/
- /Downloads/
- /Public/
filter_system_or_bundle:
ImageLoaded|contains:
- /usr/lib/
- /System/Library/
- .app/Contents/Frameworks/
- .app/Contents/PlugIns/
condition: selection and not filter_system_or_bundle
falsepositives:
- Legitimate applications that intentionally load plugins or scripting extensions
from user cache or downloads directories
- Developer tools loading self-built dylibs from a temporary build output directory
during local testing
level: high
id: 9e19bcd7-df2d-5088-877e-5ba01f284846
status: experimental
author: Vorant
Behavioural rules are generated from public reporting — validate in your environment before deploying.
Source reporting: https://objective-see.org/blog/blog_0x89.html
This is the public brief
Subscribers see the full picture: extracted IOCs, ready-to-deploy detections (Sigma, Splunk, KQL, Elastic, YARA, Suricata), the entity graph, TAXII 2.1 feed and real-time alerts matched to your sectors.
Start free