Copy Link
Add to Bookmark
Report

6x06 PeLock 1.06 Picking

eZine's profile picture
Published in 
phearless
 · 14 Jan 2024

               [ PeLock 1.06 picking by ap0x ] 

pH#6 .............F.u.l.l..R.e.v.e.r.s.e............. [ #Sadrzaj ]
0x01 ................................................ [ Intro ]
0x02 ................................................ [ Lock picking ]
0x03 ................................................ [ Contact ]
0x04 ................................................ [ Outro & Greetz ]


--[ 0x01 ]---------------------------------------------[ .Intro ]

Dobro dosli u novo izdanje pH eZina, ovaj put samo za vas kuvamo PeLock
1.06, odnosno otpakujemo aplikaciju zasticenu njime. To znaci da cemo
pokusati i uspeti da povratimo importe i ukradeni OEP. Ostanite sa mnom
jer sledi dosta RCE poslatica iz Reversing Labs kuhinje...

Da bi smo skuvali ovaj unpackme, trebace nam neki kulinarski alati:

[+] OllyDBG v.1.10 .................................. http://www.wasm.ru
[+] OllyInisible v.x ................................ http://www.wasm.ru
[+] OllyScript v.0.92 ............................... http://www.wasm.ru
[+] LordPE v.1.4 .................................... http://www.wasm.ru
[+] ImpRec v.1.6 .................................... http://www.wasm.ru
[+] PeID v0.94 ...................................... http://www.wasm.ru
[+] PELock 1.0x ImpRec plugin ....................... stize uz pH eZine
[+] PeLock 1.06 CRR ................................. stize uz pH eZine
[+] PeLock 1.06 IAT redirection Remover Script ...... stize uz pH eZine

i naravno glavni sastojci naseg glavnog jela za danas:

[+] PeLock 1.06 DEMO ............................. crackme.pelock106.exe
[+] PeLock 1.06 FULL ............................ crackme.pelock106r.exe

--[ 0x02 ]---------------------------------------------[ Lock picking ]

-#DEMO VERSION#----------------------------------------------------------

Otvoricemo metu pomocu OllyDBGa, i na OEPu cemo videti sledeci kod:

00407150 > $ /EB 01 JMP SHORT crackme_.00407153
00407152 |B8 DB B8
00407153 > \F2: PREFIX REPNE:
00407154 . 0FB6C9 MOVZX ECX,CL
00407157 . EB 01 JMP SHORT crackme_.0040715A
00407159 2A DB 2A
0040715A > E8 01000000 CALL crackme_.00407160

Posle klika na SHIFT+F9 pojavice se NAG o trial verziji protektora
(ogranicenje se ne odnosi na zastitu vec samo na NAG poruku), a kada NAG
zatvorimo klikom na OK nacicemo se ovde:

003412F7 F7F1 DIV ECX
003412F9 C3 RET
003412FA C7 ???
003412FB EB 02 JMP SHORT 003412FF
!!Virtualno alocirani kod ce imati druge adrese na vasem racunaru!!

Nastavicemo da pritiskamo SHIFT+F9 sve dok ne dodjemo do sledeceg koda:

00344986 8900 MOV DWORD PTR DS:[EAX],EAX <- Here!
00344988 EB 03 JMP SHORT 0034498D
0034498A DBE3 FINIT
0034498C 61 POPAD
0034498D EB 02 JMP SHORT 00344991
0034498F CD 20 INT 20
00344991 EB 02 JMP SHORT 00344995

Ako ovde pritisnemo SHIFT+F9 jos jednom meta ce se startovati. Iz ovog
razloga cemo pogledati STACK i videcemo sledece:

0012FFB0 /0012FFB8 Pointer to next SEH record
0012FFB4 |003446D4 SE handler <- SEH

Selektovacemo SEH i desnim klikom cemo izabrati Follow in Disassembler
sto ce nas u CPU prozoru dovesti ovde:

003446D4 E8 01000000 CALL 003446DA
003446D9 5D POP EBP
003446DA 8D6424 04 LEA ESP,DWORD PTR SS:[ESP+4]

Tu cemo postaviti breakpoint posle cega cemo se klikom na SHIFT+F9 naci
bas tu. Posto se nalazimo na na virtualno alociranoj memoriji svi
memoriski breakpointi se moraju primenjivati na nju a ne na poslednju
sekciju PE fajla. Ovo mozemo i proveriti ako probamo da izvrsimo metu sa
postavljenim memoriskim breakpointima na glavnoj .CODE i poslednjoj
sekciji. Meta ce zastati na adresi 004012E3 koja predstavlja OEP, odnosno
prvu instrukciju koja se izvrsava posle izvrsavanja ukradenog dela OEPa.
Ali kako da nadjemo ukradene bajtove sa OEPa?
Ono sto uvek mozemo da uradimo je trace pomocu Ollyjevih funkcija trace
into i trace over. Jedina negativna strana ovoga je to sto trace dugo
traje. Zbog ovoga cemo mi od adrese 003446D4 drzati F7 sve dok ne dodjemo
u ntdll.dll. Ovo se desava zbog vracanja SEHa.
Posto smo sigurni da ce se izvrsavanje programa vratiti negde u opsegu
alocirane memorije 00340000 postavicemo na taj memoriski opseg memoriski
breakpoint on access. Kada ponovo pritisnemo SHIFT+F9 nacicemo se ovde:

00344988 /EB 03 JMP SHORT 0034498D
0034498A |DBE3 FINIT
0034498C |61 POPAD
0034498D \EB 02 JMP SHORT 00344991
0034498F CD 20 INT 20
00344991 EB 02 JMP SHORT 00344995

Traceovanjem sa F7 docicemo do ovde:

00344A5D 8816 MOV BYTE PTR DS:[ESI],DL
00344A5F F9 STC
00344A60 72 01 JB SHORT 00344A63
00344A62 91 XCHG EAX,ECX

Ovaj kod predstavlja dekripciju koda koji nas ceka ispod a koji se ovde
dekriptuje. Adresa od koje pocinje dekripcija se nalazi u ESI registru.
Traceovanjem sa F7 dolazimo do sledeceg koda:

00344A98 0FBFC7 MOVSX EAX,DI
00344A9B ^ 0F85 58FFFFFF JNZ 003449F9
00344AA1 EB 01 JMP SHORT 00344AA4

koji je kraj ovog loopa za dekripciju. Iz ovog razloga mozemo da
postavimo breakpoint na JMP skok na adresi 00344AA1 i da pritisnemo F9.
Odavde ostaje da traceujemo sa F7 sve ne dodjemo do adrese 004012E3.
Kada se to desi traceovacemo u nazad koriscenjem opciji "-" na vasem
NumPadu. Iduci u nazad sledece instrukcije su se izvrsile pre skoka na
OEP:

00344E74 C3 RET <- Adrese u nazad
00344E60 C1F4 00 SAL ESP,0 <- Nulte instrukcije
00344E51 C1F2 00 SAL EDX,0 <- Ne menjaju registre
00344E4C 68 E3124000 PUSH 4012E3 <- Adresa laznog OEPa

Kao sto vidimo na adresi 00344E4C na STACK se smesta adresa laznog OEPa.
Ovo znaci da se sigurno pre ovog PUSHa izvrsio ukradeni OEP. Iz tog
razloga cemo klikom na "-" traziti instrukcije koje nisu nulte, odnosno
one koje uticu na izvrsavanje koda. Pa tako imamo:

00344E04 57 PUSH EDI
00344DE1 56 PUSH ESI
00344DBA 53 PUSH EBX
00344D94 83EC 58 SUB ESP,58
00344D68 64:8925 0000000> MOV DWORD PTR FS:[0],ESP
00344D44 50 PUSH EAX
00344D1A 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
00344CF0 68 F41D4000 PUSH 401DF4 ; Entry address
00344CC8 68 F8404000 PUSH 4040F8
00344CA1 6A FF PUSH -1
00344C7B 8BEC MOV EBP,ESP
00344C57 55 PUSH EBP

