
CVE-2026-43499 부팅별 루트 익스플로잇 — 핵심 로직 (arm64 Android GKI 6.6)
CVE-2026-43499 (Futex PI UAF) 커널 임의 주소 쓰기 익스플로잇의 핵심 로직 코드로, SELinux를 우회하여 root를 획득합니다.
본 저장소에는 핵심 익스플로잇 로직 소스(
src/)와 단일 바이너리 패커(wrapper/)만 포함되어 있습니다.src/target.h는 템플릿이며, 실행하려면 자신의 기기 파라미터를 입력해야 합니다(아래 "기기 적응" 참조).
# 环境要求: Android NDK r29+ (API 35, aarch64)
export ANDROID_NDK_ROOT=/path/to/android-ndk
# 构建纯逻辑产物
make
# → build/unplus (exploit 二进制)
# → build/unplus_preload.so (preload 库)
산출물은 두 개의 ELF이며, 외부 바이너리를 내장하지 않습니다.
익스플로잇과 외부 페이로드(magiskpolicy / ksud / kernelsu.ko)를 원버튼 실행 단일 바이너리로 패킹하려면, 해당 외부 페이로드를 직접 준비한 후 wrapper/로 패킹합니다:
# 1. 先构建 src/ 产物(见上)
# 2. 生成 payload 数据(payload_data.h 不在仓库,由用户自生成,含外部二进制字节流)
cd wrapper
python3 embed_payloads.py \
--unplus ../build/unplus \
--preload ../build/unplus_preload.so \
--magiskpolicy <path> \
--ksud <path> \
--kernelsu <path> \
--out payload/
# 3. 编译单二进制
make # → wrapper/build/unplus
src/
├── target.h 设备参数模板(◆ FILL IN 标记处需填你的设备值)
├── offset.h target.h 的路由胶水(经 -DTARGET_CONFIG_H 注入)
├── unplus.h 编排头 + 共享声明(含 P0 alias / data_addr 等派生宏)
├── main.c 入口编排
├── stage1.c Write 1/2:SELinux 关闭 + cred 覆写
├── root.c Android root 落地(SELinux golden 修复 + sepolicy + KSU allowlist)
├── slide.c KASLR leak
├── fops.c configfs/fops 路由 + 内核基址推导
├── route.c PI futex 路由线程
├── direct_write.c direct read 原语
├── pipe_direct.c direct pselect write
├── pipe_physrw.c pipe physrw 原语
├── util.c 工具函数
├── utils.h 通用工具(日志、procfs 路径)
├── kernelsnitch.h 架构层(ARM64/x86 identity-map)
├── futex_hash.h 内核 jhash 移植(通用)
└── timeutils.h 架构层计时(ARM/x86/AMD)
src/target.h는 두 종류의 상수로 나뉩니다:
◆ FILL IN 표시 항목: 기기/커널 관련이며, 반드시 자신의 값으로 채워야 합니다. 템플릿에서는 0xDEADBEEF... 자리 표시자를 사용하며, 컴파일은 가능하지만 실행하면 크래시됩니다.기기 변경 = ◆ FILL IN 부분을 채우면 됩니다. 각 필드가 무엇이고 어떻게 얻는지에 대해서는 아래 부록: 필드 설명을 참조하세요.
target.h에서 ◆ FILL IN 필드를 용도별로 그룹화합니다:
일반 경험칙: 모든 *_OFF 계열 오프셋은 루팅된 기기의 kallsyms_lookup_name으로 심볼 주소를 얻은 뒤 KIMAGE_TEXT_BASE를 빼서 구할 수 있습니다. TARGET_PCPU_*와 TARGET_SELINUX_GOLDEN은 런타임/덤프 값이므로 정적 이미지에서 얻을 수 없습니다.
WTFPL — Do What The Fuck You Want To Public License.
| 그룹 | 필드(예시) | 의미 / 획득 방법 |
|---|
| Build identity | BUILD_VARIANT_LABEL, BUILD_FINGERPRINT | 임의 식별 문자열, 로그용. 기기의 build fingerprint를 입력 |
| Memory layout | KIMAGE_TEXT_BASE, P0_PHYS_OFFSET, VMEMMAP_START 등 | 커널 가상/물리 주소 레이아웃. arm64 VA39는 보통 기본값이 제공됨; IKCONFIG / kallsyms / /proc/iomem에서 확인 |
| ASHMEM | ASHMEM_IOCTL_OFF ... ASHMEM_MISC_FOPS_OFF | ashmem 드라이버 각 fops 멤버 + misc 심볼 오프셋. kallsyms_lookup_name("ashmem_fops") 등 |
| CONFIGFS / PIPE / VFS | CONFIGFS_READ_ITER_OFF, ANON_PIPE_BUF_OPS_OFF, KMALLOC_CACHES_OFF 등 | configfs 읽기/쓰기, splice, pipe_buf_ops, kmalloc_caches 오프셋. kallsyms로 조회 |
| SELinux | SELINUX_ENFORCING_OFF, SELINUX_BLOB_SIZES_OFF, SECURITY_HOOK_HEADS_OFF | selinux_state / selinux_blob_sizes / security_hook_heads 오프셋. SELINUX_ENFORCING_OFF는 커널 빌드 매칭 앵커 포인트이며, 정확해야 함 |
| Core kernel symbols | INIT_TASK_OFF, INIT_CRED_OFF, ENTRY_TASK_PERCPU_OFF 등 | init_task / init_cred / entry_task / __per_cpu_offset / root_task_group 오프셋. kallsyms로 조회; ENTRY_TASK_PERCPU_OFF는 percpu 섹션 내 __entry_task의 오프셋 |
| Per-CPU runtime | TARGET_PCPU_BASE_ADDR, TARGET_PCPU_UNIT_SIZE | per-CPU 청크의 런타임 주소(KASLR 이후)이며, 부팅 때마다 변경됨. 런타임 덤프 필요; UNIT_SIZE는 CPU 수에 따라 달라짐 |
| SLIDE (KASLR leak) | SLIDE_NFULNL_LOGGER_OFF, SLIDE_RANDOM_BOOT_ID_DATA_OFF 등 | KASLR 누출에 사용되는 커널 데이터 심볼 오프셋(nfulnl_logger / boot_id data 등). kallsyms로 조회 |
| SELinux golden | TARGET_SELINUX_GOLDEN | selinux_state 처음 16바이트 boolean 템플릿. 재부팅에도 안정적이지만 기기마다 다름. 기기의 selinux_state 덤프에서 얻어야 함. byte0는 enforcing 비트이며, 호출부에서 0x00을 쓰면 permissive를 의미 |
| pipe inode info | PIPE_INODE_INFO_*, PIPE_HEAD_OFF 등 | pipe_inode_info 구조체 레이아웃. 동일 GKI 패밀리 내에서는 보통 안정적이며, 커널 빌드를 바꿀 경우 검증 필요 |