
(CVE-2026-43499) Programa de exploração de kernel para dispositivos OnePlus com bootloader bloqueado.
Exploit de kernel para dispositivos OnePlus com bootloader bloqueado. Usa CVE-2026-43499 para obter acesso root sem desbloquear o bootloader ou modificar o boot.img.
Apenas para pesquisa de segurança autorizada e fins educacionais.
| Item | Detalhe |
|---|---|
| CVE | CVE-2026-43499 |
| Tipo | Use-After-Free no Futex PI (Priority Inheritance) |
| Escopo | Linux kernel 2.6.39 ~ 7.1 |
| Corrigido em | Mainline 7.1 (commit 3bfdc63936dd) |
| Status Android | GKI 6.12.x ainda vulnerável |
A syscall pselect6 copia fd_set para a pilha do kernel. Quando combinada com o mecanismo de waiter do futex PI, um frame de pilha liberado pode ser realocado como uma struct rt_mutex_waiter. Durante a travessia da cadeia PI, o rebalanceamento da árvore rb-tree escreve dados controlados em endereços arbitrários do kernel.
futex PI UAF (CVE-2026-43499)
├─ Forjar objeto rt_mutex_waiter
├─ Controlar pilha do kernel via layout de fd_set do pselect/select
├─ Acionar operação rt_mutex PI para escrita arbitrária
├─ Escrita 1: selinux_state.enforcing = 0
└─ Escrita 2: cred → init_cred (uid=0, capacidades completas)
Outros dispositivos OnePlus na mesma família de SoC, Android 16 ou kernel 6.12.x podem ser adaptados via extração de offsets do boot.img.
GhostLock trata da escalada de privilégios. A instalação do KernelSU requer ksud (fornecido com kernelsu.ko específico do KMI):
| Fonte | Notas |
|---|---|
| APK ReSukiSU (recomendado) | Instale ReSukiSU; o APK inclui libksud.so |
Sem o ksud, o exploit ainda obtém shell root com uid=0, mas o KernelSU não será instalado e o
sunão persistirá.
ANDROID_NDK_HOME ou ANDROID_NDK_ROOT# Padrão (API 35)
make
# Especificar nível da API
make API=34
# Especificar caminho do NDK
NDK=/caminho/para/android-ndk make
ghostlock — executável ELF ARM64 linkado estaticamente.
# 1. Habilitar modo ADB TCP
adb tcpip 5555
# 2. Enviar chave ADB (necessária para modo bootstrap)
adb push ~/.android/adbkey /data/local/tmp/a/adbkey
# 3. Enviar o exploit
adb push ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
Após o primeiro sucesso,
resetpropdefine automaticamentepersist.adb.tcp.port=5555, permitindo execuções totalmente automáticas em reinicializações subsequentes.
/data/local/tmp/a/e
/data/local/tmp/a/e --bootstrap
setprop habilitar ADB TCP 5555127.0.0.1:5555/data/local/tmp/a/e --write1
Offsets armazenados em tabela de consulta src/devices/offsets.h, indexada por uname -r. O programa faz correspondência automática na inicialização; kernels desconhecidos são rejeitados.
static const struct kernel_offsets known_offsets[] = {
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14275539-4k", ...),
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14552068-4k", ...),
OFFSETS_ENTRY("6.12.23-android16-5-...-ab14541642-4k", ...),
{ .uname_r = NULL } /* sentinela */
};
Quando ponteiros do kernel são restritos (kptr_restrict), vaze o endereço base via boot_id sobrescrito com um endereço do kernel:
Ler /proc/sys/kernel/random/boot_id
└─ UUID contém endereço de nfulnl_logger
└─ Deslocamento KASLR = leaked_addr - image_offset
└─ kaslr_base
Quando o dispositivo ashmem está acessível, use primitivas de leitura/escrita do configfs para ler ponteiros de função da tabela fops do ashmem e calcular o deslocamento KASLR.
Forjar objetos do kernel em páginas order-3 (32KB):
file_operations — sequestrar ponteiro fops do miscdevice ashmemrt_mutex_waiter — simular nó waiter da cadeia PItask_struct — referência de tarefa durante travessia PIrt_mutex (lock) — informações corretas de waiter/ownerImplementado via SKB (socket buffer) + KernelSnitch:
mm_structsendmsg para preencher heap do kernelApós obter a base KASLR, use buffers de pipe para acesso à memória em nível físico:
1. Localizar buffer de pipe no physmap
2. Forjar tabela de operações pipe_buffer apontando para pipe_buf_ops conhecido
3. Sequestrar pipe_buffer.page para endereço físico alvo
4. Leitura/escrita física arbitrária via operações normais de pipe
Suportado: pipe_read64, pipe_write64, pipe_phys_read_data, pipe_phys_write_data
Alvo: selinux_state.enforcing (offset 0x00)
Método: escrita PI do nó filho → forjar __rb_parent_color do waiter
apontando para selinux_enforcing - 8
rebalanceamento da rb-tree escreve 0x00
Alvo: ponteiro cred do processo filho
Método: 1. fork filho → perf_find_task() localizar task_struct
2. calcular offset do campo cred
3. escrita PI do nó filho → cred = init_cred (uid=0, caps completas)
4. limpar seccomp (TIF_SECCOMP + struct seccomp zerada)
A verificação de capacidade de leitura é realizada após a sobrescrita de cred.
src/core/miniadb.c — cliente leve do protocolo ADB para modo bootstrap:
1. TCP connect 127.0.0.1:5555
2. A_CNXN → solicitação de conexão
3. A_AUTH → desafio token RSA
4. dlopen("libcrypto.so") → PEM_read_bio_RSAPrivateKey → RSA_sign
5. A_AUTH (AUTH_SIGNATURE) → resposta assinada
6. A_CNXN → conexão estabelecida
7. A_OPEN "shell:/data/local/tmp/a/e" → exploit completo
Suporta algoritmos de assinatura SHA-1 e SHA-256.
ghostlock-oneplus/
├── Makefile # Configuração de compilação (cross-compilação NDK)
├── README.md # Documentação
├── src/
│ ├── core/ # Código principal do exploit
│ │ ├── main.c # Ponto de entrada: escrita em duas etapas + shell root
│ │ ├── fops.c # Modo FOPS/CFI: rota pselect, escrita PI, vazamento KASLR
│ │ ├── util.c # Utilitários: heap spray, KASLR, primitivas R/W do kernel
│ │ ├── slide.c # Modo SLIDE: vazamento KASLR via boot_id + rota pselect
│ │ ├── pipe.c # Leitura/escrita física de memória via buffer de pipe (physrw)
│ │ ├── root.c # Sobrescrita de cred, limpeza de seccomp, gerenciamento de filho root
│ │ ├── miniadb.c # Cliente ADB embutido (TCP + autenticação RSA)
│ │ ├── common.h # Macros globais, structs, declarações, constantes
│ │ ├── target.h # Layout de memória alvo / offsets de struct / parâmetros KASLR
│ │ ├── offset.h # Ponte de configuração alvo em tempo de compilação (#include TARGET_CONFIG_H)
│ │ └── kernelsnitch/ # KernelSnitch — vazamento de endereço mm_struct
│ │ ├── kernelsnitch.h # Algoritmo principal: colisão de hash futex + força bruta
│ │ ├── futex_hash.h # Função hash futex
│ │ ├── timeutils.h # Medição de timestamp de CPU (RDTSC)
│ │ └── utils.h # Macros auxiliares (pr_info / SYSCHK / ASSERT etc.)
│ └── devices/ # Tabelas de offset por dispositivo
│ ├── offsets.h # Agrega todos os offsets de dispositivos (tabela de consulta + sentinela)
│ ├── ace6t/offsets.h # Offsets do OnePlus Ace 6T (2 versões de kernel)
│ └── op15/offsets.h # Offsets do OnePlus 15 (1 versão de kernel)
└── tools/ # Ferramentas de extração de offsets
├── extract_target.py # Extrair offsets de símbolos globais kallsyms (28 itens)
└── extract_btf.py # Extrair offsets de campos de struct BTF (57 itens)
Apenas o boot.img do dispositivo alvo é necessário — sem root, sem acesso ao dispositivo.
# 1. Extrair kernel do boot.img
python -c "import struct; d=open('boot.img','rb').read(); \
open('kernel','wb').write(d[4096:4096+struct.unpack_from('<I',d,8)[0]])"
# 2. Obter kallsyms (root: adb shell su -c 'cat /proc/kallsyms' > kallsyms.txt)
# Ou do vmlinux: nm vmlinux > kallsyms.txt
# 3. Extrair offsets de símbolos globais
python tools/extract_target.py # 28 offsets, verificado automaticamente
# 4. Extrair offsets de campos de struct
python tools/extract_btf.py kernel # 57 offsets, verificado automaticamente
src/devices/<nome>/offsets.h (ver ace6t/offsets.h)#include em src/devices/offsets.hKIMAGE_TEXT_BASE e layout de memória em src/core/target.h se necessárioCertifique-se de estar executando em um shell ADB. Contexto de aplicativo requer --bootstrap.
Sua versão do kernel ainda não é suportada. Siga Adicionar Novos Dispositivos para extrair offsets e recompilar.
CORE)PSELECT_ENTER_DELAY_USECperf_event_open (use --bootstrap em contexto de aplicativo)kaslr_base válido)ksud existe e é executávelload_policy)Apenas para pesquisa de segurança autorizada e fins educacionais.
| Dispositivo | Codinome | SoC | Kernel | Firmware | Status |
|---|
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14275539-4k | ColorOS 16.0.2.403 | ✅ Verificado |
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14552068-4k | ColorOS 16.0.8.301 | ✅ Verificado |
| OnePlus 15 | PLK110 | SM8845 (Snapdragon 8s Elite) | 6.12.23-android16-5-...-ab14541642-4k | — | ✅ Verificado |
| Release CI | Baixe de ReSukiSU CI (ksud-aarch64-linux-android.zip) |
| Tipo | Quantidade | Extração |
|---|
| Símbolos globais kallsyms | 28 | tools/extract_target.py |
| Campos de struct BTF | 57 | tools/extract_btf.py |
| Valores derivados | 9 | Calculado automaticamente |
| Constantes fixas | 12 | Hardcoded |
| Struct | Campos | Finalidade |
|---|
task_struct | 17 | Descritor de processo, cred, seccomp |
rt_mutex_waiter | 6 | Alvo de forja UAF |
cred | 4 | Credenciais, capacidades |
seccomp | 3 | Estado do filtro seccomp |
pipe_inode_info | 11 | Operações de buffer de pipe |
file_operations | 13 | Tabela fake fops |
mm_struct | 1 | Proprietário do descritor de memória |
| Módulo | Arquivo(s) | Responsabilidade |
|---|
| Entrada | main.c | Análise de CLI, despacho W1/W2, fluxo bootstrap |
| Rota PI | fops.c / slide.c | Layout de pilha pselect/select, manipulação de cadeia futex PI |
| KASLR | util.c / fops.c / slide.c | Bypass de modo duplo: vazamento via boot_id + vazamento de tabela fops |
| Heap Spray | util.c | Alocação de páginas order-3, spray SKB, layout de objetos forjados |
| R/W Físico | pipe.c | Sequestro de buffer de pipe, acesso arbitrário à memória física |
| Escalada de Privilégios | root.c | Sobrescrita de cred, verificação de capacidade, limpeza de seccomp |
| ADB | miniadb.c | Cliente leve do protocolo ADB, autenticação RSA |
| Mecanismo de Vazamento | kernelsnitch/ | Colisão de hash futex para localização de mm_struct |
| Item |
|---|
| Notas |
|---|
VA_BITS | 48 vs 39 → atualizar layout de memória em target.h |
| Temporização | Ajustar parâmetros PSELECT_* em common.h |
| Ashmem | Implementação C vs Rust → atualizar correspondência de símbolos em extract_target.py |
| Secureguard | Dispositivos não OnePlus podem simplificar a implantação |