
CVE-2026-43499를 악용하여 KernelSU를 설치하는 원클릭 Android 커널 루팅 도구로, 공식·번들·커스텀 .so 페이로드 소스를 지원합니다.
⚠️ 温馨提示: 블루팩토리 기종의 스케줄링 정책은 비교적 엄격하여, 권한 상승 시 자식 프로세스가 시스템에 의해 쉽게 회수됩니다. 먼저 「개발자 옵션」에서 「자식 프로세스 제한 중지」를 활성화한 후 권한 상승을 실행하면 성공률이 더 높습니다.
CVE-2026-43499(GhostLock) 커널 취약점 기반의 원클릭 KernelSU 권한 상승 도구입니다.
이 브랜치는 KSuRoot를 원본으로 하여 Root-My-Galaxy v0.2.6 메인라인 업데이트를 완전히 동기화하고, 이를 기반으로 페이로드 빌드, 벤더 페이로드 내장 및 일체형 리퀴드 글래스 UI를 추가했습니다.
Mod by hmascs · 버전 4.1.2 · Apache-2.0 저장소: https://github.com/hmascs/KSuRoot
vr.ko는 app에서 온 task에 마커를 찍는데, 그 오프셋은 0x04 / 0x06 두 가지가 있으며 컴파일 시점에
페이로드에 구워져 패치할 수 없습니다. 더 골치 아픈 것은 같은 기기의 vr.ko 두 개가 각각 다른 하나씩
이라는 점입니다(Y300 Pro+의 vendor_boot 안에 두 개가 들어 있고, srcversion은 완전히 동일)——
잘못 선택하면 "바이트를 잘못 지우고, 마커는 지워지지 않고, 자식 프로세스는 그대로 죽는" 증상이 나타나며, 로그에는 모든 것이 정상으로 보입니다.
이제 블루팩토리 방식은 **vendor_boot.img**를 제공하도록 요구합니다: 앱이 그 안의 실제로 로드되는
lib/modules/vr.ko에서 이 기기의 진짜 오프셋을 읽어낸 뒤 페이로드를 재작성합니다. 네 개의 자체 포함/자체 빌드 라이브러리
(libbaseline_6_1 / libbaseline_6_12 / libbs / libionstack) 모두 자신의 슬롯을 강제로 지정하며,
잘못 선택하면 제로 히트 게이트에 의해 즉시 차단되며, 원본 그대로 복사된 산출물을 주지 않습니다.
또한 **「전체 플래싱 패키지 가져오기」**가 추가되었습니다: 다운로드한 OTA zip 또는 fastboot tgz를 직접 선택하면
boot와 vendor_boot를 자동으로 추출하므로, 먼저 압축을 풀거나 수동으로 추출할 필요가 없습니다.
⚠️ 전체 패키지는 전체를 앱 캐시에 복사해야 랜덤 읽기가 가능합니다(ZIP 중앙 디렉터리는 패키지 끝에 있고, SAF의 uri는 File로 변환할 수 없음). 공간이 부족하면 즉시 거부되며, 추출이 끝나면 캐시를 즉시 삭제합니다.
4.1.2 = 4.1.0 + 19개 커밋. 이 커밋들은 원래 fix/baseline-routing 브랜치에 멈춰 있었으나,
이제 main에 병합되었습니다. 이미 배포된 4.1.0 설치 패키지에는 포함되지 않습니다 —— 아래 각 항목은 그 이후에야 수정된 것입니다.
| # | 결함 | 결과 |
|---|---|---|
| 1 | 6.1의 VR_TAG_A_OFF가 0x06으로 채워짐(실측은 0x04여야 함) | 블루팩토리 6.1 기종에서 마커가 단 한 바이트도 지워지지 않았는데 자체 검사는 성공으로 보고. 증상은 "권한 상승 성공 후 자식 프로세스가 즉시 죽음"이며, 이것이 원인임을 알 수 없음 |
| 2 | kallsyms 오프셋 테이블 위치 탐색에 음수 모듈로 사용(Python 시맨틱 직역) | 6.4+ 커널 전체 실패, 베이스 주소가 ASCII 텍스트 구간에서 가져와짐 |
| 3 | 오프셋 테이블 판별 기준이 「앞 세 항목 단조 증가」만 확인 | 거의 제로에 가까운 구분력(테이블 내 어느 위치든 단조로움); 테이블의 형태를 검사하도록 변경 |
| 4 | BASELINE_6_12.imageBase가 대상 베이스 주소로 채워짐 | 절대 주소 형태의 구성 지점이 전부 누락(39곳 → 9곳) |
| 5 | 심볼이 정렬되지 않을 때 산출물만 비우고 gate는 여전히 Proceed | blocked=false이고 산출물 0 B인데 UI가 차단 창을 띄우지 않음 |
| 6 | FopsSlot의 fallback이 한 번도 사용되지 않음 | 테이블을 찾지 못하면 바로 포기하고, 대체 심볼로 후퇴하지 못함 |
TARGET_ASHMEM_FOPS_UNSYMBOLED)07-文档/6.1-6.12-双方案清单.md 참조0x04, 6.6 / 6.12 = 0x06(세 대 실기기 벤더 펌웨어의 vr.ko)载荷构建/): 이전에는 저장소에 존재하지 않는 디렉터리를 가리키는 15곳의 참조가 있었음X100 Pro(6.1.145)에서 빌드를 실행한 결과는:
偏移解析: 28 / 28 项
需要改写: 26 项 · 校验通过: 0 项
该动态库未引用 26 项偏移
이건 "고칠 게 없다"가 아니라 "이 둘은 한 세트가 아니다"라는 뜻이다. 근본 원인은 두 개의 독립적인 경로가 갈라진 것이다:
| 무엇을 선택 | 무엇을 기준으로 선택 | 6.1.145에서 선택된 것 |
|---|---|---|
| 기반 라이브러리 | 구조체 패밀리 (F6_1) | libbaseline_6_1.so (이전 값은 baseline-6.1-tokay/target.h에서 유래) |
| 등급 | 3단계 라우팅 (커널 문자열) | up-6-1-145-… (이전 값은 GhostLock의 offsets.h에서 유래) |
패치 방식은 "등급에 있는 이전 값을 .so에서 리터럴로 찾는" 것이다. 두 세트의 이전 값은 교집합이 전혀 없으므로, 26개 항목 중 하나도 매칭되지 않고, 결과물은 기반 라이브러리를 그대로 복사한 것과 같다.
왜 기존의 하드 게이트가 막지 못했는가: hasFailures의 판정 기준은 changed && !ok && !absent ——
absent가 명시적으로 제외되어 있다. 그 근거("구버전 .so에는 해당 코드 경로가 없을 수 있다")는 개별 키에는 성립하지만,
"모든 키가 absent"인 경우에는 성립하지 않는다.
수정 방법 두 가지:
libbaseline_6_1.so / libbaseline_6_12.so)은
반드시 자체 등급(baseline-6-1-tokay / baseline-6-12-honor)과 짝을 이뤄야 하며,
업스트림 up-* 등급은 업스트림 .so에만 적용된다. BaselineLibraries.profileIdForLibrary()를 새로 추가.SpecOutcome에 kind 필드를 추가했다.회귀 테스트는 BaselineLibraryPairingTest(4개)에 있으며, 그중 하나는 두 세트의 이전 값에 교집합이 없음을 직접 단언한다 ——
"왜 반드시 짝을 이뤄야 하는가"를 실행 가능한 사실로 만든 것이다.
| # | 결함 | 결과 |
|---|---|---|
| 1 | 「페이로드 빌드 → 페이로드로 사용」이 메모리 내 산출물을 사용하는데, 프로세스가 회수되면 outputLibrary가 null이 되고, 기존 코드는 ?: return이었다 | 눌러도 아무 일도 일어나지 않는다: Toast도, 오류도, 버튼 변화도 없음 —— 사용자가 보는 것은 "눌러도 반응이 없음" |
| 2 | PayloadStaging의 캐시 키가 「동일 이름 + 동일 길이」 | 커스텀 페이로드는 개인 디렉터리에서 항상 payload.so로 불리므로, 바이트 수가 정확히 같은 페이로드로 교체하면 이전 것을 조용히 재사용한다 |
| 3 | shizukuStage의 캐시 키가 길이만 | 같은 함정을 Shizuku 경로에서 또 밟는다 |
| 4 | 커스텀 페이로드를 하나만 저장 가능 | 두 번째를 가져오면 첫 번째를 덮어쓰고, 아무런 안내도 없음 |
| 5 | 파일이 전부 앱 개인 디렉터리에 있음 | 사용자가 파일 관리자에서 볼 수 없고, 직접 백업/정리할 수도 없음 |
Download/동적라이브러리/<기종>/<파일명>.soDownload/동적라이브러리/<기종>/<파일명>.sofiles/active_payload/payload.so —— 아래의 "왜 반드시 두 개여야 하는가" 참조왜 창고의 것을 직접 dlopen할 수 없는가: 분할 저장소(Scoped Storage)에서는 앱이 자신이 MediaStore를 통해 생성한 파일만 읽을 수 있으며, 게다가
/storage는 FUSE(u:object_r:fuse:s0)이므로untrusted_app이 아닌 도메인은 아예 읽을 수 없다 —— 이 항목은pm install시 SELinux에 의해 현장에서 차단된 것이다 (avc: denied { read } ... tclass=file). 따라서 창고는 "사용자가 볼 수 있고 관리할 수 있게" 하고, 개인 사본은 "반드시 로드될 수 있게" 한다.
⚠️ 탐색 능력의 한계: 창고는
Download/동적라이브러리/에 사용자가 직접 넣은 파일을 자동 스캔할 수 없다 —— 분할 저장소는 앱이 다른 앱(파일 관리자 포함)이 생성한 다운로드 파일을 읽는 것을 허용하지 않는다. 항목은 두 가지 출처만 있다: 이 앱이 써넣은 것, 그리고 사용자가 시스템 선택기를 통해 명시적으로 권한을 부여한 것.
:app:testDebugUnitTest 추가 —— 이전에는 "컴파일된다"만 증명했지 "테스트가 맞다"는 증명하지 못했다BundledPayloadVrKoAuditTest: 표시용 주석 테이블과 디스크의 실제 바이트를 한 줄씩 대조하여, 조용한 누락이 없도록 함오프셋은 실측이지만, 「마커 제거」 단계는 어떤 실기기에서도 실행된 적이 없다. vr detag는 코드가 컴파일되어 들어갔다는 것만 증명할 뿐,
제대로 제거했는지, 더 나아가 제거 후 죽지 않는지는 증명하지 못한다 —— 따라서 세 패밀리 베이스라인은 모두 여전히 beta로 표기한다.
⚠️ 4.0.0의 설치 패키지는 아래 변경들보다 이르다 (4.0.0은 03:55에 패키징되었고, 블루팩토리 관련 변경은 04:32 이후). 즉 4.1.0이
vr.ko안티 루트 우회를 실제로 포함한 첫 정식 버전이다.
vr.ko 안티 루트: 두 개의 자체 빌드 패밀리 베이스라인이 마침내 우회를 포함4.0.0에서 libbaseline_6_1.so / libbaseline_6_12.so의 vr detag 카운트는 0 ——
이들은 어떤 vr.ko 마커 제거도 포함하지 않는다. 블루팩토리 기종에서 이 두 베이스라인을 선택하면, vr.ko의 안티 루트를 그대로 남겨두는 셈이다.
4.1.0은 두 베이스라인을 재빌드하고 두 개의 독립적인 결함을 수정했다:
vr.ko 마커 제거 미포함 (vr detag 카운트 0 → 2);root.c / io_daemon.c를 컴파일하지 않았고,
wallpaper_blob.S가 필요로 하는 소재도 제공하지 않아, install_android_root 등이 UND를 가리키는 동적 재배치가 되어
dlopen이 바로 실패한다. 이 항목은 원래 작업서에 없었으며, 재빌드 과정에서 실측으로 발견되었다.재현 가능한 레시피는 페이로드빌드/README.md에 있다 (출처 등급 및 알려진 제한 포함).
위는 소스 트리 크기다. APK 안의 두 개는 더 작다 (154856 B / 154840 B) —— release 빌드는 native 심볼 스트리핑을 수행하며, 이는
vr detag와 무관하다 (완성 패키지에서 추출해 재확인했으며, 여전히 2).
능력과 게이트는 쌍으로 등장한다: com.kernelpack.vivo 아래에 VrKoPayloadCheck(바이트만 읽는 판정 기준)와
VrKoPayloadGate(블루팩토리 방안에만 적용, 범용 방안은 단락되어 아무 검사도 하지 않음)를 새로 추가.
판정 기준은 「로그 문자열 vr detag」 + 「기계어 특징 (add #0x2c 이면서 AND ~0x400)」 두 가지 조합 ——
전체 126개 페이로드 실측: 36/36 양성 적중, 89개 음성 거짓 양성 제로.
boot.img를 뒤질 필요 없음)페이로드 빌드 페이지에 세 번째 경로가 추가되었다: 완전한 패키지(OTA ZIP)의 직링크를 바로 붙여넣기.
完整包直链 ──► 只取需要的几块 ──► boot 镜像 ──► 已有的构建流程
"전체 패키지를 다운로드한 뒤 압축을 푸는" 방식이 아니다 —— 전체 패키지는 보통 4–8 GiB이고, 휴대폰에서는 수십 GB의 트래픽에 해당한다. 실제 네트워크 비용은 다음과 같다:
| 가져오는 것 | 대략 |
|---|---|
| 파일 꼬리 (ZIP 중앙 디렉터리 찾기) | 64 KiB |
| ZIP 중앙 디렉터리 본체 | 수백 KiB |
payload.bin 헤더 + 파티션 목록 | 24 B + 수백 KiB |
boot 파티션이 실제로 사용하는 블록 | ~64–96 MiB |
두 가지 전체 패키지 형태를 모두 인식한다: