HellCrackme 2
Registry Sniffing, serial fishing e inserimento sezione nuova in un PE

26-04-2001

by Pincopall

 

UIC's Home Page

Published by Quequero


Per essere oscuri oggetti del desiderio ...

Hai fatto un bel tute, anche chiaro non ti commento il codice perchč mi hai mandato un tute formattato e se lo tocco sparisce tutto :PPP

... non basta spegnere la luce :-P

....

Home page se presente: http://pincopall.cjb.net/
E-mail: [email protected]
Pincopall on #crack-it #hackmaniaci #tcc ecc..

....

Difficoltą

(X)NewBies ( )Intermedio (X) Avanzato ( )Master

 

Allora, affrontiamo quasto crackme, ke cerca nel registro una chiave,una stringa ed il suo valore, anche se non dichiarato dall'autore =), che vuole un serial in base al nome e che noi trasformeremo in un autokeygenerator, solo che stavolta, essendo senza spazio per inserire il nostro codice, dovremo inserire una nuova sezione nel PE in cui poi mettere appunto il nostro codice.


HellCrakme 2
Registry Sniffing, serial fishing e inserimento sezione nuova in un PE
Written by Pincopall


Introduzione


Come detto nelle poche righe sopra, il crackme vuole un serial generato in base al nome, ed il serial è abbastanza facile da calcolare, per questo la crocetta su "Newbies", la tecnica di risoluzione da me usata per mettere la routine ( una volta creata ) dentro il codice del programma richiede invece, sempre secondo il sottoscritto, un po' di conoscenze, e per questo la crocetta su "Avanzato". Ah, e all'inizio c'è un nag da eliminare :-)

Tools usati


SoftIce 4.x
IDA 4.04 ----- Il mitico Interactive Disassembler
W32Dasm 8.93 ----- Un po' meno potente di IDA ma pur sempre utile soprattutto in alcune parti
HexWorkShop ---- Un Editor esadecimale qualunque

URL o FTP del programma


Dunque, lo trovate sicuramente su http://crackmes.cjb.net e credo pure nella sezione crackme della UIC http://quequero.cjb.net (bentornato vecchio url ;-))

Notizie sul programma


Vabbè non l'avete ankora capito ? E' un crackme ke vuole un serial calcolato in base al nome e poi c'è pure un nagscreen rompiballe :-) e questa è l'ultima volta ke lo dico !

Essay


Ok allora, si parte, lanciamo il crackme e subito c appare il NagScreen in cui johnes ci dice che vuole 100$ per usare il crackme, ora, johnes, vabbè che il crackme è carino, ma 100 $ mi sembra un po' caruccio ;-) , comunque , via...PARTE 1

Eliminazione NagScreen

Dunque, una volta visto il NagScreen chiudiamo il crackme, settiamo un bpx MessageBoxa dopo aver aperto il SIce (ovviamente ;-)) e lanciamo il prog. premiamo una volta F12 e ci ritroviamo alla fine della Call MessageBox chiamata all'offset 00444EDD, steppiamo un po' d vo,te co F10 finche non eseguiamo quel RET, una volta eseguito questo, arriviamo direttamente sotto la call che ci interessa all'offset 438DC9 , ovvero la call dword ptr [ebx+ 000002AC] il cui offset noi dovremo portare (per nopparla ovviamente) da FF93AC020000 a 909090909090. Bene, abbiamo finito la 1a parte, ora vediamo il resto.

Dunque ora possiamo lavorare sul nostro crackme senza il pensiero del nagscreen iniziale, mettiamo dunque il nostro nome "Pincopall" ed il nostro codice "11223344", premiamo Check e appare la finestra d Dialogo che ci dà dei lamer, e noi non staremo quì a farci dare del lamer così, vediamo d stanare sta password. Dunque apriamo IDA e cerchiamo una parola d congratulazioni che troviamo essere "good" , attenzione però perchè nel WDasm da String Data Reference questa parola non si trova, cosiccome non si trovano la maggior parte della altre .Vediamo dunque ke arriviamo quì cercando la nostra parola


