
UNFINISHED/WIP - CVE-2026-43499 (IonStack/GhostLock) 삼성 SM-T878U / gts7l 연구용 POC. 트리거 + 지오메트리 검증됨, 아직 작동하는 루트 없음.
[!CAUTION] 이 프로젝트는 미완성입니다 — 아직 동작하지 않습니다. 2026-10-06 기준 어떤 기기에서도 동작하는 root는 없습니다. 아래의 빠른 시작이 성공할 것이라고 기대하지 마십시오. 무엇이든 빌드하거나 실행하기 전에 현재 상태를 읽으십시오.
[!WARNING] 상태: 작업 진행 중 — ring 1 미달성
- 미달성: SM-T878U에서 영구적 또는 단발성
root조차 없음.- 마지막으로 확인된 실패: 스택 회수(stack-reclaim) 페이로드가 커널의 쓰기 경로에 결코 도달하지 못함. 약 470회의 계측 실행 전반에서 위조된 락이
rtmutex.c:585에서 획득되는 것이 결코 관측되지 않았으며, 따라서*(ASHMEM_MISC_FOPS) = fake_fops저장이 실행되지 않음.- 이전 블로커, 현재 해결됨: 크래시 포렌식은 이전에
uid 2000 shell에게 사용 불가였음 (/proc/kmsg,/proc/last_kmsg,/sys/fs/pstore,dmesg→ 모두EACCES). 이제 내구성 있는write()+fsync()로그 미러 (IONSTACK_LOG_MIRROR)가CONFIG_PANIC_ON_OOPS=y에서도 살아남으므로, 패닉이 발생한 실행도 완전한 추적 기록을 남김.- 전체 증거 추적은
docs/RTMUTEX_WEAPONIZATION.md§15.16–§15.18 참조.
**Samsung Galaxy Tab S7 (SM-T878U / gts7l)**을 대상으로 CVE-2026-43499 (IonStack / GhostLock)에 대한 순수 C, 호스트 보조 재-root 개념 증명.
런타임 체인은 네이티브 C/ELF 구성 요소만 사용합니다. Android 타깃에서
Python, Java, DEX, app_process 또는 JVM을 필요로 하지 않습니다. ADB는
배포 및 검증에 사용됩니다.
root는 획득되지 않았습니다. 이 섹션은 체인의 현 위치에 대한 권위 있고
최신의 설명입니다 (최종 개정 2026-10-06). 아래의 모든 내용은 이론이
아니라 실제 하드웨어(SM-T878U, T878USQS8DXE1, 커널
4.19.113-27114284)에서 측정된 것입니다.
| 단계 | 상태 | 증거 |
|---|---|---|
| 타깃 식별 + KASLR 누출 | 동작 | [reroot] LEAK_OK kaslr_base=… task=… (perf 부채널) |
CVE 트리거: FUTEX_CMP_REQUEUE_PI → -EDEADLK | 동작 | [*] requeue ret=-1 errno=35 — Linux에서 EDEADLK == 35 |
버그 있는 롤백이 dangling pi_blocked_on을 남김 | 업스트림 수정과 일치 | 업스트림 3bfdc63936dd가 current->pi_blocked_on → waiter->task->pi_blocked_on으로 변경 |
struct rt_mutex_waiter 레이아웃 (4.19) | 소스에서 검증됨 | tree_entry@0x00 pi_tree_entry@0x18 task@0x30 lock@0x38 prio@0x40 deadline@0x48 |
스택 기하 paint == rt_waiter + 0x28 | 4회 검증 (objdump 포함) | rt_waiter = do_futex_sp+0xC0; address = ___sys_sendmsg_sp+0xB8 |
| 내구성 있는 크래시 포렌식 | 동작 | IONSTACK_LOG_MIRROR write()+fsync() 추적이 패닉 재부팅 후에도 생존 |
| 메시지별 frag-page 식별 태그 | 동작 | reclaim-scan tag=1 sent=8201 range=1..8201 ok=8192 bad=0 dup=0 undecoded=0 absent=9 |
| 큐 스캔: 커널이 8192개의 큐잉된 frag 페이지에 0바이트 기록 | 검증됨 | 256 MB를 페이로드와 바이트 단위로 비교, hits=0 |
rt_mutex_adjust_prio_chain이 쓰기 경로에 도달 | 디스어셈블리에서 검증됨 | top_waiter == NULL ⇒ requeue가 true로 유지 ⇒ 664/682/685/716-725가 구조적으로 도달 가능 |
page-dump 및 45개의 ring1-page 관측치 모두가
first_diff=8000 (pristine), owner_cpu=00000000, case1_gate=0, 그리고
lock_root/lock_leftmost가 페이로드 값과 정확히 동일함을 보고한다. 이 워크는
rtmutex.c:585에서 fake_lock->wait_lock을 취하는 것이 한 번도 관측된 적이 없으므로,
*(ASHMEM_MISC_FOPS)에 저장할 수 있는 유일한 분기인
664/682/685/716-725는 실행된 적이 없다.
_raw_spin_trylock()/_raw_spin_unlock()은 out-of-line 헬퍼를 경유하며 이 벤더 트리에는
arm64 queued_spin_unlock 오버라이드가 없으므로, wait_lock.val == 1이 신뢰할 수 있는
585 증거이고 owner_cpu != 0은 2차 증거에 불과하다는 점에 유의하라.prctl(PR_SET_MM, PR_SET_MM_MAP, …)으로 프레임을 회수한다. 이 커널은
# CONFIG_CHECKPOINT_RESTORE is not set으로 빌드되어 있어 해당 syscall은 컴파일에서 제외된다.
또한 이 익스플로잇은 우리의 차량인 sendmsg를 전혀 사용하지 않는데, 이는 (1)의 근본 원인일
가능성이 매우 높다.ring1-read는 실행된 적이 없다. 링 1의 유일한 사용자 공간 읽기 백
(configfs_read_once(fd, data_addr(ASHMEM_MISC_FOPS), …))은 큐 스캔 게이트 뒤에, 그리고
하네스 MARKER 기본값 뒤에 위치하는데, 이 기본값은 8초 더 이른 ring1-page에서 멈춘다.
게이트에 도달한 모든 실행은 page-dump tag=pre-arm과 page-dump tag=post-arm 사이에서
종료되었다.664/682/685가 우리 자신의 페이지 내부에서 완료될 수 있는 유일한 구성 —
IONSTACK_FOPS_WAIT_LOCK_WORD=0과 IONSTACK_PAINT_WAITER_TASK_MODE=fake-task — 을
다시 실행하고, page-dump tag=post-arm / ring1-lock585에서 wait_lock=00000001을
확인하라.ring1-read를 실행시키라: IONSTACK_RECLAIM_SCAN_QUEUE를 설정하지 않고
MARKER='ring1-read|…'로 실행하여 하네스가 ring1-page에서 멈추지 않게 하라.IONSTACK_RECLAIM_TAG=1로 실행하고 page-dump에서
pipe_tag를 msg_tag와 비교하라. 모든 frag 페이지는 페이로드의 바이트 단위 동일 사본이므로,
first_diff만으로는 이들을 구별할 수 없다.IONSTACK_FOPS_WAIT_LOCK_WORD 질문을 제대로 정립된 기반 위에서 재검증하라 —
IONSTACK_RECLAIM_TAG를 일정하게 유지한 채 wlw=0 대 wlw=1을 비교하라. 이전의 상관관계는
두 변수가 함께 움직였기 때문에 교란되었다.res_in/res_out pselect6 페인트 표면을 이식하라.fops.c:3157 reason=selinux_write ret=-1 errno=22 EINVAL — 여전히 미해결.
| 문서 | 내용 |
|---|---|
docs/RTMUTEX_WEAPONIZATION.md | rtmutex 체인에 대한 전체 증거 기록 (가장 큰 문서) |
docs/ROOT_CHAIN_THEORY.md | 엔드투엔드 링 0→4 루트 체인 설계 |
docs/PAINT_ORACLE_ANALYSIS.md | 스택 페인트 오라클이 그렇게 읽히는 이유 |
docs/PSELECT_GEOMETRY_FINDINGS.md | 대체 페인트 차량으로서의 pselect6 |
docs/RING1_RECLAIM_IDENTITY_2026-10-06.md | 메시지별 frag 페이지 식별 태그; 큐 스캔 검증 |
docs/RING1_585_NEVER_SUCCEEDED_2026-10-06.md | rtmutex.c:585가 절대 성공하지 못했다는 증명 |
docs/RING1_ORACLE_FIX_2026-10-05.md | 오라클 수정 |
docs/RING1_ORACLE_WRONG_FRAGMENT_2026-10-06.md | 점유된 프래그먼트가 잘못 식별된 이유 |
target-artifacts/에는 기기 없이 이 대상을 분석하는 데 필요한
모든 것이 담겨 있다:
/proc/config.gz(원본 + 압축 해제본),src/exploit/offset.h 내 모든 주소 유사 상수의
기계적 검증,주요 결과: ELF에 내장된 linux_banner가 디바이스와 바이트 단위로 일치하므로
(T878USQS8DXE1 / 4.19.113-27114284 확인됨), ELF는 스트립되지 않았으며,
주소 유사 offset.h 상수 27개 중 24개가 심볼과 정확히 일치하고 해석 불가 항목은
0개입니다. 하나의 명명 함정을 포함한 전체 보고서는
target-artifacts/README.md를 참조하십시오:
CONFIGFS_READ_FILE_OFF는 실제로 configfs_read_file이 아니라
configfs_read_bin_file을 가리킵니다.
이 POC는 모든 프로필 검사가 일치하지 않으면 의도적으로 fail closed 방식으로 동작합니다:
device: gts7l
Android: 13 / SDK 33
fingerprint: samsung/gts7lsqwnc/gts7l:13/TP1A.220624.014/T878USQS8DXE1:user/release-keys
kernel: 4.19.113
build: T878USQS8DXE1
지원되지 않거나 실패한 실행은 기기를 패닉 상태로 만들거나 재부팅할 수 있습니다. 복구 경로를 항상 확보해 두십시오.
이 저장소는 위의 펌웨어 프로필로 범위가 좁게 한정되어 있습니다. 범용 루팅 도구가 아니며, 오프셋이나 가정은 독립적인 검증 없이 다른 기기에서 재사용해서는 안 됩니다.
adb devices -l
그런 다음:
./build/smt878u-ionstack-reroot -s SERIAL --preflight-only
./build/smt878u-ionstack-reroot -s SERIAL --validate-only
./build/smt878u-ionstack-reroot -s SERIAL
호스트가 성공을 보고한 후, root를 확인하고 셸을 엽니다:
adb -s SERIAL shell /data/local/tmp/su -c id
adb -s SERIAL shell /data/local/tmp/su
-s SERIAL은 ADB 기기가 정확히 하나만 연결된 경우 선택 사항입니다.
요구 사항: