
Vamos nos divertir explorando um firmware de roteador Zyxel e a MIPS Arch
Os tutoriais são apenas para fins informativos e educacionais. Acredito que hacking ético, segurança da informação e cibersegurança devem ser temas familiares a qualquer pessoa que utilize informações digitais e computadores. Acredito que é impossível se defender de hackers sem saber como o hacking é feito.
$ IDA Pro +7.0 (pode usar o Radar2, já que o IDA é bastante caro)
$ Roteador executando Rompager 4.07 : há uma quantidade imensa deles, como TP-Link TD-W8951*, ZyXEL P-660R, Billion BiPAC 51**/52**
$ UART para USB
A vulnerabilidade Misfortune Cookie existe há algum tempo, mas ainda faltam análises públicas que ilustrem os detalhes técnicos da vulnerabilidade. De acordo com a Check Point, o software afetado é o servidor web embarcado RomPager da AllegroSoft. Varreduras em toda a Internet sugerem que o RomPager é provavelmente o software de servidor web mais popular do mundo em número de endpoints disponíveis. O RomPager é tipicamente embutido no firmware que acompanha o dispositivo. Essa vulnerabilidade específica foi introduzida na base de código em 2002. Além disso, os dispositivos expostos são aqueles que usam serviços RomPager com versões anteriores à 4.34 (e especificamente 4.07).
Para este tutorial, usarei um ZXHN H108L que utiliza Rompager 4.07
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="ZXHN H108L"
Content-Type: text/html
Transfer-Encoding: chunked
Server: RomPager/4.07 UPnP/1.0
EXT:
Agora vamos usar a porta serial. Primeiro, precisamos determinar a taxa de baud.
$ sudo stty -F /dev/ttyUSB0
SAÍDA :
speed 115200 baud; line = 0;
-brkint -imaxbel
device
Eu uso o minicom; você pode usar qualquer coisa, desde screen até HyperTerminal, mas prefiro este pela sua estabilidade ;)
$ sudo minicom -s
+-----------------------------------------------------------------------+
| A - Dispositivo Serial : /dev/modem |
| B - Local do Arquivo de Bloqueio : /var/lock |
| C - Programa de Chamada : |
| D - Programa de Chamada a Cobrar : |
| E - Bps/Par/Bits : 115200 8N1 |
| F - Controle de Fluxo por Hardware : Não |
| G - Controle de Fluxo por Software : Não |
| |
| Alterar qual configuração? |
+-----------------------------------------------------------------------+
| Tela e teclado |
| Salvar configuração como dfl |
| Salvar configuração como.. |
| Sair |
| Sair do Minicom |
+--------------------------+
Agora estamos prontos:
$ sudo minicom -D /dev/ttyUSB0 -b 115200
Bootbase Version: VTC_SPI1.26 | 2012/12/26 16:00:00
RAM: Size = 8192 Kbytes
Found SPI Flash 2MiB GD25Q16 at 0xbfc00000
SPI Flash Quad Enable
Turn off Quad Mode
RAS Version: ZXHN H108LV4.0.0a_ZRQ_MA
System ID: $2.12.162.0(G94.BY.2)3.20.19.0| 2014/03/21 20140321_v006 | 2014
Press any key to enter debug mode within 3 seconds.
..........
Para mostrar os comandos possíveis:
$ ATHE
======= Lista de Comandos de Depuração =======
AT apenas responder OK
ATHE exibir ajuda
ATBAx alterar baudrate. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
ATENx,(y) definir BootExtension Debug Flag (y=senha)
ATSE mostrar a seed do gerador de senhas
ATTI(h,m,s) alterar hora do sistema para hora:min:seg ou mostrar hora atual
ATDA(y,m,d) alterar data do sistema para ano/mês/dia ou mostrar data atual
ATDS despejar pilha RAS
ATDT despejar Área Comum do Módulo de Inicialização
ATDUx,y despejar conteúdo da memória do endereço x pelo comprimento y
ATRBx exibir o valor de 8 bits do endereço x
ATRWx exibir o valor de 16 bits do endereço x
ATRLx exibir o valor de 32 bits do endereço x
ATGO(x) executar programa no endereço x ou iniciar roteador
ATGR iniciar roteador
ATGT executar Programa de Teste de Hardware
ATRTw,x,y(,z) teste de RAM nível w, do endereço x até y (z iterações)
ATSH despejar dados relacionados ao fabricante na ROM
ATDOx,y baixar do endereço x pelo comprimento y para o PC via XMODEM
ATTD baixar configuração do roteador para o PC via XMODEM
ATUR enviar firmware do roteador para a flash ROM
< pressione qualquer tecla para continuar >
Este firmware possui um conjunto de comandos ocultos muito úteis para nossa análise dinâmica. O problema é que não podemos ver os registradores nem definir pontos de interrupção, mas, com sorte, com esses comandos ocultos teremos esses recursos. Para vê-los e usá-los, precisamos usar o ATEN. No entanto, este comando requer uma senha. O que podemos fazer agora? Vamos fazer engenharia reversa do firmware para encontrar o algoritmo do gerador de senhas.
(Análise estática) Vamos primeiro ver o arquivo do firmware:
$ binwalk ras
binwalk1
$ dd if=ras of=rom1.lzma bs=1 skip=85043 count=66696
$ dd if=ras of=rom2.lzma bs=1 skip=350259 count=3350556
$ lzma -d <rom1.lzma> rom1
$ lzma -d <rom2.lzma> rom2
Vamos ver agora a assinatura nos arquivos extraídos:
$ binwalk -Y rom1
DECIMAL HEXADECIMAL DESCRIÇÃO
--------------------------------------------------------------------------------
0 0x0 Código executável MIPS, 32/64 bits, big endian, pelo menos 1250 instruções válidas
string é uma ótima ferramenta para ter uma ideia do que é um arquivo binário ou o que ele contém. Vamos ver se conseguimos encontrar o algoritmo da senha:
$ strings rom1 | grep -i aten
$ strings rom2 | grep -i aten
Aparentemente, não conseguimos vê-lo porque o firmware ainda está comprimido, o que significa que devemos extraí-lo do roteador usando o modo de depuração:
$ ATDO bfc00000, 1f0000
xmodem
A primeira coisa que vem à mente é começar a procurar uma tabela de despacho. Por quê? Apenas intuição; a única alternativa é if-elif, mas seria um conjunto longo deles para verificar a validade da senha fornecida pelo usuário. E aqui está o que encontrei:
ROM:800158A0 CmdTable: .word unk_80015C20 # DATA XREF: sub_8000E3D8+4Co
ROM:800158A0 # sub_8000E3D8+90o ...
ROM:800158A4 .word sub_8000E6D0
ROM:800158A8 .byte 0
ROM:800158A9 .byte 0
ROM:800158AA .byte 0
ROM:800158AB .byte 0
ROM:800158AC .word aJustAnswerOk # " just answer OK"
ROM:800158B0 .word aAthe # "ATHE"
ROM:800158B4 .word CMD_SHOW_HELP_ATHE
ROM:800158B8 .byte 0
ROM:800158B9 .byte 0
ROM:800158BA .byte 0
ROM:800158BB .byte 0
ROM:800158BC .word aPrintHelp # " print help"
ROM:800158C0 .word aAtba # "ATBA"
ROM:800158C4 .word CMD_ATBA
...
ROM:800158D0 .word aAten # "ATEN"
ROM:800158D4 .word CMD_ATEN
Lembre-se de que a palavra MIPS tem 4 bytes. Agora vamos ver o CMD_ATEN:
ROM:8000FF84 lw $a0, 8($s0)
ROM:8000FF88 jal sub_80013654
ROM:8000FF8C li $a1, 0
ROM:8000FF90 jal passwd_generator
e agora: passwd_generator
ROM:80010A2C passwd_generator: # CODE XREF: CMD_ATEN+50p
ROM:80010A2C lui $t9, 0xA11F
ROM:80010A30 lw $v1, ptrDO_GTABLE
ROM:80010A34 lw $t8, dword_80017050
ROM:80010A38 lw $v1, 0x18($v1) # take the seed part, generated by the ATSE command
ROM:80010A3C lbu $t8, 0x6D($t8) # take the last byte of the MAC Address
ROM:80010A40 sll $v1, 8 # $v1 = v1 << 8
ROM:80010A44 andi $t7, $t8, 7 # $t7 = t8 & 0x7
ROM:80010A48 li $t8, 0 # $t8 = 0
ROM:80010A4C srl $v1, 8 # $v1 = v1 >> 8
ROM:80010A50 li $t9, 0xA11F5AC6 # $t9 = MAGIC
ROM:80010A54 j loc_80010A68
ROM:80010A58 addu $t9, $v1, $t9 # $t9 = $v1 + $t9
ROM:80010A5C # ---------------------------------------------------------------------------
ROM:80010A5C
ROM:80010A5C loc_80010A5C: # CODE XREF: passwd_generator+40j
ROM:80010A5C sll $t9, 31 # $t9 = $t9 << 31
ROM:80010A60 or $t9, $t6, $t9 # $t9 = $t6 | $t9
ROM:80010A64 addiu $t8, 1 # $t8 = $t8 + 1
ROM:80010A68
ROM:80010A68 loc_80010A68: # CODE XREF: passwd_generator+28j
ROM:80010A68 sltu $t6, $t8, $t7 # $t6 = (t8 < t7? 1:0)
ROM:80010A6C bnez $t6, loc_80010A5C # take jump if $t6 != 0
ROM:80010A70 srl $t6, $t9, 1 # $t6 = $t9 >> 1
ROM:80010A74 jr $ra # all done, exit
ROM:80010A78 xor $v0, $t9, $v1 # $v0 = $t9 ^ $v1
O que podemos concluir:
Agora vamos criar um programa em C que faz a mesma coisa e compilá-lo:
U32 passwd_generator(U32 seed, U8 last_mac_octet)
{
U32 b = seed & 0x00FFFFFF;
U32 r = ROR(b + 0xA11F5AC6, last_mac_octet & 7);
return r^b;
}
Agora vamos executar o ATSE para obter a seed e usá-la (por exemplo, obtive 088521A78838):
$ ./gen_pass 088521A78838
Vamos executar o comando mágico que acabamos de hackear :p
$ ATEN1, A12F5AC6
ATEN1, A12F5AC6
OK
ATHE
======= Lista de Comandos de Depuração =======
AT apenas responder OK
ATHE exibir ajuda
ATBAx alterar baudrate. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
ATENx,(y) definir BootExtension Debug Flag (y=senha)
ATSE mostrar a seed do gerador de senhas
ATTI(h,m,s) alterar hora do sistema para hora:min:seg ou mostrar hora atual
ATDA(y,m,d) alterar data do sistema para ano/mês/dia ou mostrar data atual
ATDS despejar pilha RAS
ATDT despejar Área Comum do Módulo de Inicialização
ATDUx,y despejar conteúdo da memória do endereço x pelo comprimento y
ATWBx,y escrever no endereço x o valor y de 8 bits
ATWWx,y escrever no endereço x o valor y de 16 bits
ATWLx,y escrever no endereço x o valor y de 32 bits
ATRBx exibir o valor de 8 bits do endereço x
ATRWx exibir o valor de 16 bits do endereço x
ATRLx exibir o valor de 32 bits do endereço x
ATGO(x) executar programa no endereço x ou iniciar roteador
ATGR iniciar roteador
ATGT executar Programa de Teste de Hardware
AT%Tx Habilitar Programa de Teste de Hardware na inicialização
ATBTx habilitar gravação do bloco0 (1=habilitar, outro=desabilitar)
< pressione qualquer tecla para continuar >
ATRTw,x,y(,z) teste de RAM nível w, do endereço x até y (z iterações)
ATWEa(,b,c,d) escrever endereço MAC, código do país, EngDbgFlag, FeatureBit na flash ROM
ATCUx escrever código do país na flash ROM
ATCB copiar da FLASH ROM para o buffer de trabalho
ATCL limpar buffer de trabalho
ATSB salvar buffer de trabalho na FLASH ROM
ATBU despejar dados relacionados ao fabricante no buffer de trabalho
ATSH despejar dados relacionados ao fabricante na ROM
ATWMx definir os 6 dígitos baixos do endereço MAC no buffer de trabalho
ATMHx definir os 6 dígitos altos do endereço MAC no buffer de trabalho
ATBS mostrar a seed do bootbase do gerador de senhas
ATLBx upload xmodem do bootbase, x é a senha
ATSMx definir endereço MAC de 6 dígitos no buffer de trabalho
ATCOx definir código do país no buffer de trabalho
ATFLx definir EngDebugFlag no buffer de trabalho
ATSTx definir endereço ROMRAS no buffer de trabalho
ATSYx definir tipo de sistema no buffer de trabalho
ATVDx definir nome do fornecedor no buffer de trabalho
ATPNx definir nome do produto no buffer de trabalho
ATFEx,y,... definir feature bits no buffer de trabalho
ATMP verificar e despejar memMapTab
ATDOx,y baixar do endereço x pelo comprimento y para o PC via XMODEM
< pressione qualquer tecla para continuar >
ATTD baixar configuração do roteador para o PC via XMODEM
ATUPx,y enviar para o endereço RAM x pelo comprimento y do PC via XMODEM
ATUR enviar firmware do roteador para a flash ROM
ATDC desabilitar verificação de versão de hardware durante o upload do firmware
ATLC enviar arquivo de configuração do roteador para a flash ROM
ATUXx(,y) upload xmodem do bloco flash x para y
ATERx,y apagar flash ROM do bloco x para y
ATWFx,y,z copiar dados do endereço x para o endereço flash y, comprimento z
ATXSx seleção xmodem: x=0: modo CRC (padrão); x=1: modo checksum
ATLD Enviar Arquivo de Configuração e Arquivo ROM Padrão para Flash
ATBR Redefinir para o arquivo Rom padrão
ATCD Converter Arquivo ROM em Execução para Arquivo ROM Padrão na Flash
OK
Finalmente, obtivemos um conjunto totalmente novo de comandos que nos permite despejar a memória.
$ ATMP
ROMIO image start at bfc30000
code version:
code start: 80008000
code length: 1A5D4E
memMapTab: 18 entries, start = bfc44000, checksum = 9770
$RAM Section:
0: BootExt(RAMBOOT), start=80030000, len=18000
1: HTPCode(RAMCODE), start=80048000, len=E0000
2: RasCode(RAMCODE), start=80048000, len=420000
$ROM Section:
3: BootBas(ROMIMG), start=bfc28000, len=4000
4: DbgArea(ROMIMG), start=bfc2c000, len=2000
5: RomDir2(ROMDIR), start=bfc2e000, len=2000
6: BootExt(ROMIMG), start=bfc30030, len=13FD0
7: MemMapT(ROMMAP), start=bfc44000, len=C00
8: HTPCode(ROMBIN), start=bfc44c00, len=8000
(Compressed)
Version: HTP_TC V 0.05, start: bfc44c30
Length: 10488, Checksum: CB32
Compressed Length: 41CF, Checksum: D5A5
9: termcap(ROMIMG), start=bfc4cc00, len=400
10: RomDefa(ROMIMG), start=bfc4d000, len=2000
11: LedDefi(ROMIMG), start=bfc4f000, len=400
12: LogoImg(ROMIMG), start=bfc4f400, len=2000
13: LogoImg2(ROMIMG), start=bfc51400, len=2000
14: StrImag(ROMIMG), start=bfc53400, len=32000
15: StrImag2(ROMIMG), start=bfc85400, len=32000
16: Rt11nE2p(ROMIMG), start=bfcb7400, len=400
17: RasCode(ROMBIN), start=bfcb7800, len=246C00
(Compressed)
Version: ADSL ATU-R, start: bfcb7830
Length: 321D2C, Checksum: 582D
Compressed Length: 11E54B, Checksum: B30B
$USER Section:
Msecs 128
Heap0 16 300 16
Heap1 32 64 4
Heap2 64 64 4
Heap3 128 160 4
Heap4 192 256 4
Heap5 256 80 4
Heap6 320 20 4
Heap7 384 4 2
Heap8 448 20 2
Heap9 512 34 2
Heap10 1024 52 4
Heap11 2048 20 2
Heap12 3172 4 2
Heap13 4096 2 2
Heap14 0 0
...
O que acabamos de aprender nos ajudará a analisar os arquivos rom que extraímos anteriormente.
code start: 80008000
code length: 1A5D4E
Agora podemos definir o endereço de início da ROM e o endereço de carregamento como 0x80008000 após despejar um novo arquivo rom usando:
$ ATDO 80008000, 1A5D4E
Sabemos que ATGR inicializa o roteador, então podemos rastreá-lo para encontrar as instruções que passam a execução para a segunda parte do firmware.
atgr1
ROM:80011E8C loc_80011E8C: # CODE XREF: LoadAndRunImage+D8j
ROM:80011E8C jal sub_80009B24
ROM:80011E90 li $a0, 0x1F4
ROM:80011E94
ROM:80011E94 execute_image: # execute image
ROM:80011E94 jalr $s0 # jump and link to address in $s0
ROM:80011E98 nop
Agora precisamos perguntar qual é o endereço armazenado em $s0? Obviamente, ainda não podemos definir um ponto de interrupção, não podemos ver os registradores, então precisamos vazá-lo usando algum truque. Felizmente, podemos ler e escrever na memória; dê uma olhada no seguinte comando:
ATWL 80011E94, ae30001c
ATGR
Pelo que parece, este comando substitui a instrução em 0x80011E94 por ae30001c (a representação em bytes da instrução MIPS sw $s0, 0x1C($s1)). Ao sobrescrever o jalr $s0 original com sw $s0, 0x1C($s1), forçamos o programa a armazenar o conteúdo do registrador $s0 no endereço de memória 0x8001FF1C. Assim, o firmware do segundo estágio não será executado; em vez disso, a mensagem "ERROR" será apresentada e ainda teremos acesso ao console do primeiro estágio. Hooray! Então, vamos ver o que estava armazenado em 0x8001FF1C.
ATRL 8001FF1C
8001FF1C: 80020000
Peguei! ... usando 0x80020000 podemos despejar e analisar adequadamente a segunda parte do firmware.
Continua...