00444CD7           mov     eax, ds:dword_447880 ---- mette in eax la giusta
00444CDC           mov     edx, ds:dword_447878 ---- mette in edx la cifra inserita da noi
00444CE2           call    sub_403B44  ---- Se non sono uguali : Brutto Lamer 
00444CE9           inc     [ebp+var_4]   |  Se sono uguali fà 
00444CEC           add     ebx, 4        |  ricominciare il ciclo 
00444CEF           inc     esi           |  ovviamente controllando la cifra
00444CF0           dec     [ebp+var_8]   |  successiva finchè finite le cifre
00444CF3           jnz     loc_444C5D    |  questo salto non salta più 
00444CF9 
00444CF9 loc_444CF9:                             ; CODE XREF: sub_444B24+11Fj
00444CF9           push    0
00444CFB           mov     cx, ds:word_444DE4   ---- e se tutto è andato bene : GOOD ---- 
00444D02           mov     dl, 2
00444D04           mov     eax, offset aGoodWorkCracke ; "Good work cracker!! Correct Code"..
00444D09           call    sub_441BF8
00444D0E           jmp     short loc_444D25

Per ora riporto solo questa parte di codice, ma dopo riporterò anche quello che si trova sopra in qunto la ci studieremo anke la routine che porta alla creazione del numero giusto. Ma perchè non la riporti ora? bhè, andiamo per ordine, se infatti provate a noppare o ad invertire quel jnz 00444D10 che è appunto quello che porta all'errore, vedrete che il crackme vi darà ancora dei lamer, quasto perchè cerca ,prima di arrivare a questa parte di codice una chiave con un determinato valorenel registro e se la chiave non è presente od ha un valore sbagliato, la locazione a cui c portano i salti è sempre la solita 444D10. Vediamo dunque ora questa parte :

Registry Sniffing

00444B6B      xor     ecx, ecx
00444B6D      mov     edx, offset aSoftwareMicros ; "SOFTWARE\\Microsoft\\Exploder\\"
00444B72      mov     eax, ds:dword_447894
00444B77      call    sub_44216C  --- questa call contiene la call RegOpenKeyA e mi pare si
00444B7C      test    al, al      --- veda che chiave vada a cercare nel registro :-) eggià 
00444B7E      jz      loc_444D10  --- "Exploder" e se non la trova al=0 e salta a errore 
00444B84      mov     edx, offset dword_444D84
00444B89      mov     eax, ds:dword_447894
00444B8E      call    sub_442430  --- questa call contiene la call RegQueyValueExA, e cosa
00444B93      test    al, al      --- cerki lo vediamo con un "d edx" , cerka la stringa 
00444B95      jz      loc_444D10  --- "HellCrackme 2" e se non la trova al=0 e quindi errore 
00444B9B      lea     ecx, [ebp+var_C]
00444B9E      mov     edx, offset dword_444D84
00444BA3      mov     eax, ds:dword_447894
00444BA8      call    sub_442308
00444BAD      mov     edx, [ebp+var_C]
00444BB0      mov     eax, offset dword_44787C
00444BB5      call    sub_40380C
00444BBA      mov     eax, ds:dword_447894
00444BBF      call    sub_4420D8
00444BC4      mov     eax, ds:dword_447894
00444BC9      call    sub_402C20
00444BCE      mov     eax, ds:dword_44787C ---- Bhè ma una stringa deve aver un valore no? 
00444BD3      mov     edx, offset aErvdjfregokjuo ; "ervdJfregokjuOtydkjgHsdkfhlkjhNsdflkEhq"..
00444BD8      call    sub_403B44 ---- dunque eccolo qua sopra, e in questa call confronta ogni 
00444BDD      jnz     loc_444D10 ---- carattere da noi immesso kon quello giusto, e come ne 
00444BE3      lea     edx, [ebp+var_110] ---- trova uno sbagliato :ERRORE, sennò prosegue
00444BE9      mov     eax, [edi+2E0h]

Dunque eccosi quà, il programma di vedere se la password da noi immessa sia adatta al nostro nick, cerka nel registro una kiave ke si kiamerà "Exploder" e dove metterla ce lo dice IDA :-), una stringa d questa chiave, ovvero "HellCrackme 2" ed il valore di questa stringa, per vedere tutto il valore d tale stringa, visto ke è abbastanza lungo e da disassembato non si vede tutto, basta andare nell'editor esadecimale, cercare chessò, "ervdJfre" e l'editor vi porterà a vedere tutti i caratteri della valore della stringa, volete ke ve li scriva? vabbè, il valore è questo : "ervdJfregokjuOtydkjgHsdkfhlkjhNsdflkEhqwerpovdSfrekjuotydkjghsdkfhlkj " ;-)

