Basic Reverse Engineering with White ScorpionWhite básicos de engenharia inversa com escorpião
For this "tutorial" we will use a real program called PDF2Word. Para este "tutorial", vamos utilizar um programa chamado PDF2Word real. I stumbled upon this program when trying to convert a pdf document to a word document (duh..). Eu tropeçou em cima deste programa quando tenta converter um documento pdf para um documento word (duh..).
The funny thing on this program is that it costs $39.95 and that it is released under the GPL. A coisa engraçada sobre este programa é que ela custa R $ 39,95 e que é distribuído sob a GPL.
Let's start shall we? Vamos começar vamos?
1: Obtain a copy of the program, We will use version 1.6 in this tutorial (You'll need1: Obter uma cópia do programa, vamos utilizar a versão 1.6, neste tutorial (Você precisará
Google to get this version).Google para obter essa versão).
2: Obtain a copy of ollydbg at http://www.ollydbg.de2: Obter uma cópia do ollydbg em http://www.ollydbg.de
Start PDF2Word and you will see a screen with title "Please register .." Iniciar PDF2Word e você verá uma tela com o título "Por favor, registre .." Type in an email address and a bogus registration key and hit OK. Escreva em um endereço de e-mail falso e um registro fundamental e bateu OK. Write down the error message you get since we will need it later on: Anote a mensagem de erro que você começa uma vez que iremos precisar dele mais adiante: "Series number error, please check it and try again.""Série número de erro, verifique isso e tente novamente."
Now close pdf2word and start Ollydbg. Agora feche pdf2word e começar Ollydbg.From within ollydbg go to file, open and browse to A partir de dentro ollydbg ir para arquivo, e navegue para abrir C:Program FilesPDF2Word v1.6 and select pdf2rtf.exe .C: Program FilesPDF2Word V1.6 e selecione pdf2rtf.exe.
Once the program is loaded right-click somewhere in the code table and select Search for Depois que o programa estiver carregado direito do mouse em algum lugar na tabela de códigos e Search para seleccionar Then select All referenced text strings". Em seguida, selecione Todas as strings texto referenciado ". A new window will open with all text strings in the program.Uma nova janela será aberta com todas as strings no texto do programa.Scroll up and right-click once more.Scroll up e clique com o botão direito mais uma vez. Now select [i]Search for text and put in the errorstring you had earlier in the program:Agora selecione [i] Procurar texto e colocar no ErrorString você tinha no início do programa: "Series number error, please check it and try again." ."Série número de erro, verifique isso e tente novamente.". deselect "Case Sensitive" and press OK. desmarque "case sensitive" e pressione OK.
You will see the following line highlighted: Você verá a seguinte linha destacada: CODE : CÓDIGO:
00429F6F | PUSH pdf2rtf.00468270 | ASCII "Series number error, please check it and try again."00429F6F | PUSH pdf2rtf.00468270 | ASCII "Série número de erro, verifique isso e tente novamente."
Now press <F2> to put a breakpoint on it. Agora pressione <F2> para colocar um breakpoint sobre ela.Directly above you will find some other strings Diretamente acima você vai encontrar algumas outras seqüências which might be of interest as well so put a breakpoint on them to. que possam ser de interesse, bem assim ponha-os a um breakpoint.These are: Estes são: "Thank you registered" and "Thank you registered VeryPDF PDF2Word v1.6.""Obrigado registados" e "Obrigado registrado VeryPDF PDF2Word V1.6."
Now double click on one of the lines and press <F9> to start the program. Agora clique duplo sobre uma das seguintes linhas e pressione <F9> para iniciar o programa.
The registration window will come up again, so now put in an email address, a dummy registration-key O registo janela irá subir novamente, então agora colocar em um endereço de e-mail, um registro simulado-chave and press OK. e pressione OK.
Go back to Olly and you will see the following line highlighted: Volta a Olly e você verá a seguinte linha destacada: CODE : CÓDIGO:
00429F6F .00429F6F.68 70824600 PUSH pdf2rtf.00468270 ; |Text = "Series number error, please check it and try again."68 70824600 PUSH pdf2rtf.00468270; | Text = "Série número de erro, verifique isso e tente novamente."
This is our error message again and the program has stopped right before displaying it. Esta é a nossa mensagem de erro e de novo o programa parou antes de exibi-lo direito. You can see this error message is part of a [color=red]MessageBoxA[/color] call, this is the Você pode ver essa mensagem de erro é parte de um [color = red] MessageBoxA [/ color] chamada, esta é a API responsible for displaying the Message. API responsável pela exibição da mensagem.If you look a couple of lines earlier you will Se você procura um par de linhas mais cedo você vai see another MessageBoxA call where instead of our errormessage now theMessageBoxA ver outra chamada quando, em vez de agora o nosso errormessage message "Thank you registered VeryPDF PDF2Word v1.6." is located. mensagem "Obrigado registrado VeryPDF PDF2Word V1.6." está localizado. This means that if we have the correct serial it will display the registered message, and if Isto significa que, se temos o serial correto ele irá exibir a mensagem registrada, e se we don't we will get the error. nós não vamos pegar o erro. The program will need to decide if your serial is correct before it can display any of these O programa terá de decidir se o seu serial está correcto antes de poder exibir qualquer um desses messages. mensagens.The code to do so is usually located close to the messages so scroll up a bit until O código a fazê-lo normalmente está localizado perto de mensagens de modo a se deslocar para cima um pouco até que you see a piece of code containing a JNE,JE,JNZ or JZ. você vê um pedaço de código contendo um Jne, JE, jnz ou JZ.These are jumps that occur when a specific Estas são saltos que ocorrem quando um determinado event is met. caso seja cumprida. Usually the event is tested in the code directly in front of it. Normalmente o evento é testada no código diretamente na frente dela. In this case you should end up at the following lines: Neste caso, você deve acabar nas seguintes linhas: CODE : CÓDIGO:
00429F2E .00429F2E.85C0 TEST EAX,EAX85C0 TEST EAX, EAX 00429F30 .00429F30.74 39 JE SHORT pdf2rtf.00429F6B74 39 JE SHORT pdf2rtf.00429F6B
As you can see EAX is tested against itself which in this case will jump to 00429F6B if Como você pode ver EAX é testado contra ela, que neste caso vai saltar para se 00429F6B EAX has the value 0. EAX tem o valor 0. if we trace the jump we will see that it will jump over the registered message and end up se nós traçar o salto, veremos que ele irá saltar sobre o registrado mensagem e acabam right before the error message. direito antes da mensagem de erro.This means that if EAX = 0 we will get the error message and Isto significa que se EAX = 0 iremos receber a mensagem de erro e our serial is wrong. nossa série é errado.
At this point we could remove the JE SHORT pdf2rtf.00429F6B code and fill it with Neste ponto, poderíamos eliminar o JE SHORT pdf2rtf.00429F6B código e preenchê-lo com NOP so we will always get the correct message since the jump is never made, but that won't help NOP então iremos semper chegar a mensagem correta desde o salto é feito nunca, mas isso não vai ajudar here cause if you restart the program it will still ask you to register. causar aqui se você reiniciar o programa vai ainda pedir-lhe para se cadastrar.
So we need to continue our search. Por isso, precisamos de continuar a nossa pesquisa.We need to figure out where EAX is getting it's value from. Precisamos que descobrir onde está pegando EAX é de valor. 2 lines above TEST EAX,EAX we see 2 linhas acima TEST EAX, vemos EAX CODE : CÓDIGO:
00429F26 .00429F26.E8 F5F7FFFF CALL pdf2rtf.00429720E8 F5F7FFFF chamada pdf2rtf.00429720
This is a call to a function somewhere else in the program and you can bet your life it is this Esta é uma chamada para uma função em outro lugar no programa e você pode apostar a tua vida é isto function that sets the EAX value. função que estabelece o valor EAX. And so we need to figure out what this function does. E assim temos que descobrir o que faz essa função.To do this we will put another breakpoint Para fazer isso, vamos colocar uma outra interrupção at CALL pdf2rtf.00429720 by highlighting the line and press <F2>. em CALL pdf2rtf.00429720, destacando a linha e pressione <F2>. Now we want to restart the program to make it break on the function call. Agora queremos reiniciar o programa para torná-lo quebrar sobre a chamada da função.This is done by Isso é feito por pressing <CTRL>+<F2>. <CTRL> <F2> pressionando +.Select YES to the question asked (press left arrow and hit enter) and the program is restarted. Selecione SIM para a pergunta (pressione a seta para esquerda e pressione Enter) e do programa é reiniciado. Now press <F9> again to let the program run. Agora <F9> prima novamente para deixar o programa executado. You will see the registration box pop-up again, so put in an email address and a bogus serial and press OK. Você verá a caixa registo pop-up de novo, por isso ponha em um endereço de e-mail e uma série de araque e pressione OK.
As you can see the program will break on the CALL pdf2rtf.00429720 line. Como vocês podem ver o programa irá quebrar sobre o CALL pdf2rtf.00429720 linha. Now press <F7> to step into the call. Agora pressione <F7> a passo para a chamada. The first 4 lines are not of interest to us so we will start analyzing the code from 00429725 . As primeiras 4 linhas não são de interesse para nós e vamos começar analisando o código de 00429725. The code we have there is O código que temos aí é CODE : CÓDIGO:
I've copied the entire block until the first check of the serial above to safe space, so refer Eu já copiou todo o quarteirão até a primeira verificação da série acima de espaço seguro, então se referem to above code in this explanation. ao código acima, nesta declaração. [quote] [cotação] 1st line --> move our entered serial to ESI 1a linha -> move o nosso serial entrou para ESI 2nd line --> not important 2a linha -> não é importante 3rd line --> move the first byte (character) of our serial into AL 3a linha -> mover o primeiro byte (caractere) da nossa série em AL 4th line --> move the second byte (first+1) of our serial into CL 4a linha -> mova o segundo byte (primeira +1) de nossa série em CL 5th line --> move the 13th byte (first+E) of our serial into DL 5a linha -> mover o 13 º byte (primeira + E) do nosso serial em DL 6th line --> move content of AL (first character of our serial) into [ESP+18] 6a linha -> mover conteúdo da AL (primeiro personagem da nossa série) em [ESP 18] 7th line --> clear the contents of AL 7a linha -> limpar o conteúdo de AL 8th line --> move the content of CL (second character) into [ESP+30] 8a linha -> mova o conteúdo de CL (segunda personagem) em [ESP 30] 9th line --> move the 14th byte (first+F) of our serial into CL 9a linha -> mover o 14 º byte (primeira + F) em LS seriadas dos nossos 10th,11th,12th,13th line --> clear the contents of [ESP+19],[ESP+31],[ESP+25] & [ESP+D] since AL still is empty. 10 ª, 11 ª, 12 ª, 13 ª linha -> limpar o conteúdo de [ESP 19], [ESP 31], [ESP 25] & [ESP + D], uma vez que ainda está vazio AL. 14th line --> move the third byte (first+2) of our serial into AL 14a linha -> mover o terceiro byte (primeira +2) de nossa série em AL 15th line --> compare content of AL with 0x24 (hex for the $ sign) 15a linha -> comparar conteúdo de AL com 0x24 (hexadecimal para o sinal de R $) 16th line --> move the 13th byte of our serial into [ESP+24] 16a linha -> mover o 13 º byte do nosso serial em [ESP 24] 17th line --> move the 14th byte of our serial into [ESP+C] 17a linha -> mover o 14 º byte do nosso serial em [ESP + C] 18th line --> Jump to 004297B0 if AL is not equal to 24 ($ sign). 18a linha -> Ir para 004297B0 AL se não for igual a 24 ($ sinal). [/quote] [/ quote] If you trace the jump in the 18th line you will see that it jumps to the following code: Se você rastrear o salto na 18a linha você vai ver que ele pula para o seguinte código: CODE : CÓDIGO:
004297B0 |> 5F POP EDI004297B0 |> 5F POP EDI 004297B1 |.004297B1 |.5E POP ESI5E POP ESI 004297B2 |.004297B2 |.33C0 XOR EAX,EAX33C0 XOR EAX, EAX 004297B4 |.004297B4 |.5D POP EBP5D POP EBP 004297B5 |.004297B5 |.83C4 30 ADD ESP,3083C4 30 ADD ESP, 30 004297B8 .004297B8.C3 RETNC3 RETN
Which means so much as restore values, set EAX to 0 and return from where we were called. O que significa tanto como restaurar valores, EAX set a 0 e voltar de onde nós fomos chamados. If we let this happen then EAX will be 0 which will give us the error message. Se deixarmos isso acontecer, então EAX será 0, que nos dará a mensagem de erro.
So what do we know now from this code? Então o que nós sabemos a partir de agora esse código?
- AL should be equal to 0x24 or we will get the error message - AL deve ser igual a 0x24 ou iremos receber a mensagem de erro - the program moves the third character of our serial into AL before comparing it to 0x24 - O programa transfere a terceira personagem da nossa série em AL antes de compará-lo a 0x24 - the program moves the 14th byte of our serial into CL - O programa move o 14 º byte do nosso serial no CL
from above we can conclude that the third character of our serial should be a $ sign and a partir de cima, podemos concluir que a terceira personagem da nossa série deveria ser um sinal e $ that our serial should be at least 14 characters long since the 14th character is moved. que o nosso serial deve ser de pelo menos 14 caracteres desde a 14 ª personagem é movida.
So our serial will be something like: ..$........... Por isso, a nossa série será algo como: ..$...........
It's time for the next piece of code: É tempo para o próximo pedaço de código: CODE : CÓDIGO:
Let's analyze it: Vamos analisá-lo: [quote] [cotação] 1st line --> move the address of the function MSVCRT.atoi to EDI 1a linha -> mover o endereço da função MSVCRT.atoi para EDI atoi is a function which converts ASCII characters to integers (numbers).atoi é uma função que converte ASCII para inteiros (números). 2nd line --> put the 16th byte of our serial into EDI 2a linha -> ponha o 16 º byte do nosso serial em EDI 3rd line --> push our byte to the stack as an argument to atoi 3a linha -> empurre a pilha para o nosso byte como um argumento para atoi 4th line --> call atoi. 4a linha -> atoi chamada.the result will be in EAX o resultado será em EAX 5th line --> move content of EAX into EBP 5a linha -> mover conteúdo do EAX em EBP 6th line --> move the first byte of our serial into EAX 6a linha -> mover o primeiro byte do nosso serial em EAX 7th line --> push our byte to the stack as an argument to atoi 7a linha -> empurre a pilha para o nosso byte como um argumento para atoi 8th line --> call atoi. 8a linha -> atoi chamada.the result will be in EAX o resultado será em EAX 9th line --> add EAX to EBP and store the result in EBP 9a linha -> EAX para adicionar EBP e armazenar o resultado em EBP 10th line --> not important to us 10a linha -> não é importante para nós 11th line --> compare EBX with the value 0x0A (10) 11 ª linha -> EBX comparar com o valor 0x0A (10) 12th line --> if EBX is not 0x0A then jump to 004297B0 (put 0 into EAX and return). 12 ª linha -> EBX se não for 0x0A então salte para 004297B0 (0 postas em EAX e volta). [/quote] [/ quote] NOTE: You probably wonder how i figured out which byte is used to put into atoi, well hereNOTA: Você provavelmente quer saber como eu descobri que byte é usado para colocar em atoi, bem aqui it is: I've put in serials multiple times with different digits as values and compared them to ela é: eu tenha colocado em folhetins várias vezes com diferentes valores e os dígitos como comparação para eles the output of atoi in EAX. a saída do atoi em EAX.This resulted in the corresponding bytes. Isso resultou nos bytes correspondentes.
What do we know from this code? O que se sabe a partir deste código? - our 16th byte is put into EDI, this means that our serial must be at least 16 characters long - O nosso 16o byte é colocado em EDI, isto significa que o nosso serial tem de ser pelo menos 16 caracteres - the 16th byte is put into atoi, which means it much have a value between 0-9 - O 16 º byte é colocado em atoi, que significa que muito têm um valor entre 0-9 - the 1st byte is put into atoi as well, which also means it must have a value between 0-9 - O 1 º byte é colocado em atoi tão bem, o que também significa que deve ter um valor entre 0-9 - the value of our first byte is added to the value of our 16th byte and together they must be - O valor do nosso primeiro byte é adicionado ao valor do nosso 16o byte e juntos eles devem ser equal to 0xA (10). igual a 0xA (10).
So now we have the following serial: 1.$............9 Agora temos a seguinte série: 1 .$............ 9 as you can imagine the values of our 1st and 16th byte can be anything as long as they both como vocês podem imaginar os valores dos nossos dias 1 e 16 byte pode ser qualquer coisa, desde que ambos are digits and when added to each other are equal to 10 decimal. dígitos e quando são adicionados a cada outros são iguais a 10 decimal.
Time for the next piece of code: Tempo para o próximo pedaço de código: CODE : CÓDIGO:
Let's analyze it: Vamos analisá-lo: [quote] [cotação] 1st line --> our 15th byte is put into ECX 1a linha -> nosso 15o byte é colocado em ECX 2nd line --> push our byte to the stack as an argument to atoi 2a linha -> empurre a pilha para o nosso byte como um argumento para atoi 3rd line --> call atoi. 3a linha -> atoi chamada.the result will be in EAX o resultado será em EAX 4th line --> our 2nd byte is put into EDX 4a linha -> nosso 2o byte é colocado em EDX 5th line --> move the result of atoi into EBP 5a linha -> move o resultado de atoi em EBP 6th line --> push our 2nd byte to the stack as an argument to atoi 6a linha -> empurrar o nosso 2o byte para a pilha como um argumento para atoi 7th line --> call atoi. 7a linha -> atoi chamada.the result will be in EAX o resultado será em EAX 8th line --> add the result of our 15th and 2nd byte together and store in EBP 8a linha -> adicionar o resultado do nosso 15 º e 2o byte juntos e armazenar em EBP 9th line --> not important to us. 9a linha -> não é importante para nós. 10th line --> check if our 15th byte + our 2nd byte added together is equal to 0x0A (10). 10a linha -> verificar se o nosso 15o byte + nosso 2o byte somados é igual a 0x0A (10). 11th line --> if not, then another jump to 004297B0 11 ª linha -> se não for, então um outro salto para 004297B0 [/quote] [/ quote] As you can see this code is very similar to the codeblock before, so i won't explain it any Como você pode ver esse código é muito semelhante ao do codeblock antes, pelo que não vou explicar-lhe qualquer further. adicional.
Now we have the following serial: 12$...........89 Agora, temos a seguinte série: 12 $........... 89 We still need to analyze some code, but we're getting somewhere ;-) Temos ainda de analisar alguns códigos, mas estamos a ficar em algum lugar ;-)
Lets take a look at the final piece of code from this call: Permite dar uma olhada na última parte do código a partir deste convite: CODE : CÓDIGO:
Analysis: Análise: [quote] [cotação] 1st line --> since ESI still contains our serial, the 4th byte is now checked against value 0x24 1a linha -> ESI uma vez que ainda contém a nossa série, o 4 º byte é agora verificado em relação a valor 0x24 2nd line --> if not equal, then goto the famous 004297B0 2a linha -> se não for igual, então goto o famoso 004297B0 3rd line --> move our 6th byte to CL 3a linha -> move o nosso 6o byte para CL 4th line --> check if our 6th byte is equal to 0x23 (# sign) 4a linha -> verificar se o nosso 6o byte é igual a 0x23 (sinal #) 5th,6th,7th line --> not important 5 º, 6 º, 7 º linha -> não é importante 8th line --> sets the byte in AL to 1 if our check above is equal 8a linha -> define o byte na AL para verificar se o nosso 1 acima, é igual 9th line --> not important 9a linha -> não é importante 10th line --> return to where this call was called from. 10a linha -> retornar para onde foi chamado a partir deste convite. [/quote] [/ quote] What we see here is that our 4th byte is compared to 0x24 ($ sign remember?) as well and that O que vemos aqui é que o nosso 4o byte é comparado ao 0x24 ($ assinar lembra?), E que tão bem the 6th byte is compared to 0x23 (the # sign). o 6 º byte é comparado ao 0x23 (o sinal #).
If that is correct then AL is set to 1 meaning EAX won't be 0 and so causing the program to Se isso é correto, em seguida, AL está definido para 1 significado EAX não será 0 e assim causar o programa para give the registered message. dar a mensagem registrada.
In short: Em resumo: -check if 3th == $verificar-se 3th == $ -check if 1st + 16th == 10verificar-se o dia 1 == 16a + 10 -check if 15th + 2nd == 10verificar-se 15o + 2a == 10 -check if 4th == $verificar-se 4o == $ -check if 6th == #verificar-se 6o == #
All other characters are of no importance to create a valid serial so our result will be: Todos os outros personagens não têm qualquer importância para criar um serial válido tão nosso resultado será:
12$$.#........8912 $$.#........ 89
You can fill in the remaining dots with anything you like and as long as the rules above are Você pode preencher os restantes pontos com qualquer coisa que você gosta, e enquanto as regras acima são correct you can change the 1th,2nd,15th and 16th byte as well. corretas você pode mudar o 1th, 2 º, 15 º e 16 º byte também.
Now close OllyDbg and start PDF2Word. Agora feche OllyDbg e começar PDF2Word. Enter your email-address and enter one of your newly created serials. Digite seu endereço de e-mail e entra um de seus recém-criada folhetins.
When you press ok you will be thanked for registering. Quando você pressiona ok você será agradeceu para o registo.You're welcome ;-) Seja bem-vindo ;-) The result of your entered information is put in a string and written to O resultado de suas informações inseridas são colocados em uma string e escrita para %WINDIR%system32pdf2word.dat% WINDIR% system32pdf2word.dat
In case you want another serial just delete the dat file and put in a new one. Caso você queira excluir o outro serial apenas dat e colocar em um novo.
Of course this is a very simple protection, but it is a nice example to cover the basics of Claro que essa é uma proteção muito simples, mas é um bom exemplo para cobrir as noções básicas de reverse engineering. engenharia reversa.
Cast your vote on this article Elenco seu voto sobre este artigo *Note: the order of the votes has been reversed. * Nota: a ordem das votações foi revertida.
Good Stuff, Reverse Engineering will get you out of problems or give you a solution to one a lot of times. Good Stuff, Engenharia Reversa vai te tirar de problemas ou de lhe dar uma solução para um monte de vezes um. A learn a lot on this article although I was unable to do its content do to lack of update, the PDF2words 1.6 is no longer available on the NET, all mirrors and Links will download the 3.0 version and the current version of ollydgb doesnt have the \"Search for\" option required on STEP 2 it appears the hold Right Click menu is different. Um aprender muito sobre esse artigo, embora eu não era capaz de fazer o seu conteúdo para fazer a falta de atualização, o PDF2words 1-6 já não está disponível na NET, todos os espelhos e links irão baixar o versão 3.0, e da versão atual do ollydgb doesn't ter a \ "Procurar \" opção exigida no STEP 2 afigura-se segurar o botão direito no menu é diferente. Could you please update the article? Poderia, por favor, atualizar o artigo? Thank you for knowledge Sir I look forward to learn more from you and your colleagues. Obrigado por Sir conhecimento Aguardo com expectativa de aprender mais com você e seus colegas. All the best always... Todos os melhores semper ... -Luckyperfect- -Luckyperfect - \"Scientia est Potentia\" \ "Potentia Scientia est \"
tjszl1 - 07:18 am Tuesday February 12th, 2008tjszl1 - 07h18 terça-feira 12 de fevereiro de 2008
white_scorpion : white_scorpion: I\'m very angry.It\'s not a malicious software.You can use anti-virus software to check it. I \ 'm muito angry.It \' s não software.You malicioso pode utilizar um software anti-virus para checar isso.
lol 10/10 this pwns! lol 10/10 esta pwns! you should write more :) você deve escrever mais:)