Registry Sniffing, serial fishing e inserimento sezione nuova in un PE | ||
26-04-2001 |
by Pincopall |
|
Published by Quequero | ||
|
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 |
.... |
|
.... |
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.
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
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 :
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). 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 :
Minore o uguale a 22
Compreso fra ]22, 2C]
Compreso fra ]2C, 36]
Compreso fra ]36, 39]
Compreso fra ]39, 4B]
Compreso fra ]4B, 54]
Compreso fra ]54, 5A]
Compreso fra ]5A, 7A]
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.....
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
|
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.