Iza ovoga nema validnih instrukcija veci niz bajtova. Zbog ovoga a i
zbog cinjenice da se PUSH EBP nalazi kao prva instrukcija u VC++ i Delphi
OEPima zakljucujemo da je prvi ukradeni bajt PUSH EBP. Ove bajtove cemo
zalepiti na mesto ukradenog OEPa. Ali gde tacno?
Ako pogledamo adresu 004012E3 i skrolujemo malo na gore videcemo
sledece:

004012BF 90 NOP
004012C0 74 DB 74
004012C1 3A DB 3A
004012C2 9D DB 9D
004012C3 4E DB 4E
004012C4 A7 DB A7
004012C5 53 DB 53
004012C6 29 DB 29
004012C7 > 94 XCHG EAX,ESP
004012C8 . CA E572 RETF 72E5
004012CB . B9 5C2E170B MOV ECX,0B172E5C
004012D0 . 05 020180C0 ADD EAX,C0800102
004012D5 .^ E0 F0 LOOPDNE SHORT crackme_.004012C7
004012D7 . F8 CLC
004012D8 . 7C 3E JL SHORT crackme_.00401318
004012DA . 9F LAHF
004012DB . 4F DEC EDI
004012DC . 27 DAA
004012DD . 93 XCHG EAX,EBX
004012DE . 49 DEC ECX
004012DF . 24 12 AND AL,12
004012E1 . 89C4 MOV ESP,EAX
004012E3 . 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP

iz cega se jasno vidi da OEP pocinje na adresi 004012C0. Od te adrese
pocinjemo ubacivanje ukradenih instrukcija tako da kad sa tim zavrsimo
OEP izgleda ovako:

004012C0 55 PUSH EBP <- Vraceni OEP
004012C1 8BEC MOV EBP,ESP
004012C3 6A FF PUSH -1
004012C5 68 F8404000 PUSH crackme_.004040F8
004012CA 68 F41D4000 PUSH crackme_.00401DF4 ; Entry address
004012CF 64:A1 0000000> MOV EAX,DWORD PTR FS:[0]
004012D5 50 PUSH EAX
004012D6 64:8925 00000> MOV DWORD PTR FS:[0],ESP
004012DD 83EC 58 SUB ESP,58
004012E0 53 PUSH EBX
004012E1 56 PUSH ESI
004012E2 57 PUSH EDI <- Vraceni OEP
004012E3 . 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP

Kada zavrsimo ovo mozemo da uradimo dump pomocu LordPEa. Importe cemo
probati da popravimo ImpReca. Posle klika na Get Imports dobicemo niz
invalidnih importa, Trace Level 1 nece vratiti sve tako da cemo morati da
ili da rucno popravljamo importe ili da napisemo plugin za ImpRec.
Da bi smo napisali plugin potrebno je da poznajemo nacin redirekcije
APIja, a to bi bili svi moguci tipovi redirekcije.

003F0019 68 2B2E837C PUSH kernel32.LCMapStringA
003F001E EB 02 JMP SHORT 003F0022
003F0020 CD 20 INT 20
003F0022 C3 RET
...
003F004F /EB 02 JMP SHORT 003F0053
003F0051 |CD 20 INT 20
003F0053 \68 B4010000 PUSH 1B4
003F0058 EB 01 JMP SHORT 003F005B
003F005B 68 B87B917C PUSH 7C917BB8
003F0060 - E9 A279527C JMP ntdll.7C917A07
...
003F033B /EB 02 JMP SHORT 003F033F
003F033D |CD 20 INT 20
003F033F 68 62DBD477 PUSH user32.PostMessageA
003F0344 EB 01 JMP SHORT 003F0347 <- Ili EB02
003F0347 C3 RET

