Cracking From a Beginner’s View

Bom esse é meu primeiro “tutorial” sobre engenharia reversa. Se você sabe tanto quanto eu (ou seja, quase nada), talvez isso seja um bom começo. Vou explicar algumas coisas básicas e iniciar fazendo um “debug” manual de um arquivo PE retirado do site CrackMe(O PE simula um sistema básico de ativação utilizando um arquivo .dat como chave). Existe diversas maneiras de se realizar um Crack de binário, inicialmente irei fazer da maneira mais simples possível apenas como uma introdução e posteriormente de um modo mais especifico entendendo melhor o que se passa pelo programa e as verificações feitas.

Tive a ideia de começar essa “serie” baseando no ótimo artigo de Fernando Mercês do blog Mente Binaria(Recomendo muito para quem pretende se aprofundar na área).

Nesse artigo ele cita “Tenha um site/blog onde você poste suas experiências, estudos e avanços.” Acho que aqui é um bom lugar para começar e também poder compartilhar um pouco de conhecimento.


Começando - Study of the Target

Antes de tudo, precisamos de algo que transforme o nosso executável em uma linguagem que o ser humano possa entender (ou ao menos tentar). Para isso, você precisa de um Debugger ou Disassembler. Nestes guias eu vou utilizar um dos Debuggers mais completos atualmente (um dos mais famosos também), por ter uma interface mais visual, simples para quem está começando, ser open source e freeware: OllyDbg.

Tela principal do OllyDBG com o Arquivo ReverseMe.exe já carregado, maior parte do tempo passaremos nessa tela.

Quanta coisa né? Com o tempo você fica mais familiarizado. Na janela principal (superior esquerda), você tem 4 colunas: Address, Hex Dump, Disassembly, Comment. Address contém o endereço de cada instrução, é por esse endereço que você vai determinar saltos (jumps), chamadas (calls), etc…
Hex Dump é a instrução no formato hexadecimal. Disassembly é o mesmo que o Hex Dump, mas “traduzido” em letras, digamos assim. Comments não tem relação com o código, apenas ajuda a identificar algumas coisas (Chamadas de função por exemplo). O Restante das telas vou detalhando melhor conforme a analise.

Primeiramente realizo um estudo do alvo, que seria basicamente rodar a aplicação e verificar o comportamento dela, pode ser feita diretamente pelo Olly(apertando a tecla F9).

Primeiro bloqueio

Logo ao executar a primeira coisa que é jogado na tela é uma mensagem dizendo que o período de avaliação foi expirado, isso, por incrível que pareça é bom, por alguns motivos.

A mensagem aparece numa MessageBox (que é uma chamada de API). Podemos localizar a região onde é feito essa verificação colocando um breakpoint em todos os locais onde é feita uma chamada para a função MessageBoxA por exemplo. E também Através dessa mensagem de “Purchase new license”, podemos observando onde ela é utilizada (provavelmente em conjunto com a MessageBox).

Com uma rápida analise utilizando o comando “Search for > All referenced text strings” do Olly, encontrei o local onde estava sendo gerado esse alerta.

Bloco responsável pela MessageBox

Observando um pouco essa parte do código, podemos notar que antes de ser exibido a mensagem de bloqueio, existe um comando chamado JNZ(Jump if not zero)e caso o Jump não for pego a mensagem de “Purchase new license” é mostrada e logo depois é feito um ExitProcess.

Olhando um pouco antes desse Jump encontraremos uma outra chamada de API(CreateFileA), nessa parte podemos notar que o código faz uma verificação procurando um arquivo chamado Keyfile.dat, ou seja, caso ele encontre algum arquivo com o nome Keyfile.dat o Jump é setado, caso contrario a mensagem de vencimento da chave é mostrado.

Local onde ocorre a busca pelo arquivo Keyfile.dat.

Posso realizar o ajuste agora mudando a função JNZ para JMP(Realiza o Jump independente de nenhuma Flag)desse modo sabemos como podemos passar pela primeira tela de bloqueio, mas por enquanto vou continuar debugando o código para verificar o restante do comportamento do arquivo e realizar todos os ajuste de uma só vez, para passar por essa parte do código temporariamente eu mudo a Flag Z para zero de modo que o JNZ seja ativado, também vou deixar um BreakPoint nessa parte do código para facilitar nas próximas execuções.

Os tipos de Flags.

Explicando um pouco melhor sobre as flags, elas são apenas um único bit de memória localizado dentro do processador. Como cada flag é apenas um bit, num dado momento elas só podem ter o valor 1 ou 0, um uso comum das flags é o de desviar a execução para um ponto em particular do código usando instruções de salto condicional.

