Copy Link
Add to Bookmark
Report
3x06 Full Reverse (Target MrStop's Crackme #1)
[ Target: Crackme #1 by MrStop ]
pH#3 .............F.u.l.l..R.e.v.e.r.s.e............. [ #Sadrzaj ]
0x01 ................................................ [ Intro ]
0x02 ................................................ [ Tools of trade ]
0x03 ................................................ [ Fishing 1 ]
0x04 ................................................ [ Fishing 2 ]
0x05 ................................................ [ Fishing 3 ]
0x06 ................................................ [ Outro & Greetz ]
--[ 0x01 ]----------------------------------------------[ Intro ]
Sada cemo "upecati" par seriskih brojeva uz pomoc naseg [h]Olly
debuggera ;)
--[ 0x02 ]---------------------------------------------[ Tools of trade ]
Da bi smo "popravili" ovaj crackme, trebace nam neki "vaspitni" alati:
[+] OllyDBG v.1.10 ............................... http://www.ollydbg.de
[+] HexDecChar v.0.4 ........................ http://ap0x.headcoders.net
i naravno meta:
[+] Crackme #1 ....................................... my.target3.zip
Svi ovi alati su neophodni svakom reverseru pa predlazem da ako ih vec
nemate, podhitno ih nabavite! Bez njih se dalje citanje ovog teksta ne
isplati!
--[ 0x03 ]---------------------------------------------[ Fishing #1 ]
Vec smo naucili razne nacine za hvatanje seriskih brojeva koji se
nalaze u formi stringa u memoriji fajla, ali sta ako se seriski brojevi
ne nalaze u ovom obliku. Ovaj slucaj cemo razmotriti na meti Crackme1.exe
koju cemo otvoriti pomocu Ollya. Kao sto vidite ova meta ima ukupno
cetiri nivoa, a mi cemo ovde resiti samo tri. Cetvrti nivo ostavljam vama
za vezbu.
Text strings referenced in Crackme1:.text, item 4
Address=004012E0
Disassembly=PUSH Crackme1.00403000
Text string=ASCII "Level 1 Complated"
Posle otvoranja mete pomocu Ollya potrazicemo karakteristicne stringove
koji se odnose na level1. I u string referencama cemo videti sledece:
004012E0 68 00304000 PUSH 00403000 |Text = "Level 1 Complated"
Posto se negde iznad proverava tacnost seriskog broja odskrolovacemo na
pocetak ovog CALLa i postavicemo break-point na njegov pocetak, odnosno
postavicemo break-point na 004012A0. Posto smo ovo uradili mozemo da
unesemo u metu seriski broj po zelji. Ja sam uneo 111111 i pritisnuo
Register sto me je odvelo do mog break-pointa. Dalje slobodno traceujemo
kroz kod sa F8 sve do adrese 004012B4 gde se ocigledno proverava da li je
unet bilo koji seriski broj. Posto je EAX jednak 6, odnosno duzini unetog
seriskog broja, a ESP pokazuje na uneti seriski broj, znamo da smo na
pravom mestu. Dalje se krecemo kroz kod sve dok ne dodjemo do:
004012BB 8136 504F5453 XOR DWORD PTR DS:[ESI],53544F50
004012C1 8176 04 454C5>XOR DWORD PTR DS:[ESI+4],52554C45
Ocigledno je da je ovo kod za proveru tacnosti seriskog broja iz razloga
sto se odmah ispod ovoga nalaze skokovi koji odlucuju o tome da li ce se
prikazati poruka o tacnosti unetog seriskog broja. Dakle sada treba da
saznamo kako se to proverava uneti seriski broj. Da bi smo ovo uradili
pogledacemo sta se to nalazi na ESI adresi kada smo sa izvrsavanjem
programa dosli do adrese 004012BB. Ako uradimo Follow in dump na ESI
registar videcemo ovo:
0012FB00 31 31 31 31 31 31 00 00 111111..
Dakle prve cetiri cifre naseg seriskog broja se XORuju sa 53544F50. A
onda se na adresi 004012C1 i druge cetiri cifre naseg unetog seriskog
broja XORuju sa 52554C45. Kada se izvrsi i ova druga komanda sledi
provera tacnosti unetog seriskog broja pomocu dve sledece komande:
004012C8 813E 123D3525 CMP DWORD PTR DS:[ESI],25353D12
004012CE 75 21 JNZ SHORT Crackme1.004012F1
004012D0 817E 04 2A6D7 CMP DWORD PTR DS:[ESI+4],73746D2A
004012D7 75 18 JNZ SHORT Crackme1.004012F1
Kao sto vidimo XORovane vrednosti prvog i drugog dela seriskog broja se
porede sa 25353D12 i 73746D2A. Ovo nije nikakav problem. Malo reversne
matematike i resecemo nas problem, to jest pronacicemo tacan seriski
broj. Dakle:
Deo_seriskog_broja_1 XOR 53544F50 = 25353D12
Deo_seriskog_broja_2 XOR 52554C45 = 73746D2A
Posto je XORovanje revezibilna funkcija onda imamo:
Deo_seriskog_broja_1 = 53544F50 XOR 25353D12
Deo_seriskog_broja_2 = 52554C45 XOR 73746D2A
A ovo mozemo da izracunamo:
Deo_seriskog_broja_1 = 76617242
Deo_seriskog_broja_2 = 2121216F
Ostaje nam jos samo da pretvorimo ove hexadecimalne brojeve u string
koji se unosi. Srecom po nas HexDecChar ovo moze da uradi mnogo brze od
nas i stoga u njemo izabiramo mod 2 umesto moda 1 jer pretvaramo ceo
sadrzaj registra u string. Kada paste-ujemo Deo_seriskog_broja_1 kao Char
ce se pokazati string varB. Ali posto su registri uvek invertovani moramo
da uradimo i invert register, ondnosno klikom na zelenu strelicu dobijamo
umesto varB, string Brav. A kada isti postupak uradimo i za
Deo_seriskog_broja_2 dobijamo string o!!!. Dakle ceo seriski je
Deo_seriskog_broja_1 + Deo_seriskog_broja_2 = Bravo!!!. Konacno kad
unesemo tacan seriski broj u metu dobijamo odgovor Level 1 ComplAted!!!
Predjimo sada na Level 2.
--[ 0x04 ]---------------------------------------------[ Fishing #2 ]
Posto smo sa izuzetnom lakocom resili Level 1, vreme je da predjemo na
Level2, koji donosi par novina. Dakle ponovo cemo kao i za prvi Level
pronaci gde se to porede uneti i tacan seriski broj. Ovo cemo uraditi
pomocu string referenci, kao i prosli put:
Text strings referenced in Crackme1:.text, item 8
Address=00401355
Disassembly=PUSH Crackme1.00403012
Text string=ASCII "Level 2 Complated"
Duplim klikom na ovaj string dolazimo ovde:
00401355 68 12304000 PUSH 00403012 ; |Text = "Level 2 Complated"
Kao i prosli put skrolujemo do samog pocetka CALLa i postavljamo
break-point na 00401309 posle cega u nasu metu unosimo lazni seriski broj
111111 i pritiskamo dugme Register. Ovo nas zaustavlja izvrsavanje nase
mete i stavlja nas na nas break-point. Posto se sada nalazimo gde treba
mozemo da tracujemo kroz kod sa F8. Ovo radimo sve dok ne dodjemo do
sledece adrese:
0040131D 83F8 11 CMP EAX,11
00401320 75 44 JNZ SHORT 00401366
Posto se ova provera CMP EAX,11 nalazi odmah ispod GetWindowTextA API
poziva zakljucujemo da je potrebna duzina seriskog broja 11h odnosno 17
karaktera. Stoga umesto 111111 kao seriski broj unosimo
11111111111111111. Ponovo zastajemo kod naseg break-pointa i tracujemo
kroz kod sve do JNZ skoka koji se ovaj put ne izvrsava! Tracujemo dalje
sve dok ne dodjemo do:
00401325 807E 08 2D CMP BYTE PTR DS:[ESI+8],2D
00401329 75 3B JNZ SHORT 00401366
Sada vidimo da se jedan bajt poredi sa 2D, odnosno sa karakterom '-'.
Ako pogledamo malo ispod CPU windowa videcemo sledeci tekst:
Stack DS:[0012FB08]=31 ('1')
Njegovom selekcijom i klikom na Follow address in Dump videcemo ovo:
0012FB08 31 31 31 31 31 31 31 31 11111111
0012FB10 31 00 00 00 4C 10 40 00 1...L.@.
Odnosno videcemo da 9 slovo u unetom seriskom broju mora biti '-'.
Ponovo unosimo novi seriski broj u nasu metu samo sto sada umesto
predhodno unesenog seriskog broja unosimo 11111111-11111111. Kada sada
budemo stigli do poredjenja sa 2D videcemo da se ovaj JNZ skok vise ne
izvrsava i da cemo nastaviti sa daljim izvrsavanjem koda, stizuci do:
00401340 33C3 XOR EAX,EBX
00401342 05 444F4F47 ADD EAX,474F4F44
00401347 3D 504F5453 CMP EAX,53544F50
Primetite samo da se pre ovoga nas seriski broj podelio na dve celine
koje se sada nalaze u registrima EAX i EBX. Posto su EAX i EBX ne
promenjeni u odnosu na unetu formu zakljucujemo da program trazi unosenje
seriskog broja u hexadecimalnoj formi. Da vidimo sta se dalje desava sa
registrima EAX i EBX. Oni se dalje medjusobno XORuju i na vrednost EAXa
se dodaje 474F4F44, posle cega se EAX poredi sa 53544F50. Dakle ponovo
imamo jednacinu:
(Deo_seriskog_1 XOR Deo_seriskog_2) + 474F4F44 = 53544F50
odnosno
53544F50 - 474F4F44 = Deo_seriskog_1 XOR Deo_seriskog_2
C05000C = Deo_seriskog_1 XOR Deo_seriskog_2
Ali sta dalje? Sada imamo dva nepoznata dela seriskog broja! To stvarno
nema veze u ovom slucaju posto se ni jedan deo ne poredi direktno, vec se
samo poredi rezultat jednacine od gore. Posto se seriski broj proverava
na ovaj nacin postoji prakticno neogranicen broj seriskih brojeva. Ne
zavisno od svega ovoga mi mozemo da predpostavimo da je Deo_seriskog_1 =
11111111 i onda imamo sledecu jednacinu:
C05000C = 11111111 XOR Deo_seriskog_2, odnosno
Deo_seriskog_2 = C05000C XOR 11111111.
Deo_seriskog_2 = 1D14111D.
Tako da je nas seriski broj jednak Deo_seriskog_1 + '-' +
Deo_seriskog_2. I konacno jedan o mnogo tacnih seriskih brojeva je
11111111-1D14111D. Ostavljam vama da pronadjete jos par tacnih seriskih
brojeva za ovaj level.
--[ 0x05 ]---------------------------------------------[ Fishing #3 ]
Videli smo da ni drugi level nije bio velika prepreka za nas, a sta se
to nalazi u Levelu 3 ostaje nam da vidimo. Bez neke velike mudrosti
pronalazimo rutinu koja se koristi za proveru levela 3, i postavljamo
break-point na adresu 0040137E posle cega mozemo da unesemo lazne podatke
u nasu metu. Unecemo ap0x kao ime i 111111 kao seriski broj. Posle klika
na dugme Register dolazimo do naseg break-pointa. Sada mozemo da
tracujemo dalje kroz kod sve dok ne dodjemo do ovde:
00401393 E8 28010000 CALL <JMP.&USER32.GetDlgItemInt>
Kao sto znamo GetDlgItemTextA vraca sadrzaj nekog EditBoxa kao string, a
sta onda radi GetDlgItemInt? Mozete konsultovati dokumentaciju ili mozete
jednostavno pogledati kod ispod i bice vam jasno da ova funkcija takodje
cita EditBox ali umesto stringa vraca vrednost u brojevnom obliku.
Tracejuci dalje stizemo do koda:
004013A8 E8 19010000 CALL <JMP.&USER32.GetWindowTextA>
koji cita ime koje smo uneli u metu. Posto je kod za proveru seriskog
broja blizu zakljucujemo da sledeci loop racuna tacan seriski broj na
osnovu unetog imena:
004013BB /8D0C9B /LEA ECX,DWORD PTR DS:[EBX+EBX*4]
004013BE |8D0C4B |LEA ECX,DWORD PTR DS:[EBX+ECX*2]
004013C1 |0FBE16 |MOVSX EDX,BYTE PTR DS:[ESI]
004013C4 |83C1 21 |ADD ECX,21
004013C7 |0FAFD1 |IMUL EDX,ECX
004013CA |03FA |ADD EDI,EDX
004013CC |43 |INC EBX
004013CD |46 |INC ESI
004013CE |3BD8 |CMP EBX,EAX
004013D0 \7C E9 \JL SHORT Crackme1.004013BB
Sam algoritam za generisanje seriskog broja i nije toliko bitan posto
cemo mi samo pronaci tacan seriski broj za nase (moje) ime. Dakle mozemo
slobodno da postavimo break-point odmah ispod ovog loopa. Postavicemo
break-point na sledecu komandu:
004013D2 3B7D FC CMP EDI,DWORD PTR SS:[EBP-4]
Ovo radimo iz razloga sto se odmah ispod ove komande nalazi JNZ skok od
kojeg zavisi da li ce se prikazati poruka o tacnom, odnosno netacnom
seriskom broju. Iz ovog razloga cemo pogledati sta se to nalazi u
registru EDI, ali i na adresi EBP-4. Ono sto vidimo u registrima je:
EAX 00000004
ECX 00000042
EDX 00000C60
EBX 00000004
ESP 0012FAEC
EBP 0012FB1C
ESI 0012FAFB
EDI 0000351C <- Vrednost koja se poredi
Dok na stacku (EBP-4) imamo sledece podatke:
Stack SS:[0012FB18]=0001B207 <- Vrednost sa kojom se EDI poredi
EDI=0000351C
Posto znamo da je decimalno 111111 jednako 1B207h zakljucujemo da se na
adresi EBP-4 nalazi nas uneti seriski broj, sto ujedno znaci da se u
registru EDI nalazi tacan seriski broj! Ali da je to bas tako? Nije, 351C
nije tacan seriski broj za ime ap0x iz razloga sto se porede
hexadecimalne vrednosti unetog i izracunatog seriskog broja! Dakle posto
je 111111 pretvoreno u hexadecimalno i 351C mora biti pretvoreno nazad u
decimalno kako bi uneti seriski broj bio ispravan! Ovo znaci da je tacan
seriski broj za ime ap0x ustvari 13596, sto mozemo i proveriti njegovim
unosenjem u metu. I to bi bilo to sto se tice ove mete, ostao nam je jos
samo Level 4, ali iz razloga sto je njegovo resanje isto kao i resavanje
Levela 3, to ostavljam vama da sami resite.
--[ 0x06 ]---------------------------------------------[ Outro & Greetz ]
Uz pomoc malo mozga i naseg voljenog [h]Olly-ja je kao sto smo videli,
izuzetno lako :)
Greetz:
SeekNDestroy | TSRh | EMiNENCE | CoolPHat | ELUSIVE
b4d_s3c70r | B0r0 | loco | Kostolomac | Virus Krew | Jezgra | BlackHat
--[ EOF ]----------------------------------------------[ made by Ap0x ]