E aí, pessoal, tudo tranquilo?

O Vargola arrebentou com o desafio número 4. Não teve pena. Ele estava tentando direto e sempre evoluindo, até que o escondedor revelou o seu segredo 🙂 Parabéns cara. Foste o primeiro a conseguir.

O Amudi também conseguiu resolver o problema algum tempo depois (teria sido antes??). Está contando o primeiro comentário feito 🙂

Não sei se o passo a passo dele foi parecido com o meu mas.. vamos lá!

[[ O próximo passo, antes de tudo ]] 

O 5º desafio já está disponível e é só um pouco mais difícil que o 4°. Deve ser quebrado bastante rápido. Para tentar, baixe o Escondedor – Versão 5, e descobra o nome do artigo escondido neste programa.

Escondedor – Versão 5 – Corrigido novamente em 02/08/07 🙁 Bug

Essa versão do desafio tem uma característica particular.. eu ainda não resolvi :S É claro que tenho uma idéia de como fazê-lo, mas eu só terminei ele ainda agora. Preparem-se porque nós vamos subir o nível. A versão 6 será muito mais difícil.

Calma!!! Chegaremos lá 🙂 

[[ De volta para o 4 – Maldito botão ]]

Bom, A versão 4 já começa como uma diferença um pouco intrigante… O botão Tentar vem desabilitado!!?!!

Lá também existe uma mensagem dizendo "Atenção! Você não possui todos os requisitos necessários para a tentativa". Mas que droga, maldito programador (EU)!! O cara precisa de algum pré-requisito antes de tentar a senha…

Vamos com calma, explorando o programa apenas um pouquinho, vemos que ele tem um bug bem simples… Digite a senha e pressione ENTER.

Simples, né? Bem, isso acontece de vez em quando no mundo real QUE EU JÁ VI, HUAHAUHHUA!! Porém, sem mais risos, como eu conheço alguns cidadãos que cometem essas gafes eletrônicas, eu não vou citar nomes nem copyrights.

[[ Entrando com tudo ]] 

Apesar do caráter erótico do título desta seção, estou me referindo a entrar no software e quebrá-lo de uma vez, já que a sua segurança pareceu trivial. O que vamos tentar fazer é resolver o resto da mesma forma que foi feito com o desafio 3: Iniciar o programa com o OllyDebugger e sair vasculhando a pilha. É só seguir as dicas do desafio 3!!

Oop´s!! Acontece uma coisa bastante chatinha quando você inicia o programa através do Olly Debugger… Ele mostra a mensagem: "Debugger eu não tolero". Sacanagem, ele tem proteção contra debuggers! Fumou-se tudo. É hora de tentar o suicídio…

Ou não 🙂 Quando você estava a ponto de se jogar do teto do seu prédio em cima daquele muro cheio de vidros, você teve uma idéia. Já caindo, mas vibrante, você segura em um mastro e volta vivo ao prédio pela janela! Você não vai ser vencido tão facilmente.

Você, em sua jornada rumo ao fim, refletiu um bocado sobre como um software poderia se proteger de debuggers e você lembrou que o programador do Escondedor é um amador, que provavelmente pegou uma dica de outro amador… E a maneira mais simples de criar uma proteção contra debuggers é perguntar ao sistema operacional se existe algum debugger executando este programa. Isso é feito, no Windows, através da função IsDebuggerPresent. Ela retorna 1 (um) se o programa estiver sendo executado através de um debugger.

http://msdn2.microsoft.com/en-us/library/ms680345.aspx

Aha! Ainda com o sentimento de que o cara é um novato, você utiliza o PE Explorer pra verificar as funções importadas de DLL. Conforme você leu no link (err… você leu, não é?), essa função é exportada pela DLL kernel32.dll.

Você utiliza menu View | Imports para dar uma olhada nas funções importadas e, dentre as funções importadas de kernel32.dll, você encontra o que você queria.


