Demorei a postar a terceira parte? Bem, eu estava deixando a galera absorver o desafio. Infelizmente, o post não recebeu nenhum comentário informando que alguém havia conseguido burlar sua segurança, nem tirando dúvidas, nem pedindo dicas.. 🙁

Enfim, para quem queria saber como burlar a segurança desse terceiro programa, prepare-se para viajar!

Se você não leu o texto dos desafios anteriores, recomendo que você faça antes de ler esse texto pra ficar por dentro.

Desafio 1

Desafio 2

 

[[ O Terceiro Alvo ]]

Veja bem, embora a mensagem dele (sobre o artigo de Visual Basic), seja a mesma o software é diferente.. Isso porque eu esqueci de mudar a mensagem :S Não sofreis!

Bem, você provavelmente pensou: "Agora eu já sei como quebrar qualquer programa" e foi, carinhosamente, atrás do seu querido PE Explorer pra olhar onde começava o código do botão de teste, através de editor de resources dele:

Que coisa mais estranha! O nome do botão (que você reconhece pelo TButton) mudou. Uma forma de te confundir. Maldito programador. Além disso, o resource não te mostra o método que está sendo chamado através do evento OnClick, que ocorre quando o botão é clicado… Mas o botão está funcionando.

Isso quer dizer que o código do botão foi adicionado dinamicamente. Na segunda versão, este método podia ser encontrado facilmente, como pode ser visto na figura abaixo:

Bem, as coisas mudaram.  O mundo ficou mais selvagem do que antes. E como vamos descobrir onde o código que verifica a senha está? Vamos procurar pela string da mensagem de erro: "cara… Tenta de novo ae 😀"!

Escondedor - Strings

Não encontramos. Porque?? Porque ela está encriptada no código do programa. Vamos decriptá-la? Não!! Excesso de violência e risco de insucesso. Por ora, existe uma maneira um pouco mais simples de resolvermos o problema de encontrar o trecho de código.

[[ Capturando chamadas ]] 

Embora o programa tenha adicionado eventos dinamicamente aos seus componentes, o que nos impossibilita de fazer uma análise estática para encontrar o nosso "ponto de impacto", tem uma coisa que o programa tem que fazer em determinado momento. Chamar a API do Windows.

Mas porque isso??? Porque o programa não é dono do seu próprio nariz. Ele não pode, por exemplo, mexer no hardware. Ele tem que pedir pro Windows fazer o trabalho sujo pra ele. E ele o faz através de chamadas de sistema.

Essas chamadas são feitas através de DLLs que o Windows fornece às aplicações. Por exemplo, a chamada de sistema MessageBox, que mostra uma mensagem na tela, está na DLL user32.dll, que você nunca deu valor na vida.

Então, já que aparece uma mensagem na tela, vamos ver se essa API está sendo chamada pelo alvo. Vamos fazer isso através do seu já conhecido Olly Debugger

Você precisa, antes de tudo, abrir o alvo Escondedor.exe com essa ferramenta do mesmo jeito que você fez no desafio anterior. O Olly Debugger possui um recurso muito poderoso para analisar as chamadas de sistema feitas pela aplicação. Basta você clicar com o botão direito do mouse na área do Disassembler (painel superior esquerdo) e clicar em Analysis | Analyse code.

Com isso, já que o OD conhece as principais chamadas de sistema, ele decodifica as chamadas, resolvendo os parâmetros que foram chamados.  Do mal!! Pra verificar se a nossa chamada foi feita, vamos clicar com o botão direito do mouse na área do Disassembler e depois clicar em Search for | All intermodular calls.

Olly Debugger - Intermodular Calls

Na janela que aparece, você ordena por "destination" (clicando na coluna, da mesma forma que você ordena arquivos no explorer do windows). Aí você procura por MessageBox.

 

Olly Debugger - MessageBox

 

Beleza! Encontramos e colocamos breakpoints em cada chamada, utilizando a tela F2. Agora vamos executar o programa pra ver se a chamada é executada!

 

 

 

Erro de novo.. mas que sacanagem! Isso ocorre porque essa chamada provavelmente foi feita utilizando o comando ShowMessage do Delphi que, ao invés de utilizar a chamada MessageBox, cria uma janela própria e mostra a mensagem. E agora???

Bem.. sejamos mais simplórios. Se você explorar o Olly Debugger, vai ver que dá pra fazer mágica com ele. O que nós vamos fazer é capturar a chamada feita ao botão OK. Para isso, vamos fazer o seguinte:

  1. Executar o programa novamente, do zero, através do Olly Debugger;
  2. Clicar em View | Windows. Por algum bug do destino, a janela apareceu vazia inicialmente e só funcionou depois que eu cliquei pela segunda vez. Se alguém souber o motivo, poste nos comentários!

Ao clicar nesse menu, você verá a seguinte janela:

 

Olle Debugger - Windows

O campos ClsProc está te mostrando o endereço virtual da procedure que é chamada quando a janela recebe uma mensagem. Do ponto de vista do Windows, os controles do usuário como botões e caixas de texto também são Janelas. Isso é muito importante.

Quando uma aplicação cria uma janela (janela de verdade ou controle de usuário) ,
ela passa como parâmetro uma função callback que será chamada quando essa janela receber uma mensagem. A janela recebe uma mensagem toda vez que você clica nela, passa o mouse por cima, fecha, abre, etc. O que nós vamos fazer aqui é definir um breakpoint na ClsProc pra parar o programa no momento em que o botão for pressionado. Para fazer isso, vamos clicar com o botão direito em cima da linha do botão (&Tentar) e depois vamos clicar em Toggle Breakpoint on ClassProc.

E, pra ver se a coisa funciona de fato, vamos executar. Sem piedade. Volte ao Escondedor e clique no botão OK.

Muito bem! O programa ficou pausado. Parou no breakpoint! Achamos parte do "caminho das pedras". Mas… e agora??

[[ A pilha ]]

Você, em seus intensos momentos reflexivos, já parou pra pensar no que acontece quando uma procedure é chamada, certo? Bem, se não, vou te explicar.

Como você bem sabe, o seu programa, quando compilado, é formado por várias instruções Assembly espalhadas pelo executável. Quando você cria uma procedure, o compilador arruma um espaço separado para ela e inclui lá apenas as instruções dela. Toda vez que a sua procedure é chamada, é executada uma instrução CALL que contém o endereço da procedure na memória.

Mas a sua procedure possui parâmetros, certo? Esses parâmetros são repassados para o programa através da pilha. A pilha é uma estrutura de dados especial que serve pro programa ser executado de forma eficiente. Outra forma de executar um programa seria através de uma tabela de procedimentos, o que os tornaria bastante lentos, provavelmente.

Pois bem, os parâmetros da procedure sendo chamada são incluídos na pilha através da instrução push. Antes de chamar a procedur, porém a instrução CALL coloca na pilha o endereço da próxima instrução, isto é, o endereço que deve ser executado quando a procedure chamar a instrução RETN.

Pense que quando você executa um CALL, tudo o que acontece é a definição do registrador EIP e quando um RETN é executado, o valor de EIP é setado pro valor da pilha 🙂 Muito inteligentes os caras que bolaram isso, a meu ver.

Bom, mas pra que tudo isso? Entendendo como funciona a pilha, você sabe que a pilha contém todos os endereços de procedures que foram chamadas até chegar no ponto atual e os parâmetros das procedures também estão lá 😀

Além disso, você precisa saber que, para utilizar a procedure ShowMessage do Delphi, o programador teve que decriptar a string antes… Então a string está na pilha!! Vamos procurar a string na pilha. Ela pode ser vista, no Olly Debugger, no painel do canto inferior direito.

 

Olly Debugger - Pilha

 

Bom, agora você precisa saber que a pilha vai sendo escrita de baixo para cima… Surpreso?? Bem, já vi uma explicação sobre o motivo disso, mas não lembro. Acredito que é pra ficar mais fácil de saber se o tamanho da pilha foi excedido, mas deixa pra lá 😀

Você tem que ir procurando, para baixo, até encontrar a string "Cara… tenta de novo ae 😀". Procure bastante por que está longe!

 

Olly Debugger - Pilha - String

 

Beleza!!! Encontramos a bendita string. Está esquentando. Só que precisamos encontrar a primeira ocorrência da string porque ela está sendo passada várias vezes por sub-chamadas. Por isso ela aparece duas vezes na tela acima.

 

Olly Debugger - Pilha - String final

 

Achamos. Estamos chegando perto. Calma!! Você pode ver um Return to Esconded.00455020. Esse é o endereço de retorno que eu expliquei anteriormente. Vamos aceitar a sugestão e clicar com o botão direito em cima da linha e clicando em Follow In Disassembler.

 

Olly Debugger - Disassembler

 

Saímos da pilha e voltamos pro código. É um bom sinal. Parece que chegamos a algum lugar. É uma procedure bastante grande. Uma vez que foi ela quem fez a primeira chamada com a mensagem de erro, sabemos que ela é uma procedure do usuário e não da VCL. Provavelmente é a nossa procedure alvo. Só temos que achar o ponto onde ela faz a comparação pra saber se a senha está correta.

Para isso vamos fazer o seguinte. Vá para o início da procedure. Ela está delimitada por um colchete preto e sempre possui um 55 hexa no início. Pressione F9 pro programa voltar a executar e sair dali. (Mas como??? Não vamos aproveitar???)

Calma! Vamos fazer um trace desta procedure, especificamente, para saber o que ela está fazendo. Para isso, clique com o botão direito no disassembler e depois clique em Run trace | Add procedure. Isto vai fazer com que a procedure deixe marcados todos os pontos onde ela passar. Agora coloque uma senha maluca qualquer e clique em OK.

Você vai ver que a procedure deixou um rastro vermelho nas instruções que foram executadas. 

 

Olly Debugger - Run Trace

 

Bom, agora siga a estrada dos tijolos vermelhos (eu já li isso antes, mas eram amarelos, enfim..). Você vai ver que a procedure é chamada com um JNZ (Jump If not Zero), precedida por um CMP (Compare). Sugestivo, não é? 😀

 

Olly Debugger - Comparação Final

 

 

Bem, pra saber se o CMP acima é a nossa comparação final, vamos colocar um breakpoint lá, utilizando a tecla F2, e mudar a sequência da execução, como fizemos antes.

Repita as coisas, coloque uma senha e pressione OK. Muito bem, o programa parou naquele ponto. O painel estranho logo abaixo do disassembler mostra a mensagem "Jump Is Taken". Então, vamos contrariá-lo e executar a próxima instrução após o Jump.

Para isso, clicamos na instruç&atild
e;o abaixo do JUMP

00454E7B  8D8D C8FAFFFF  LEA ECX,DWORD PTR SS:[EBP-538]

E clicamos no menu New origin here. O programa continua parado mas.. pulamos o JUMP. Cruze os dedos e pressione F9 pra continuar a execução.

 

Sucesso!!

 

Aeeeeeeeeeee Sucesso absoluto. Trabalho recompensado. Depois de clicar no OK, você vai ver que o programa vai dar uma travadinha e voltar pro Olly Debugger. Não se preocupe. É uma exceção que pode ser tratada pela aplicação.

No Olly Debugger, pressione Shift+F7 pra passar o problema pro Escondedor tratar e depois F9 pro programa continuar executando. Expliquei isso no desafio anterior.

 

Salvando artigo

 

 

Salve o arquivo numa pasta qualquer e descompacte. Você salvou o dia 😀

[[ Pensa que acabou?? ]] 

Pensa que eu vou deixar a sua vida continuar nessa preguiça mortal? Nada disso 😀 Agora eu te desafio a vencer o Escondedor – Versão 4!!

Esse tem proteções adicionais. Vamos ver se você é um Jedi.

 

[[ Conclusões ]] 

Bem, espero que tenham gostado do desafio 3. Ele deu trabalho pra resolver, né? Pensou que a vida era fácil? Os desafios do mundo real são ainda maiores.

Sugestões? Críticas? Xingamentos? Ameaças? Aguardo Feedback. Deixe um comentário!! 

Aguardo soluções! Vou postar o código-fonte do segundo desafio depois… Estou com preguiça agora.

Grande abraço.