Come precisazione vorrei dire ke se anke non si fossero viste queste stringhe per vedere se andava a cercare ki o ke kosa nel registro si poteva usare lo strafamoso RegMon e per vedere il valore della stringa basta vedere kosa viene pushato prima della chiamata RegQueryValueExA.

Bene, ora possiamo ,tranquillamente dedicarci al nostro serial fishing che inizierà proprio da dove è finita la ricerca nel registro, ovvero dall'offset 444BE3....Dunque:

Calcolo del Seriale

Riporto di seguito la routine di calcolo del seriale ke spiegherò passo passo :


00444BEF     call    sub_423608 - dopo questa call eax contiene il numero di lettere del nick
00444BF4     mov     edx, [ebp+var_110] - viene mosso il nome in edx 
00444BFA     lea     eax, [ebp+var_10C] - viene mossa in eax la lunghezza del nome 
00444C00     mov     ecx, 0FFh   - viene messo in ecx il valore FFh (256 decimale)
00444C05     call    sub_403A10  - dentro questa call si controlla ke il nome esista,
                                   che la sua lunghezza sia maggiore di 0, ma minore di 256
00444C0A lea edx, [ebp+var_10C] - viene messa in edx la lunghezza del nome 00444C10 mov eax, offset byte_447884 - stessa cosa viene messa anke in eax 00444C15 mov cl, 0Ch - viene messo in cl il valore 0Ch (12 decimale) 00444C17 call sub_402814- in questa call controlla se il numero di lettere del nome
è maggiore di 0Ch, se lo è eax mantiene il suo valore, sennò prima viene incrementato di uno
e poi subisce l'operazione "and eax,03" , e, ad esempio, per "Pincopall" alla fine eax= 2
00444C1C lea edx, [ebp+var_110] - qui viene messo in edx il nome 00444C22 mov eax, [edi+2C4h] 00444C28 call sub_423608 - Dentro questa call viene calcolato, in base al valore ex
della prima lettera del nostro nome, quello che sarà il primo numero della nostra password
più giù dirò le cose nel dettaglio :-)
00444C2D cmp [ebp+var_110], 0 - qui viene controllato ke il seriale esista 00444C34 jz loc_444D10 - se il box del serial è vuoto : ERRORE 00444C3A xor eax, eax - viene azzerato eax 00444C3C mov al, ds:byte_447884 - muove in al il numero di caratteri del nome 00444C41 test eax, eax - guarda ke il nome non abbia 0 cifre 00444C43 jle loc_444CF9 - e, credo sia un bug, ma se il nome non c'è si salta a "GOOD" ! 00444C49 mov [ebp+var_8], eax - il numero di lettere viene messo in ebp-08 00444C4C mov [ebp+var_4], 1 - viene spostato "1" in ebp-04 00444C53 mov esi, offset unk_447885 - viene messo in esi il nostro nome 00444C58 mov ebx, offset unk_447898 - mette in ebx la prima cifra trovata prima 00444C5D 00444C5D loc_444C5D: ; CODE XREF: sub_444B24+1CFj 00444C5D cmp byte ptr [esi], 20h - Confronta il valore ex del primo carattere con 20 00444C60 jz short loc_444C85 - se è uguale salta 00444C62 xor eax, eax - azzera eax 00444C64 mov al, ds:byte_447884 - muove in al il numero di caratteri del nome 00444C69 xor edx, edx - azzera edx 00444C6B mov dl, [esi] - muove in dl il val. ex. del primo nostro char 00444C6D add eax, edx - bhè, somma edx ed eax :-) 00444C6F lea edx, [ebp+var_C] - muove in edx il valore della stringa d prima 00444C72 call sub_407680 00444C77 mov eax, [ebp+var_C] - viene messo on eax il valore della prima cifra 00444C7A mov dl, [eax] - che viene poi messo il dl 00444C7C mov eax, ebx - vabbè se non sapete ke fà questo ;-) 00444C7E call sub_40395C - Questa call non èimportante, ma usciti d quì.... 00444C83 jmp short loc_444CA3 - ...eax contiene il valore dell 1a cifra, e si salta 00444C85 ; --------------------------------------------------------------------------- 00444C85 00444C85 loc_444C85: ; CODE XREF: sub_444B24+13Cj 00444C85 lea edx, [ebp+var_C] - Bhè quì arriviamo solo se avete un nome il cui 00444C88 xor eax, eax - valore esadecimale del primo carattere si minore d 20h 00444C8A mov al, ds:byte_447884 - e siccome dubito ke voi l'abbiate mi risparmio d 00444C8F add eax, 3 - raccontarvi la routine :-)) 00444C92 call sub_407680 00444C97 mov eax, [ebp+var_C] 00444C9A mov dl, [eax] 00444C9C mov eax, ebx 00444C9E call sub_40395C 00444CA3 00444CA3 loc_444CA3: ; CODE XREF: sub_444B24+15Fj 00444CA3 mov eax, offset dword_447880 - viene messo in eax il nome 00444CA8 mov edx, [ebx] - in edx viene spostata la cifra del serial giusta 00444CAA call sub_40380C - dopo questa call viene .... 00444CAF lea edx, [ebp+var_110] - .... mosso in edx il serial inserito da noi 00444CB5 mov eax, [edi+2C4h] 00444CBB call sub_423608 00444CC0 mov eax, [ebp+var_110] - qui viene mosso il serial in eax 00444CC6 mov edx, [ebp+var_4] 00444CC9 mov dl, [eax+edx-1] - ed in dl vien mossa prima cifra del seriale "dummy" 00444CCD mov eax, offset dword_447878 - che viene poi mossa pure in eax 00444CD2 call sub_40395C - dopo questa call che non è importante 00444CD7 mov eax, ds:dword_447880 - viene messa in eax la cifra del serial giusto 00444CDC mov edx, ds:dword_447878 - ed in edx quella del serial nostro 00444CE2 call sub_403B44 - le due cifre vengono comparate in questa call 00444CE7 jnz short loc_444D10 - se non sono uguali salta ad errore ....

...e se lo sono rinizia il ciclo kome ho fatto vedere sopra. Ma è ora il momento d darvi la preecisazione ke vi avevo promesso a proposito del calcolo della prima cifra del sriale giusto in base al valore esadecimale della iniziale del nostro nome, bene, se andrete ad esaminare la call con un bel F8, troverete questi valori per le prime cifre :


Valore ex. dell'iniziale
Prima cifra del serial
Minore o uguale a 22
3
Compreso fra ]22, 2C]
4
Compreso fra ]2C, 36]
5
Compreso fra ]36, 39]
6
Compreso fra ]39, 4B]
7
Compreso fra ]4B, 54]
8
Compreso fra ]54, 5A]
9
Compreso fra ]5A, 7A]
1

Dopo il calcolo della prima cifra succede poi una cosa curiosa, :-) infatti dopo il calcolo della prima cifra del serial giusto, che differisce apuunto a seconda della lettera iniziale ( e a volte neanke da quella ), le restanti cifre sono tutti "1", in un numero uguale alle lettere del nome meno uno, se non c credete, provate a seguire la routine sopra commentata per il calcolo d ogni numero, e vi accorgerete che dopo la prima volta, eax conterrà, prima del confonto sempre 1 :-) così ad esempio il serial per "Pincopall" è "811111111" con la prima cifra uguale a 8 in quanto il valore esadecimale di "P" è 50 che viene seguita da otto "1". ma la stessa pass vale per qualunuqe nome di nove lettere la cui iniziale sia compresa fra "I" (4Bh) (esclusa) e "T" (54h) (inclusa).
Ohhhh..ora abbiamo finito d trovarci il seriale e possiamo arrivare al vero scopodi questo tutorial finora piuttosto facile, ovvero la creazione di un keygenerator in assembly che verrà poi inserito dentro al programma tramite l'inserimento di una nuova sezione nel PE, johnes infatti non cu ha lasciato abbastanza zeri ( vedi il mio tute sull'Oliver's First Crackme) nel prog in cui inserire il nostro keygenerator ke calcolerà la password giusta e, una volta inserita da noi la pass sbagliata ci farà apparire una message box con la password adatta al nostro nome :-) quindi.....

Creazione del Keygenerator

Bene, dato ke il keygenerator verrà poi inserito nel programma, c possiamo risparmiare tutte le dikiarazioeni iniziali e passare direttamente alla routine :


 8B1584784400            mov edx, dword ptr [00447884] - Mettiamo in edx il numero di caratteri
 668B0D85784400          mov cx, word ptr [00447885]   - e in cx il val. ex. dell'iniziale 
 33C0                    xor eax, eax      - azzeriamo eax
 B890784400              mov eax, 00447890 - e lo facciamo puntare ad un offset mai usato
 80F922                  cmp cl, 22 - Bhè mi sembra intuitivo, confronta il val. ex. con 22
 7E28                    jle DoveMetterą 3 - e se è minore o uguale salta, indovinate dove :-)
 80F92C                  cmp cl, 2C - se non è minore d 22 lo sarà d 2C ? 
 7E28                    jle DoveMetterą 4 - bhè, se lo è salta sennò...va avanti...
 80F936                  cmp cl, 36
 7E28                    jle DoveMetterą 5
 80F939                  cmp cl, 39
 7E28                    jle DoveMetterą 6
 80F94C                  cmp cl, 4C
 7C28                    jl  DoveMetterą 7
 80F955                  cmp cl, 55
 7C28                    jl  DoveMetterą 8
 80F95A                  cmp cl, 5A
 7E28                    jle DoveMetterą 9
 80F97A                  cmp cl, 7A
 7E28                    jle DoveMetterą 1
 E9XXXXXXXX       jmp 00444D10 Questo porta all'errore,ma kon ke kakkio inizia il vostro nome? ;-) 
DoveMetterą 3: C60033      mov byte ptr [eax], 33 - bhè qui si mette in eax ,33h = 3 decimale 
               EB21        jmp DoveMetterąGli 1   - e poi si salta ...bhè..dove? ;-)
DoveMetterą 4: C60034      mov byte ptr [eax], 34
               EB1C        jmp DoveMetterąGli 1
DoveMetterą 5: C60035      mov byte ptr [eax], 35
               EB17        jmp DoveMetterąGli 1
DoveMetterą 6: C60036      mov byte ptr [eax], 36
               EB12        jmp DoveMetterąGli 1
DoveMetterą 7: C60037      mov byte ptr [eax], 37
               EB0D        jmp DoveMetterąGli 1
DoveMetterą 8: C60038      mov byte ptr [eax], 38
               EB08        jmp DoveMetterąGli 1
DoveMetterą 9: C60039      mov byte ptr [eax], 39
               EB03        jmp DoveMetterąGli 1
DoveMetterą 1: C60031      mov byte ptr [eax], 31


DoveMetterąGli 1 : C64410FF31        mov [eax+edx-01], 31 - |Bene, quì mette tanti "1" quante
                   4A                dec edx    |sono le lettere del nome meno uno infatti ...
                   83FA01            cmp edx, 00000001 |... qui confronta il numero di lettere
                   75F5              jne 0045606D | rimaste con uno 
Creazione MessageBox:  6A00            push 00000000 - Stile della message box 
                       6885784400      push 00447885 - viene pushato il titolo "il nostro nome"
                       50              push eax - viene pushato l'argomento "il serial esatto"
                       6A00            push 00000000 - Handler della message box 
                       E8XXXXXXXX      call 0040123D  - Chiamata a MessageBox
                       E9XXXXXXXX      jmp 00444D10 - Dopo la msg box si torna all'ERRORE 

Bene , direi ke si capisce cosa faccia questa routine, guarda il valore esadecimale del primo carattere del nostro nome, e , a seconda del suo valore mette in eax un numero secondo la tabella sopra riportata, poi mette tanti uni, dietro quesat cifra per un valore uguale a quello della lunghezza del nome meno uno. C'è inoltre da dire che i registri uati sono stati scelti perkè, come vedremo alla fine, sia ke le cifre da noi immesse siano giuste o siano sbagliate, essi vengono manipolati senza uindi lascaire traccia del nostro passaggio. Da notare ancora è come ad alcune funzioni sia possibile già dare un opcode, infatti alcune lo hanno fisso, quali ad esempio i vari push o i vati mov, ed altri , come i jle, si trovano sempre alla medesima distanza dalla loro destinazione a quaòlunque offset li si piazzi, le uniche funzioni a cui non è ankora possibile dare un opcode sono i due salti e la call a MessageBox, infatti , non sapendo ankora la distanza a cui si trovano dalla loro destinzaione è impossibile affidarglielo. Lo faremo più avanti quando avremo deciso dove inseire la nostra routine. Quindi ....

Inserimento Sezione nel PE

Bene , eccoci alla parte più interesante del tutorial, l'inserimento di una nuove sezione nel PE (Portable Executable) vediamo intanto kome appaiono le sezioni prima del nostro cambiamento :


   Object01: CODE     RVA: 00001000 Offset: 00000400 Size: 00044200 Flags: 60000020
   Object02: DATA     RVA: 00046000 Offset: 00044600 Size: 00001000 Flags: C0000040
   Object03: BSS      RVA: 00047000 Offset: 00045600 Size: 00000000 Flags: C0000000
   Object04: .idata   RVA: 00048000 Offset: 00045600 Size: 00002000 Flags: C0000040
   Object05: .tls     RVA: 0004A000 Offset: 00047600 Size: 00000000 Flags: C0000000
   Object06: .rdata   RVA: 0004B000 Offset: 00047600 Size: 00000200 Flags: 50000040
   Object07: .reloc   RVA: 0004C000 Offset: 00047800 Size: 00005000 Flags: 50000040
   Object08: .rsrc    RVA: 00051000 Offset: 0004C800 Size: 00005000 Flags: 50000040
   

Bene, iniziamo, vedete ke a fianco ad ogni sezione c'è la scritta "Object", e ke ce ne sono 8, bene, noi vogliamo aggiungere una sezione e dunauq il numero d object dovrà passare da 8 a 9, si, ma dove andiamo a modificare questo numero? Dunque, apriamo L'editor esadecimale, e, subito dopo la scritta "This program must be run under Win32" comune a quasi tutti i programmi, vedete la scritta "PE", bene , contando sette byte vedete, nei valori esadecimali e arriverete al numero 08, ke sarà ovviamente da cambiare in 09, ecco come si vede da HexWorkShop:

5045 0000 4C01 0800 195E 422A 0000 0000    PE..L....^B*....

Ok, una volta cambiato con 09 abbiamo detto al prgramma che c sarann nove oggetti, bene, ora ci sono un po' di cose da sistemare di questo nuovo oggetto, intanto il nome, se venite ancora un pò più giù nell'editor esadecimale, noterete i nomi delle varie sezioni, e se contate i byte che distaccano il punto di .rdata dal punto d .reloc (compreso), potete vedere ke distano la belezza di 40 bytes l'uno dall'altra, e questa distanza ovviamente vale per tutte le sezioni che distano appunto l'una dall'altra 40 bytes, dunque una volta deciso come kiamare la nostra sezione andremo ad inserire il punto precedente il suo nome a 40 bytes di distanza dal punto di .rsrc, ovvero dall'ultima sezione. Ecco come appare questo cambiamento da HexWorkShop:

 
2E72 7372 6300 0000 0050 0000 0010 0500    .rsrc....P......
0050 0000 00C8 0400 0000 0000 0000 0000    .P..............
0000 0000 4000 0050 2E70 696E 636F 0000    [email protected]..

Bhè...ovviamente, come avrei potuto chiamare la mia sezione altrimenti :-P Ora potete vedere come la distanza sia di 40 bytes, oltre al nome però della sezione vanno definit altre proprietà, iniziamo dalla DIMENSIONE ovvero il Virtual Size, questa sarà ovviamente la grandezza della sezione rappresentata dal numero di bytes (ovviamente esadecimale) che la compongono, per inserire la nostra routine, più qualche altra funzione indispensabile al nostro scopo che andrò a presentarvi dopo, ci servono circa 170 bytes, ma noi non siamo taccagni e facciamo che di bytes ne aggiungiamo 200 ( C8h ), dunque andiamo a cambiare di nuovo da editor esadecimale inserendo, la doubleword C800 0000 subito dopo quella recante il nome della sezione.

