Skip to main content

dylib-hijack-scan

Scan macOS for hijackable dynamic libraries, separating exploitable privesc hijacks from harmless ones. Use to check if an app is hijackable.

Quellinformationen

Repository
forefy/.context
Letzte Quellaktivität
31. August 2026 um 22:36
Erkannte Sprache von SKILL.md
Englisch
Sterne
149
Forks
30

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
5 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
dylib-hijack-scan
description
Scan macOS for hijackable dynamic libraries, separating exploitable privesc hijacks from harmless ones. Use to check if an app is hijackable.
compatibility
macOS only; requires otool, codesign, python3
# Dylib Hijack Scan ## Identity macOS dylib-hijacking auditor. Parse Mach-O load commands from scratch, decide exploitability by library validation, and separate user-context hijacks from real privilege escalation by reading directory permissions. Read/query only - never plant, modify, or delete. Report susceptibility and coverage honestly; state blind spots as loudly as findings. Ambiguous slot is not a finding. --- ## When to use Targeted, explainable dylib-hijack analysis: is this app hijackable and why, does any hijack cross a privilege boundary, sweep a whole machine and reason about each hit. For a raw full-disk sweep where only speed matters, Objective-See's compiled DylibHijackScanner is faster; the value here is that every finding carries the load command, the writable slot, the writer principal, and the mitigation. ## The two vulnerability classes 1. Weak-dylib hijack (`LC_LOAD_WEAK_DYLIB`): the binary weak-links a dylib that does not exist on disk. Because the link is weak the app still runs, so anyone who can write that path plants a dylib and gets code execution inside the process. 2. Rpath-order hijack (`@rpath/...` import with multiple `LC_RPATH`): dyld searches the rpath directories in declared order and loads the first match. An earlier, attacker-writable rpath that lacks the file lets a planted copy win over the real one found later. ## The mitigation that decides exploitability Library validation. Under the hardened runtime, absent the `com.apple.security.cs.disable-library-validation` entitlement and with a real Team ID, dyld refuses to load a dylib not signed by the host's team or Apple. A plantable slot on such a host is not practically exploitable. Determined from `codesign`, invoked only on hosts that have a slot, so there is no per-file cost. ## Elevation: ordinary hijack vs privilege escalation The axis that matters is whether a principal who can write the slot is less privileged than the one who loads it. - Who can write is read from the slot directory's permission bits and owner/group, and from any ACL - never from the euid running the scan, so the verdict is identical as standard user, admin, or root. Classes: `world` (any user), `anylocal` (group staff, gid 20, meaning any local user), `admin` (gid 80), `user` (one owner), and `root`/`none` (only root can plant, so not attacker-exploitable and never reported). - Who loads is the loader principal: root iff a LaunchDaemon with no or `root` `UserName`, a setuid/setgid-root binary, or a `/Library/PrivilegedHelperTools` helper. A normal app runs as whoever launches it. - Severity: `world`/`anylocal` writer plus root loader plus library validation off is CRITICAL (any local user to root). `admin`/`user` writer plus root loader is HIGH elevation. Writer equal to the loader's own user is HIGH but no elevation (user-context code execution, most findings). Library validation on is LOW. ACLs are honored. A `chmod +a` grant can widen access beyond the POSIX bits. `slot_writer()` checks for an extended ACL in-process via `acl_get_file` (one C call, no fork; dirs without an ACL are the vast majority) and parses `ls -lde` only for the rare dirs that carry one. An allow of a write right to a broader principal upgrades the writer class. Deny entries are not applied as a downgrade - for a scanner, over-reporting a writable slot is safer than missing one. ## Running it ```bash python3 scripts/scan.py / --json /tmp/scan.json python3 scripts/build_report.py /tmp/scan.json --html /tmp/report.html ``` `scan.py --json` always emits the full inventory: every analyzable Mach-O host (executable, dylib, bundle) with all its imports classified. It reads the magic bytes of every regular file, skipping known text and asset extensions so a full-disk walk stays tractable, and parses each Mach-O in process. Scan as a normal or admin user, not `sudo`, or the writability test no longer reflects a real attacker. Scope options: ```bash python3 scripts/scan.py "/Applications/Target.app" # one app, fast python3 scripts/build_report.py /tmp/scan.json --match target # focus report by substring ``` ## The report `build_report.py` renders the inventory into a per-app page. Flagged binaries get a full verdict table with a who-can-plant column; clean binaries are grouped at each app's foot as a compact dylib list, keeping a whole-system page inside the artifact size limit. It is theme-aware and self-contained, orders apps and rows most-severe first, starts collapsed, and offers a live text filter and an Elevation (privesc) only toggle. `--json` also writes the structured report. ## Reporting Lead with a one-line verdict (elevation count first, then user-context hijackable, then protected). Group multiple binaries in one bundle rather than listing near-identical lines. State the coverage numbers and named blind spots the tool prints: files and directories unreadable without elevation, and the dyld shared cache, whose system dylibs are not on-disk files and are Apple-signed with library validation. Never claim literal full coverage. ## Verifying a finding by hand ```bash otool -l "<host>" | grep -A2 -E 'LC_RPATH|LC_LOAD_WEAK_DYLIB|LC_LOAD_DYLIB' codesign -d --entitlements - --xml "<host>" | grep disable-library-validation codesign --display --verbose=2 "<host>" ls -lde "<slot directory>" ``` See `references/methodology.md` for the full detection algorithm, the writer and loader classification, the ACL handling, and the blind spots.
Auf GitHub ansehen