Prvi i najlaksi je jednostavan PUSH adrese na kojoj se nalazi API i on
moze najlakse biti popravljen. Drugi tip je komplikovaniji jer on "krade"
instukcije iz .dll fajla i nastavlja izvrsavanje posle izvrsavanja
ukradenih instrukcija. Nesto kao ukradeni OEP. Da bi smo popravili drugi
tip redirekcije potrebno je da saberemo duzine svih validnih instrukcija
ignorisuci sve 0xEB skokove. Krajnja intrukcija je LONG JUMP koja
redirektuje izvrsenje pravo na API. Kada od adrese na koju vodi JUMP
oduzmemo duzinu svih validnih instrukcija dobijamo pravu adresu APIja.
Ovo zato i nije najlaksi plugin koji postoji za ImpRec ali ga je moguce
napraviti. To sam i uradio i ovaj plugin mozete preuzeti sa mog web
sajta a nalazi se i u ovom eZinu.
Ali ono sto je zanimljvo za ovu zastitu je ono sto sam slucajno otkrio
posle kodiranja ovog plugina je to da on nije ni potreban. Da, importi se
lako mogu popraviti pomocu obicnog Level 1 tracea. Kako?
Startujte metu normalno, ne preko debuggera, i na nju nakacite ImpRec.
Unesite 0x00001000 kao OEP, klik na Get Imports posle cega ce se pojaviti
invalidni importi. Sada slobodno izaberite Trace Level 1 i videcete da
cete popraviti sve invalidne importe. Da, ocigledno je da nema potrebe za
pisanjem plugina, zar ne?

-#FULL VERSION#----------------------------------------------------------

Iako smo vec videli DEMO verziju ovog protectora i iako smo utvrdili da
nivo zastite koji ona pruza nije zadovoljavajuci, pogledacemo sta puna
verzija nudi.
Pocecemo od otvaranja mete crackme.peLock106r.exe iz foldera Target na
cijem cemo OEPu videti sledeci kod:

0040705C > $ F3: PREFIX REP:
0040705D . C1E0 17 SHL EAX,17
00407060 . F3: PREFIX REP:
00407061 . 0FB6C9 MOVZX ECX,CL
00407064 . EB 02 JMP SHORT crackme_.00407068

Pritiskacemo SHIFT+F9 sve dok ne dodjemo do ovde:

00336744 8900 MOV DWORD PTR DS:[EAX],EAX

Ovo je poslednji exception sto znaci da ako sada postavimo memoriski
breakpoint na .code sekciju i ponovo pritisnemo SHIFT+F9, nacicemo se na
laznom OEPu. Kazem laznom zato sto i ovaj put nedostaju ukradeni OEP
bajtovi. Ovaj put necu objasnjavati kako se popravlja ukradeni OEP posto
je to objasnjeno u DEMO verziji a posto je nacin popravke isti, posto je
u pitanju ista meta samo cemo "zalepiti” stare OEP bajtove na istu
adresu.
Ono sto donosi registrovana verzija PeLocka je novi nacin API
redirekcije sa jednim jako zanimljivim trikom. Pogledajmo kako izgleda
prvi API CALL koji u slucaju VC++ aplikacije uvek vodi ka GetVersion
APIju:

