Hello World 😀 Acredito que as pessoas ficaram meio tímidas de resolver o desafio número 2. Talvez por medo de rodar o executável do site.. 🙁 Tá bom, tá bom, eu deixo vocês desconfiarem de mim (Eu desconfiaria também, respeitosamente). A sugestão é, se você tem medo que haja algum vírus escondido no executável, rode ele dentro de uma máquina virtual. De qualquer forma, você vai ver que não tem nada de malévolo no executável em questão. Pra quem não leu nada sobre o desafio, eu recomendo que não leia direto esse post, mas primeiro o post abaixo:

http://www.codebunker.org/index.php/2007/05/07/das-cinzas-crackeando-parte-1/

Para quem queria ver a solução.. leia mais! Conforme prometido, segue abaixo o link contendo o código fonte do alvo do primeiro desafio, pra quem quiser dar uma olhada. Source 1 Só agora que eu percebi uma coisa.. :S O artigo da versão 2 não era sobre Visual Basic. Era um outro artigo, mas eu esqueci de mudar a figura do programa.. Deixa pra lá! Se você for um cara sensível, isso não vai dar certo! Esse aí de baixo é o cara… o fato é que a única coisa diferente nele é a barra de títulos.. mas esqueçamos essas formalidades!

Escondedor - Versão 2

E a mensagem de erro continua a mesma do primeiro desafio, com a mesma diferença:

 

Escondedor - V2 - Erro!

 

Porém, quando você viu essas coincidências, você lembrou do primeiro artigo e disse a si próprio: "Já sei como resolver isso! Eu sou um cracker, sou muito inteligente! A minha mãe sempre disse!!". Aí você foi lá e fez a mesma coisa, olhou o resource de novo mas.. de repente, com o sorriso mudando lentamente, você percebeu que algo está diferente…
Resource Hacker
 
Mas você persiste, salva o zip e tenta descompactar. Meras mensagens de erro não são capazes de te abalar 😀
 
WinRAR
 
Ao repetir a tentativa pela 53ª vez, sem sucesso, você percebe que está na hora de tentar outra abordagem 🙁 O fato é que existe um resource no programa, chamado MF, do tipo RCDATA, que contém dados de algum tipo desconhecido. Na verdade, os dados não fazem nenhum sentido.. Neste momento, você tem um "boom" interno e faz uma especulação: "Maldito seja o Code.Ripper, ele encriptou o Resource!! Desgraçado, eu mato ele". Eu peço a sua calma, de todo o coração. Bom, apesar de ser uma especulação, isso faz muito sentido, ou o programa não teria aquele resource maluco. O que fazer neste caso então?
 
[[ A Análise! ]]
 
A resposta surge com uma reflexão um pouco mais interna sobre o alvo. Este testa a senha que foi recebida e, se esta estiver correta, ele salva o artigo em algum lugar para o usuário… Mas pra que este arquivo seja utilizável, ele precisa ser decriptado (ou desencriptado, ou decodificado, como queira).
Isso te faz deduzir que o programa tem um procedimento que faz isso. E o faz logo depois de confirmar que a senha está correta. Mais uns minutos refletindo sobre a vida (ser ou não ser?), a sua mãe pede pra você comprar algo pra ela e você fica revoltado porque ela está impedindo o progresso da [in]segurança computacional. Isso não te impede de obedecê-la. Mas na volta, você já tem um plano e agradece à sua mãe com um beijo.
Você sabe que precisa que o código do programa seja executado para que o resource seja decriptado, e ele faz isso naturalmente. Ele só tem uma restrição: a maldita senha! Você não é o tipo do cara que toma decisões sem estar bem informado. Por isso, você decide analisar o programa mais a fundo pra saber como ele funciona. Na hora de escolher uma ferramenta para a análise, você lembra de duas coisas:
  1. É preciso deduzir o máximo possível do código executado pelo programa, o que te leva a um disassembler!
  2. O Delphi utiliza a VCL (Visual Class Library ou Biblioteca de Classes Visual), o que a faz gerar executáveis que tenham um nível um pouco mais alto do que outros

Por isso, você acaba escolhendo o PE Explorer. Essa ferramenta espetacular te dá um monte de informações sobre o executável e ainda possui uma otimização para executáveis gerados pelo Delphi, onde ele detalha algumas coisas pra você. Então você clica em File | Open File… e escolhe o seu alvo.

 

