Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-43499-S26 — Android GKI 6.12 커널 익스플로잇으로, CVE-2026-43499를 대상으로 하며 rt_mutex 롤백 버그와 pselect 스택 덮어쓰기를 연쇄하여 Samsung 및 Pixel 기기에서 root 권한을 획득합니다. | Kitploit
도구/GitHubGitHub/sammyenigma/cve-2026-43499-s26
Android SecurityPrivilege EscalationMemory ForensicsPersistence MechanismsExploitationReverse EngineeringShellcodePost-ExploitationMobile SecurityPayload DevelopmentBinary Exploitation
122일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
GitHub
sammyenigma/cve-2026-43499-s26

CVE-2026-43499-S26

Android GKI 6.12 커널 익스플로잇으로, CVE-2026-43499를 대상으로 하며 rt_mutex 롤백 버그와 pselect 스택 덮어쓰기를 연쇄하여 Samsung 및 Pixel 기기에서 root 권한을 획득합니다.

저장소 보기

CVE-2026-43499 — Android GKI 6.12 pselect / configfs 커널 익스플로잇

Android GKI 6.12 라인(Samsung 및 Pixel 기기)을 대상으로 하는 Linux 커널 익스플로잇으로, CVE-2026-43499를 겨냥합니다: rt_mutex_start_proxy_lock() 내의 버그가 있는 remove_waiter() 롤백이 waiter::task 대신 current를 사용하여, waiter의 pi_blocked_on이 (나중에 pop되는) 커널 스택 rt_mutex_waiter를 가리킨 채로 남게 됩니다. 여기에 pselect() fd_set 스택 덮어쓰기와 consumer의 sched_setattr 기반 가짜 rb_tree 순회를 결합하면 결정론적인 커널 쓰기 프리미티브와 완전한 root를 얻을 수 있습니다.

이 익스플로잇은 LD_PRELOAD 공유 라이브러리(preload.so)로 실행되며, root 획득 후 아티팩트로 root su 데몬과 월페이퍼를 설치합니다.

상태: 활발히 개발 중. m1q (ZF1) 타겟이 bring-up의 초점입니다. pipei tmp_page-uname 부트스트랩이 현재 활성 경로입니다: 순회는 온디바이스에서 깨끗함이 입증되었고(build #33: 자식별 시드된 rt_mutex 영역), 전체 168개 후보 스윕이 진행 중입니다. configfs CFI 경로는 m1q에서 막다른 길이며(Rust ashmem — 주입 가능한 fops 슬롯 없음), C-ashmem 타겟을 위한 경로로 남아 있습니다. 타겟별 오프셋은 기기마다 다르므로 신뢰하기 전에 실제 커널 바이너리와 대조하여 검증하십시오.

취약한 프리미티브 (CVE-2026-43499)

FUTEX_CMP_REQUEUE_PI가 waiter를 requeue하고 requeue의 교착 감지 체인 순회가 -EDEADLK를 반환하면, __rt_mutex_start_proxy_lock()은 remove_waiter()를 통해 롤백합니다(rtmutex.c:1535). 롤백은 waiter를 대기 트리에서 올바르게 디큐하지만, waiter->task->pi_blocked_on 대신 requeue 호출자의 pi_blocked_on을 클리어합니다. WAITER의 pi_blocked_on은 스택 rt_mutex_waiter를 가리킨 채 dangling 상태로 남고, 이는 futex가 타임아웃되면 pop됩니다.

타임아웃 후 waiter의 커널 스택 영역이 재사용됩니다: core_sys_select()가 세 개의 fd_set을 해당 스택 버퍼로 복사합니다(ZF1의 nfds < 344 스택 경로). 조작된 fd_set 워드 배열이 가짜 rt_mutex_waiter / 가짜 task / 가짜 rt_mutex(포인터가 제어되는 rb_tree 루트 포함)를 재구성합니다. 그런 다음 consumer 스레드가 sched_setattr_tid(waiter) → rt_mutex_adjust_pi() → rb_erase_cached를 호출하여 제어된 값의 임의 주소 쓰기를 만들어냅니다.

전체 프리미티브는 PI 체인 사이클을 필수로 요구합니다: owner가 f_pi_target을 보유하면서 동시에 (waiter가 보유한) f_pi_chain에서 블록되므로, 체인 순회가 owner → chain → waiter → target → owner에 도달하여 -EDEADLK로 실패합니다. 사이클을 제거하면 requeue가 성공을 반환하고 커널 효과는 전무합니다.

익스플로잇 체인

  1. Slide (KASLR) — 커널 베이스를 유출합니다. 두 가지 경로:
    • tracefs sched_blocked_reason (m1q 주 경로, 온디바이스 입증): 블록된 kworker의 저장된 반환 PC(stack_trace_save_tsk)를 링 버퍼에서 읽어 컴파일 내장된 worker_thread 오프셋과 비교합니다. 부트_id 경로 워드가 사용되기 전에 실행되므로 데이터-앨리어스 쓰기 타겟(data_addr() = p0 앨리어스 + slide_p0_offset)이 0이 아닌 slide에서도 올바르게 유지됩니다.
    • boot_id pselect 경로 (폴백, slide 독립적): pselect 쓰기가 선형 맵 앨리어스를 통해 SLIDE_LOGGERS_0_1을 boot_id sysctl 데이터에 심고, 유출된 값이 stext를 재구성합니다. m1q에서는 보류됨: W1 타겟 (SLIDE_RANDOM_BOOT_ID_DATA_OFF, 낮은 물리 RAM)은 페이지 의존적 쓰기 가능성을 가지며 — slide가 부팅마다 타겟을 페이지 경계 너머로 이동시키므로 약 6/7 실행이 폴트합니다. SLIDE_FORCE_BOOTID(메커니즘 테스트)로 명시적 실행할 때만 tree_pc/tree_left가 스프레이된 페이지로 리다이렉트됩니다.
  2. KernelSnitch — mm_struct 크기의 객체를 스프레이하고 futex-hash 충돌을 사용하여 힙에서 mm_struct를 찾아내어, 가짜 객체 스프레이 베이스로 사용되는 커널 힙 페이지 주소를 유출합니다. 정리 시 waiter는 (join하지 않고) 분리되어 #26 이전 빌드를 크래시시킨 커널 스택 OOM을 피합니다.

순회 형태 (m1q, 온디바이스 입증)

pselect fd_set 워드가 waiter의 커널 스택에 가짜 rt_mutex_waiter를 재구성하고, consumer 스레드의 sched_setattr_tid(waiter)가 rt_mutex_adjust_pi()를 통해 이를 순회합니다. ZF1 워드 맵(디스어셈 검증): PSELECT_WAITER_WORD_SHIFT = 0, word 12 = task (@+0x50), word 13 = lock (@+0x58), word 14 = wake_state (@+0x60 = 3). 시드된 가짜 rt_mutex를 사용하면 순회가 깨끗하게 완료됩니다: [7]의 rb_erase W1 *(tree_left)=tree_pc / W2 *(tree_pc&~3+8)=tree_left가 유일한 커널 쓰기이며, [11] (setprio / dequeue_pi)과 [9] wake는 모두 건너뜁니다(prio 100의 로컬 가짜 waiter가 스택 노드를 top-waiter 밖에 유지). build #19 이후 모든 순회 진입 완료가 온디바이스에서 생존합니다; 그 이전의 결정론적 크래시는 순회 본체 결함이 아니라 8바이트 페이로드 배치 오류(SKB_DATA_DELTA)였습니다.

Stage 3 (pgd-swap 브리지, 정적/빌드 전용)

선택적 STAGE3=1 단계로, 브리지 자식을 fork하고 그 mm->pgd를 준비된 가짜 페이지 테이블(3레벨: PGD→L1→L2, RX 루프 리프 + RW 스택 리프)로 교체한 뒤, 자식이 레지스터 전용 어셈블리 블롭을 실행하여 2MB 물리 스캔 윈도우를 통해 자신의 cred를 패치하도록 합니다 — configfs/pipe 프리미티브 없이 전 RAM 물리 R/W. 현재 m1q 타겟에만 연결되어 있으며 온디바이스에서 실행된 적은 없습니다.

지원 타겟

src/targets/<codename>-<build>/에 41개 타겟이 있으며, 각각 최소한 target.h(커널 심볼 오프셋, KIMAGE_TEXT_BASE, direct-map 베이스, 구조체 오프셋)를 필요로 합니다. Pixel 타겟(comet, tokay, tegu, caiman, komodo, frankel, mustang, rango, stallion, blazer)은 공유 소스를 오버라이드하고, Samsung 타겟(m1q-*)은 기기별 로직을 추가합니다.

root@kitploit:~
make list-projects   # full list

커널 구조체 레이아웃은 기기마다 다르므로 — 오프셋은 각 타겟의 실제 커널 바이너리 / kallsyms와 대조하여 검증해야 합니다.

빌드

출력: build/<PROJECT>/bin/preload.so (LD_PRELOAD로 로드되는 공유 라이브러리).

root@kitploit:~
# Default project
CC=clang make

# Specific device target (default: blazer-CP2A.260605.012)
CC=clang make PROJECT=m1q-BP4A.251205.006

# Without CC=clang: uses NDK if found ($NDK_ROOT / $ANDROID_NDK_HOME /
# $ANDROID_NDK_ROOT), otherwise host clang + Android sysroot
make PROJECT=m1q-BP4A.251205.006

# Show build configuration
make info

# Clean
make clean

빌드는 PIE su_daemon 바이너리(src/su_daemon.c, build/embed/su_daemon_aarch64_pie로 빌드됨)와 assets/wallpaper.webp를 src/su_blob.S / src/wallpaper_blob.S를 통해 preload.so에 내장합니다.

기기에서 실행

빌드 출력을 /data/local/tmp로 푸시한 다음, LD_PRELOAD 하에서 익스플로잇을 실행합니다. 라이브 bring-up 타겟에서는 tee 없이 실행하십시오 — tee는 자체 stdio를 버퍼링하여 커널 패닉 시 로그의 꼬리를 잃습니다(익스플로잇 stdout은 언버퍼링이므로 파일로 바로 리다이렉트하면 모든 줄이 보존됩니다):

root@kitploit:~
adb push build/m1q-BP4A.251205.006/bin/preload.so /data/local/tmp/preload.so
adb push build/embed/su_daemon_aarch64_pie /data/local/tmp/su_daemon_aarch64_pie
adb shell "chmod 755 /data/local/tmp/preload.so /data/local/tmp/su_daemon_aarch64_pie"

adb shell "LD_PRELOAD=/data/local/tmp/preload.so \
  /data/local/tmp/su_daemon_aarch64_pie \
  > /data/local/tmp/output.log 2>&1"

성공하면 데몬이 /data/local/tmp/temp_su.sock에서 리스닝하고 su가 /apex/com.android.virt/bin 아래에 설치됩니다.

m1q pipei 스윕 (현재 bring-up)

tools/run_pipei.sh는 바이너리를 푸시하고, 온디바이스에서 sha256 검증한 뒤(오래된 preload.so는 조용히 판독 불가능한 판정을 낳습니다 — ladder가 한때 로그 형식이 다른 build < #22를 실행했습니다), 전체 168개 후보 스윕을 3x56으로 청크하여 패닉 시 최대 한 청크(~10분)만 잃도록 실행합니다. 익스플로잇 stdout은 adb를 통해 직접 스트리밍됩니다(온디바이스 리다이렉트 없음 — 기기 측 tee는 패닉 시 꼬리를 잃습니다); 각 청크의 호스트 측 사본은 /tmp/m1q_pipei_chunk{1..3}_stream.log에 보관됩니다:

root@kitploit:~
sh tools/run_pipei.sh

PASS = 어느 청크든 tmp_page uname changed + after uname='CatOS를 보이는 경우. PIPEI_CHILD_REGIONS는 최소한 청크 크기로 설정되어야 하며, 그렇지 않으면 자식별 rt_mutex 영역이 시드되지 않은 채로 남아 스윕이 후보 0에서 패닉합니다. 전체 커버리지는 또한 TMP_UNAME_PIPEI_SPLIT_ORDER_PAGES=1을 요구합니다 — 이것 없이는 해제된 8페이지 mm 블록 중 한 페이지만 스윕됩니다. run_pipei_slim.sh는 단일 후보 진단 변형이고, run_m1q_ladder.sh는 순회/격리 배터리(B16-2 오라클, slide 메커니즘, 스윕 단계)입니다.

런타임 구성 (환경 변수)

프로젝트 레이아웃

root@kitploit:~
exploit/
  Makefile
  assets/                     # wallpaper.webp (embedded post-root artifact)
  src/
    main.c                    # run_exploit() entry point (shared)
    preload.c                 # LD_PRELOAD constructor, su/wallpaper install
    util.c                    # addr translation, page prep, configfs helpers
    pipe.c                    # pipe-based physical read/write
    root.c                    # cred patching / task walk
    slide.c                   # KASLR slide (tracefs + boot_id routes)
    fops.c                    # pselect corruption + fops manipulation
    faketables.c              # stage-3 fake page-table builders (3-level)
    stage3.c                  # pgd-swap bridge child (no-op unless configured)
    stage3_loop.S, stage3_poll.S  # bridge blob + enter trampoline
    su_daemon.c               # root daemon (compiled as separate PIE)
    su_blob.S, wallpaper_blob.S   # embedded binaries
    offset.h                  # pulls per-target target.h via -DTARGET_CONFIG_H
    kernelsnitch/             # mm_struct futex-hash leak library
    targets/<codename>-<build>/    # per-device target.h + optional overrides
poc/poc.c                     # standalone POC (separate from the exploit)

타겟은 Makefile pick_src 메커니즘을 통해 공유 소스를 오버라이드합니다: src/targets/<PROJECT>/<file>.c가 존재하면 공유 src/<file>.c 대신 사용되고, 그렇지 않으면 공유 버전이 사용됩니다.

참고 및 주의사항

  • PI 체인 사이클을 절대 제거하지 마십시오. 쓰기 프리미티브는 requeue가 -EDEADLK(errno 35)로 실패하는 것에 의존합니다. 사이클이 없으면 커널 효과 없이 success=1로 나타납니다.
  • waiter는 pselect 전반에 걸쳐 PI 체인 락을 보유해야 합니다. 먼저 해제하면 owner가 깨어나 가짜 rb_tree 순회와 경쟁 → 패닉합니다.
  • m1q: PSELECT_WAITER_WORD_SHIFT는 0이어야 합니다 (ZF1 스택 깊이를 ELF에서 검증). 다른 타겟은 여전히 기본값 1이므로 — 신뢰하기 전에 기기별로 검증하십시오.
  • p0_data_alias()는 DIRECT_MAP_BASE(선형 맵)를 사용하며, 이는 ZF1의 P0_PAGE_OFFSET과 다릅니다. 역참조되는 커널 객체의 데이터 앨리어스는 선형 맵을 사용해야 합니다.
  • pr_error()는 치명적입니다(exit(-1)), 경고/정보 매크로와 달리.
  • Slide 재구성은 SLIDE_NFULNL_LOGGER가 아니라 SLIDE_LOGGERS_0_1을 사용합니다; 이 워드는 무작위화되지 않은 선형 맵 앨리어스이므로 boot_id 경로는 slide 독립적입니다(slide=0에서만 사용 — tracefs 유출을 먼저 실행하십시오).
  • SKB_DATA_DELTA는 -0xe78입니다 (온디바이스 측정, build #19) — 실제 skb frag head는 디스어셈 유도값 -0xe80보다 8바이트 작습니다; 그 8바이트 오류가 build #6-18의 모든 결정론적 pselect 크래시를 일으켰습니다 (순회 진입 → 가비지 역참조). GKI 6.12 공유 값; 타겟별 util.c 사본에는 환경 A/B 노브가 있습니다. 내장 상수 위에 를 중첩하지 마십시오.

면책 조항

이것은 Android 기기용 익스플로잇 코드이며, 보안 연구, 승인된 취약점 테스트, 그리고 본인이 소유하거나 명시적 테스트 허가를 받은 하드웨어에서의 방어 작업을 위한 것입니다. 소유하지 않은 기기에서의 오용은 불법입니다. 저자는 벽돌이 된 기기, 벽돌이 된 커널, 또는 무효화된 보증에 대해 책임지지 않습니다.

도구 다운로드
  • 주 경로 — pipei tmp_page 부트스트랩 (m1q, 현재 초점) — 원래의 configfs CFI 경로는 m1q에서 막다른 길입니다: Rust ashmem에는 주입 가능한 정적 write_iter 슬롯이 없고 ASHMEM_SET_NAME 힙 객체는 레이아웃이 configfs_bin_write_iter의 private_data와 정렬되지 않는 KVec입니다. m1q는 대신 kmalloc 쓰기로 전환합니다: 유출된 mm order-3 블록을 pipe_inode_info 객체로 재점유하고 pselect W1 쓰기(*(tree_left) = tree_pc)를 사용하여 후보의 tmp_page 슬롯(+0x90)을 UTS 네임스페이스 페이지(init_uts_ns)로 덮어씁니다. fanout 쓰기가 sysname 오프셋에 마커 이름을 심고 uname()이 "CatOS"를 보고합니다 — 정적 객체 의존성이 없는 검증 가능한 커널 쓰기입니다. C-ashmem 타겟은 configfs 경로를 유지합니다.
  • Pipe physrw — 물리적 읽기/쓰기를 위해 스프레이된 커널 페이지에 pipe 버퍼 페이지를 위조합니다: cred 패칭, SELinux 비활성화, 직접 커널 메모리 조작.
  • Root — root 자식의 cred(uid/gid/caps/SELinux SID)를 패치한 다음, preload.c가 내장된 su 데몬(/apex/com.android.virt/bin에 tmpfs 마운트, plus adbd-namespace 및 로컬 변형)을 설치하고 월페이퍼를 교체합니다.
  • VariableDefaultPurpose
    PSELECT_ROUTE_SHIFTcompile-time주 경로(m1q)의 A/B fd_set 워드 시프트
    SLIDE_SHIFTcompile-timeslide 경로의 A/B fd_set 워드 시프트
    PSELECT_ROUTE_DELAY_USEC50000sched_setattr 전 consumer 지연 (0보다 커야 함)
    SLIDE_CONSUME_USEC, SLIDE_ENTER_DELAY_USEC, SLIDE_CONSUMER_CORE—Slide 경로 타이밍/피닝
    SKIP_SLIDE0direct-map 폴백 사용 (slide = 0)
    SLIDE_ONLY0KASLR slide만 실행하고 종료
    SLIDE_P0_OFFSET, SLIDE_BOOTID_OFF—slide p0-앨리어스 / boot_id 오프셋 오버라이드
    SLIDE_FORCE_BOOTID0tracefs slide 후 boot_id pselect 경로 강제 (메커니즘 테스트)
    KSNITCH_COLLISIONS4KernelSnitch 충돌 횟수
    STAGE30pgd-swap 브리지 자식 단계 활성화 (m1q)
    STAGE3_DRYRUN0테이블 준비/검증 후 swap 전에 중단
    PAGE_RECLAIM_SENDS, PSELECT_SIMPLE_LAYOUT—스프레이/fd-set 레이아웃 조정
    TMP_PAGE_UNAME0m1q pipei tmp_page-uname 부트스트랩 실행
    TMP_UNAME_PIPEI_SWEEP, TMP_UNAME_PIPEI_ALIGN_ORDER, TMP_UNAME_PIPEI_SPLIT_ORDER_PAGES—스윕 모드; split_order는 해제된 mm 블록의 8페이지 전부를 스윕
    TMP_UNAME_PIPEI_SLOT, TMP_UNAME_PIPEI_SLOT_CANDIDATES—스윕 범위 (청크 시작 / 개수)
    PIPEI_CHILD_REGIONS0자식별 시드된 rt_mutex 영역; 스윕 청크 이상이어야 하며, 그렇지 않으면 시드되지 않은 영역이 후보 0에서 패닉
    PIPEI_RECLAIM_COUNT, PIPEI_DRAIN_COUNT—pipe 쌍 재점유/드레인; 재점유 실패 시 증가
    PIPEI_SPONGE_MB3072재점유 전반에 걸쳐 유지되는 order-0 플러드 스폰지 (build #29)
    PSELECT_W0_PRIO_OVERRIDE130Top-waiter prio; 시드된 영역에서는 무효 (레거시 stale-tree 가드, A/B 전용)
    PSELECT_SKB_DELTA_OVERRIDE0A/B 페이로드 페이지 내 오프셋 (기기가 -0xe78과 다를 경우에만)
    TMP_UNAME_NAME, TMP_UNAME_HOLD_SEC"CatOS", 5성공 후 마커 이름 / 유지 시간
    SKB_DATA_DELTA
    PSELECT_SKB_DELTA_OVERRIDE
  • 순회 본체는 깨끗합니다; 배치가 버그였습니다. 모델링된 오프셋에 시드된 페이로드를 두면 체인 순회가 온디바이스에서 폴트 없이 완료됩니다. 순회 진입 크래시는 fd-word 주소의 메모리가 페이로드가 아님(재점유/배치 경쟁)을 의미하며, 모델 오류가 아닙니다.
  • m1q: configfs CFI 경로는 막다른 길입니다 (Rust ashmem) — 주입 가능한 정적 fops 슬롯이 없고 ASHMEM_SET_NAME KVec 엔벨로프가 configfs_bin_write_iter와 정렬되지 않습니다. pipei tmp_page 부트스트랩을 사용하십시오. m1q target.h의 PSELECT_WRITE_RIGHT_SPRAYED / PSELECT_PI_TOP_TASK_SELF 가드가 순회의 [11] 쓰기를 RO 정적 fops 밖으로 리다이렉트합니다.
  • 자식별 rt_mutex 영역 (build #33): 각 스윕 자식은 fd word w13을 재점유된 페이지 내 자신의 시드된 영역(payload+0x6000 + idx*0x40)으로 리다이렉트합니다. 공유 fake_lock 스윕은 후보 ~9-12에서 패닉했고(오래된 커널 스택 노드 재활용), build #32의 빈 영역은 후보 0에서 패닉했습니다(0x41로 채워진 fake_task에서 [9] owner==NULL wake). PIPEI_CHILD_REGIONS를 설정하지 않으면 영역이 시드되지 않은 채로 남습니다.
  • m1q boot_id pselect slide는 보류됨 — W1 타겟이 낮은 RAM으로, 페이지 쓰기 가능성이 부팅마다 변합니다; tracefs가 주 경로이며 매 실행마다 slide를 측정합니다.