004012E6 > \FF15 58404000 CALL NEAR DWORD PTR DS:[404058]
...
00350556 /EB 02 JMP SHORT 0035055A
00350558 |0C 49 OR AL,49
0035055A \64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
00350560 EB 02 JMP SHORT 00350564
00350562 CD 20 INT 20
00350564 8B48 30 MOV ECX,DWORD PTR DS:[EAX+30]
00350567 EB 01 JMP SHORT 0035056A
0035056A 8B81 B0000000 MOV EAX,DWORD PTR DS:[ECX+B0]
00350570 C1F0 00 SAL EAX,0
00350573 0FB791 AC000000 MOVZX EDX,WORD PTR DS:[ECX+AC]
0035057A EB 02 JMP SHORT 0035057E
0035057C 0C 49 OR AL,49
0035057E 83F0 FE XOR EAX,FFFFFFFE
00350581 EB 02 JMP SHORT 00350585
0035056A 8B81 B0000000 MOV EAX,DWORD PTR DS:[ECX+B0]
00350570 C1F0 00 SAL EAX,0
00350573 0FB791 AC000000 MOVZX EDX,WORD PTR DS:[ECX+AC]
0035057A EB 02 JMP SHORT 0035057E
0035057C 0C 49 OR AL,49
0035057E 83F0 FE XOR EAX,FFFFFFFE
00350581 EB 02 JMP SHORT 00350585
00350583 CD 20 INT 20
00350585 C1E0 0E SHL EAX,0E
00350588 EB 02 JMP SHORT 0035058C
0035058A 0C 49 OR AL,49
0035058C 0BC2 OR EAX,EDX
0035058E EB 02 JMP SHORT 00350592
00350590 0C 49 OR AL,49
00350592 C1E0 08 SHL EAX,8
00350595 EB 02 JMP SHORT 00350599
00350597 0C 49 OR AL,49
00350599 0B81 A8000000 OR EAX,DWORD PTR DS:[ECX+A8]
0035059F EB 02 JMP SHORT 003505A3
003505A1 CD 20 INT 20
003505A3 C1E0 08 SHL EAX,8
003505A6 68 B0053500 PUSH 3505B0
003505AB EB 01 JMP SHORT 003505AE
003505AE C3 RET
...
003505B0 0B81 A4000000 OR EAX,DWORD PTR DS:[ECX+A4]
003505B6 EB 02 JMP SHORT 003505BA
003505B8 CD 20 INT 20
003505BA C3 RET

Prilicno velika redirekcija... Ali ovo je samo jedan primer iz kojeg se
vidi da PeLock krade dobar deo (ponekad i sve) instrukcija iz API poziva
zbog cega se popravka IATa mora zasnivati na poredjenju koje zahteva
identifikaciju ispravnih bajtova i njihovom daljem pronalazenju na osnovu
poredjenja tih bajtova sa svakim bajtom svakog APIja odredjenog .dll
fajla. Prilicno standardan nacin zastite ali ono sto me je impresioniralo
je to sto je u FULL verziji programa ubaceno mnogo PUSH/RET kombinacija
unutar svake redirekcije tako da neki PUSHevi pokazuju na RET instrukcije
koje se nalaze unutar APIja, pretpostavljam da je ovo neka vrsta
antiTrace tehnike. Sve ovo je zahtevalo pisanje novog plugina koji ce
zaobici sve ovo. Takav plugin je napravljen i mozete preuzeti sa mog web
sajta.
Sledeca novina je antiDump tehnika koja podrazumeva uklanjanje dela koda
iz .code sekcije i njegovo smestanje u kod protectora. Ovo znaci da ce
sav kod biti izmesten tako da ako uradimo dump odredjeni deo koda ce
nedostajati. Primer ukradenog koda izgleda upravo ovako:

0040103B .- E9 D8EFF7FF JMP 00380018 ;Ukradeno
00401040 . 55 PUSH EBP
00401041 .- E9 DDEFF7FF JMP 00380023 ;Ukradeno
00401046 00 DB 00 ;
00401047 .- E9 E3EFF7FF JMP 0038002F ;Ukradeno
0040104C 00 DB 00 ;

Kao sto se vidi na ovom primeru ukradeni kod je duzine 5 ili 6 bajta
koliko iznosi i duzine JMPa i CALLa. Ali nisu to jedine instrukcije koje
se "kradu”, zasticene su i MOV i neke CMP instrukcije. Smisao zastite je
u menjanju duzine intrukcije. Odnosno ako je ukradena instrukcija od 5
ili 6 (osim u slucaju CALL/PUSHa) bajta ona ce biti zamenja sa JMP
instrukcijom, a JMP ce pokazivati na instrukciju koja je ista kao ona
"ukradena" samo sto je duza za odredjenu kolicinu bajtova. Pa tako MOV
ESI,0040568C postaje:

003802FD 8D35 1C346B3B LEA ESI,DWORD PTR DS:[3B6B341C]
00380303 8DB6 59E0F9D2 LEA ESI,DWORD PTR DS:[ESI+D2F9E059]
00380309 8DB6 B2C0F3A5 LEA ESI,DWORD PTR DS:[ESI+A5F3C0B2]
0038030F 8DB6 6581E74B LEA ESI,DWORD PTR DS:[ESI+4BE78165]