PE Explorer

 

 

Ele te mostra informações sobre o cabaçalho do programa, seções etc. É claro que você não olhar endereço por endereço :S Você explora outros pontos do programa e descobre que ele pode, inclusive, pesquisar os resources do programa, igual ao Resource Hacker, no menu View | Resources. Ele não foi usado para o primeiro desafio porque o Resource Hacker era 1% mais simples para a tarefa 😀 Porém, quando você olha os Resources do programa utilizando o PE Explorer, ele te faz uma surpresa agradável.

 

PE Explorer - Form

 

 

Ele lê o resource que é gerado pelo Delphi pra gravar as informações de formulário (dentro do projeto, isso fica gravado no arquivo .DFM), e mostra pra você essas informações formatadinhas, bonitinhas e gostosas. Você inclusive sabe o nome do método que está sendo chamado quando o botão "Tentar" é pressionado: btnTentarClick. Você deu um passo 😀 Feliz de saber o que ocorre quando você pressiona o botão em questão, você parte pra ignorância. É como você chama o disassembler, carinh
osamente. Você faz isso através do menu Tools | Disassembler. Você deixa as opções padrão e clica em Start Now. Aí ele gera o código que você tanto queria.

 

PE Explorer - Disassembler

 

 

Aí, como você é um cara esperto, você vai direto ao ponto. Você clica em VCL Methods, no painel de baixo e depois clica no nome do método que você identificou antes: btnTentarClick. Aí você vê o código que é executado quando o botão é pressionado, no painel do Disassembler.

 

PE Explorer - VCL Methods

 

 

Olhando o código do método, você encontra uma referência de string: 00454D65 B8DC4E4500 mov eax,SLP00454EDC_Isso_ae__D_O_sr____o_cara_mesmo_ Um duplo clique nessa referência te leva a esse outro código: db 'Isso ae 😀 O sr. © o cara mesmo! Eu sempre soube!' Essa parece uma mensagem de sucesso e você deduz que ela deve ser mostrada quando a pessoa acertar a senha 😀 😀 😀

Você sabe que tem que fazer o programa seguir o fluxo dele até que essa mensagem seja carregada. Não se sinta assustado com o código Assembly. Leia um tutorial básico que é o suficiente. Em dois dias você está apto para o mercado. Você sabe que precisa encontrar o ponto onde é feito o teste pra saber se a senha está correta. Em uma linguagem de alto nível, como Delphi ou C, você faz isso com um comando if.

// Exemplo Delphi

if senha_digitada = senha_final then

begin

// O ShowMessage está sendo utilizado como exemplo porque é o mais utilizado

// para mostrar caixas de mensagens.

ShowMessage('Isso ae 😀 O sr. © o cara mesmo! Eu sempre soube!');

end;

Quando esse código é compilado, ele gera, na maioria dos casos, dois tipos de comandos assembly:

CMP – Compara dois valores e modifica os flags da CPU para mostrar a relação entre os valores (como maior, menor, igual, etc..);

JE, JNE, JZ, JNZ, JG, JLE etc. – Pula (JUMP) para determinado endereço, dependendo do resultado da última comparação. Você se preocupa em procurar, dentro da procedure, o IF que foi feito pra saber se a senha está correto. Uma busca rápida te mostra que existe apenas uma instrução CMP na procedure, logo acima da referência feita à string de sucesso.

00454D55 mov [ebp-0Ch],eax

00454D58 cmp dword ptr [ebp-0Ch],000004E0h

00454D5F jnz L00454E63 00454D65 mov eax,SLP00454EDC_Isso_ae__D_O_sr____o_cara_mesmo_

00454D6A call SUB_L004286A0

No endereço 00454D58, ele faz o teste de algum valor com o valor hexadecimal 4E0h, que corresponde ao decimal 1248. Seria esta a senha? Testando, verifica-se que não é. Então continuamos com a estratégia anterior. Vemos que a instrução JNZ, no endereço 00454D5F, aponta para um determinado endereço, que será chamado, caso a comparação não tenha valores iguais. Procurando nesse endereço, vemos que ele está fazendo referência ao seguinte código:

00454E63 L00454E63: 00454E63 mov eax,SLP00454F34_Infelizmente____N_o_foi_dessa_ve

00454E68 call SUB_L004286A0

A string completa é 'Infelizmente… Não foi dessa vez :('. !!!!!!!!!! Já sabemos o seguinte:

  • Que existe um único IF no método btnTentarClick;
  • Que se a comparação detectar valores iguais, então uma string contendo uma mensagem de sucesso será carregada;
  • Que se a comparação detectar valores diferentes, então uma mensagem de erro será retornada. Aquela mesma que vemos quando erramos a senha.

Dá concluímos que, ou existe a maior coincidência do mundo ou achamos o ponto de comparação. O trecho do código que queríamos encontrar. Fácil e rápido. Nem doeu. Como você é enjoado (aliás, muito, não sei como as pessoas te aguentam), você continua olhando o código e descobre a seguinte chamada:

00454E29 lea ecx,[ebp-00000410h]

00454E2F lea edx,[ebp-00000310h]

00454E35 mov eax,[ebp-04h]

00454E38 call TfrmPrincipal.Decripta

Hummmmmm… ele está decriptando, como havíamos previsto. Então estamos no caminho certo. A esta altura, os campeões de receita de bolo vão saber onde devem crackear o programa e estão todos felizes… MAS VOCÊ NÃO!!! Você não quer crackear o programa. Você só quer burlar essa senha maluca uma única vez pra ganhar o seu artigo. Por isso, você decide executar o programa com um debugger!!

 

[[ O Debugger ]]

 

Bom, o PE Explorer já ajudou tudo o que ele poderia ajudar até o momento (já deu o que tinha que dar, como dizem alguns, mais ousados), mas esta é uma ferramenta que te permite fazer uma análise estática de um programa. Só que agora você quer ver a coisa acontecer. Por isso, você vai usar um debugger! O Olly Debugger. Com a sua velha mania de clicar em File | Open, você abre o executável Escondedor.exe e vê o código "disassemblado" dele.

Olly Debugger

Se você ainda não conhece o Olly Debugger, esse é o único fato que justifica você não estar apaixonado por ele. É uma ferramenta fantástica pra debugging de programas executáveis no formato PE. Mas porque utilizar um debugger? Bem, tudo o que você quer é mudar o fluxo de execução do programa, uma única vez, durante o seu curto ciclo de vida. E um debugger é a ferramenta ideal pra isso, como você vai ver.

Lembra dos endereços onde você encontrou o CMP e o JNZ (00454D5F para o JNZ)?? Pois bem, esses endereços são exatamente os mesmos no debugger. Mas como isso é possível??? Bem, o fato é que, para facilitar a vida do SO, os processos em execução (instâncias dos programas) não fazem referência a endereços de memória reais. Eles fazem referência a endereços de memória fictícios, que são constantes no executável.

Na hora em que um programa lê ou grava dados da/na memória, o SO converte esses endereços em endereços reais realiza a operação desejada no endereço correto. Os endereços existentes dentro do programa são chamados de Espaço de Memória Virtual. Já q
ue esses endereços são os mesmos, você pode pressionar Ctrl+G no Olly Debugger e digitar o endereço do IF que encontramos anteriormente, pra ver se é verdade mesmo, já que você não confia em mim:

Olly Debugger - IF

Se você clicar com o botão direito em cima do código descompilado do programa e clicar no menu Analysis | Analyse Code, ele vai, como o nome diz, analisar o seu código e deixar ele mais completo. É bom você fazer isso antes do próximo passo. Você já ouviu falar em breakpoint? Este termo significa um ponto de parada em um programa e você o aplica a uma instrução específica.

Se você adicionar um breakpoint na instrução JNZ, no endereço 00454D5F, isso quer dizer que, quando você executar o programa através de debugger, ele vai executar normal e vai parar quando aquela instrução for executada. Já que este é o ponto onde queremos mexer, vamos fazer isso, pressionando a tecla F2 em cima da linha dessa instrução e, então, vamos executar o programa, pressionando F9.

O programa é executado normalmente e, então, digitamos uma senha aleatória qualquer, como qwerty (que você pode usar no seu email à vontade, sem ninguém nunca hackear), e pressionamos o botão Tentar. Dessa vez, ao invés de te mostrar a mensagem irritante, a janela do Olly Debugger vem à frente e te mostra o código que você já viu, mas dessa vez, você enxerga também os valores dos registradores (painel superior direito) e a pilha (painel inferior direito). O programa está pausado. A janela dele fica travada. ISSO É NORMAL! Você também percebe que um painel abaixo do disassembler mostra a mensagem