E' ora la volta di inserire la posizione della nuova sezione relativamente all'ImageBase il cui valore , lo vediamo dal disassemblato, è 400000, ovvero è giunto il turno dell' RVA, per vedere quale sarà quello della nostra nuova sezione basta fare la somma dell'RVA dell'ultima sezione e del suo SIZE, come potete vedere prendendo ad esempio le sezioni già inserite, infatti vediamo che .rsrc ha sotto la colonna RVA il valore 51000 dato appunto dalla somma dell'RVA di .reloc ( 4C000 ) e del suo SIZE ( 5000 ), dunque vediamo che quello della sezione .pinco sarà 51000+5000 = 56000, bene, andiamo dunque ad inserire la doubleword 0060 0500 subito dopo doubleword del Virtual Size, ed anche la seconda proprietà è assegnata :-)

Vediamo ora cosa mettere nella doublword successivaa quella dell'RVA , bene lì ci và messo il valore del Physical Size, cha ha un valore uguale a quello del Virtual Size dunque anch'esso è uguale a C8 .

Come si può vedere dalla tabella delle sezioni, alla nostra manca ancora l'OFFSET che non è altro che l'indirizzo assoluto del primo byte della nostra sezione,cioè l'RVA a partire dal quale la sezione verrà mappata in memoria; anche calcolare questo è piuttosto facile, basta infatti sommare l'offset della sezione precedente ed il suo size, quindi l'offset per la nostra sezione sarà 4C800 + 5000 = 51800, e per settare questa proprietà inseriamo la dword 0080 5100 subito dopo la dword del Physical Offset .

Bene, manca solo una cosa, il settaggio dei FLAG, che per la nostra sezione sarà uguale a quello della sezione CODE, ovvero a quello della sezione che contiene il codice, e cioè 60000020 che non è altro che la somma di 00000020 + 40000000 + 20000000 il che vuol dire che tale sezione sarà una sezione di codice, eseguibile e leggibile, per aggiungere questo, nell'editor esadecimale mettiamo la dword 20000060 ben 3 doubleword dopo quella dell'offset.

Ok, come tocco finale, per si che il programma giri anche sotto NT bisogna aggiungere il nostro Virtual SIZE che sarà uguale al SIZE ( C8) alla Image Size : 56000 + C8 = 560C8, bene, a questo punto il nuovo skema delle sezioni ci apparirà così :

   Object01: CODE     RVA: 00001000 Offset: 00000400 Size: 00044200 Flags: 60000020
   Object02: DATA     RVA: 00046000 Offset: 00044600 Size: 00001000 Flags: C0000040
   Object03: BSS      RVA: 00047000 Offset: 00045600 Size: 00000000 Flags: C0000000
   Object04: .idata   RVA: 00048000 Offset: 00045600 Size: 00002000 Flags: C0000040
   Object05: .tls     RVA: 0004A000 Offset: 00047600 Size: 00000000 Flags: C0000000
   Object06: .rdata   RVA: 0004B000 Offset: 00047600 Size: 00000200 Flags: 50000040
   Object07: .reloc   RVA: 0004C000 Offset: 00047800 Size: 00005000 Flags: 50000040
   Object08: .rsrc    RVA: 00051000 Offset: 0004C800 Size: 00005000 Flags: 50000040
   Object09: .pinco   RVA: 00056000 Offset: 00051800 Size: 000000C8 Flags: 60000020 

Ed ecco come ci apparirà il tutto dentro l'editor esadecimale :

0000 0000 4000 0050 2E70 696E 636F 0000    [email protected]..
C800 0000 0060 0500 C800 0000 0018 0500    .....`..........
0000 0000 0000 0000 0000 0000 2000 0060    ............ ..`

Bene, abbiamo dunque aggiunto una sezione che ci offre 200 bytes da usare per inserire la nostra routine di generazione del seriale , mancano peò, come vi dicevo, ancora alcuni accorgimenti, di cui ho già parlato nel mio tutorial sull'Oliver's First Crackme, e che quì ripeterò perkè sò che siete pigri ;-) . Quindi....

Inserimento Routine nel codice

