
# GhostLock (CVE-2026-43499) exploit de kernel para dispositivos Android com bootloader bloqueado
Exploit de kernel para dispositivos Android com bootloader bloqueado. Alcança root temporário + instalação do KernelSU sem desbloquear o bootloader ou modificar a imagem de boot. Detecção automática em tempo de execução da versão do kernel com tabela de offsets para múltiplos dispositivos.
CVE-2026-43499 — Futex PI (Priority Inheritance) Use-After-Free
Afeta o kernel Linux 5.7 ~ 7.1. Corrigido nas versões estáveis 6.1.175, 6.6.140, 6.12.86. A maioria dos dispositivos Android permanece sem correção até setembro de 2026.
A syscall pselect6 copia dados de fd_set para a pilha do kernel. Quando combinada com o mecanismo de waiter futex PI, um frame de pilha liberado pode ser reutilizado como uma estrutura rt_mutex_waiter. O rebalanceamento da rb-tree durante a caminhada da cadeia PI então escreve valores controlados em endereços arbitrários do kernel.
O overlay de pilha do pselect exige que o rt_mutex_waiter liberado caia dentro da região stack_fds controlável pelo usuário (words 0–14). Onde ele cai é determinado pelos perfis PGO/LTO do compilador, não pela versão do kernel. Consulte Layout da Pilha.
Nota sobre viabilidade 6.1: Kernels OPLUS 6.1 são consistentemente inviáveis devido ao inline PGO de
do_futex. No entanto, alguns kernels não-OPLUS 6.1 (vivo) mantêm a cadeia de chamadas padrão e são viáveis (vivo T4, X Fold3 Pro). A viabilidade deve ser verificada por dispositivo.
Dois caminhos de root, selecionados automaticamente com base nas capacidades do dispositivo:
Requer off_ashmem_misc_fops != 0 (ashmem C com miscdevice estático em BSS).
Escrita PI (mode=4) → redireciona fops do miscdevice para fops falsos
→ r/w configfs → physrw via pipe (r/w de kernel preciso de 1 byte)
→ SELinux enforcing = 0 (byte único, sem corrupção de policycap)
→ UMH: injeta work_struct em system_unbound_wq
→ script de root → late-load do ksud → KSU instalado
Disponível em: OnePlus 13, OPPO Pad 4 Pro, dispositivos com ashmem C 5.10/6.1. Não disponível em ashmem Rust (GKI 6.12) — miscdevice alocado no heap.
Escrita 1 (mode=1) → SELinux enforcing = 0 (escrita de 8 bytes, corrompe bytes adjacentes)
Escrita 2 (mode=2) → task->cred = init_cred (uid=0, todas as capacidades)
Shell root → late-load do ksud → KSU → correção da política SELinux
Após W1+W2, o exploit corrige o campo de configuração do binário da política SELinux (|= 0xC0000000 para ANDROID_NETLINK_ROUTE + GETNEIGH) e recarrega via /sys/fs/selinux/load para restaurar a conectividade de rede.
App (seccomp) → Escrita 1 → mini-adb TCP → adb shell: exploit completo → root
O launcher de inicialização é fornecido pelo aplicativo separado GhostLock Anchor.
Com NFDS=320, core_sys_select aloca um buffer stack_fds de 256 bytes na pilha do kernel:
stack_fds: 0 5 10 14 | 15 20 25 29
├─in─┤─out─┤─ex──┤ ├res_in┤res_out┤res_ex┤
◄── CONTROLADO PELO USUÁRIO ──►│◄── ZERADO PELO KERNEL ──►
O exploit coloca campos falsos de waiter (task, lock) nos bitmaps de entrada do fd_set. Para waiter aninhado 6.12 (14 words): word máxima viável do waiter = 3. Para waiter compacto 5.10/6.1 (10 words): word máxima viável do waiter = 7.
A posição do waiter depende da profundidade da cadeia de chamadas:
Todas as escritas no kernel usam o alias do mapa linear. O bootloader escolhe kernel_phys_load, que varia por SoC:
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
Um valor incorreto falha silenciosamente. Leia-o em uma unidade com root:
su -c 'grep -i "Kernel code" /proc/iomem' # c7810000-... → 0xc7800000
Substitua em tempo de execução: KPHYS=0xc7800000 /data/local/tmp/a/e
/data/local/tmp/a/e # Padrão (shift=0)
PSELECT_SHIFT=-2 /data/local/tmp/a/e # OnePlus 13 (6.6)
Kernels 5.10 usam 0xffffffc008000000 (VA_BITS=39, diferente do padrão 6.x 0xffffffc080000000). Isso é tratado automaticamente via o campo kimage_text_base na entrada de offsets do dispositivo.
make NDK_ROOT=/caminho/para/android-ndk
Ou diretamente:
NDK=/caminho/para/android-ndk
"$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android35-clang" \
-O2 -Wall -Isrc/core -Isrc/devices -DTARGET_CONFIG_H=\"target.h\" \
src/core/main.c src/core/util.c src/core/slide.c \
src/core/fops.c src/core/pipe_physrw.c src/core/root.c \
src/core/miniadb.c src/core/umh_root.c \
-o ./ghostlock -fPIE -pie -pthread
O GhostLock fornece root temporário. A instalação do KernelSU requer o ksud, que inclui o kernelsu.ko para cada versão KMI.
| Método | Passos |
|---|---|
| APK ReSukiSU (recomendado) | Instale o ReSukiSU ou este . Inclui . |
adb shell mkdir -p /data/local/tmp/a
adb push ./ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
adb shell /data/local/tmp/a/e
Execute após a conclusão da inicialização e quando o ADB estiver pronto.
Apenas o boot.img é necessário — sem root, sem acesso ao dispositivo.
Consulte o guia de ferramentas kallsyms para o fluxo de trabalho completo, ou:
python tools/extract_target.py --kallsyms kallsyms.txt
python tools/extract_btf.py kernel
Verifique se do_futex tem inline PGO pesquisando no binário do kernel todas as instruções de branch que visam futex_wait_requeue_pi. Se __arm64_sys_futex o chama diretamente (ignorando do_futex), o dispositivo provavelmente não é viável.
Adicione src/devices/<nome>/offsets.h com os offsets extraídos e inclua-o em src/devices/offsets.h. Use a macro de offsets de struct apropriada:
Para dispositivos com waiter compacto 5.10/6.1, defina também .kimage_text_base=0xffffffc008000000ULL.
Apenas para pesquisa de segurança autorizada e fins educacionais.
| Dispositivo | SoC | Kernel | Ramo GKI | SHIFT |
|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38 | android16-5 | 0 |
| OnePlus 15 (CPH2745/2747/2749) | SM8850 | 6.12.23 | android16-5 | 0 |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23 / 6.12.69 | android16-5 / android16-6 | 0 |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89 | android15-8 | -2 |
| OPPO Pad 4 Pro | SM8750 | 6.6.89 | android15-8 | -2 |
| Dispositivo | SoC | Kernel | Notas |
|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38 | Mesmo kernel do Ace 6T |
| OPPO Reno10 Pro+ (CPH2521) | SM8475 | 5.10.236 | Waiter compacto 5.10, waiter word=0 |
| Vivo X Fold3 Pro (PD2337) | SM8650 | 6.1.124 | Waiter compacto 6.1, waiter word=3 |
| Vivo T4 | SM8650 | 6.1.145 | Waiter compacto 6.1, waiter word=3 |
| Dispositivo | SoC | Kernel | Causa Raiz |
|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58 | PGO elimina do_futex → waiter word=14 |
| OnePlus 12 | SM8650 | 6.1.141 | PGO inline de do_futex → waiter word=13/19 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | OPLUS 6.1: waiter word=13 |
| realme RMX5070 | SM6650 | 6.1.141 | OPLUS 6.1: waiter word=13 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | OPLUS 6.1: waiter word=13 |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | Não-OPLUS 6.1: mesmo resultado |
| iQOO Neo 10 CN | SM8650 | 6.1.84 | Frame do_futex 0xD0 → waiter word=-11 |
| OPPO PKW110 | — | 5.15.180 | Frame do_futex 0x140 → waiter word=-29 |
| iQOO Z9 5G | — | 5.15.178 | Frame do_futex grande demais |
| CPH2763 (OPPO) | — | 6.1.115 | OPLUS 6.1: PGO inline, waiter word=24 |
| Padrão | Cadeia de Chamadas | Viável |
|---|
| android16-5 (6.12) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 |
| android15-8 (6.6) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 (SHIFT=-2) |
| vivo 6.1 | sys_futex → do_futex → fwrpi | ✅ waiter word=3 |
| OPLUS 6.1 | sys_futex → fwrpi (inline PGO) | ❌ waiter word=13+ |
| android16-6 (X9 Ultra) | sys_futex → fwrpi (inline PGO) | ❌ waiter word=14 |
| 5.10 OPLUS | sys_futex → do_futex → fwrpi | ✅ waiter word=0 |
| SM8650 (vivo T4, X Fold3 Pro) |
0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |
libksud.so| Release CI | Baixe do CI do ReSukiSU |
| Kernel | Layout do Waiter | Macro |
|---|
| 6.12.x | Aninhado (14 words) | STRUCT_OFFSETS_6_12 |
| 6.6.x | Aninhado (14 words) | STRUCT_OFFSETS_6_6 |
| 6.1.x (vivo) | Compacto (10 words) | STRUCT_OFFSETS_6_1 |
| 5.10.x | Compacto (10 words) | STRUCT_OFFSETS_5_10 |
| Arquivo | Descrição |
|---|
src/core/main.c | Entrada do exploit, W1/W2, caminho UMH, bootstrap, script de root, correção da política SELinux |
src/core/fops.c | Rota pselect, escrita PI, estágio CFI, suporte a waiter compacto |
src/core/util.c | Heap spray, KernelSnitch, slab drain, configuração do payload |
src/core/pipe_physrw.c | R/W de memória física via buffer de pipe |
src/core/umh_root.c | Root UMH via injeção em workqueue |
src/core/miniadb.c | Cliente Mini ADB (TCP + autenticação RSA) |
src/core/target.h | Layout de memória, padrões de campos de struct (6.12) |
src/core/runtime_struct_offsets.h | Substituição de campos de struct por dispositivo |
src/devices/offsets.h | Tabelas de offsets de dispositivos + macros STRUCT_OFFSETS_* |
tools/extract_target.py | Extração de offsets do kallsyms |
tools/extract_btf.py | Extração de offsets de struct do BTF |
tools/kallsyms/ | Fluxo de trabalho completo de recuperação de kallsyms |