Jump is taken 00454E63=Esconded.00454E63

Isso te informa que a instrução CMP, executada na linha anterior, retornou que os valores são diferentes e que o JUMP será executado. Como você é curioso, você executa o programa passo a passo, utilizando a tecla F8, pra ver o programa fazer o pulo e acompanhar os valores dos registradores.

Olly Debugger - Passo a Passo

Você percebeu que o valor do registrador EIP sempre corresponde à linha que está para ser executada? De fato, essa é a função desse registrador, indicar qual o endereço da próxima instrução a ser executada… E o Olly Debugger permite modificar os valores de qualquer registrador.

"Ei,.. já que podemos indicar o endereço da próximo instrução… Não podemos mudar o fluxo de execução do programa??" – Diz você mesmo, retoricamente, enquanto a sua mãe passa por perto e ouve, imaginando se você não está usando drogas. A verdade é que podemos utilizar isso sim, e é o que vamos fazer 😀 Lembra do breakpoint que foi colocado na instrução JNZ com a tecla F2? Ele continua lá, então execute o programa de novo com a tecla F9 e pressione o Botão Tentar pela segunda vez.

Como anteriormente, a janela do Olly Debugger veio à frente e o programa é pausado. Você quer que o programa continue a sua execução sem efetuar o JUMP que ele faz se a senha estiver correta. Pra isso, você precisa mudar o valor do registrador EIP pro endereço 00454D65, que é o da instrução abaixo (Mas não faça isso diretamente!). Felizmente, o Olly Debugger te poupa desse trabalho de digitação e você pode clicar com o botão direito na próxima instrução que você quer executar e clicar no menu New origin here.

 

Olly Debugger - Mudando EIP

 

 

Com isso, você vê que o valor do registrador EIP mudou para o endereço da instrução que você queria. Agora você respira fundo, sai pra beber uma água e volta… e pressiona F9 pro programa continuar executando!!

 

Olly Debugger - Mensagem de Sucesso

 

Aeeeeeeeeeee, parece que deu certo! Mas quando você clica no Ok… O programa trava e o Olly Debugger é chamado novamente, mostrando umas mensagens sombrias na barra de status :S E agora? Será que eu perdi o meu tempo?? Não! Isso quer dizer que uma exceção (geralmente um erro) foi capturado pelo OllyDbg, mas isso não quer dizer que o programa não trate a exceção. Se você clicar em Shift+F7, conforme a mensagem que aparece, a exceção é repassada para o programa, mas ele fica pausado.. Bah, aperta F9 de novo!

 

Escondedor - Salvar MF.zip

 

 

Tan Tan Tan Tan Tarararararanan… (Música que a Globo toca quando o Brasil faz um gol na copa). Bem, você salva o ZIP numa pasta qualquer, descompacta e.. muito bem! Está lá um artigo chamado Monografia Forense que você queria tanto ler, sem precisar da maldita senha 😀

 

[[ Reflexões ]]

 

O artigo ficou meio longo porque eu fui explicando diversos conceitos no caminho e ensinando várias técnicas de análise, apresentando ferramentas… Mas se você for ver a mão-de-obra executada de fato, foi pequena.

Não se perdeu muito tempo pra encontrar as coisas. É claro que você poderia ter resolvido este mesmo problema de outras formas, talvez mais fáceis, mas eu estou te mostrando a coisa de um ponto de vista diferenciado, onde te explico coisas que você não vai encontrar em qualquer lugar. Espero que vocês tenham gostado do artigo e da explicação. Aguardo os seus posts comentando, sugerindo, reclamando, xingando, dando opiniões e tirando dúvidas. Ficarei muito grato em ajudá-los a entender cada detalhe da técnica utilizada!

 

[[ Pensa que terminou?? ]]

 

Acharam muito fácil, muito difícil? Bem, o próximo alvo é mais difícil que esse. Espero que vocês se divirtam com ele. Agora vocês têm um arsenal poderoso pra isso.

Escondedor – Versão 3

Quando eu postar o artigo que mostra a solução para a versão 3, eu coloco o código-fonte da versão 2 disponível. Vou deixar um intervalo um pouco maior antes de postar essa solução. Enquanto isso, eu vou postar coisas sobre outros assuntos, como um ser-humano qualquer 😀 😀

Abraços a todos!!