Za uklanjanje ovog tipa antiDump tehnike mozete da iskoristite moj
PeLock 1.06 CRR alat koji uklanja PeLock antiDump redirekciju.

-#INLINE IAT FIXING#-----------------------------------------------------

Vec smo videli da se API redirekcija moze popraviti preko ImpRec
plugina, ali da li je to mozemo da uradimo i bez njega?
Pocecemo od otvaranja mete crackme.peLock106r.exe iz foldera Cas10 kao i
prosli put. Posto svaka zastita bez obriza na to koju vrstu redirekcije
koristi mora da pozove LoadLibrary kako bi ucitala potrebne .dll fajlove
uvek mozemo da postavimo breakpoint na ovaj API i nadjemo se blizu koda
za pravljenje redirekcije. Breakpoint je najbolje postaviti na kraj ovog
APIa, odnosno na RET 4 instrukciju. Kada ovo uradimo pritisnucemo F9 i
odmah cemo se zaustaviti na nasem breakpointu. Ali ovo nije mesto koje
trazimo iz razloga sto .dll koji se ucitava je kernel32.dll i posto je
ovo prvi CALL ka LoadLibrary APIju ovo je sigurno handle koji je potreban
zastiti kako bi pozvala neke APIje iz kernel32.dll-a koji nemaju veze sa
IATom. Pritiskajmo SHIFT+F9 sve dok ponovo ne dodjemo do istog
breakpointa. Kada se to desi pritisnimo F2 da uklonimo breakpoint i F8
kako bi smo se vratili u kod PeLocka. Sada se nalazimo ovde:

003341C4 E8 01000000 CALL 003341CA
003341C9 A7 CMPS DWORD PTR DS:[ESI],DWORD PTR ES:[EDI]
003341CA 8D6424 04 LEA ESP,DWORD PTR SS:[ESP+4]
003341CE C1F4 00 SAL ESP,0

Ako se podsetimo videcemo da se na adresi 00404000 nalazio prvi API
pointer. Zato cemo sada postaviti hardwareski breakpoint na tu adresu i
sacekacemo da PeLock zapise API redirekciju na tu adresu. Kada pritisnemo
SHIFT+F9 nacicemo se ovde:

00334661 8919 MOV DWORD PTR DS:[ECX],EBX
00334663 EB 03 JMP SHORT 00334668

a sadrzaj registara ce biti:

EAX 77E7AD86 kernel32.GetModuleHandleA
ECX 00404000 crackme_.00404000
EDX 77E60000 kernel32.77E60000
EBX 00350000

Kao sto vidimo EBX sadrzi adresu redirekcije a EAX sadrzi adresu APIja na
koji vodi redirekcija. Ovo znaci da ako izmenimo MOV DWORD PTR[ECX],EBX u
MOV DWORD PTR[ECX],EAX sve redirekcije ce biti izmenjene na prave API
pointere? Pa ne... Iako je nasa pretpostavka tacna PeLock koristi sistem
racunanja CRCa na delu memorije koji se koristi za ucitavanje i
zapisivanje API redirekcije. Iz tog razloga pri svakom prolazu moramo da
izmenimo instrukciju da zapisuje pravi API pointer iz EAXa i da kada se
ovo izvrsi instrukciju vratimo na staro stanje. Posto je ovo vema zamoran
posao ja sam napisao Olly skriptu kako bi ovaj posao bio olaksan i
automatizovan. Ova skripta se moze preuzeti sa mog web sajta.

--[ 0x03 ]---------------------------------------------[ .Contact ]

WebSite: http://ap0x.jezgra.net
email: ap0x.rce[at]gmail[dot][com]

--[ 0x04 ]---------------------------------------------[ Outro & Greetz ]

Kuvanje ovog protectora i nije bilo nekakav problem, zar ne :)

Greetz:

deroko | SND | TSRh | Reversing Labs | b4d_s3c70r | Jezgra

--[ EOF ]----------------------------------------------[ made by ap0x ]

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT