"BloodHound" for Android Internals, SELinux Policies, and Sandbox Escapes.
Discover multi-hop privilege escalation paths across Android SELinux domains, Binder IPC services, shared memory handles, allowxperm ioctl allowlists, mount namespaces, seccomp-bpf filters, and DAC permissions.
Quickstart • How It Works • Case Study: audioserver Blast Radius • OEM Firmware Diffing • MCP & LLM Tools • Roadmap
In modern Android, a single vulnerability rarely grants full device compromise. Exploiting a bug inside a sandboxed app (untrusted_app / isolated_app) or a media/audio daemon (audioserver / mediacodec) requires chaining multiple hops across SELinux domains, Binder/HwBinder services, UNIX sockets, shared memory (ashmem/dmabuf), allowxperm ioctl allowlists, and DAC capabilities.
Today, platform security researchers and vulnerability hunters answer "Where can I pivot from this process?" by running dozens of manual sesearch -A -s ... commands and cross-referencing service_contexts by hand.
SEGraph-Android brings BloodHound-style graph theory to Android internals:
- Multi-Layer Correlation: Combines binary
sepolicyand CIL/TE rules with realservice_contexts,hwservice_contexts,vndservice_contexts,allowxpermioctl command ranges, seccomp-bpf filters, and live/procDAC/namespace states—eliminating theoretical SELinux edges that are blocked by DAC, mount namespaces, or seccomp in practice. - Shortest-Path Sandbox Escape Queries: Instantly calculates the shortest viable pivot chains from any starting domain (e.g.,
untrusted_app,webview_zygote,audioserver) to high-value targets (system_server,init,vendor_init, or raw block/character devices). - OEM Vendor Diffing &
allowxpermAuditing: Compares an OEM firmware's SELinux + Binder graph against baseline AOSP to automatically spotlight custom vendor HALs, services, and unrestricted/dev/*ioctl surfaces dangerously exposed to untrusted apps.
flowchart TD
subgraph Sources["📱 Data Sources (Live ADB or Firmware Dump)"]
SEPol["Binary sepolicy\n(/sys/fs/selinux/policy)"]
Contexts["Binder Contexts\n(plat / vendor / hwservice_contexts)"]
ProcSnap["Live Runtime State\n(/proc/pid/status, mountinfo, attr, lshal)"]
end
subgraph Engine["🧠 SEGraph Correlation Engine"]
Parser["Binary sepolicy / SETools / CIL Parser"]
Filter["DAC + Mount Namespace + Seccomp Pruner"]
GraphDB["Weighted Directed Attack Graph\n(NetworkX / Pure-Python DiGraph)"]
end
subgraph Outputs["🎯 Actionable Outputs"]
PathFinder["Shortest-Path Escape Finder\n(Dijkstra / Yen K-Shortest Paths)"]
OEMDiff["AOSP vs. OEM Over-Privilege Diff\n+ allowxperm ioctl Analyzer"]
WebUI["Interactive Cytoscape.js Graph UI"]
MCPServer["FastMCP Server & LLM Tool Schemas"]
end
SEPol --> Parser
Contexts --> Parser
ProcSnap --> Filter
Parser --> Filter
Filter --> GraphDB
GraphDB --> PathFinder
GraphDB --> OEMDiff
GraphDB --> WebUI
GraphDB --> MCPServer
Every node represents an SELinux Domain, Binder Service, File/Device Type, or Socket, connected by weighted, actionable edges:
CAN_BINDER_CALL(binder { call transfer }+service_manager { find })CAN_PASS_FD(fd { use }+ sharedashmem_device/dmabuf_system_heap_devicerw access)CAN_RW_UNIX_SOCKET(unix_stream_socket { connectto }+ socket file write access)CAN_DOMAIN_TRANSITION(process { transition dyntransition }+ entrypointfile { execute })CAN_PTRACE_OR_SIG(process { ptrace sigchld }within permitted UID boundary)CAN_IOCTL_CHR_DEV(chr_file { read write ioctl }+allowxpermcommand range intersection)
Android's audio stack (audioserver, libaudioflinger, and vendor audio HALs) processes complex Parcel structures and shared-memory ring buffers accessible from regular apps. Suppose you discover a memory corruption bug in libaudioflinger.so. Where can you pivot next?
Run a 1-command blast-radius and pivot query:
$ segraph path --policy samples/pixel9_android16/sepolicy \
--contexts samples/pixel9_android16/all_service_contexts \
--source audioserver \
--target system_server \
--max-hops 3[*] Loaded 1,428 SELinux domains, 412 Binder/AIDL services, and 38,910 policy rules.
[*] Pruning unreachable edges using DAC UID/GID & mount namespace constraints...
[+] Found 3 viable pivot paths from [u:r:audioserver:s0] to [u:r:system_server:s0]:
Path #1 (Score: 92/100 - High Viability | Shared Memory + HAL Pivot)
1. [untrusted_app] ──(FIND + BINDER_CALL: media.audio_flinger)──► [audioserver]
2. [audioserver] ──(BINDER_CALL + FD_USE: android.hardware.audio.core.IConfig/default)──► [hal_audio_default]
3. [hal_audio_default] ──(RW_CHR_FILE: /dev/vndbinder + CALLBACK_TRANSFER)──► [system_server]
Path #2 (Score: 84/100 - Direct Callback Surface)
1. [audioserver] ──(FIND + BINDER_CALL: permission_checker / audio_policy)──► [system_server]
└── Exposed Native/Java Services: IAudioFlingerClient callbacks, SensorPrivacyService, MediaMetricsManager
flowchart LR
App["untrusted_app\n(UID: 10xxx)"]
AudioSvc["Service: media.audio_flinger\n(libaudioflinger.so)"]
AudioDom["audioserver\n(UID: 1041 / audio)"]
Ashmem["ashmem / dmabuf\n(Shared Ring Buffer FD)"]
AudioHAL["hal_audio_default\n(Vendor Audio HAL)"]
VendorDev["/dev/snd/* & Vendor Sockets\n(Driver Attack Surface)"]
SysSrv["system_server\n(UID: 1000 / system)"]
App -- "1. service_manager:find\nbinder:call" --> AudioSvc
AudioSvc --> AudioDom
App -- "2. fd:use (mmap)" --> Ashmem
Ashmem --> AudioDom
AudioDom -- "3. binder:call + fd:use\n(Audio Effect / Stream HAL)" --> AudioHAL
AudioHAL -- "4. ioctl / rw" --> VendorDev
AudioDom -- "3b. binder:transfer\n(Client Callback Binder)" --> SysSrv
Vendor customizations frequently introduce permissive SELinux rules or expose custom C++ system/vendor services to untrusted_app. Use segraph diff to automatically surface high-risk OEM additions:
$ segraph diff --baseline profiles/aosp_android15.json \
--target dumps/oem_flagship_v2/ \
--from untrusted_app┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ New Reachable Target ┃ Edge Type ┃ Exposed Service / Device Node ┃ Risk ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ vendor_diag_service (C++ Native) │ CAN_BINDER_CALL │ vendor.oem.diag.IDiagManager/default │ CRITICAL │
│ hal_perf_oem_default │ CAN_BINDER_CALL + FD_USE │ vendor.oem.perf.IPerfBooster │ HIGH │
│ oem_logd_socket │ CAN_RW_UNIX_SOCKET │ /dev/socket/oem_netlog │ HIGH │
└────────────────────────────────────┴────────────────────────────┴──────────────────────────────────────┴──────────┘
[!] Exported interactive HTML report to: ./reports/oem_diff_report.html
SEGraph-Android includes a FastMCP / JSON-RPC 2.0 stdio server and direct function-calling schema exporters (segraph llm-tools --format openai|gemini|mcp) so AI agents can autonomously query SELinux attack paths during vulnerability triage:
| MCP Tool Name | Description |
|---|---|
find_escape_paths(source_domain, target_domain, snapshot_path) |
Computes ranked K-shortest privilege escalation paths between two SELinux domains with runtime DAC/mountinfo/seccomp pruning. |
compute_blast_radius(source_domain, snapshot_path, max_hops) |
Enumerates all Binder services, HALs, UNIX sockets, and character devices reachable within N hops of a compromised domain. |
diff_oem_against_aosp(target_dump_path, baseline_path, from_domain) |
Compares an OEM firmware snapshot against baseline AOSP to identify newly exposed services, HALs, sockets, and ioctl surfaces. |
analyze_ioctl_attack_surface(domain, snapshot_path) |
Audits allowxperm ioctl allowlists on character devices reachable from domain to spot missing or overly broad driver command ranges. |
inspect_domain_constraints(domain, snapshot_path) |
Returns UID/GID, effective capabilities, /proc/<pid>/mountinfo visibility, seccomp-bpf status, and pruned edges for domain. |
export_attack_graph_html(snapshot_path, focus_domain, output_path) |
Generates a standalone interactive HTML/Cytoscape.js attack-path graph focused on a target domain. |
You don't even need a rooted device attached to try SEGraph-Android—the repository includes pre-extracted policy and service context snapshots for stock AOSP Android 15, Pixel 9 Android 16, and a synthetic OEM Flagship v2 firmware dump.
git clone https://github.com/<your-username>/SEGraph-Android.git
cd SEGraph-Android
uv sync
# 1. Generate an interactive HTML attack-path graph from the included AOSP snapshot:
uv run segraph explore --snapshot samples/aosp_android15 \
--focus audioserver \
--output audioserver_graph.html
# 2. Audit allowxperm ioctl character-device attack surface:
uv run segraph ioctl-audit --snapshot dumps/oem_flagship_v2 --domain untrusted_app
# 3. Or pull live state directly from an attached ADB device / Cuttlefish instance:
./collector/collect_live.sh --output ./my_device_dump
uv run segraph path --dump ./my_device_dump --source untrusted_app --target system_server
# 4. Export LLM tool schemas for OpenAI, Gemini, or MCP agents:
uv run segraph llm-tools --format openai > openai_tools.json
uv run segraph llm-tools --format gemini > gemini_tools.json- Binary
sepolicy+plat/vendor/hwservice_contextsgraph construction viasetools& pure-Python binary parser - K-shortest-paths solver (
untrusted_app/isolated_app/audioserver➔ privileged domains) - Standalone zero-dependency HTML/Cytoscape.js interactive graph exporter
- AOSP baseline vs. OEM firmware over-privilege diff engine
- Live
/proc/<pid>/mountinfoand seccomp-bpf syscall intersection pruning - Automated
ioctlallowlist (allowxperm) analyzer for reachable/dev/*character devices - MCP Server wrapper so AI agents can query SELinux attack paths during vulnerability triage
SEGraph-Android is a defensive attack-surface analysis and platform security auditing tool designed for Android OEM security teams, platform engineers, and vulnerability researchers.