Bom, seguindo com o debug, o programa executa uma nova chamada de API(ReadFile) no endereço onde está o arquivo Keyfile.dat.

Como ele não consegue ler o arquivo, uma outra mensagem é exibida na tela.

Verificação da Chave de Registro

Coloquei outro Breakpoint nesse segundo Jump que leva até essa mensagem e fiz o mesmo procedimento anterior mudando o valor na Flag Z para assim o JNZ ser ativado.

Resumidamente alterei a Flag Z novamente para o programa pensar que o arquivo KeyFile.dat foi lido, para assim a execução do programa continuar normalmente, basicamente estou guiando o modo que eu quero que o programa seja executado visto que o modo como ele faz as verificações é bem simples.

Existe outras duas verificações e dessa vez elas realizam um comando chamado CMP(Compare) o resultado dessa comparação ajusta a Flag S utilizada pelo comando JL(Jump if less) para validar a chave de registro, também é possível notar um loop sendo feito entre esses jumps.

Todos os BreakPoints utilizados na segunda parte do programa.

Inseri BreakPoints em todos os jumps em que eu precisei fazer alguma alteração, para evitar a mensagem de “KeyFile not valid” e apenas quando todas elas foram alteradas, foi possível passar pela segunda tela de bloqueio e chegar na mensagem desejada.

Local onde é exibido a mensagem que estamos buscando.

Agora meu próximo objetivo é de algum modo passar por todos esses comandos de Jump para sempre que executarmos o programa nenhuma mensagem de bloqueio seja apresentada.


Finalizing the Patches

Existem diversos caminhos para se realizar o Crack de algum binário, vou começar pelo modo mais simples, alterando basicamente todos os locais que realizam algum tipo de verificação e setar todos como um Jump padrão que independente de Flag sempre ira realizar o salto para o próximo bloco de código. É claro que não são em todos os casos que você vai poder recorrer desse modo, mas como esse é um Crack de nível “newbie” ele pode facilmente ser crackeado dessa forma.

Portando basicamente fiz a seguinte alteração, mudando o comando JNZ SHORT reverseM.0040109A dando um duplo clique na linha que está sendo chamado o comando e substituir por JMP SHORT reverseM.0040109A, claro que eu poderia alterar esse jump diretamente para a mensagem que desejamos, mas como já mencionei, nem sempre é assim tão fácil, nesse caso optei por alterar todos os lugares possíveis.

Exemplo do comando Jump já alterado, e que dessa vez não foi necessário nenhuma alteração na flag Z

004010BF . /7C 36 JL SHORT reverseM.004010F7 nessa chamada irei fazer diferente, não podemos colocar para ela realizar toda vez o salto, pois desse modo ela sempre iria exibir a tela de KeyFile não valida, desse modo podemos simplesmente preencher essa Jump com NOP(No Operation), fazendo com que nada seja executado nessa linha do código.

Basicamente substituí o comando de Jump if less para NOP e mantive o campo Fill With NOP’s marcado

A ultima parte do código ficou desse modo

Sendo o ultimo JMP que leva direto para a mensagem desejada

Agora é só copiarmos todas essas alterações em um novo executável e realizar os teste para assim verificarmos se está tudo correto, para isso basta apertar o botão direito e ir na parte de “Copy to Executable” e selecionar “All Modifications”, ira abrir uma nova tela e novamente, botão direito e “Save File”. Desse modo iremos criar um novo arquivo PE com todas as alterações feitas.

Após salvar, isso nos leva a ultima parte, que é a de executarmos o novo arquivo e analisarmos se tudo que fizemos foi o suficiente para passar das telas de bloqueio.

Congratz!!

Bom, esse foi o meu primeiro “tutorial”, estou usando mais como um modelo para fixar uma ideia ou apresentar algo que achei interessante, e nada melhor do que gerar uma documentação/step-by-step do que foi feito, e assim também, quem sabe, passar um pouco do que eu aprendi durante esse processo. Esse foi o meu primeiro Crack e apenas documentei o modo como eu realizei na primeira vez que me deparei com esse modelo, no próximo artigo vou apresentar uma outra maneira um pouco mais “complexa”(mas ainda bem simples) de modo a entender melhor o que está sendo feito em cada linha do código que com o decorrer do tempo fui aprendendo, e também passarei a pegar software de terceiros que já foram descontinuados para realizar o Crack, nada melhor que aprender usando como base situações reais.

Download: ReverseMe.exe