TeMaT : Jak rozpakowac lub rozszyfrowac dosowe exe pliki. NARZEDZIA : The SUPER TRACER Version 2.50 (http://www.netease.com/~ayliutt)
Jak zapewne kazdy sie zorientowal, wiele dosowych plików exe spakowanych jest przez tzw.exe pakery. Przykladami takich pakerów sa PKLite, Diet, WWPack itp. Podobnie duzo plików exe blokowanych jest roznego rodzaju szyfratorami, blokerami z sztuczkami anty-debug.
Co z takimi plikami poczac, jezeli chcemy je modyfikowac. Ano pasuje je rozpakowac lub zdeszyfrowac. Sa do tego specjalne programiki rozpakowujace dany exe-paker badz tez uniwersalne rozpakowujace co sie tylko da. Jednak nalezy pamietac, ze rozpakowuja one z reguly tylko znane im pakery. Przy nowych wersjach po prostu wymiekaja. Co wtedy mozemy zrobic. Ano pasuje zabrac sie za reczne rozpakowywanie za pomoca debuggera.
Kazdy jak przypuszczam z czasem przyzwyczaja sie do swojego ulubionego debuggera i na nim wykonuje wiekszosc czynnosci. Chcialbym jednak polecic wszystkim bardzo dobry debugger pewnego faceta ze wschodu LiuTaoTao. Program ten nazywa sie The SUPER TRACER i obecna jego wersja to 2.50. Umownie przyjmijmy nazywac ten debugger TR. A co w nim takiego ciekawego, a no posiada bardzo dobre funkcje umozliwiajace zapisywanie programów z pamieci do plików i konstruowanie z nich plików wykonalnych.
Najpierw pasowaloby sie zapoznac z owym debuggerem. Mysle jednak, ze kazdy kto mial do czynienia z innym np. SoftICE itp nie bedzie mial z nim zadnego problemu. Nie bede go opisywal bo nie jest to naszym celem a potrzebne funkcje debuggera wyjasnie w ponizszym tekscie.
Aby zabrac sie za rozpakowywanie plików com i exe nalezy zrozumiec na czym polega caly proces i jaki problem jest z plikami exe.
Otóz pliki com, sa prostymi plikami uruchomieniowymi o max. dlugosci 64kb. Pliki com ladowane sa do pamieci i traktowane przez nia jako jeden ciagly blok pamieci. Sprowadza sie to do tego ze w pamieci jest po prostu obraz pliku com bez jakichkolwiek modyfikacji. Taki przypadek umozliwia nam skopiowanie pliku z pamieci (np. po rozpakowaniu w pamieci) i przeniesieniu go do pliku na dysku. Inaczej sie maja pliki exe, które posiadaja inna strukture i moga posiadac teoretycznie dowolne rozmiary. Powoduje to jednak, ze w pamieci umieszczane sa one w odpowiednich blokach i przy kazdym zaladowaniu do pamieci adresy poszczególnych fragmentów kodu moga byc inne.
Skopiowanie obraz pliku exe z pamieci na dysk nie jest jego poprawnym odpowiednikiem, co wynika wlasnie z natury plików exe. W celu poprawnego skonstruowania pliku exe z pamieci wymagane jest powtórne jego skopiowanie z innych lokacji pamieci i dopiero porównanie obu zrzutów pozwoli nam znalezc tzw. relokacje potrzebne do skonstruowania poprawnego pliku exe.
Na poczatek za przyklad posluzy nam maly pliczek pk150.exe zawarty w tym tutorze. Znalazlem go gdzies w sieci i dokladnie sie do tego nadaje. Jest on spakowany exe-pakerem PKLite v1.50.
Ladujemy pliczek do debuggera czyli --> tr pk150.exe
Pojawia sie nam ekran na którym mamy trzy glówne sekcje, u góry jest stan poszczególnych rejestrów, po srodku mamy kod aktualnie sledzonego programu natomiast na dole mamy linie komend. Kod jaki nam sie pojawi to :
PUSH AX ;2978:0100 50
MOV AX,01B9 ;2978:0101 B8B901
MOV DX,000B ;2978:0104 BA0B00
ADD AX,2988 ;2978:0107 058829
CMP AX,[0002] ;2978:010A 3B060200
JB 013A ;2978:010E 722A
MOV AH,09 ;2978:0110 B409
MOV DX,011C ;2978:0112 BA1C01
INT 21 ;2978:0115 CD21
MOV AX,4C01 ;2978:0117 B8014C
..................
..................
PUSH CX ;2978:0140 51
SUB AX,0019 ;2978:0141 2D1900 ---> AX = 2B08
MOV ES,AX ;2978:0144 8EC0 adres rozpakowywanej proc.
PUSH AX ;2978:0146 50
MOV CX,00C5 ;2978:0147 B9C500
XOR DI,DI ;2978:014A 33FF
PUSH DI ;2978:014C 57
MOV SI,0154 ;2978:014D BE5401
CLD ;2978:0150 FC
REPZ ;2978:0151 F3
MOVSW ;2978:0152 A5
RETF ;2978:0153 CB
Widzimy, ze nasz CS:IP czyli entry point wynosi 2978:0100. Nie jest to teraz wazne ale pózniej sie przyda gdy bedziemy musieli skopiowac program z innych lokacji. Interesuje nas na razie pierwszy fragment kodu az do instrukcji powrotu RETF. Kod ten jak dobrze mysle powoduje rozpakowanie glównego kodu algorytmu dekompresji Pklite w jakies miejsce w pamieci. Nie bedziemy tu analizowac algorytmów Pklite bo nie jest to naszym celem.
Interesuje nas dostanie sie do momentu powrotu (RETF). TR posiada instrukcje sledzenia programu az do momentu powrotu, jest to 'pret' a wiec wpisujemy pret i program nam sie wykona i kursor zatrzyma na linijce kodu pret. Jestesmy ciekawi co dalej program robi, naciskamy sledzenie jednej instrukcji czyli F8 lub wpisujemy 't' (trace) i oto mamy :
STD ;2B08:0000 FD
MOV BX,DS ;2B08:0001 8CDB
PUSH BX ;2B08:0003 53
ADD BX,2E ;2B08:0004 83C32E
NOP ;2B08:0007 90
ADD BX,DX ;2B08:0008 03DA
MOV BP,CS ;2B08:000A 8CCD
MOV AX,DX ;2B08:000C 8BC2
AND AH,0F ;2B08:000E 80E40F
MOV CL,04 ;2B08:0011 B104
MOV SI,DX ;2B08:0013 8BF2
SHL SI,CL ;2B08:0015 D3E6
...................
...................
XOR BX,BX ;2B08:0155 33DB
MOV CX,BX ;2B08:0157 8BCB
MOV DX,BX ;2B08:0159 8BD3
MOV BP,BX ;2B08:015B 8BEB
MOV SI,BX ;2B08:015D 8BF3
MOV DI,BX ;2B08:015F 8BFB
RETF ;2B08:0161 CB
Powyzszy algorytm pklite dekompresuje pod pewne adresy pamieci glówny program, do którego chcemy sie dorwac. Sledzenie tego kodu moze byc troche meczace bo jest tam wiele petli, ale predzej czy pózniej dojdziemy do konca algorytmu i instrukcji powrotu RETF.
Jezeli nie chcecie analizowac algorytmu krok po kroku to dajemy pret i TR ustawi kursor na instrukcji powrotu RETF. Not idziemy dalej czyli t i wchodzimy do naszego glównego juz rozpakowanego programu :
PUSH AX ;2988:0000 50
PUSH BX ;2988:0001 53
MOV AX,DS ;2988:0002 8CD8
MOV BX,CS ;2988:0004 8CCB
SUB BX,10 ;2988:0006 83EB10
CMP AX,BX ;2988:0009 3BC3
JNE 0016 ;2988:000B 7509
MOV AX,2988 ;2988:000D B88829
MOV DS,AX ;2988:0010 8ED8
INC [BYTE 00A7] ;2988:0012 FE06A700
MOV AX,2988 ;2988:0016 B88829
MOV DS,AX ;2988:0019 8ED8
POP BX ;2988:001B 5B
POP AX ;2988:001C 58
Czyli w 2988:0000 jest poczatek naszego glównego programu. Skoro doszlismy juz do tego momentu bez zadnych klopotów (nie bylo nic anty-debug -:)) to powinno nam sie juz wszystko udac. Musimy zapamietac jak doszlismy do poczatku naszego rozpakowanego glównego kodu, czyli ze robilismy dwa razy wykonanie do powrotu 'pret' i pózniej sledzenie jednej linijki 't'.
Ok. Mozemy zaczac wszystko od nowa. Najlepiej wyjsc z debuggera 'q' i zaladowac ponownie program do niego.
TR posiada komendy ulatwiajace nam a wrecz umozliwiajace zapisanie plików z pamieci na dysk.
Najpierw musimy przygotowac program w pierwszych lokacjach (jak pamietamy beda nam potrzebne dwie rozne lokacje). Robimy to za pomoca komendy EXE1 która przygotowuje pamiec na 1 exe a nastepnie komenda RELOAD która przeladowuje program do tej lokacji.
Nastepnie sledzimy program za do momentu gdzie zaczyna sie zdekompresowany kod, który chcemy zapisac na dysku. Gdy znajdziemy sie w pierwszej linijce tego kodu to wykonujemy zapisanie pliku z pamieci na dysk za pomoca komendy WEXE1 czyli po prostu write exe1. Jak wszystko poszlo dobrze program napisze nam ok.
Czyli wykonalismy :
EXE1 RELOAD pret pret t WEXE1
Teraz jak pamietamy musimy umiescic program w innych lokacjach pamiec i ponownie go zapisac na dysk. Pozwólmy aby program uruchomil sie do konca czyli 'g'.
Nastepnie deklarujemy przydzielenie nowych adresów pamieci dla pliku czyli dajemy EXE2 a pózniej RELOAD. Jezeli uwaznie przygladniemy sie np. segmentowi kodu CS, to okaze sie, ze jest on inny niz poprzednio i oto nam wlasnie chodzilo. Dalej wykonujemy juz tak samo jak przedtem.
Czyli po kolei:
EXE2 RELOAD pret pret t WEXE2
I jestesmy juz po robocie. Mamy dwa obrazy rozpakowanego kodu programu z roznych lokacji pamieci. Mozemy teraz spokojnie wyjsc z TR czyli 'q'.
Podczas tej pracy na dysku utworzyly nam sie dwa pliki : mem1.dat i mem2.dat. Oczywiscie wiemy skad one sie wziely. Teraz uruchamiamy programik mkexe.exe, który z tych dwóch plików utworzy nam mem.exe, a który jest juz naszym poprawnym rozpakowanym plikiem pk150.exe. Wystarczy podgladnac oba pliki pk150.exe i mem.exe zeby zobaczyc, ze rozpakowywanie nam sie udalo.
Mysle, ze kazdy kto przerobil powyzszy tekst zalapie o co chodzi i bedzie potrafil rozpakowac takze programy spakowane innymi pakerami np. WWPack, LZexe itp. Wszystkie te pakery dzialaja na podobnej zasadzie wiec nie powinno byc problemu. Nalezy jednak pamietac, ze najnowsze wersje szyfratorow maja pulapki wykrywajace TR i wtedy nalezy dokladnie analizowac kod programu i w razie czego go zmodyfikowac.
P.S. WAZNE!!!, przed kazdym nowym rozpakowywaniem usunmy z katalogu stare pliki mem1.dat i mem2.dat bo inaczej nowe zostana dopisane do starych.
Autor przygotowal dla nas takze automatyzacje powyzszego procesu. Jezeli dojdziemy do momentu naszego rozpakowanego kodu wystarczy napisac getknl [count] gdzie count oznacza ile TR shell'i ma wykonac i wykonuje automatycznie nastepujace instrukcje :
exe1 reload goknl count wexe1 exe2 reload goknl count wexe2 q
a pózniej wystarczy uruchomic mkexe.exe i mamy rozpakowany plik.
Czasami okazuje sie, ze pliki exe sa nie tylko spakowane exe-pakerem ale jeszcze na dodatek zaszyfrowane jakims szyfratorem lub protektorem aby uniemozliwic ich rozpakowanie. Zasada dzialania protektorów jest w zasadzie podobna do dzialania kompresorów, tyle ze glownie nastawione one sa nie na kompresje a na funkcje anty-debug i anty-unpack. Program chroniacy dopisuje swój kod na koncu pliku, ewentualnie jeszcze szyfruje glówny program a entry point ustawiony jest na wlasnie te funkcje dolaczonego protektora. Idea usuniecia takiego protektora bedzie wiec polegac na przejsciu funkcji protektora i znalezieniu oryginalnego programu i jego zapisowi z pamieci na dysk.
Posluzymy sie przykladem pliku zawartego w tutorze - wwpack.exe. Pliczek, który poprzednio rozpakowywalismy spakowalem pakerem WWPack 3.04a Enh a nastepnie zablokowalem protektorem Secure 0.19 Piotra Warezaka (jednego z autorów WWPack). Autor TR, kody takich protektorów i pakerow dzialajacych w danym pliku okresla shell'ami. Przygotowal nam tez, jak juz wczesniej wspomnialem komendy ulatwiajace usuwanie takich zabezpieczen.
Jedna z takich komend jest getknl, która wyjasnialem powyzej. Powoduje ona automatyczne uruchamianie pliku i zapisu jego obrazu na dysku z pominieciem danej ilosci shell'i. Mozna ten proces zrobic recznie analizujac kod ale akurat w naszym przypadku automatyczna komenda dziala bardzo dobrze.
A wiec ladujemy tr wwpack.exe i mamy :
CALL 0143 ;2D88:000F E83101
CMP CX,DX ;2D88:0012 39D1
SUB [BYTE DI+0031],82 ;2D88:0014 826D3182
XCHG AX,DX ;2D88:0018 92
OR [WORD DI+8248],6A ;2D88:0019 838D48826A
INC DI ;2D88:001E 47
STOSB ;2D88:001F AA
XCHG AX,SI ;2D88:0020 96
ADC [WORD SI+BP+6596],8F6B ;2D88:0021 819296656B8F
dajemy teraz getknl a program automatycznie zrobi caly proces, a pózniej tylko mkexe i mamy plik mem.exe w którym pominiety zostal kod protektora Secure. Glebsza analiza powstalego pliku pokaze, ze jednak kod nie zostal usuniety a jedynie pominiety, co jednak nie wplywa nasza prace.
Kopiujemy plik mem.exe na wwpack.exe i ponownie ladujemy do Tr. Teraz bedziemy musieli usunac kompresora WWPack. Mozna spróbowac ponownie automatycznie za pomoca komend getknl itp. Zróbmy jednak (tak dla wprawy) to recznie. Po wgraniu programu mamy taki oto fragment kodu :
MOV AX,0024 ;2CFE:0001 B82400
MOV DX,CS ;2CFE:0004 8CCA
ADD DX,AX ;2CFE:0006 03D0
MOV CX,CS ;2CFE:0008 8CC9
ADD CX,0087 ;2CFE:000A 81C18700
PUSH CX ;2CFE:000E 51
......................
REPZ ;2CFE:0031 F3
MOVSW ;2CFE:0032 A5
DEC AX ;2CFE:0033 48
JNS 0024 ;2CFE:0034 79EE
MOV DS,BP ;2CFE:0036 8EDD
PUSH CS ;2CFE:0038 0E
POP ES ;2CFE:0039 07
XOR DI,DI ;2CFE:003A 33FF
MOV SI,0008 ;2CFE:003C BE0800
RETF ;2CFE:003F CB
Tak jak poprzednio, pomijamy analize kodu, i przechodzimy do miejsca powrotu funkcji RETF. Czyli dajemy pret. Nastepnie znajdujemy sie w nowym fragmencie kodu, który rozpakowywuje nasz glówny program do pamieci. Poniewaz program wywoluje kilka funkcji a zatem tez kilka powrotów z funkcji RETF po chwilowej analizie znajdziemy koncowy RETF. Bedzie on w adresie CS:017D. Proponuje wiec od razu g 17d co powoduje wykonanie programu do linii cs:17d. Mamy tam funkcje powrotu a wiec jedna linijke F8 i jestesmy znów w nowym fragmencie kodu. Nie jest to jeszcze nasz glówny program wiec znów dajemy pret i wreszcie znajdujemy:
PUSH AX ;2988:0000 50
PUSH BX ;2988:0001 53
MOV AX,DS ;2988:0002 8CD8
MOV BX,CS ;2988:0004 8CCB
SUB BX,10 ;2988:0006 83EB10
CMP AX,BX ;2988:0009 3BC3
JNE 0016 ;2988:000B 7509
MOV AX,2988 ;2988:000D B88829
MOV DS,AX ;2988:0010 8ED8
INC [BYTE 00A7] ;2988:0012 FE06A700
MOV AX,2988 ;2988:0016 B88829
MOV DS,AX ;2988:0019 8ED8
POP BX ;2988:001B 5B
POP AX ;2988:001C 58
Teraz wiedzac juz gdzie zaczyna sie nasz glówny kod wystarczy wykonac opisywana juz procedure zrzutów obrazu programu do pliku.
A wiec :
EXE1 RELOAD pret g 17d t pret WEXE1
a pózniej
EXE2 RELOAD g 17d t pret WEXE2
Teraz wychodzimy z TR i tylko mkexe i mamy rozpakowany wwpack.exe w pliku mem.exe. Po dluzszej zabawie TR z plikami spakowanymi innymi pakerami lub protektorami okazuje sie ze prawie wszystko mozna takim sposobem rozpakowac. Nalezy tylko umiejetnie znajdywac odpowiednie fragmenty kodu i w razie potrzeby usuwac zbedne (np. wywalajace debugerra itp).
GustawKit [CrackPl]