Muito bem. Como você é esperto, você pensou o seguinte… O cara pode ter feito uma coisa meio burra… Ele pode ter feito o teste anti-debugger apenas no início do programa… Mas você sempre pode anexar um debugger a um processo já em execução 🙂 A tentação te faz tentar. Dentro do OllyDebugger, você utiliza o menu File | Attach e procura pelo processo do Escondedor.

Porém.. você faz a triste descoberta de que.. o Escondedor exibe a mesma indesejável mensagem novamente, irritando-o, deixando-o vermelho. Como ele fez isso imediatamente após a anexação? Existe um jeito.. ele está utilizando outro Thread para testar de tempos em tempos se um debugger é anexado..

Bom, é melhor não nos preocuparmos com isso ainda… A segurança foi feita de forma burra mesmo. Vamos resolver na unha logo.

[[ Burlando o anti-debugger burro ]] 

Bom, o fato de termos encontrado a função IsDebuggerPresent na seção de Imports quer dizer que ele está utilizando a biblioteca estaticamente, isto é, o próprio Windows vai checar se essa DLL existe antes da execução do programa e vai criar um endereço virtual para a função dentro do EXE, o que nos dá o caminho das pedras.

Para encontrar a chamada da função dentro do executável, vamos utilizar o menu de contexto da área de disassembler do OllyDebugger (traduzindo, clique com o botão direito onde você o código Assembly do OllyDebugger) e clicar em Search For | All intermodular calls.

Aí dentro, vamos encontrar a nossa chamada e dar um duplo-clique nela. Após isso, encontramos uma procedure que faz a bendita chamada. Maldita seja.

< p>

Encontramos o nosso ponto de "segurança". Ele faz um test e um jump logo após.. Sabemos que a função retorna 1 se houver um Debugger trapaceando, então sabemos que a instrução TEST seta o FLAG ZERO igual a 0 se o seu resultado for diferente de zero… E isso faria com que o jump JE SHORT Esconded.004553CE não fosse executado (ele só faz isso quando este flag está setado).

Com todas essas informações em mãos, deduzimos que precisamos garantir que este jump seja executado pra que o software continue vivo mesmo com um debugger. Tenho uma notícia muito legal.. Temos 4 bytes disponíveis pra fazer isso sem estragar o resto do programa. O que temos que fazer é substituir a função test por um um JUMP direto para o endereço 004553CE.

Para fazer isso, clicamos com o botão direito na instrução malvada (O TEST) e depois em Assemble. Cada byte da instrução precisa ser substituído e o Ollydebugger, como bom cãozinho, faz mais esse trabalho sujo pra você.  Vai aparecer uma caixa de texto, onde voc~e vai digitar JMP 004553CE. Fácil, né?

A modificação acabou utilizando 2 bytes como antes, então você nem precisa se preocupar com a corrupção do programa. Dessa vez os 2 bytes são EB 41. Para fazer com que este programa nunca mais precise ser modificado, basta modificar estes dois bytes no arquivo executável, no mesmo offset, mas outro dia eu explico como fazer isso.  Agora você clica novamente no botão Run ou pressiona F9.

Aeeeee, o programa está rodando agora 🙂 Sem anti-debugger.

[[ Para fechar com chave de ouro ]] 

Agora você continua utilizando as mesmas técnicas do Desafio 3, com uma única diferença: dessa vez você vai ter que procurar o evento do teclado ao invés do evento do botão. A partir daí, você vai seguindo a pilha, conforme foi feito naquele outro dia.

Lembra de como fizemos pra capturar o evento anterior? Utilizamos o menu View | Windows.

O que estamos procurando é uma caixa de texto.. Sabe como é chamada uma caixa de texto no Delphi? TEdit. Encontramos uma janela desse tipo lá. Lembre-se de que cada controle, no Windows, é considerado uma janela.

