URL:

Opção :




PIRATEANDO E CRACKEANDO PROGRAMAS

Conceitos básicos


Assim que conheci os computadores fiquei impressionado com a pirataria de software. Como poderia um programa acabar de ser lançado e já possuir uma cópia pirata dele?

Tinha várias suposições para isso: alguma pessoa de dentro das empresas de software deixava vazar o projeto, quem sabe vendia no mercado negro ou ainda o cracker invadia a rede da empresa e furtava o projeto.

Depois conheci a engenharia reversa e vi que nada disso era necessário, era possível alterar o programa sem ter seu código-fonte.

Cracking e engenharia reversa de softwares são conceitos muito ligados, um quase chega a ser sinônimo do outro. Cracking consiste em atacar uma tecnologia de proteção de cópias para conseguir passar por ela.

Crackear programas comerciais é ilegal. Esse artigo não tem a intenção de incentivar o cracking, muito pelo contrário, a ideia é mostrar um pouco como funciona.

Caso você seja desenvolvedor de software ou trabalhe com segurança da informação é recomendável que você possua conhecimentos de cracking para proteger seus próprios sistemas. Tecnologias de proteção de cópias desenvolvidas por pessoas que nunca tentaram crackear um programa nunca serão efetivas.

Até na engenharia reversa de malwares o conhecimento sobre cracking é importante, as vezes é necessário “crackear” o malware para passar por uma criptografia, chamar alguma outra função, desviar o processamento, etc.

Esse artigo é recomendado para os iniciantes do tema. Focarei na técnica mais básica do cracking, que é a de inserir um “remendo” no código do programa para burlar ou passar pela proteção. Ela é conhecida como Patching.

Vamos ver agora na prática como isso funciona.

Ferramentas

Para realizar os procedimentos desse artigo são necessários esses três programas:

 
CrackMe é um tipo de programa feito especificamente para ser crackeado. Para treinarmos cracking não é preciso passar por cima de direitos autorais, existem inúmeros desses programas na Internet. Esse CrackMe foi eu mesmo que fiz, pode ser crackeado e pirateado a vontade. :)

Análise Inicial

O primeiro passo é fazer uma sondagem no programa para descobrir o maior número de informações possíveis. Antes de executar o programa vamos ver se o executável possui algum compactador. O Exeinfo PE é ótimo para fazer isso.


Nenhum compactador encontrado, “Not packed”, e ainda identificou o ambiente de programação utilizado, “Borland C++”.

Agora vamos executar o CrackMe.exe para ver como ele funciona.


Podemos ver dois campos, Nome e Serial, e um botão Registrar. Geralmente quando registramos um programa nos é fornecido um nome (nosso próprio nome, nome da empresa, nome fantasia, etc) e uma chave de números e/ou letras que é o chamado Serial Number.

Vamos inserir algumas informações aleatórias nos campos para testar o funcionamento.


Para todas as informações que inserimos nos campos Nome e Serial foi exibida a Mensagem: “Erro. Serial invalido, tente novamente!”.

Apesar de nosso CrackMe não fornecer muitas informações, ele já nos deu uma muito útil, a mensagem de erro. Ela deve estar próxima do trecho de validação do programa, isso nos dá uma pista de onde procurar no código.

Quando abrimos um arquivo binário em disassemblers são geradas milhares de linhas de código, analisar uma a uma seria inviável. Então agora que descobrimos a mensagem de erro podemos procurá-la diretamente no código para poupar tempo, localizando-a poderemos estar próximos do trecho de validação do registro do programa.

Geralmente as strings (frases) dentro de um programa mesmo após o disassembler mantém a estrutura original. Vamos tentar encontrar a frase da mensagem de erro para prosseguirmos com nosso intento.

Por dentro do código

Vamos abrir o OllyDbg e através da opções Files – Open abrir o CrackMe.exe.


Para buscarmos as strings, no quadrante superior esquerdo clique com o botão direito e em Search for – All referenced text strings.

Na janela que abriu já é possível ver a string que procuramos.


Junto dela existe uma outra string bastante sugestiva. Vamos clicar duas vezes em cima da string de Erro para sermos levados diretamente para o código onde ela é chamada.


Transcrevo abaixo parte do trecho encontrado próximo à mensagem de erro:

004019CF CALL CrackMe.@TForm1@compare

004019D5 TEST AL,AL
004019D7 JE SHORT CrackMe.004019EE

004019D9 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004019DB PUSH CrackMe.0046320E ; |Title = "Sucesso"
004019E0 PUSH CrackMe.004631CC ; |Text = "Parabens! Programa registrado com suce...”
004019E7 CALL <JMP.&USER32.MessageBoxA>

004019EC JMP SHORT CrackMe.00401A01

004019EE PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004019F0 PUSH CrackMe.00463238 ; |Title = "Erro"
004019F5 PUSH CrackMe.00463216 ; |Text = "Serial invalido, tente novamente!"
004019FC CALL <JMP.&USER32.MessageBoxA>

00401A01 POP ECX
00401A04 RETN

A primeira vista todos esses códigos podem assustar, mas se formos seguindo linha a linha as instruções poderemos entender a lógica por trás dele. Vou escrever abaixo o mesmo trecho explicando o que cada linha faz:

004019CF CALL CrackMe.@TForm1@compare
-Chama a função “compare” que está no formulário TForm1.

004019D5 TEST AL,AL
-Essa função é a mesma que “CMP AL,0”, o compilador escolhe utilizar o TEST porque ele ocupa menos bytes na memória. Seu significado é: compare o valor 0 (falso) com o valor que está no registrador AL (que é a resposta da função “compare”), ou seja quer saber se a função “compare” retornou falso.

