Krypton 2
Capiamolo fino in fondo

Data

by "LittleLuk"

 

02/02/2002

UIC's Home Page

Published by Quequero

lalalalala
Vai a farti fottere
lalalala

Molti mi avevano chiesto il tute sul K2, grazie mille

Se credi che non sia facile puoi chiedere un aiuto!

....

E-mail: [email protected]
irc.azzurra.it / irc.tin.it      #crack-it
 

....

Difficoltà

( )NewBies ( )Intermedio ( )Avanzato (x)Master

 

Tutti ci abbiamo provato. Tutti ci abbiamo sbattuto sopra i denti. Tutti abbiamo consumato il tasto del reboot. Tutti abbiamo maledetto Yado e il K2. Il Krytpon fluttuava nel suo flat: inattaccabile, imperscrutabile, indisassemblabile, questa creatura rideva in faccia al softice e ai suoi ridicoli tentativi di attacco: ogni attacco significava inevitabilmente la morte in quel mare di bytes dominati dal K2, che sfidava ogni legge di reversing. Ma ecco un animo tenace armare a punto il suo debugger e sferrare finalmente un unico attacco: letale, continuo, da ogni lato, senza lasciare spazio a nessuna via di fuga. Il prode Krypton fu colpito a morte, gli fu stroncata la possibilità di fuggire a ring0 mentre il suo codice veniva violato sempre più a fondo... l'ultimo fugace tentativo fu di scappare sulla strada lastricata del globalalloc, ma il softice lo inseguì senza tregua alcuna, e ormai l'innalzamento delle SEH erano un ultimo disperato rantolo del K2, rantolo che ormai preannunciava l'inevitabilità. E la morte lo colpì. Quel fatal JLE fu trovato e il K2 non ebbe scampo: e lo videro sprofondare morente nel verde siliceo tra una segment e l'laltro, risucchiato dal vortice del paging . Poi nulla più. Ma la morte del K2 non ha segnato la fine... un nuovo mostro è in attesa, una beta embrionale che è già preludio di un crisalide: schiusa la sua vecchia  pelle di K2 si prepara a ergersi maestoso e inarrestabile in quell'array di celle di memoria che diventeranno la sua casa; chissà, un giorno forse potrebbe prevalicare anche l'ultima realtà del pmode....

Da AndreaGeddon

Krypton 2
Capiamolo fino in fondo

Written by
LittleLuk


Introduzione

Avete molta pazienza? Allora questo crackme fa per voi

Tools usati

SoftIce
Frogsice
Icedump
HexEditor
PeDitor
IDA 4. 15
Pomata anticrampi prodotti dalla pressione prolungata del tasto reset (no, questa volta la MicroSoft non c' entra)

URL o FTP del programma

quequero.cjb.net sezione crackme

allegato (con il disassemblato e il dump)

Notizie sul programma

Il k2 è un programma che non gira sotto WIN2000 perché questo sistema operativo non permette la modifica della tabella contenente i vettori di interruput (IDT), quindi mi sono armato di molta, molta pazienza e, non curante dei crampi , ho cominciato a lavorare su questo programma da WIN98.

Essay


Appena lanciato, col sice attivo, mi appare una finestrella che mi sa tanto di trick antisoftice, ah è inutile tentare di mettere qualsiasi bpx, bmp o bpr perchè in questo modo il K2 ci condanna inesorabilmente a dover riavviare il pc.
Allora attivo il frogsice con l' analisi dell' idt e le protezioni dell' int 3 ( il cui opcode è CCh ed è usata dai debugger per piazzare i break point), il K2 mi fa poppare il Sice dato che genera un fault mentre esegue l' istruzione a 401000 (che di solito è l' Entry Point degli eseguibili) infatti il codice che si vede li è molto strano... è probabile quindi che quella sezione di codice sia cryptata e sia stata decryptata male a causa della presenza del sice e frogsice.
Ad ogni modo il log del frogsice dice cose molto interessanti:

** IDT DETECTION ** code 0F, at 016F:00406224
Interrupt: 01h

** IDT DETECTION ** code 0F, at 016F:0040626E
Interrupt: 01h

** IDT DETECTION ** code 0F, at 016F:00406407
Interrupt: 03h

** IDT DETECTION ** code 0F, at 016F:00406451
Interrupt: 03h

** IDT DETECTION ** code 0F, at 016F:0040671C
Interrupt: 05h

** IDT DETECTION ** code 0F, at 016F:00406766
Interrupt: 05h

** IDT DETECTION ** code 0F, at 016F:0040688B
Interrupt: 01h

** IDT DETECTION ** code 0F, at 016F:004068D5
Interrupt: 01h

** IDT DETECTION ** code 0F, at 016F:00406992
Interrupt: 03h

** IDT DETECTION ** code 0F, at 016F:004069DC
Interrupt: 03h

** IDT DETECTION ** code 0F, at 016F:00406A99
Interrupt: 05h

** IDT DETECTION ** code 0F, at 016F:00406AE3
Interrupt: 05h

Dirattamente dal file Code.txt dato insieme al frogsice:

Code 0F
Returned when FrogsICE hooked any write attempt/modification to the IDT.
This part prevent any app to fool FrogsICE by modifying the int01 vector
inside the IDT and then freely checking the Debug Registers.
FrogsICE will always avoid any attempt.

Questo vuol dire che il K2 sostituisce gli handler dell' int 1 (usata per il sigle step) - int 3 (usata per i bp) - int 5 con indirizzi dei suoi spezzoni di codice in modo da farci fare quello che vuole: come bloccare il pc, decryptare dati...

Col PeEditor apro il k2 e vedo che l' ultima sezione si chiama Yado e parte da 406000 (Image Base + Virtual Offset) che coincide con l' Entry Point del file, proprio la zona di codice che si occupa di modificarmi gli intra quindi questa sezione è il loader che almeno in teoria decripta la code e ci aggiunge qualche scherzetto :-).
Dico in teoria perché la CODE (quella che comincia a 401000, già nominato in precedenza) ha come flags 60000020 cioè Text Executable Readable ma non scrivibile il che è strano perchè se un processo che gira a ring3 (cosa che avviene normalmente) prova a riscrivere una sezione che non è riscrivibile genera un fault ma chi ha letto il tute di Quequero relativo alle SEH sa che questa cosa è possibile farla da ring0: ed ecco spiegata anche la manomissione dell' int5 (gli intra vengono eseguiti a ring0).

Dato che scendere a ring0 è pericoloso perché al minimo sbaglio dobbiamo riavviare conviene moltissimo rimanere a ring3 così la maggior parte delle volte si bloccherà solo il K2 e non tutto il pc e per evitare i fault setto i flag di tutte le sezioni a
E0000020 (come prima + Writable).

Ora cerco di recuperarmi il file decryptato: chiudo il frogsice, lancio l' icedump e setto un bpint 3 per poter usare la funzione break and enter del peeditor.
Appena il sice poppa risistemo l' opcode, setto un bpx sul primo indirizzo dell' istruzione che mi va a modificare l' IDT (quello segnalato dal frogsice), F5, arrivo all' istruzione che modifica la tabella e sposto l' eip al valore dell' istruzione successiva. Faccio così perchè non eseguo l' istruzione e non modifico il suo opcode (con dei nop per esempio) evitando problemi legati al CRC che il signor Yado potrebbe aver inserito. A questo punto sempre per sicurezza disabilito il bp e setto quello all' istruzione successiva (evito solo la manomissione degli int 1 e 3 e non dell' int 5 perché come già detto questa si occupa del decrypt della sezione di codice) e così via fino all' Original Entry Point, quando ho evitato l' ultima manomissione dell' IDT un bel bpx 401000 che presumo essere l' OEP e ancora un ultimo F5. Come previsto mi trovo a 401000 all' inizio della CODE, ancora un bd* per evitare di dumparmi il CCh dei breakpoint e ora un bel /dump 401000 c:\code.dmp; cioè dico all' icedump di scrivere nel file c:\code.dmp il contenuto della sezione codice (che dal peeditor si vede che ha una lunghezza di 1000 byte).

-------------------------------Funzionamento del loader ---------------------
Se volete sapere come funge il loader, lanciate il K2, quando vi dirà che è scaduto (sempre se avete l' icedump) dumpatelo e disassemblatelo, vedrete che passa la maggior parte del tempo a mandarvi in giro senza fare nulla. Le operazioni importanti sono:

Yado:00406066 sidt ds:qword_4073D3 ---> pone l' indirizzo base della IDT in questa variabile
...
Yado:004060D3 mov ebx, dword ptr ds:qword_4073D3+2
Yado:004061FD mov eax, offset unk_406BBA
Yado:00406224 mov [ebx], ax
che mi sostiuisce il valore presente a dword ptr ds:qword_4073D3+2, cioè l' handler dell' int1 con 406BBA,
questo è la prima manomissione della idt di una certa importanza: infatti se eseguissi, con F10, un single step finirei non come al solito all' istruzione successiva ma a 406BBA e da questo indirizzo arrivo a
Yado:00406BDC jmp short loc_406BDC --> autojump e dato che ci arrivo se uso l' int1 rimango intrappolato a ring0!!!.

La manomissione per l' int3 è del tutto analoga.

Per quando riguarda l' int 5 la prima volta sostituisco il suo handler con
Yado:004066F5 mov eax, offset loc_406D12
Yado:004067AE int 5 mi manda a 406D12
a 406d12 c'è del codice non disassemblato perchè non essendoci nessun riferimento IDA non sapeva da dove cominciare e quindi lo dobbiamo fare noi a mano (basta premere 'C') e vedo che controllo che controllo i 4 Debug Register alla ricerca di bpmb (lo posso fare perché sono a ring0):
Yado:00406D78 mov eax, dr0
Yado:00406DE9 mov eax, dr1
Yado:00406E5A mov eax, dr2
Yado:00406ECB mov eax, dr3
Yado:00406EF0 test eax, eax
Yado:00406F14 jnz loc_4072D6 se salta va ad un auto jump e si rimani bloccati a ring0 (arrivo qui partendo da un int 5) altrimenti ho bypassato tutti i controlli e

Yado:00406F1A jmp short loc_406F56
Yado:00406F5E mov eax, offset loc_401000 come già detto è l' OEP e inizio della CODE
Yado:00406FA7 mov ecx, offset unk_402000 --> fine della CODE
Yado:00406FF0 mov ebx, 1012000h --> chiave per il decrypt
Yado:0040707D xor [eax], ebx --> decrypto la CODE
Yado:004070C3 mov edx, [eax]
Yado:00407109 ror edx, 2 --> secondo layer del decrypt
Yado:00407150 mov [eax], edx
Yado:00407196 xor [eax], ebx

Ho evitato di riportare i vari loop ma il codice per il decrypt mi sembra sufficientemente chiaro.
Yado:004072B3 iret ---> ritorno al punto dopo in cui ho chiamato l' int 5 modificata cioè a 4067B0

Vedo anche che:
Yado:00406B09 mov eax, offset dword_401000
Yado:00406B30 jmp eax --> il loader ha finito il suo lavoro e vado nella CODE
---------------------- fine sezione loader -------------------------------

A questo punto non resta che sostituire la sezione di codice: apro il k2 con l' editor hex, mi sposto all' offset 600h (usando FLC del peeditor vedo che VA=401000 ---> offset=600h) sovrascrivo la sezione e metto l' entry point = 1000h.
Chiamo tale file dump1.exe.

Ok ora posso lanciare il file senza i bei giochetti del loader!!! E il 50% del lavoro è già fatto (ora mi aspettano gli altri, di giochetti sigh :-( ).

Disassemblo dump1.exe e vedo che ida dice:
CODE:00401000 jmp loc_401634
CODE:00401634 call sub_401697 --> mi decripta la sezione dei dati infatti:

CODE:00401697 mov eax, offset unk_402000 ---> inizio DATA, corrisponde ad un offset=1600h
CODE:0040169C mov ecx, 41Ah ---> con un hex editor si vede che i byte della DATA != 0 vanno da 1600h a 1A1Ah cioè è grande esattamente 41Ah byte. Solitamente gli 0 non vengono cryptati per rendere più difficile a noi aspiranti reverser l' algo di decodifica
CODE:004016A1 mov ebx, offset start ---> start = 401000
CODE:004016A6 mov ebx, [ebx]
CODE:004016A8 xor [eax], ebx
CODE:004016AA sub ecx, 4
CODE:004016AD add eax, 4
CODE:004016B0 cmp ecx, 0
CODE:004016B3 jge short loc_4016A8
CODE:004016B5 retn

L' algo di decofica qui però è abbastanza semplice e lineare:
byte DATA decryptato = byte DATA cryptato XOR byte CODE decryptato.

Manco a dirlo riabilito il bpint 3, lancio dump1 usando la funzione break and enter eseguo questa call (ora posso steppare liberamente dato che il loader non viene eseguito e quindi la IDT rimane intatta) e mi dumpo anche la sezione DATA col solito comando:
/dump 402000 41A c:\data.dmp che andrò a sostituire all' offset 1600h ottenendo così dump2.exe.

Per evitare che la sezione DATA venga ridecodificata ottenendo quella codificata (per la simmetria dello XOR) sposto l' EP all' istruzione successiva al decrypt della sezione cioè a 401639: EP = 1639h.
CODE:00401639 call sub_4016F7
tale call fa:

CODE:00401719 sidt qword ptr ds:unk_40200A ---> prelevo l' indirizzo della IDT: mi devo aspettare un'ulteriore manomissione dell' IDT, e infatti
CODE:00401742 mov ebx, ds:dword_40200C
CODE:0040176A add ebx, 18h --> prelevo handler dell' int3
.....
CODE:004017FD mov dx, [ebx]
CODE:00401822 mov ds:dword_402006, edx
....
CODE:0040184A mov eax, offset loc_401D7F -->mi manda a un auto jump relativo a int 3
CODE:00401871 mov [ebx], ax --> il nuovo handler dell' int 3 è 401D7F
CODE:004018BB mov [ebx+6], ax
questo nuovo handler no fa altro che bloccarmi a ring0:
CODE:00401D7F jmp short loc_401D7F ; auto jump relativo a int 3

Se non piazzo nessun int3 proseguo con la call e vado a finire a:
CODE:00401908 call GetModuleHandleA ; user32.dll
CODE:0040197E call GetModuleHandleA ; kernel32.dll
CODE:004019CD push offset aGetsystemtime ; "GetSystemTime"
CODE:00401A1C call GetProcAddress ; ottengo GetSystemTime
CODE:00401A43 add ds:dword_402150, eax--> 40214C è un vettore contenente gli indirizzi delle api
CODE:00401A6B push offset aMessageboxa ; "MessageBoxA"
CODE:00401ABA call GetProcAddress ; ottengo MessageBoxA
CODE:00401AE1 add ds:dword_402154, eax ; Messageboxa
.....
MessageboxExa
....
ExitProcess
.....
GlobalAlloc
....
ret

cioè prendo tutti gli entry point delle api che mi servono e li vado a mettere in un vettore così in seguito quando li dovrò usare non farò nessuna call messageboxa.

Non posso noppare le istruzioni che alterano la IDT per via del CRC ma posso continuare a lavorare senza problemi basta EVITARE I BPX (o in alternativa eliminare la manomissione della idt ma preferisco seguire il programma passo - passo) .

Subito dopo questa call c'è un vecchio trucco per trovare il sice:
CODE:0040163E mov ah, 43h
CODE:00401640 int 68h ; - APPC/PC
CODE:00401642 cmp ax, 0F386h
CODE:00401646 jz loc_401D2B ---> salta se il sice è attivo
....
CODE:00401660 mov ds:dword_402002, edx
CODE:00401666 mov eax, offset byte_4016B6
CODE:0040166B mov [ebx], ax
CODE:0040166E shr eax, 10h
CODE:00401671 mov [ebx+6], ax
CODE:00401675 int 5
Questa volta l' INT 5 mi esegue il codice compreso tra 4016B6 e IRET, IDA non lo interpreta correttamente, lo deve unassemblare ('U') e ricompilare ('C') così ottengo:

CODE:004016B6 mov eax, offset loc_401634 <--inizio zona dove ho il controllo sul sice, preparo la IT,...
CODE:004016BB mov ebx, offset loc_401695
CODE:004016C0 xor ecx, ecx
CODE:004016C2 add ecx, [eax] ---> Il valore di ECX dipende dagli opcode presenti tra 401634 e 401695, è un crc sulla call analizzata prima e sul rilevamento del sice
CODE:004016C4 inc eax
CODE:004016C5 cmp eax, ebx
CODE:004016C7 jle short loc_4016C2
CODE:004016C9 mov eax, offset dword_4011AF
CODE:004016CE mov ebx, 482h
CODE:004016D3 xor [eax], ecx ---> usando il crc ottenuto prima decrypto 482h byte a partire da 4011AF
CODE:004016D5 add eax, 4
CODE:004016D8 sub ebx, 4
CODE:004016DB cmp ebx, 0
CODE:004016DE jge short loc_4016D3
CODE:004016E0 iret ---> ritorno a 401677

CODE:00401677 mov ebx, ds:dword_40200C
CODE:0040167D add ebx, 28h
CODE:00401680 mov edx, ds:dword_402002
CODE:00401686 mov [ebx], dx
CODE:00401689 shr edx, 10h
CODE:0040168C mov [ebx+6], dx ---> risistemo l' int5
CODE:0040168C call 401DE7 ---> un po' di crc sulla sezione codice

CODE:00401DE7 pusha
CODE:00401DE8 mov eax, offset loc_401000 ---> gran parte della sezione codice
CODE:00401DED mov ebx, offset dword_4011A7 ---> qui ho un gestore di eccezioni
CODE:00401DF2 xor ecx, ecx
CODE:00401DF4 add ecx, [eax] ---> controllo sul crc simile a quello di prima
CODE:00401DF6 inc eax
CODE:00401DF7 cmp eax, ebx
CODE:00401DF9 jle short loc_401DF4
CODE:00401DFB cmp ecx, 421C4B97h --> comparo il mio crc con il valore corretto
CODE:00401E01 jnz loc_401D2B -->se è diverso eseguo il codice che eseguo quando trovo il sice
cioè messageboxa con "Can Not Start Apllication"
CODE:00401E07 popa
CODE:00401E08 retn --->401695

Subito dopo installo un gestore di eccezioni:
CODE:004016E1 push offset sub_401D06 ---> è il gestore
CODE:004016E6 push dword ptr fs:0
CODE:004016EC mov fs:0, esp
CODE:004016F2 jmp loc_401005
...
CODE:00401005 reindirizzo l' int 5 a 4010E1
....
CODE:004010A6 dec ecx
CODE:004010A7 jz short loc_4010D2
CODE:004010A9 mov ebx, [eax]
CODE:004010AB add eax, 4
CODE:004010AE cmp ebx, 544E4950h <-- TNIP: vi dice nulla bPINT ???
CODE:004010B4 jnz short loc_4010A6
CODE:004010B6 add eax, 1
CODE:004010B9 mov ebx, [eax]
CODE:004010BB cmp ebx, 65746E69h <--- ETNI
CODE:004010C1 jz short loc_4010C8
CODE:004010C3 sub eax, 1
CODE:004010C6 jmp short loc_4010A6
CODE:004010C8 mov ebx, 7961646Fh ; yado
CODE:004010CD jmp loc_401030 ;tramite int 5 4010e1, va ad allocare la memoria
CODE:004010D2 and eax, 0FFFh
CODE:004010D7 mov ds:dword_402050, eax
CODE:004010DC jmp loc_401030 ;tramite int 5 4010e1, va ad allocare la memoria

Questo ciclo mi genera una eccezione (un page fault) e quindi vado dritto, dritto a
CODE:00401D06 mov eax, fs:0 ; arrivo qui tramite eccezione generata dal loop posto a 4010B4
CODE:00401D0B mov esp, [eax]
CODE:00401D0D pop dword ptr fs:0
CODE:00401D13 mov ebp, [esp-4+arg_4]
CODE:00401D17 add esp, 8
CODE:00401D1A xor ecx, ecx
CODE:00401D1C mov eax, 0EACh
CODE:00401D21 mov ds:dword_402050, eax
CODE:00401D26 jmp loc_401030 ; 4010e1, va ad allocare la memoria

quindi con o senza eccezione finisco sempre a 401030

CODE:00401030 int 5 --> mi manda a 4010e1

CODE:004010E1 jmp short loc_401112
...
CODE:00401112 cmp ebx, 7961646Fh ; yado, (se lo merita)!!!
vi ricordate: 4010C8 mov ebx, 7961646Fh se trovavo ETNI
CODE:00401118 jz short loc_401170
CODE:0040111A cmp ecx, 0
CODE:0040111D jz short loc_401133 ;salto e vado ad allocare la memoria
....
CODE:00401133 mov ebx, eax
CODE:00401135 pusha
CODE:00401136 push 0F82h
CODE:0040113B push 40h
CODE:0040113D mov eax, offset unk_40214C ---> inizio vettore contenente gli indirizzi delle API
CODE:00401142 add eax, 14h
CODE:00401145 call dword ptr [eax] ---> chiamo la Globalalloc che alloca una zona di memoria e la ritorna in eax
CODE:00401147 mov ds:dword_402010, eax
CODE:0040114C popa
CODE:0040114D mov edi, ds:dword_402010 --> edi= zona allocata
CODE:00401153 mov esi, 400303h ---> il sice dice un' altra cosa: 4011AF
CODE:00401158 add esi, ebx
CODE:0040115A inc ecx
CODE:0040115B dec ecx
CODE:0040115C add ecx, 0F82h ---> numero di byte da copiare
CODE:00401162 repe movsb --> copio i dati che si trovano a 4011AF nella zona allocata
CODE:00401164 mov eax, offset dword_401069
CODE:00401169 mov dword ptr [eax], 0FFFFh ---> scrivo in 401069 FFFF che è un invalid opcode e se lo eseguo mi genera una eccezione
CODE:0040116F iret ---> ritorno a 401032
.....
CODE:00401170 sub eax, 5
.....
CODE:0040118C jmp short 401133 <-- anche in questo caso vado ad allocare la memoria e poi ritorno a 401032
CODE:00401032 cmp ecx, 1234h
CODE:00401038 jnz short loc_40104B ---> se ecx è diverso salto lasciando intatto il contenuto del fs
CODE:0040103A push offset sub_401DAC ; altro gestore eccezioni
CODE:0040103F push dword ptr fs:0
se non salto installo un gestore di eccezioni che mi fa apparire la messageboxa iniziale, quella con "Can Not Start Apllication" altrimenti lascio invariato il fault segment

CODE:00401045 mov fs:0, esp
...
risitemo int 5
....
CODE:0040118E mov eax, ds:dword_402010
CODE:00401193 push eax ---> nuovo gestore è l' indirizzo della zona di memoria appena allocata
CODE:00401194 push dword ptr fs:0
CODE:0040119A mov fs:0, esp
CODE:004011A0 mov eax, offset dword_401069
CODE:004011A5 jmp eax --> vado a eseguire il codice non valido e so già che se tutto è andato bene vado alla zona di memoria appena allocata che è una copia di 4011AF.

--------------------- Riassunto per chi si è perso -----------------------
In poche parole: 401671 --> tramite int 5 mi manda a 4016B6 dove decodifico 482h byte a partire da 4011AF --> ritorno a 401677--> risistemo l' int 5 --> un po' di crc --->dichiaro 401D06 un gestore di eccezioni (ci arrivo con un jmp da: 401695) ---> ridefinisco int 5 come 4010E1 --> loop che mi genera una eccezione ---> arrivo a 401D06 ---> chiamo int 5(40100b - 401093 - 4010c8 - 401030) ---> mi crea un alias dei dati a partire da 4011AF, e pone un invalid op code a 401069 ---> ritorno a 401032, 401038 deve saltare --> definisco la nuova zona allocata come un gestore di eccezioni ---> risistemo int 5 --> eseguo un opcode non valido (lo fisso da 401169) --> vado a eseguire l' alias di 4011AF.
----------------------- Fine riassunto ----------------

Dato che fin'ora non ne ho trovato traccia è probabile che a 4011AF ci siano i controlli sulla data, zona che ora devo andare a decodificare, dumpare e sostituire: dal sice appena decodificata la zona faccio /dump 4011AF 482 c:\cont.dmp
e li vado a sostituire all' offeset corretto che è 7AFh.
Il prg adesso non funge perchè va a decryptare il codice già sistemato però lo si può disassemblare.
Vado a vedere a 4011AF, anche ora ida non interpreta corretamente i byte e quindi faccio la solita procedura:
e vedo che
......
CODE:00401330 mov eax, offset 40214C ; --> vettore che contiene gli indirizzi delle funzioni
CODE:00401335 add eax, 4 ; prendo indirizzo di GeSsystemTime
CODE:00401338 mov ecx, 14h
CODE:0040133D cmp byte ptr [eax], 0CCh ; controllo se a questo indirizzo ho messo dei BPX, 14h è la dimensione del vettore contente gli indirizzi
CODE:00401340 jz short loc_4013AC ; se lo trovo azzero alcuni byte della .Code, segnalo expired ed esco
CODE:00401342 add eax, 1
CODE:00401345 dec ecx
CODE:00401346 jnz short loc_40133D
CODE:00401348 push offset data_odierna
CODE:0040134D mov eax, offset vettore_contenente_indirizzi
CODE:00401352 add eax, 4
CODE:00401355 call dword ptr [eax] ; GetSystemTime
CODE:00401357 mov eax, ds:data_odierna
CODE:0040135C and eax, 0FFFFh ; prelevo solo l' anno
CODE:00401361 xor ecx, ecx
CODE:00401363 mov ebx, 740h ; 740h=1856d
CODE:00401368 cmp eax, ebx ; Il 1856 è già passato?
CODE:0040136A jle salta_se_superato_controllo_data_parte_applicazione_vera
CODE:00401370 mov eax, offset vettore_contenente_indirizzi
CODE:00401375 add eax, 8
CODE:00401378 mov eax, [eax] ; MessageBoxa
CODE:0040137A mov ecx, 14h
CODE:0040137F cmp byte ptr [eax], 0CCh
CODE:00401382 jz bpx_su_messageboxa_o_messageboxexa ;salto se ho un bpx
CODE:00401388 add eax, 1 ; come 401338
CODE:0040138B dec ecx
CODE:0040138C jnz short loc_40137F
CODE:0040138E mov eax, offset vettore_contenente_indirizzi
CODE:00401393 add eax, 0Ch ; MessageBoxExa
CODE:00401396 mov eax, [eax]
CODE:00401398 mov ecx, 32h
CODE:0040139D
CODE:0040139D loc_40139D: ; CODE XREF: preparo_congratulazioni+195j
CODE:0040139D cmp byte ptr [eax], 0CCh
CODE:004013A0 jz bpx_su_messageboxa_o_messageboxexa
CODE:004013A6 add eax, 1
CODE:004013A9 dec ecx
CODE:004013AA jnz short loc_40139D
CODE:004013AC pusha ; se ho trovato dei BP su getsystemTime
CODE:004013AD jmp short loc_4013F6 ; azzero code segnalo exipred (codice posto a 4013AF) ed esco
......
......
ODE:004011C4 salta_se_superato_controllo_data_parte_applicazione_vera:
CODE:004011C4 push 0
CODE:004011C6 call GetModuleHandleA
CODE:004011CB mov ds:hInstance, eax
CODE:004011D0 jmp loc_401285 ; vado a controllare i DR e decodifico le risorse infatti:
.....
.....
CODE:0040129F mov eax, offset dword_4012CE
CODE:004012A4 mov [ebx], ax
CODE:004012A7 shr eax, 10h
CODE:004012AA mov [ebx+6], ax
CODE:004012AE int 5 --> mi manda a 4012CE che oltre a controllare i DR mi decripta le risorse

CODE:004012CE mov eax, dr0 ; controllo i registri usati dai bpmb
CODE:004012D1 test eax, eax
CODE:004012D3 jnz short trovato_bpmb
.......
CODE:004012EA mov eax, offset loc_401634 <--- la solita zona già usata per il crc all' inizio dove ho il controllo sul sice, preparo la IT,
CODE:004012EF mov ebx, offset sub_401DE7; lo stesso indirizzo del CRC_su_sezione_code di prima
CODE:004012F4 xor ecx, ecx
CODE:004012F6 add ecx, [eax]
CODE:004012F8 inc eax ; preparo ECX per usarlo nel prossimo ciclo
CODE:004012F9 cmp eax, ebx
CODE:004012FB jle short loc_4012F6
CODE:004012FD mov eax, 405430h ; usando un flc si vede che questo indirizzo appartiene alla sezione delle risorse e quindi questo ciclo decripta le risorse
CODE:00401302 mov ebx, 3E0h
CODE:00401307 xor [eax], ecx ; la chiave di decofica esatta è E3D42DF6h.

come al solito mi dumpo 3E0h byte a partire da 405430 e li vado a sovrascrivere all' offset 2430h e finalmente riesco a vedere la vera icona del K2!!!!

CODE:00401309 sub ebx, 4
CODE:0040130C add eax, 4
CODE:0040130F cmp ebx, 0
CODE:00401312 jge short loc_401307
CODE:00401314 iret ---> ritorno a 4012B0

CODE:004012B0 risistemo l' int 5
CODE:004012C9 jmp loc_4011D5 ; ho decodificato le risorse e superato i controlli sui DR
....
CODE:00401470 mov eax, offset controllo_data
CODE:00401475 mov ebx, offset loc_40146F
CODE:0040147A xor ecx, ecx
CODE:0040147C add ecx, [eax]
CODE:0040147E inc eax ; CRC su Codice comprendente il controllo sulla data
CODE:0040147F cmp eax, ebx
CODE:00401481 jle short loc_40147C
CODE:00401483 cmp ecx, 45536EFFh ; se il CRC è esatto non salto
CODE:00401489 jnz crc_codice_controllo_data_fallito <--- solita messageboxa con "Can Not Start Apllication" + ricerca di bpx su msgboxa e msgboxexa
reinderizzo l' int5 per andare ad azzerare la sezione CODE risistemo l' int 5 e definisco un nuovo gestore di eccezioni.

CODE:004014EC mov eax, ds:indirizzo_area_allocata
CODE:004014F1 add eax, ebx
CODE:004014F3 push eax
CODE:004014F4 push dword ptr fs:0
CODE:004014FA mov fs:0, esp
CODE:00401500 jmp short loc_401519
.....
CODE:00401519 mov eax, 0C0003000h
CODE:0040151E mov ecx, 6F2C8h ; vedi 4010A1
CODE:00401523 dec ecx
CODE:00401524 mov ebx, [eax]
CODE:00401526 add eax, 4
CODE:00401529 cmp ebx, 544E4950h ; TNIP
CODE:0040152F jnz short loc_401523
CODE:00401531 add eax, 1
CODE:00401534 mov ebx, [eax]
CODE:00401536 cmp ebx, 65746E69h ; inte
CODE:0040153C jz short loc_401543 ; mi manda a bpx_su_messageboxa_o_messageboxexa
CODE:0040153E sub eax, 1
CODE:00401541 jmp short loc_401523

....bpx_su_messageboxa_o_messageboxexa:
CODE:0040157A mov ebx, 4F444159h ; ODAY
CODE:0040157F mov [eax], ebx
CODE:00401581 add eax, 4
CODE:00401584 dec ecx
CODE:00401585 jnz short loc_40157F
CODE:00401585 ; ---------------------------------------------------------------------------
CODE:00401587 db 3 dup(0)
Queste ultime parti sono analoghe a quelle viste prima.

Quindi il loop a 401523 prima o poi fa si che eax vada a leggere in una zona di memoria non valida, genera un' eccezione e allora vado dove mi manda l' ultimo gestore, qui ho avuto un po' di problemi dato che il sice mi fa vedere una cosa e IDA un' altra però andando a senso vado a 4011DA e questa è la vera applicazione!!! Se arrivo fino a li vuol dire che l' applicazione è stata avviata correttamente perciò prima di uscire risistemo tutti gli int originali.

Ora sono arrivato in fondo, ho un eseguibile con tutte le parti di codice decriptate ma il lavoro non è ancora finito infatti non posso mettere l' OEP a 4011DA perché così non avrei il vettore con gli indirizzi delle api corretti e inoltre ho ancora il controllo sul sice (per ora non ho avuto problemi perchè avevo l 'icedump): quindi noppo il salto relativo alla segnalazione del sice a 401646 e al posto dell' int 5 ci metto un bel jmp 4011DA.

Ora uno se vuole, dopo tanta fatica, può cominciare a giochicchiare:
dato che con un editor di risorse tipo exescope mi da ancora problemi lancio l' ultima versione del K2, lo dumpo col peeditor lo riallineo e già che ci sono azzero i Forwarder channel e il time datastamp della IT, noppo l' ultima manomissione dell' int3, volendo si può anche eliminare il loader in modo da avere qualche byte libero in più sull' harddisk e chi più ne ha più ne metta.

E questo è tutto.

LittleLuk

 

Note finali

Tanta fatica per un programmino che in realtà si poteva fare con un centinaio di righe!!!!
Vabbè, un saluto a Yado che come persona non so ma come programmtore è un gran bastardo, poi un saluto a Que[Zzzz], ad AndreaGeddon, a Ph0b0s, a Spider, a tutti gli altri del pianeta uic e #crack.it e a tutti i miei amici.

Disclaimer

Vorrei ricordare che il software va comprato e  non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial.
In questo caso questo documento è stato scritto per spiegare a quelli che ci hanno provato come funzionano tutti i vari trick del K2 e per far comprendere ad ogni programmatore nuove tecniche di protezione che può usare sui suoi programmi
.

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

Capitoooooooo????? Bhè credo di si ;))))