O problema do evento de teclado é que cada tecla pressionada lá dispara o evento. Por isso, antes de fazermos a parte negra da coisa, vamos primeiro digitar uma senha qualquer lá dentro (sim, 99 por exemplo :D), na caixa de senha do Escondedor.

Agora, de volta ao OllyDebugger, clicamos com o botão direito em cima do nosso TEdit e depois em Toggle Breakpoint on Classproc. Agora vamos pressionar ENTER no Escondedor e ver o resultado. Lembrando que provavelmente é feito um teste para saber se a tecla ENTER foi pressionada.

Aha!!! O programa é pausado pelo OllyDebugger. O breakpoint foi encontrado. Agora vamos colocar um breakpoint na próxima criação de janela (função CreateWindow), que é onde a mensagem enviada por ShowMessage é mostrada. Estamos fazendo um pouco diferente do que antes.

Para isso, clicamos com o botão direito no código do programa, em seguida em Seach for… | All intermodular calls. Procuraremos lá dentro a função CreateWindow. Você vai encontrar duas. Clique com o botão direito sobre cada uma e depois em Toggle Breakpoint.

E vamos colocar o programa para executar novamente (F9).

O código pára na criação da janela. O resto é igualzinho ao que fizemos no desafio anterior, então não vou me prender muito nisso. Esta caixa de mensagem que vai aparecer, já que digitamos uma senha incorreta, ele vai mostrar a mensagem de erro "Cara… faz de novo que você consegue!! :D".

Ele faz isso porque o teste já foi feito. Vamos ir procurando para baixo na pilha de novo! Queremos encontrar a primeira menção à string de erro. O endereço da pilha 0012F700, mostra isso para nós!

Ainda na pilha, clicando na instrução que faz referência a essa string e depois em Follow in Disassembler, encontramos o nosso código!

Uma procedure bastante grande aparece novamente é ela quem decripta a string em algum lugar e faz o teste para saber se a senha está correta! Estamos quase lá.

Vamos de novo ao início da procedure (sim, aquele linha 55 de sempre), clicar com o botão direito nessa linha e depois em Run trace | Add procedure. É claro, vamos colocar um breakpoint nessa linha e remover todos os outros breakpoints que colocamos antes. Eles não interessam mais!

O programa está pausado. Coloque-o para executar. Vamos digitar uma senha qualquer e pressionar ENTER para ativar o nosso breakpoint.

Se você seguiu as instruções direitinho, o programa vai parar nesse ponto da figura. Aí é só executar novamente e verificar o resultado do trace pra sabermos como o programa está se comportando.

Após a execução, a mensagem de erro é mostrada novamente, e o código que foi executado fica "sujo" de vermelho dentro do OllyDebugger. No final do vermelho, olha o que encontramos:

Muito bem. Seguindo o livro de receitas do desafio 3, vamos colocar um breakpoint no Jump (00454E99 JNZ Esconded.00455015), executar tudo de novo e pular a instrução logo depois. É só fazer exatamente a mesma coisa.

Aee, tudo deu certo novamente e o seu artigo, logicamente, vem de brinde.

[[ Momentos Finais ]] 

As técnicas usadas aqui não são, necessariamente, as melhores e mais rápidas para resolvemos esse tipo de problema, apenas aquelas que julguei de mais fácil entendimento.

Nesse artigo, utilizei um nível de detalhe muito menor do que nos outros, não é? Bem, não vou repetir em cada artigo as mesmas informações. Acho que deu pra aprender pelos outros artigos.

A solução desse em relação ao anterior não foi muito difícil. O próximo também não é muito difícil em relação ao atual… mas… como eu disse no início… Estejam preparados.. O Desafio número 6 vai fazer isso aqui pegar fogo 🙂

Postem seus comentários, sugestões, críticas e afins… PARA EU PODER IGNORAR, HAHAHAHAH!!! (Brincadeira :D). Lembrando que temos o fórum para discutir as dúvidas do desafio:

forum.codebunker.org

Abraços a todos