004019D7 JE SHORT CrackMe.004019EE
-Jump if Equal, Pule para o endereço 004019EE se os dois valores da comparação anterior forem iguais (0,0), ou seja, se a função “compare” retornou falso.

004019D9 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
-Na linha anterior ele pula para um endereço a frente caso a comparação seja falsa, logo podemos concluir que se ele não pulou e chegou até essa linha quer dizer que não era falso, ou seja, verdadeiro. Essa linha escolhe o estilo da mensagem que será exibida.

004019DB PUSH CrackMe.0046320E ; |Title = "Sucesso"
- Escolhe o título da mensagem.

004019E0 PUSH CrackMe.004631CC ; |Text = "Parabens! Programa registrado com suce...”
- Escolhe o texto da mensagem.

004019E7 CALL <JMP.&USER32.MessageBoxA>
- Chama e exibe a mensagem padrão da API USER32 do Windows.

004019EC JMP SHORT CrackMe.00401A01
-Jump. Pula para o endereço 00401A01.

004019EE PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
-Se olharmos com atenção esse é o endereço para onde a função JE anteriormente pularia caso o retorno da função “compare” fosse falso. Essa linha escolhe o estilo da mensagem que será exibida.

004019F0 PUSH CrackMe.00463238 ; |Title = "Erro"
- Escolhe o título da mensagem.

004019F5 PUSH CrackMe.00463216 ; |Text = "Serial invalido, tente novamente!"
- Escolhe o texto da mensagem.

004019FC CALL <JMP.&USER32.MessageBoxA>
- Chama e exibe a mensagem padrão da API USER32 do Windows.

00401A01 POP ECX
- Esse é o endereço para onde a função JMP que estava no final do trecho da primeira mensagem (verdadeira) pularia.

00401A04 RETN
- Finaliza a validação e retorna os resultados.

Apesar de a princípio parecer um pouco complicado, esse é o trecho que o compilar gerou em Assembly da famosa instrução IF-ELSE codificada na linguagem C++.

Agora entendemos o que o código faz, simplificando é: chama a função “compare”, se ela retornar “falso” exibe mensagem de Erro, se retornar verdadeiro exibe mensagem de Sucesso.

Qual dessas linhas poderíamos alterar para o programa sempre exibir a mensagem de Sucesso independentemente do valor que inserirmos nos campos Nome e Serial?

Isso poderia ser feito de várias formas, vou apresentar duas soluções.

Como vimos, o trecho principal da validação é esse:

004019D5 TEST AL,AL
004019D7 JE SHORT CrackMe.004019EE

Uma solução seria substituir a instrução JE (Jump if Equal) por JNE (Jump if Not Equal). Inverteria o fluxo, sempre que inserirmos Nome e Serial inválidos o programa exibiria mensagem que o registro havia sido feito com Sucesso.

Outra solução, na minha opinião mais elegante :), seria substituir o JE pela instrução NOP (No Operation). Nesse caso o programa faria a comparação com o TEST mas na linha debaixo não faria nada e continuaria o fluxo normal nas linhas seguintes até chegar na mensagem de registro efetuado com sucesso.

Vamos ver como aplicar essa solução com NOP.

Aplicando o Patch

Com o CrackMe.exe aberto no OllyDbg, vamos clicar uma vez na linha que desejamos alterar para selecioná-la.

004019D7 JE SHORT CrackMe.004019EE

Agora clique duas vezes em cima da instrução JE SHORT. Será exibida a janela “Assemble at 004019D7”.


Nessa janela iremos inserir a instrução que desejamos para substituir a JE. Apague JE SHORT 004019EE e digite NOP. Deixe marcada a opção “Fill with NOP's”.


Um detalhe interessante sobre a opção “Fill with NOP's”. Ela irá adicionar NOP's se a nova instrução for menor que a antiga. Isso porque estamos lidando com código de máquina onde mover até mesmo 1 byte é uma tarefa complicada, muitas referências da linguagem Assembly são relativas, então mover um código poderia invalidar esses endereços relativos.

Agora clique no botão Assemble e no X para fechar a janela.

Pronto, o código já está alterado com nosso Patch mas ainda não foi salvo diretamente no EXE, por enquanto a alteração está válida somente dentro do OllyDbg.

Para torná-la permanente clica com o botão direito em cima da área de código e selecione “Copy to executable – All modifications”. Na janela que abrir escolha “Copy all”. Uma nova janela irá se abrir com o novo executável já com as modificações. Em cima dessa janela clique com o botão direito e escolha “Save file”.


Escolha o nome que desejar e clique em salvar.

Feito! Agora feche o OllyDbg e execute o CrackMe que você salvou. Inseria qualquer informação nos campos Nome e Serial e veja o resultado.


O programa está crackeado! Mesmo sem termos um Nome e Serial válido ele foi registrado. Por mais simples que seja esse tipo de validação, acredite, existem muitos programas que ainda utilizam essa técnica, muitos desses sharewares que baixamos na Internet são similares.

Desafio

Caso tenha chegado até aqui imagino que realmente se interessou pelo assunto. Agora eu proponho um desafio para treinar as habilidades de cracking e engenharia reversa.

A técnica que utilizamos foi a de Patching, que é a mais simples, apenas desviamos da validação. Uma outra técnica bastante conhecida é a de KeyGen (Key Generator). É um programinha que os crackers fazem para gerar serial válido para qualquer nome que for digitado.

Compartilhar usando :

DEIXE SEU COMENTARIO :

Comentarios - Mundo Hacker | Facebook-copyright(™ © ®)