Dunque, abbiamo deciso di inserire la nostra routine all'offset 00456000, e quindi qul jnz 00444D10 alla locazione 0044CE7 andrà sostituito con un bel jmp 00456000, che però , essendo un jmp far ci occuperà la bellezza di 10 bytes cancellandoci anke la istruzione seguente quel jnz, ovvero quel " inc [ebp+var_4] " che siamo dunque costretti a portarci dietro ed a metterlo alla fine della nostra routine, subito dopo il jmp 00444D10 che avevamo messo dopo la Call a MessageBox.

A questo inc ci porterà un je che posizioneremo all'offset 00456000, ovvero subito prima dell'inizio della nostra routine e che salterà solo se le cifre confrontate da quella call all'offset 00444CE2 saranno uguali. A seguire il nostro inc, metteremo un jmp 00444CEC, ovvero un salto che c porterà alla normale esecuzione che il prohramma avrebbe se le due cifre fossero appunto uguali. Ma vediamo tutto nel codice:

:00456000 0F8486000000 je 0045608C - Ecco il salto che ci porta all'inc

---SNIP----SNIP-----

:00456042 E9C9ECFEFF jmp 00444D10 - Questo è il salto dopo tutta la serie di jl

---SNIP----SNIP-----

:00456082 E8B6B1FAFF call 0040123D
:00456087 E984ECFEFF jmp 00444D10

* Referenced by a (C)onditional Jump at Address: |:00456000(C)

:0045608C FF45FC inc [ebp-04]
:0045608F E958ECFEFF jmp 00444CEC - Ecco il salto che ci riporta alla giusta esecuzione

Dunque, ho approfittato anke per riportarvi i due salti e la call d cui prima non potevamo calcolarci l'opcode, come vedete ora è segnato, in quanto ora , avendo l'offset di partenza è possibile utilizzare la formula ( OffsetDiDestinzaione - OffsetDell'operazioneSuccessivaAQuellaDiPartenza ) per ottenere o 4 bytes da mettere , mi raccomando, sempre capovolti, dopo l'opcode E8 ( per la call ) e l'opcode E9 ( per i jmp far ).

Vediamo ora come modificare il jnz 00444D10 per trasformarlo in jmp 4560000, ecco che cosa avremo alla fine :

:00444CE7 E914130100 jmp 00456000

* Referenced by a (U)nconditional Jump at Address: |:0045608F(U)

:00444CEC 83C304 add ebx, 00000004



Come detto sopra, sia ke il je iniziale salti, sia ke non salti e quindi il programma faccia saltare il jmp 00444D10 i registri utilizzati dalla routine vengono ritoccati, sono stati scelti apposta per questo :-), e non ci son quindi conseguenze. Ok, Abbiamo finito, facciamo partire HellCrackme2.exe , mettiamo il nostro nick "Pincopall" , un serial ad cazzum, ed ecco apparire la msg box che ha come titolo "Pincopall" e come argomento "811111111" alèèèè funzia :-) ..ecceerto, dubitavate? :-P

Cmq con questo credo di aver raggiunto il limite del masochismo :-P

Alla prossimaaaaaaaaaaaaaa

Pincopall


Note finali

Ok, bel crackme , dunque un saluto a johnes, che se non era per lui che non metteva gli zeri alla fine l'inserimento della funzione non mi venive neanke in mente, poi un saluto a tutti gli altri frequentatori di #crack-it #hackmaniaci e #hackit99.
Un carissimo saluto a tutti gli hitmen ( a già non son + tali :-) ed in particolare a TheMR che da 2 mesi e più si stà sbattendo per fare un patchmaker causando interminabli thread in ML :-)...e poi via, un saluto a Quequero che non lo saluto mai per bene :-).
Come non ringraziare poi il mitico Pusillus dei r0, che non ho mai avuto il piacere d incontrare in chat :-( e da cui ho imparato 'na vagonata di cose belle :-)

Bhè non può mancare il mio saluto a GiPOCO, Ra1n, C1CC10, beb0s e alla mia cara Giulietta ...ciauzzzzzzzz

Disclaimer

Vorrei ricordare che il povero johnes, o The HellFish chiamatelo come volete, si è sbattuto per stò crackme, quindi mandategli i 100 verdoni!! Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento č stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly.