EXE PACKERY FAQ

v0.3 - 1o.o2.2ooo

(polskie znaki w windows CP-1250)


Wstępniak

Wersja i historia tego faq
Podziękowania
Kontakty z autorami tekstów

Podstawowe informacje

Co to jest ten exe packer - smola
Różnica między packerem a crypterem - smola
Jak dziala taki program - smola
Jak rozpoznać czy i czym program jest spakowany - smola

Metody odzyskiwania oryginalnego pliku exe

Metoda standardowa - smola
Procdump
Zrzucanie zawartości procesu z pamięci do pliku exe - smola (niepełny)
Procdump i Bhrama server - smola
SoftIce i DumpIce - smola
TRW2000
Odbudowa tabeli importów w plikach PE - TiTi/BLiZZARD (tłum. smola)

Rozpakowywanie przykładowych programów

Skrypty w Procdumpie na przykładzie UPX v.84 - smola
Jak rozpakowywać pliki for newbies - bEANUS^CookieCrK
Jak rozpakować programy spakowane nieznanymi exe-packerami pod Win - GustawKit
Usunięcie ProcDumpem pakietu Vbox4 z Ulead COOL 3D v2.0 - GustawKit
Komercyjne zabezpieczenie softSENTRY Release 2.008 - GustawKit
Jak debugować i rozpakować Crunch v1.0 - GustawKit

Budowa pliku exe

Nagłówek PE - smola (niepełny)
Nagłówek sekcji
Tabela importów

Dodatkowe informacje

Słownik pojęć
Lista przydatnych tekstów - smola
Linki do stron


Wstępniak


Ze względu na dość duże zainteresowanie zagadnieniami związanymi z plikami exe, ich pakowaniem, rozpakowywaniem i budową a także tym że od dłuższego już czasu zajmuję się prawie wyłącznie tym tematem, postanowiłem coś o tym wszystkim napisać. Mam nadzieję że to pomoże chociaż kilku osobom poznać głębiej ten temat i zachęci do własnych eksperymentów. Chciałbym również aby ten tutorial przeistoczył się w coś w rodzaju FAQ a mianowicie każdy kto czuje się na siłach i posiada jakąś wiedzę w tym temacie dołożył do niego swoje 3 grosze. Sądzę, że dzięki istnieniu kilku grup crackerskich w Polsce a co za tym idzie wielu specjalistów ten tutorial stanie się prawdziwą skarbnicą wiedzy. Więc jeśli już napisałeś coś na ten temat, chcesz przetłumaczyć jakiś tekst albo rozpakowałeś już jakiegoś progsa, to skontaktuj się ze mną (smola@pcplus.com.pl) a ja z pewnością umieszczę Twój tekst wraz z Twoją ksywką. Tekst nie musi być formatowany, mile widziane polskie znaki, najlepiej w windows (notatnik rulez! :). Prawdopodobnie od następnej wersji będzie on wydawany w formie pliku html więc będzie prościej coś znaleść i oczywiście będzie go można umieścić na swojej stronie www.
smola


Wersja i historia tego faq

Najnowsza wersja tego faq będzie zawsze dostępna na www.crackpl.site.pl i www.smola.prv.pl.


Podziękowania


Kontakty z autorami tekstów


Podstawowe informacje


Co to jest ten exe packer

Najprościej jest to program mający za zadanie ukryć dane w wykonywalnym pliku exe przed oczami niepowołanych osób, np. przed crackerami, a przez to utrudnić zminę jego zawartości, jak również zmniejszenie objętości zajmowanej przez plik na dysku (nie zawsze). Generalnie exepackery dzielą się na dwie podstawowe grupy:

Najczęściej jednak spotyka się pakery które zawierają w sobie zarówno procedury pakujące oraz szyfrujące. W zasadzie to i packer jest swojego rodzaju crypterem bo kod wyjściowy programu jest totalną "kaszanką" i nie przypomina normalnego kodu programu.

Wypadałoby teraz wyjaśnić dlaczego używam nazwy packer dla obu tych rodzajów. Otóż w potocznym języku zwykło się tak mówić na wszelkie programy modyfikujące plik wykonywalny. Dla dokładniejszego określenia można oczywiście użyć słowa crypter ale zazwyczaj wystarczy powiedzieć że progs jest spakowany jakimś exepackerem. Warto jeszcze dodać, że dla większości pakerów istnieją ich przeciwne odpowiedniki zwane depakerami (zwanymi również depacker, unpacker, decruncher), czyli programy przywracające zawartość spakowanych programów do ich pierwotnych wersji.
smola


Różnica między packerem a crypterem

W zasadzie to po wyciągnięciu wniosków z poprzedniego tekstu można się tego domyślić. :) Otóż program spakowany packerem jest zawsze krótszy niż przed spakowaniem. To chyba oczywiste. Natomiast w przypadku cryptera plik wyjściowy jest dłuższy niż oryginalny (np. PE-Pack), oczywiście jeśli program nie jest dodatkowo skompresowany.
smola


Jak działa taki program

Ogólna zasada działania exepackerow jest podobna do działania loadera czy nawet wirusa :), tzn. najpierw jest uruchamiana procedura rozpakowująca która to odtwarza strukturę execa sprzed kompresji i kiedy taki exec jest już odtworzony następuje skok do oryginalnego EP (entry point - to taki punkt startowy od którego zaczyna się wykonywać program). Nasze zadanie polega na znalezieniu właśnie tego miejsca i wykonaniu zrzutu zawartości pamięci tego odbudowanego execa. Nie zawsze jest to proste, często taki packer zwiera procedury antydebug, zbędny kod utrudniający śledzenie jak również może zamazywać cześć nieistotnych już danych w kodzie execa a to się wiąże z tym że po zrobieniu zrzutu pamięci taki exec po prostu nie będzie działał. Jedynym wyjściem jest tylko analiza krok po kroku procedury rozpakowującej execa pod debuggerem.
smola


Jak rozpoznać czy i czym program jest spakowany

Oto kilka zasad które nas upewniają że program jest spakowany (kolejność od najbardziej wiarygodnego):

  1. W oglądanym kodzie programu pod hex edytorem występują sygnatury packerów i/lub dziwne nazwy sekcji (typowe to .code, .text, .data, .rdata, .rsrc itp.).
  2. Próba wczytania programu pod wdasm go zawiesza.
  3. Tabela importów (import table) w kodzie programu zawiera tylko kilka funkcji jak np. GetProcAddress, LoadLibrary, GlobalAlloc, ExitProcess.
  4. Ogólnie zawartość execa nie przypomina standardu gdzie wydaje się być sporo wolnego miejsca wypełnionego zerami.
  5. EP (entry point) jest ustawiony na inną wartość niż 401000. Jak zauważył massh^CookieCrK, ten punkt jest najmniej prawdopodobny ze względu na to, że jeśli jakiś program korzysta z jakiś procedur zawartych w includach, to są one wkompilowywane zawsze na początku. Wtedy EntryPoint jest przesuwany dalej i wlaściwie to cieżko jest teraz znaleźć jakiś komercyjny program, którego EP wynosiłoby 401000 (dzięki stary!).

Generalnie dobrym zwyczajem przed debugowaniem każdego proga jest obejrzenie jego kodu pod jakimś hex edytorem i ew. Procdumpem. Najczęściej na podstawie powyższych testów można już określić rodzaj użytego exepackera i podjąć stosowne kroki celem rozpakowania. Nieocenionym programem tutaj jest oczywiście Procdump. Jeśli jednak wciąż nie wiemy czym spakowany jest dany progs to możemy jeszcze użyć jakiegoś analizatora. Jest to specjalny program który rozpoznaje kilkadziesiąt rodzajów formatów plików. Wartym użycia jest np. FileInfo. Jego obecna wersja to 2.12 z dnia 31/01/2000. Jeśli i to nie pomaga to niestety pozostaje tylko jego prześledzenie pod debuggerem krok po kroku. Niezastąpionymi są wtedy TRW2000 albo SoftIce + DumpIce.
smola


Metody odzyskiwania oryginalnego pliku exe


Metoda standardowa

Stosunkowo najprościej i najszybciej jest rozpakować jakiś program używając depakera napisanego tylko do konkretnego pakera. Czyli np. do programu spakowanego aspack'iem najlepiej użyć unaspack. Zazwyczaj depakery mają taką samą nazwę jak paker z tym że zawierają przedrostek 'Un' bądź 'De'. Niestety wciąż są wypuszczane coraz to nowsze wersje programów pakujących które są niekompatybilne w dół (tzn. że depaker napisany do wersji np. 1.30 najczęściej nie działa z wersją 1.31) w wyniku czego jesteśmy zmuszeni do użycia innych metod dekompresji. Mimo wszystko jest to i tak najlepszy sposób rozpakowywania, ponieważ w 99% przypadków rozpakowany program wygląda tak samo jak przed kompresją.
smola


Procdump

 


Zrzucanie zawartości procesu z pamięci do pliku exe

Termin ten zwany również ProcessDump polega na przeniesieniu procesu z pamięci komputera do wykonywalnego pliku exe. W zasadzie można to zrobić na dwa sposoby: albo przez FullDump albo przez PartialDump. Pierwszy z nich polega na zrzuceniu zawartości procesu w jednym całym kawałku czyli wszystkie sekcje programu znajdują się w tych miejscach na które wskazują ich RVA. Mankamentem tego rozwiązania jest to że taki plik może zajmować bardzo dużo miejsca na dysku i dlatego jest też druga metoda znana pod nazwą PartialDump, czyli zrzut procesu (a w zasadzie jego poszczególnych sekcji) z pamięci po kawałku. Ten sposób pozwala na znaczne oszczędności miejsca na dysku jednak zmusza nas do późniejszego ręcznego "posklejania" tych wszystkich sekcji. Jakiego by jednak sposobu nie użyć, to i tak czeka nas ręczna odbudowa takiego pliku. Przede wszystkim chodzi tutaj o sekcję importów, czyli miejsce w pliku PE gdzie znajdują się nazwy wszystkich funkcji z jakich korzysta program. W uproszczeniu problem leży w tym iż w miejscach gdzie powinny być wskaźniki (pointer) na stringi z nazwami funkcji są rzeczywiste adresy tych funkcji. Dokładny opis tego zagadnienia wraz ze sposobem naprawy znajduje się w Odbudowa tabeli importów w plikach PE.

(to jeszcze nie koniec)

smola


Procdump i Bhrama server

Do czego właściwie służy ta opcja Bhrama Server?

Dzięki uaktywnieniu Bhrama Server możemy zdalnie sterować ProcDumpem czy to poprzez pluginy (m.in. do vbox, securom czy petit) czy SoftIce (z zainstalowanym DumpIce). Generalnie chodzi o to aby przejść prockę depakujacą exepackera, zatrzymać dalsze wykonywanie procesu i przekazać sterowanie do Procdumpa który to pięknie nam zrzuca pamięć procesu i zapisuje na dysk gotowego execa. Bhrama jest właśnie takim łącznikiem.

Komunikacja z Bhrama polega na samodzielnym rozpakowaniu programu ew. ominięciu procedur antydebug, zamrożeniu śledzonego procesu (suspend) i umieszczeniu jego identyfikatora PID (process ID) oraz dodatkowych opcji rozpakowania (szczególowe info w pliku bhrama.txt dołączonym do Procdumpa) w odpowiednim miejscu struktury BhramaComStruc, znalezieniu uchwytu okna 'ProcDump32 - Dumper Server' a następnie wysłaniu tego wszystkiego funkcją SendMessage i zakończenia własnego procesu.

SendMessage uchwyt_okna_Bhrama_Server,WM_COPYDATA,0,offset DataServices

W zależności od potrzeby Bhrama oferuje 2 rodzaje usługi: Full Dump (wszystkim zajmie się Procdump) albo Partial Dump. W tym drugim przypadku musimy sami określić początek i długość obszaru pamięci do zrzucenia. Po wysłaniu komunikatu WM_COPYDATA Procdump automatycznie odwali za nas całą "czarną robotę" i zapisze gotowego exeka do pliku. Więcej szczegółów można znaleść w dokumentacji Procdumpa jak również poprzez analizę źródeł pluginów.
smola


SoftIce i DumpIce

SoftIce jak już pewinie wiesz jest debuggerem, czyli programem mogącym śledzić wykonywanie się innego programu krok po kroku. Natomiast DumpIce jest swoistego rodzaju nakładką na SI, dodającą jemu wiele nowych możliwości. Obecnie DumpIce jest w wersji 6.11 (26/01/2000) i pozwala nam nawet na słuchanie swoich ulubionych mp3 w trakcie debugowania... :) Ale to nie jest jego najważniejszą cechą. Otóż po zainstalowaniu go umożliwia nam bezproblemowe zrzucenie zawartości pamięci bezpośrednio z SI do pliku, jak równeż może się komunikować przez Bhrama serwer z Procdumpem. A co to oznacza to chyba nie muszę mówić. Wystarczy że uruchomimy Procdumpa i uaktywnimy Bhrama Serwer, następnie przejdziemy w SI przez procedure depakującą exepackera, ustawimy sie na oryginalnym EP (entry point) i wpiszemy komendę:

PAGEIN B ProcDump32 - Dumper Server

a Procdump nam pięknie zrzuci proces do pliku exe. Działa bezbłędnie. Jeśli masz jakieś kłopoty z działaniem tej komendy to dopisz sobie do winice.dat następującą linijkę:

F3=" PAGEIN B ProcDump32 - Dumper Server; "

Po przeładowaniu systemu naciśnięcie klawisza F3 powoduje zapisanie gotowego exeka na dysk (oczywiście Bhrama Server musi być aktywny).
smola


TRW2000

 


Odbudowa tabeli importów w plikach PE

Tekst napisany 18.07.99 przez TiTi/BLiZZARD
Dość swobodnie przetłumaczony 3.02.00 (rev. 01) przez smola/crackpl

1. Komu to jest przydatne?

Cześć wszystkim! Napisałem ten tekst, ponieważ w czasie kiedy pracowałem nad programem typu process dumper (program który zrzuca zawartość uruchomionego procesu do pliku exe) testowałem wiele pakerów/enkrypterów które czyniły tablicę importów nieużyteczną i zrzucone pliki exe wymagały odbudowywania tej tablicy. Szukając w wielu miejscach w sieci informacji na ten temat nie znalazłem nic konkretnego, więc jeśli się tym interesujesz, to masz przed sobą tego małego helpa.

Dla przykładu program spakowany Petite v2.1 po zrzuceniu z pamięci do pliku wymaga odbudowania tabeli importów (a dokładniej jej skorygowania) aby plik exe uruchamiał się poprawnie. Podobnie jest w przypadku programów spakowanych aspack'iem, pepack'iem, pesentry itp. To właśnie dlatego funkcje odbudowy tabeli importów są niezbędne w każdym programie zrzucającym proces do pliku. Np. Phoenix Engine napisany przez G-RoM/UCF użyty w ProcDump'ie albo PERebuilder napisany przez Virogen/PC i mnie.

Temat ten jest bardzo specyficzny i dość skomplikowany, dlatego zakładam że znasz już strukturę plików exe. Jeśli nie, to powinieneś zapoznać się z jakąś dokumentacją na ten temat (na końcu pliku zamieściłem spis użytecznych tekstów - smola).

2. Wstępny komentarz.

Najpierw parę słów o tabeli importów oraz RVA/VA (uwaga, autor w oryginale używa zamiennie słów offset i adres - smola).

Względny adres tabeli importów (ang. import table relative virtual address - RVA) jest zapisany w odpowiednim miejscu w nagłówku pliku PE. Miejsce to nazywa się directory entry a jego offset można wyliczyć następująco: offset nagłówka PE + 80h. Adres ten nie odpowiada offsetowi tabeli importów w pliku (z wyjątkiem sytuacji kiedy plik został zrzucony z pamięci), więc pierwszą rzeczą jaką trzeba zrobić jest znalezienie tabeli importów w pliku PE i przeliczenie RVA na odpowiedni adres wirtualny VA (virtual address). Jest kilka sposobów aby to osiągnąć. Można napisać własną procedurę "mielącą" (parser) nagłówki sekcji (sections directory) i wyliczającą poprawny adres wirtualny VA ale łatwiej jest to zrobić poprzez użycie funkcji API która została specjalnie do tego celu stworzona. Funkcją tą jest zawarta w bibliotece IMAGEHLP.DLL (biblioteka używana przez Windows 9x oraz Windows NT) i nazywa się ImageRvaToVa. Poniżej jej opis (pełny jej opis jest zawarty w msdn library):

# LPVOID ImageRvaToVa(
#  IN PIMAGE_NT_HEADERS NtHeaders,
#  IN LPVOID Base,
#  IN DWORD Rva,
#  IN OUT PIMAGE_SECTION_HEADER *LastRvaSection
#);
#
#Parametry :
# NtHeaders 
#   Wskaźnik do struktury IMAGE_NT_HEADERS. Tą strukturę
#   można uzyskać poprzez wywołanie funkcji ImageNtHeader.
# Base
#   Określa adres bazowy obrazu pliku który jest mapowany
#   wewnątrz pamięci poprzez wywołanie funkcji MapViewOfFile.
# Rva
#   Określa gdzie ma położyć RVA.
# LastRvaSection
#   Wskaźnik do struktury IMAGE_SECTION_HEADER która
#   opisuje ostatnią sekcję RVA. Parametr opcjonalny.
#   Jeśli podany, wskazuje na zmienną która zawiera
#   wartość ostatniej sekcji użytej do określenia
#   obrazu pliku do przeliczenia RVA na VA. 

Jak widać jest bardzo prosta w użyciu... :) Po prostu musisz mieć mapę swojego pliku PE w pamięci i wtedy wywołujesz tą funkcję aby otrzymać poprawny VA do tabeli importów.
Zauważ, że powyżej pominąłem wszystkie znaczniki RVA/VA, ale nie zapomnij o przeliczeniu jednego na drugi kiedy będziesz odczytywać lub zapisywać RVA z/do pliku PE podczas jego odbudowy.

3. Pełne objaśnienie.

Poniżej jest pełny opis odbudowania zmienionej tabeli importów w pliku PE skompresowanego przez petite v2.1 (plik został zrzucony bezpośrednio z pamięci).

00 są reprezentowane przez spację ' '
inne znaki są reprezentowane przez '-'
0000C1E8h : 00 00 00 00 00 00 00 00 00 00 00 00 BA C2 00 00              ----
0000C1F8h : 38 C2 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ----            
0000C208h : C5 C2 00 00 44 C2 00 00 00 00 00 00 00 00 00 00  --------        
0000C218h : 00 00 00 00 D2 C2 00 00 54 C2 00 00 00 00 00 00      --------    
0000C228h : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                  
0000C238h : 7F 89 E7 77 4C BC E8 77 00 00 00 00 E6 9F F1 77  --------    ----
0000C248h : 1A 38 F1 77 10 40 F1 77 00 00 00 00 4F 1E D8 77  --------    ----
0000C258h : 00 00 00 00 00 00 4D 65 73 73 61 67 65 42 6F 78        MessageBox
0000C268h : 41 00 00 00 77 73 70 72 69 6E 74 66 41 00 00 00  A   wsprintfA   
0000C278h : 45 78 69 74 50 72 6F 63 65 73 73 00 00 00 4C 6F  ExitProcess   Lo
0000C288h : 61 64 4C 69 62 72 61 72 79 41 00 00 00 00 47 65  adLibraryA    Ge
0000C298h : 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 00  tProcAddress    
0000C2A8h : 47 65 74 4F 70 65 6E 46 69 6C 65 4E 61 6D 65 41  GetOpenFileNameA
0000C2B8h : 00 00 55 53 45 52 33 32 2E 64 6C 6C 00 4B 45 52    USER32.dll_KER
0000C2C8h : 4E 45 4C 33 32 2E 64 6C 6C 00 63 6F 6D 64 6C 67  NEL32.dll_comdlg
0000C2D8h : 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00 00 00  32.dll          

Jak widać tabela importów podzielona jest na trzy główne części:

   IMAGE_IMPORT_DESCRIPTOR struct
      OriginalFirstThunk  	dd 0  ;RVA do original unbound IAT
      TimeDateStamp		dd 0  ;tutaj nie używany
      ForwarderChain		dd 0  ;tutaj nie używany
      Name			dd 0  ;RVA do stringu z nazwą biblioteki DLL
      FirstThunk		dd 0  ;RVA do tablicy IAT
   IMAGE_IMPORT_DESCRIPTOR ends

Małe wyjaśnienie nt. tabeli importów

OriginalFirstThunk jest tablicą IAT (import address table - IAT) którą PE loader poszukuje w pierwszej kolejności. Jeśli występuje, to wtedy PE loader używa jej do skorygowania ewentualnych problemów w tablicy FirstThunk IAT. Jednorazowo wczytuje do pamięci każdy DWORD z tablicy FirstThunk zawierający RVA do stringu z nazwa funkcji i podmienia go z RVA na prawdziwy adres funkcji (ta lokacja w pamięci nie może być używana kiedy wywoływana jest ta funkcja). Więc najprościej: to nie jest problem z tablicą importów, bo jest ona odpowiednio wypełniana a OriginalFirstThunk zostaje niezmieniony.

I tutaj dochodzimy do naszego problemu

Po tym krótkim wyjaśnieniu dochodzimy do sedna problemu. Otóż jeśli spróbujesz teraz uruchomić taki plik exe zawierający tabelę pokazaną powyżej, nie zostanie on wczytany a windows wyświetli komunikat o błędzie. Dlaczego? Ano dlatego, że tablica OriginalFirstThunk została usunięta.

Zapamiętaj to, że dla każdej struktury IMAGE_IMPORT_DESCRIPTOR w tej tabeli importów OriginalFirstThunk zawiera wartość 00000000h. Hm, domyślamy się, że kiedy plik exe jest uruchamiany to PE loader próbuje wziąć nazwy importowanych funkcji z tablicy FirstThunk, ale jak sobie przypominasz, ta tablica nie zawiera RVA do stringów z nazwami funkcji, tylko RVA do adresów funkcji w pamięci.

Co mamy do zrobienia

To co teraz powinniśmy uczynić aby otrzymać działający plik exe, to odbudowa zawartości tablicy FirstThunk poprzez wstawienie do niej wartości wskazujących na stringi z nazwami funkcji które widzieliśmy w trzeciej części tabeli importów. Wbrew pozorom nie jest to trudne zadanie, ale potrzebujemy wiedzieć który IAT odpowiada danej funkcji jako że stringi z nazwami funkcji nie są poukładane w ten sam sposób jak członkowie FirstThunk.

No więc dla każdego IAT potrzebujemy zidentyfikować nazwę funkcji która jemu odpowiada. W tej chwili mamy już nazwy bibliotek DLL, ponieważ mamy IMAGE_IMPORT_DESCRIPTOR. Wskaźniki DWORD do ich nazw nie zostały oczywiście zmienione.

W jaki sposób zidentyfikować każdą funkcję

Jak już wspomniałem wcześniej, każdy uszkodzony IAT jest RVA do adresu funkcji w pamięci. Te adresy w trakcie trwania sesji, czyli dopóki nie zrestartujesz kompa, nie zmieniają się na inne, więc możemy porównać je z adresami funkcji na które wskazuje uszkodzony IAT i ustawić na nim wskaźnik (pointer) do stringów z nazwami funkcji.

Aby to zrobić skorzystamy z bardzo użytecznej funkcji API z biblioteki Kernel32.dll która nosi nazwę GetProcAddress. Zwraca nam ona adres zadanej funkcji. Poniżej jej opis:

GetProcAddress(
    HMODULE	hModule,	// uchwyt (handle) do biblioteki DLL
    LPCSTR	lpProcName 	// nazwa funkcji
);
    HMODULE GetModuleHandle(
        LPCTSTR  lpModuleName 	// adres nazwy modułu dla którego zwrócony zostanie uchwyt
    );

Więc aby naprawić uszkodzony IAT, musimy sprawdzić wszystkie nazwy funkcji występujące w trzeciej części tabeli importów dopóki GetProcAddress nie zwróci nam adresu szukanej funkcji.

Wiedz, że czasem funkcja jest importowana poprzez liczbę (ordinal number). Te numery są słowami (WORDS) i wyliczać je należy następująco: offset nazwa_funkcji - 2. Tak więc Twoja procedura "mieląca" powinna sprawdzać jak dana funkcja jest importowana; czy przez nazwę czy przez numer.

Poniżej przykład rekonstrukcji tabeli importów

Spróbuje wyjaśnić w jaki sposób należy naprawić pierwszą importowaną funkcję z pierwszej importowanej biblioteki DLL na podstawie powyższego opisu tabeli importów.

  1. Szukamy pierwszej tablicy struktury IMAGE_IMPORT_DESCRIPTOR (C1E8h), i pobieramy z niej nazwę biblioteki DLL, wskazywaną przez członka .Name (C1E4h, który wskazuje na C1BAh). Widzimy że jest to USER32.dll.
  2. Patrzymy na członka struktury .FirstThunk, który wskazuje na tablice IAT; każdy jeden odpowiada jednej importowanej funkcji z tej biblioteki DLL (user32.dll). W tym przypadku jest to C1F8h, który wskazuje na C238h. Więc pod C238h mamy nasz uszkodzony IAT który oczywiście musimy naprawić (możesz zapamiętać że ta tablica IAT zawiera 2 długie słowa (DWORD), więc 2 funkcje są importowane z tego DLL'a.
  3. Teraz bierzemy pierwszy uszkodzony IAT. Jego wartość to 77E7897Fh. To jest właśnie adres jakiejś funkcji leżącej w pamięci.
  4. Dla każdej nazwy funkcji z trzeciej części tabeli importów musimy wywołać funkcję API GetProcAddress. Kiedy funkcja ta zwróci nam właśnie wartość 77E7897Fh, odnaleźliśmy właściwą funkcję. Teraz ustawiamy uszkodzony IAT tak żeby wskazywał na nazwę poprawnej (w tym przypadku jest to 'wsprintfA').
  5. Teraz musimy zmienić IAT aby wskazywał na offset (string nazwa_funkcji) -2. Dlaczego -2? Ponieważ czasami jest używane normalne sortowanie funkcji. W tym przypadku zamieniamy zawartość adresu C238h tak aby wskazywał na C26Ah (zamiast 77E7897Fh).
  6. To wszystko, teraz funkcja jest naprawiona i trzeba tylko powtórzyć te zabiegi dla pozostałych IAT.

Nota końcowa

Opisałem ogólny sposób postępowania. Oczywiście działa on tylko na DLL'e które są aktualnie wczytane do pamięci. Dla pozostałych musisz je najpierw wczytać lub przekształcić ich tablice eksportów aby znaleźć poprawne adresy funkcji.

To chyba tyle. Komentarze, raporty o jakości itp. miłe rzeczy mile widziane... :)
smola


Rozpakowywanie przykładowych programów


Skrypty w Procdumpie na przykładzie UPX v.84

Mam pewien drobny problemik z niemiecką wersją winrara 2.6. Polską i angielską skraczyłem ale ta nie wiem czemu jest spakowana UPX'em i niestety nie mogę jej rozpakować procdumpem. Chciałem zastosować si loadera i jakoś dojść do właściwego entrypoint'a ale loader nie zatrzymuje się na nim więc uruchomiłem pe-editor i niestety nie wiem co dalej bo tam zamiast zwykłych .code, .data itp. jest UPX0 i UPX1. Jak mam się za to zabrać?

Aby rozpakować takiego UPX należy posiadać Procdumpa 1.5 (obecna wersja to 1.6.2), jakiś hex edytor np. Hex Workshop i oczywiście Notepada... :) Pierwszym krokiem który należy uczynić jest użycie standardowego skryptu UPX z Procdumpa. Niestety w moim przypadku on nie działał a kilka prób jego modyfikacji również nie przyniosło żadnych rezultatów. No to zabrałem się za samego execa. I tu właśnie jest ta sytuacja o której piszesz z niemożnością użycia loadera z si. Ale my już wiemy co trzeba zrobić z tym fantem (vide wcześniejsze problemy z pająkiem itp. - polecam poczytać archiwum listy crackpl), więc zmieniamy characteristic pierwszej sekcji UPX0 z e0000040 na e0000020.

Gdyby Procdump z jakiś powodów nie mógł wczytać execa (czasami tak mam) to należy użyć jakiegoś hex edytora (np. Hex Workshop lub Hiew). Atrybuty sekcji znajdują się na samym końcu nagłówka sekcji i zaraz przed nazwą następnej sekcji. Pamiętać należy że bajty zapisywane są w notacji intela czyli np. liczba 12345678h jest zapisana jako 78563412h.

Dobra, teraz odpalasz loadera i swój prog i lądujesz w si. Jesteś? :) Ok. Więc teraz przewijasz okienko code aż dochodzisz do miejsca w którym następuje ostatni skok jmp xxxxxxxx. W tym to właśnie miejscu procedura rozpakowująca skacze do rozpakowanego i gotowego już do użycia pliku exe. Zapisujesz ten adres gdzie ma nastąpić skok np. jmp 401000 oraz mnemoniki tego skoku czyli e9 i bajty odpowiadające długości skoku (w si można włączyć ich podgląd komendą code on) i wychodzisz z si oraz zamykasz tego proga. Teraz dla odmiany odpalasz Notepada i edytujesz plik scrip.ini z Procdumpa. Twoja wersja UPX powinna wyglądać tak:

Pxx=UPX 0.84
gdzie xx jest kolejnym numerem skryptu, nazwa może być dowolna.

[UPX 0.84]
L1=OBJR
L2=LOOK E9,xx,xx,xx,xx
L3=BP
L4=EIP
L5=STEP
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001
OPTL4=00030000
OPTL5=00000000
gdzie xx,xx,xx,xx są właśnie tymi bajtami odpowiadającymi długości skoku z jmp, nazwa oczywiście taka sama jak powyżej.

Zapisujesz to wszystko, odpalasz ProcDumpa i rozpakowujesz swojego execa używając tego skryptu. Po rozpakowaniu możesz jeszcze (ale nie musisz) ustawić poprawny entry point bo ten wskazuje na adres jmp xxxxxxxx a nie na sam xxxxxxxx. EP obliczasz odejmując od xxxxxxxx adres bazowy (image base), czyli np. xxxxxxxx to 401000 a image base to 400000, wiec entry point to 1000.
smola


Jak rozpakowywać pliki for newbies

Poniżej sopsób rozpakowania przykładowego programu calc.exe spakowanego aspackiem. Opis na podstawie orginalnego tekstu napisanego przez bEANUS^CookieCrk (unexe_tutorial.txt - 5186 bajtów, do ściągnięcia z http://www.cookiecrk.z.pl/).

Potrzebne narzędzia:

Patchowanie SoftIce'a

Aby SI poprawnie działał trzeba go zpatchować. Służy do tego IceDump v5.17 (jest już 6.11). Więc jedziemy. Po rozpakowaniu IceDump’a wchodzimy do katalogu Patcher i odpalamy plik patcher.bat aby podać wersję, ścieżkę i akcję czyli czy zrobić backup czy odtworzyć już zpatchowany winice.exe. Ja mam wersję 3.25 więc wpisuję:

Patcher 325 c:\soft P

"P" służy do tego aby zrobić backup w pliku winice.id. Ten kto ma SI v4.0 wpisuje zamiast 325 - 400. Natomiast 'c:\soft' to katalog gdzie masz zainstalowanego SI. Proste chyba. :) Ok, po zpatchowaniu winice.exe należy zrestartować system aby móc korzystać z dodatkowych opcji jakie daje DumpIce.

Rozpakowywanie plików

Jedziemy dalej. Uruchamiamy ProcDumpa i opcję Bhrama Server. Teraz proponuje spakować jakiś program aspackiem, np. calc.exe. Włączamy więc ascpacka i robimy kaszankę... Ok, tyko jak to później rozpakować? Już się robi. Należałoby najpierw złapać w SI Entry Point ale to nie jest takie łatwe, bowiem EP jest zmieniony przez aspacka. Ja opisze inny sposób. Każdy program możemy złapać na przerwaniu 3 czyli CCh. I tak też zrobimy. Wchodzimy do Hiew'a ładujemy spakowanego calc.exe i teraz idziemy do Entry Point, czyli zmieniamy wyświetlanie pliku w hexach -> F4 potem F8 i F5 i jesteśmy w Entry Point. Jest tam mnemonik PUSHAD czyli polecenie dla procesora wysyłające wszystkie rejestry na stos. Zamiast niego wpisujemy Int 3. Czyli F3, F2 i Int 3. Zapisujemy zmiany naciskając F9. Teraz przechodzimy do SI gdzie musimy włączyć łapanie programu na przerwanie 3 (jeśli tego nie zrobimy to nasz program wygeneruje wyjątek o błędzie), więc wpisujemy:

i3here on

OK, po tym zabiegu uruchamiamy calc.exe... WOW, program się zatrzymał i mamy jakiegoś tam calla... Tylko że wcześniejszy kod pushad został zmieniony na CCh i coś trzeba z tym zrobić. Jakby tu cofnąć kod? To proste, od EIP trzeba odjąć jeden. Mamy EIP = 00413001h, zmieniamy go na 00413000. Oto kod wskazywany przez EP:

0137:00412FFF FFCC                DEC     ESP
0137:00413001 E800000000          CALL    00413006
0137:00413006 5D                  POP     EBP
0137:00413007 81ED0A4A4400        SUB     EBP,00444A0A
0137:0041300D BB044A4400          MOV     EBX,00444A04
0137:00413012 03DD                ADD     EBX,EBP
0137:00413014 2B9DB1504400        SUB     EBX,[EBP+004450B1]
0137:0041301A 83BDAC50440000      CMP     DWORD PTR [EBP+004450AC],00

Pod adresem 00412FFFh mamy FFCCh. CCh to wiadomo Int 3 i właśnie na to złapał się SI. I teraz aby została wykonana komenda PUSHAD musimy przywrócic orginalny EP (zmiana EIP z 00413001h na 00413000h) i dopisac mnemonik PUSHAD, więc zmieniamy najpierw EIP:

r eip eip-1

Teraz zmieniamy mnemonik Int 3 na PUSHAD:

a eip

Komenda ‘a’ uaktywnia wbudowany w SI prosty kompilator, więc teraz wpisujemy:

pushad [RETURN][ESC]

Ok, jedziemy dalej. Musimy wyjść z calla rozpakowującego kod execa. Naciskamy F10 aż dojdziemy do kodu:

0137:004132F2  0BC9                OR      ECX,ECX
0137:004132F4  741C                JZ      00413312
0137:004132F6  781A                JS      00413312
0137:004132F8  AC                  LODSB
0137:004132F9  3CE8                CMP     AL,E8
0137:004132FB  7408                JZ      00413305
0137:004132FD  3CE9                CMP     AL,E9
0137:004132FF  7404                JZ      00413305
0137:00413301  43                  INC     EBX
0137:00413302  49                  DEC     ECX
0137:00413303  EBED                JMP     004132F2
0137:00413305  291E                SUB     [ESI],EBX
0137:00413307  83C305              ADD     EBX,05
0137:0041330A  83C604              ADD     ESI,04
0137:0041330D  83E905              SUB     ECX,05
0137:00413310  EBE0                JMP     004132F2

Tutaj jest procedurka która ładuje rozpakowane bajty dopóki ECX jest różne od zera. Musimy albo wciskać F10 tyle razy ile jest w ECX albo napisać:

g 00413312

OK, jesteśmy dalej. Teraz już możemy nacisnąć F12 bowiem program został rozpakowany. SI zatrzyma nam się w tym miejscu:

0137:0040534E  64A100000000        MOV     EAX,FS:[00000000]
0137:00405354  55                  PUSH    EBP
0137:00405355  8BEC                MOV     EBP,ESP
0137:00405357  6AFF                PUSH    FF
0137:00405359  6830A64000          PUSH    0040A630
0137:0040535E  686C654000          PUSH    0040656C
0137:00405363  50                  PUSH    EAX
0137:00405364  64892500000000      MOV     FS:[00000000],ESP

I to właśnie tu zaczyna się nasz rozpakowany program! wuuaaalaaaaaaaaa! Teraz czas zrzucić to przez Bhrama Server w Procdumpie, czyli wydajemy komendę:

Pagein B ProcDump32 Dumper – Server

Co oznacza że całość pamięci zostanie przepuszczona przez okienko Bhrama Server a Procdump się grzecznie zapyta o nazwę pliku. I już. Mamy rozpakowanego execa. !!! moje gratulacje !!!

bEANUS^CookieCrK
http://www.cookiecrk.z.pl/
e-mail: cookiecrk@z.pl


Jak rozpakować programy spakowane nieznanymi exe-packerami pod Win

Oryginał tekstu napisany przez Gustawa dostępny pod adresem http://www.crackpl.site.pl/teksty/exepack1.htm (angielska wersja tłumaczenia napisana przez Zomo dostępna pod http://www.crackpl.site.pl/teksty/exepack1.zip).

Kompresja plików exe może sprawić początkującym trochę kłopotów z dobraniem się do programu. Dostaję często pytania na ten temat więc postanowiłem rozpocząć serię tekstów na ten temat. Na początek informacje o których dyskutowaliśmy na liście. Postanowiłem napisać parę rad jak dobrać się do takich plików. Za przykład posłuży nam WinAmp v2.00 i świetny programik ProcDump 1.0 beta. Otóż pewne jest, że każdy plik uruchomieniowy który jest skompresowany, względnie szyfrowany, można zawsze zdekompresować, ponieważ to właśnie się dzieje w pamięci podczas uruchomienia programu. Często program tak skompresowany zawiera sztuczki antydebug a szczególnie anty SoftIce. Problem sztuczek anty na razie pominę bo nie jest on istotny w naszym przykładzie (może opiszę innym razem). Cóż, na początek zawsze należy przyglądnąć się startowemu kodowi programu (tam gdzie skacze 'entry point'). Otóż, dla programów Win32 często taki kod wygląda podobnie i wywołuje kilka standardowych startowych funkcji API. Dla np. Notatnika Win95 przy Entry Point 1000h taki kod wygląda mniej więcej:

014F:00401000  55                  PUSH    EBP                    --> Entry Point
014F:00401001  8BEC                MOV     EBP,ESP
014F:00401003  83EC44              SUB     ESP,44
014F:00401006  56                  PUSH    ESI
014F:00401007  FF1548734000        CALL    [KERNEL32!GetCommandLineA]
014F:0040100D  8BF0                MOV     ESI,EAX
014F:0040100F  8A00                MOV     AL,[EAX]
................ coś tam
014F:0040104C  50                  PUSH    EAX
014F:0040104D  FF1558734000        CALL    [KERNEL32!GetStartupInfoA]
..............., coś tam
014F:00401064  6A00                PUSH    00
014F:00401066  6A00                PUSH    00
014F:00401068  FF155C734000        CALL    [KERNEL32!GetModuleHandleA]
014F:0040106E  50                  PUSH    EAX
014F:0040106F  E87B0E0000          CALL    00401EEF               -->uruchomienie programu
014F:00401074  50                  PUSH    EAX
014F:00401075  8BF0                MOV     ESI,EAX
014F:00401077  FF1554734000        CALL    [KERNEL32!ExitProcess] --> zakończenie programu.

Dla większości programów wygląda to podobnie. Natomiast w przypadku kompresji lub szyfracji programu w miejscu Eentry Point jest z reguły funkcja dekompresująca lub deszyfrująca. Wygląda to tak:

W taki wypadku należałoby znaleźć adres gdzie w pamięci lokowany jest dekompresowany kod i moment skoku do niego. Cóż, nie będę opisywał sposobu jak to szukać bo kod dekompresji jest z reguły krótki i można go prześledzić czy to SoftIce czy innym debuggerem. Przyglądnijmy się w takim razie kodowi startowemu WinAmp 2.0:

:u 4d1000 l f
014F:004D1000  669C                PUSHF
014F:004D1002  60                  PUSHAD
014F:004D1003  E8CA000000          CALL    004D10D2       ---> skok do proc. dekompresji
014F:004D1008  0300                ADD     EAX,[EAX]
014F:004D100A  0400                ADD     AL,00
014F:004D100C  0500060007          ADD     EAX,07000600
:u eip l 8f
014F:004D10D2  58                  POP     EAX
014F:004D10D3  2C08                SUB     AL,08
014F:004D10D5  50                  PUSH    EAX
...coś tam
014F:004D1108  50                  PUSH    EAX
014F:004D1109  800424BF            ADD     BYTE PTR [ESP],BF
014F:004D110D  833A00              CMP     DWORD PTR [EDX],00
014F:004D1110  0F84A7140000        JZ      004D25BD	   ---> zakończenie dekompresji
014F:004D1116  F70200000080        TEST    DWORD PTR [EDX],80000000
014F:004D111C  741B                JZ      004D1139
...itd.
014F:004D25BD  8B6C2418            MOV     EBP,[ESP+18]
014F:004D25C1  8BFD                MOV     EDI,EBP
014F:004D25C3  81EF00004000        SUB     EDI,00400000
014F:004D25C9  85FF                TEST    EDI,EDI
014F:004D25CB  7443                JZ      004D2610         ---> tu jakieś sprawdzenia
...itd.
:u eip l 2f
014F:004D2617  81C62A160000        ADD     ESI,0000162A
014F:004D261D  6A05                PUSH    05
014F:004D261F  59                  POP     ECX
014F:004D2620  F3A4                REPZ MOVSB
014F:004D2622  61                  POPAD
014F:004D2623  669D                POPF
014F:004D2625  E94653F5FF          JMP     00427970          ---> skok do głównego programu
014F:004D262A  E96B69F5FF          JMP     00428F9A

Po czym poznałem, że w tym miejscu jest skok do głównego programu, ano po tym że tam już zaczyna się standardowy kod z wywołaniami funkcji startowych API. Zresztą jak sobie na starcie wyświetlimy zawartość pamięci d cs:00427970 to zobaczymy podczas śledzenia, że funkcja dekompresji właśnie tam zapisuje dane. Najważniejszy jest dla nas JMP 00427970 po którym następuje wykonanie już zdekompresowanego kodu a jak do niego dojdziemy to już obojętne (nawet metodą prób i błędów).

Teraz wykorzystamy program ProcDump do dekompresji. Umożliwia on oprócz dekompresji dowolnie spakowanych exe (co nie zawsze działa), zdefiniowanie za pomocą skryptu sposobu śledzenia i zapisania dekompresowanego pliku konkretnym packerem. Jest tam plik skript.ini w którym właśnie to definiujemy. Są tam już zdefiniowane Shrinker, PEShield, WWPack. Program wykorzystuje kilka komend do takiej definicji, zresztą sami zaglądnijcie do pliku to zobaczycie. W każdym razie dodajemy nowa sekcję np. WinAmp.

[INDEX]
P1=PEShield
...
P7=WinAmp
[WinAmp]
L1=LOOK E9,46,53,F5,FF
L2=BP
L3=STEP

O co chodzi w tym skrypcie? Po prostu: szukaj ciągu bajtów naszego skoku JMP 00427970 (jego postaci szesnastkowej), po jego znalezieniu zastaw na nim pułapkę i po jej wykonaniu zapisuj śledzony program jako zdekompresowany. Proste prawda. Uruchamiamy ProcDump wybieramy trace nasz typ WinAmp, wybieramy WinAmp.exe i program pięknie się dekompresuje i co najważniejsze działa po tej dekompresji.

Myślę, ze ProcDump wart jest zainteresowania i przećwiczenia np. właśnie na WinAmp. Zawsze możemy trafić na program skompresowany nieznanym kompresorem i wtedy damy sobie radę. Ci co nie znają ProcDump powinni go jak najszybciej ściągnąć.

GustawKit - 16 listopad 1998


Usunięcie ProcDumpem pakietu Vbox4 z Ulead COOL 3D v2.0

Oryginał tekstu napisany przez Gustawa dostępny pod adresem http://www.crackpl.site.pl/teksty/exepack2.htm (angielska wersja tłumaczenia napisana przez Zomo dostępna pod http://www.crackpl.site.pl/teksty/exepack2.zip).

W poprzedniej części przedstawiłem sposób rozpakowywania plików exe za pomocą ProcDump. Okazuje się, że program ten może posłużyć nam do zcrackowania programów zabezpieczonych komercyjnymi pakietami typu TimeLock lub Vbox4 by PreviewSoftware. Zasada działania tych zabezpieczeń jest stosunkowo prosta. Za przykład weźmiemy program Ulead Cool3D v2.0 (PCWK 12A/98). Jeżeli załadujemy program U3dedit2.exe do debuggera (np. SoftIce) pojawi się nam następujący kod :

014F:004F1000  PUSH    DWORD PTR [ESP+0C]
014F:004F1004  PUSH    DWORD PTR [ESP+0C]
014F:004F1008  PUSH    DWORD PTR [ESP+0C]
014F:004F100C  PUSH    55E239F5          ---> przygotowanie adresu
014F:004F1011  PUSH    55AD2D76          ---> spakowanych danych
014F:004F1016  PUSH    55E23DA9
014F:004F101B  PUSH    55E23D53
014F:004F1020  CALL    [004F11F0]        ---> wywołanie 1 funkcji vbox4
014F:004F1026  PUSH    FFFFFFFF
014F:004F102B  CALL    EAX               ---> wywołanie programu
014F:004F102D  RET     000C

Funkcja CALL [004F11F0] wywołuje procedury (PreviewExecGate...) z bibliotek vbox4, które dekodują pierwszą część danych programu a w EAX jest zwracany nowy Entry Point (w moim przypadku F0000) do rozkodowanych danych. Śledząc dalej program w CALL EAX (F8) przechodzimy do nowego fragmentu kodu :

014F:004F0000  PUSH    DWORD PTR [ESP+0C]
014F:004F0004  PUSH    DWORD PTR [ESP+0C]
014F:004F0008  PUSH    DWORD PTR [ESP+0C]
014F:004F000C  PUSH    B6A4DD7F
014F:004F0011  PUSH    BBC60E1F
014F:004F0016  PUSH    6D171A8C
014F:004F001B  PUSH    415F4B5A
014F:004F0020  CALL    [004F01D4]        ---> następna funkcja vbox4
014F:004F0026  PUSH    FFFFFFFF
014F:004F002B  CALL    EAX
014F:004F002D  RET     000C

Jak widzimy kod jest analogiczny do poprzedniego. CALL [4F01D4] wywołuje funkcję vbox4, która uruchamia procedury sprawdzające warunki trial i w przypadku pomyślnego spełnienia dekoduje resztę programu i danych a w EAX jest zwracany adres rzeczywistego programu (w naszym wypadku Cool3D). W przypadku niepomyślnego sprawdzenia warunków trial w EAX zwracany jest adres funkcji ExitProcess, czyli zakończenia programu. Jeżeli prześledzimy dalej nasz kod ( w CALL EAX - F8) to wejdziemy na nasz główny program pod adresem 6CF20. Adres ten jest wart zapamiętania, gdyż jest on po prostu Entry Point głównego programu, który jest już pełną wersją bez vbox4.

Ok, wiemy już wszystko. Rozwiązanie problemu vbox4 polegać będzie na przeniesieniu z pamięci rozpakowanego programu i zapisaniu go do pliku uruchomieniowego. Można się pokusić o wykorzystanie SoftIce i np. SoftDump do zapisania pamięci w plik. Wymaga to jednak dobrej znajomości struktury PE exe i jest uciążliwe a opisywanie tego nie jest naszym celem. Jest prostsze rozwiązanie ponieważ znamy wspaniały program ProcDump, który umożliwia nam zapisanie procesów z pamięci do pliku przy utrzymaniu struktury plików uruchomieniowych.

Jak już opisywałem w poprzedniej części ProcDump posiada plik script.ini w którym zapisywane są instrukcje debugowania dekodowanych programów. W najnowszej wersji ProcDump32 1.1.6 (jest już 1.6.2) powinna być już gotowa sekcja dla Vbox :

[VBOX Dialog]
L1=LOOK FF,D0
; szukamy pierwszego call eax
L2=BP
; pułapka na znalezionym adresie
L3=BPREG EAX
; ustawia pułapkę na adresie zawartym w rejestrze EAX
; a jak wiemy tam jest adres następnej części kodu
L4=OBJR
; ustala adres podstawowy szukania na aktualne EIP
L5=LOOK FF,D0
; szuka drugiego call eax
L6=BP
; zastawia na nim pułapkę
L7=STEP
; i dalej już śledzi zapisując rozpakowany program

Ważne jest odpowiednie ustawienie opcji procesu ładowania i rekonstrukcji pliku. Ponieważ program spakowany za pomocą vbox4 ma także spakowane segmenty i tabele danych musimy zaznaczyć opcje rekonstrukcji, tzn. Create New Import. W razie problemów włączamy także opcje Ignore Faults w sekcji Trace.

Po pozytywnym rozpakowaniu pliku możemy także usunąć sekcję WeiJunLi ze struktury naszego nowego pliku (w opcji PE Editor). Z ciekawości zaglądnijmy jaki jest Entry Point naszego pliku - 6CF20. Ok, właśnie taki miał być.

GustawKit - 24 listopad 1998

Komercyjne zabezpieczenie softSENTRY Release 2.008

Oryginał tekstu napisany przez Gustawa dostępny pod adresem http://www.crackpl.site.pl/teksty/exeprot1.htm

Myślę, że wszyscy którzy zaglądneli na strony CrackPl potrafią już obslugiwac ProcDump i są w stanie rozpakować większość plików uruchomieniowych spakowanych lub szyfrowanych. Okazuje się, że na podobnej zasadzie działa większość komercyjnych pakietów autoryzacyjnych do ograniczeń czasowych i wersji trial oprogramowania. Znamy już takie pakiety jak TimeLock lub Vbox, które mimo zastosowania skomplikowanych algorytmów szyfracji i rozbudowanych procedur ochrony dają się w kilka sekund usunąć z programów. Z reguły są dwa rodzaje takich pakietów zabezpieczeń, jedne które wprowadzają procedury i funkcje już na poziomie pisania kodu programu i po kompilacji są na trwałe wbudowane w program i drugie dołączające i szyfrujące już gotowe pliki uruchomieniowe. Te pierwsze mogą być lepsze lub gorsze ale czasami mogą spełniać swoją rolę, natomiast te drugie są po prostu do niczego. Przykładem było już TimeLock lub Vbox, teraz przedstawię inne softSENTRY oferowane m.in. w zestawie www.componentsource.com i można je znaleść m.in. na płytkach1/99 tego zestawu.

Ogólne założenia programu są dobre, program umożliwia przygotowanie skryptów tworzących procedury trial takie jak time limit, limit uruchomień, okienka rejestracyjne, okienka informacyjne i generowanie kodu dołączanego do wykonywalnych plików exe lub bibliotek dll. Właściwie wszystko pięknie, tyle że usunięcie tego kodu z plików uruchomieniowych nie nastręczy żadnych problemów nawet początkującym crackerom a nawet wręcz ułatwi im zcrackowanie programu.

Zobaczmy co ten program wyrabia z kodem np. w pliku sentry32.exe (sam pakiet jest zabezpieczony swoim kodem). Po wstępnej analizie kodu startowego, znajdujemy sprawdzanie ograniczeń i wywoływanie odpowiednich okienek dialogowych lub informacyjnych. Można się bawić w modyfikacje tego kodu ale nie ma to sensu. W każdym razie dochodzimy do takiego fragmentu kodu :

014F:004A3B27  FF1558A44A00        CALL    [USER32!UnregisterClassA]
014F:004A3B2D  E87E000000          CALL    004A3BB0
014F:004A3B32  E819000000          CALL    004A3B50
014F:004A3B37  8B45B8              MOV     EAX,[EBP-48]
014F:004A3B3A  50                  PUSH    EAX
014F:004A3B3B  FF15D0A34A00        CALL    [KERNEL32!ExitProcess]
014F:004A3B41  8B45B8              MOV     EAX,[EBP-48]
014F:004A3B44  E900000000          JMP     004A3B49

Wywołanie CALL 4A3B50 wywołuje następną procedurę, która nas będzie interesować. Szukamy bowiem kodu głównego programu z pominięciem kodu pakietu SoftSENTRY. Obejrzyjmy więc to wywołanie :

014F:004A3B50  56                  PUSH    ESI
014F:004A3B51  A1C0894A00          MOV     EAX,[004A89C0]
014F:004A3B56  33C9                XOR     ECX,ECX
014F:004A3B58  8B7002              MOV     ESI,[EAX+02]
014F:004A3B5B  337006              XOR     ESI,[EAX+06]
014F:004A3B5E  33700A              XOR     ESI,[EAX+0A]
014F:004A3B61  033548884A00        ADD     ESI,[004A8848]
014F:004A3B67  A1C0894A00          MOV     EAX,[004A89C0]
014F:004A3B6C  41                  INC     ECX
014F:004A3B6D  41                  INC     ECX
014F:004A3B6E  8B5006              MOV     EDX,[EAX+06]
014F:004A3B71  31548EF8            XOR     [ECX*4+ESI-08],EDX
014F:004A3B75  A1C0894A00          MOV     EAX,[004A89C0]
014F:004A3B7A  8B500A              MOV     EDX,[EAX+0A]
014F:004A3B7D  31548EFC            XOR     [ECX*4+ESI-04],EDX
014F:004A3B81  83F914              CMP     ECX,14
014F:004A3B84  7CE1                JL      004A3B67
014F:004A3B86  8B0DF4884A00        MOV     ECX,[004A88F4]
014F:004A3B8C  E88FF5FFFF          CALL    004A3120
014F:004A3B91  FFD6                CALL    ESI  <---- !!!!
014F:004A3B93  6A00                PUSH    00
014F:004A3B95  6820634A00          PUSH    004A6320
014F:004A3B9A  6810634A00          PUSH    004A6310

Krótkie prześledzenie tego kodu pozwoli nam znaleść wywołanie CALL ESI, które jak się okazuje wywołuje nasz główny program. Widzimy tu fragment kodu przygotowujący EntryPoint do kodu głównego i zachowujący go w rejestrze ESI. Wywołanie Call ESI prowadzi do :

014F:00414CA0  64A100000000        MOV     EAX,FS:[00000000]
014F:00414CA6  55                  PUSH    EBP
014F:00414CA7  8BEC                MOV     EBP,ESP
014F:00414CA9  6AFF                PUSH    FF
014F:00414CAB  68B8424400          PUSH    004442B8
014F:00414CB0  68C4AA4100          PUSH    0041AAC4
014F:00414CB5  50                  PUSH    EAX
014F:00414CB6  64892500000000      MOV     FS:[00000000],ESP
014F:00414CBD  83EC60              SUB     ESP,60
014F:00414CC0  53                  PUSH    EBX
014F:00414CC1  56                  PUSH    ESI
014F:00414CC2  57                  PUSH    EDI
014F:00414CC3  8965E8              MOV     [EBP-18],ESP
014F:00414CC6  FF15B0374500        CALL    [KERNEL32!GetVersion]
014F:00414CCC  A3A4D74400          MOV     [0044D7A4],EAX

To jest już nasz główny program, zaczynający się w moim wypadku od cs:414CA0 i taka wartość była zapisana w ESI. Ponieważ jak pisałem, kody zabezpieczeń przyłączane są do gotowego pliku uruchomieniowego ich usunięcie nie powinno sprawić problemów. Należy dojść do początku głównego programu i zapisać obraz pliku z pamięci na dysk i odtworzyć nową strukturę pliku exe. Sposobów jest wiele ale najłatwiejszy to ProcDump. Tworzymy sobie nową sekcje w pliku script.ini

[softSentry]
L1=LOOK E8,19,00,00,00
; szukamy pierwszego call 43a3b50
L2=BP
; pułapka na znalezionym adresie
L3=LOOK FF,D6
; szuka drugiego call ESI
L6=BP
; zastawia na nim pułapke
L7=STEP
; i dalej już śledzi zapisując rozpakowany program

No i program pięknie nam usunie zabezpieczenia SoftSENTRY. Jeżeli jeszcze zaglądniemy do nagłówka pliku znajdziemy niepotrzebną sekcje 20/20teaćj, którą możemy usunąc za pomocą edytora PE zawartego w ProcDump.

Proste, prawda? Szkoda tylko, że praca nad niezłym pakietem zabezpieczeń owocuje tak kiepskim zabezpieczeniem. Po prostu przerost formy nad treścią.

GustawKit - 13 grudnia 1998


Jak debugować i rozpakować Crunch v1.0 czyli tworzenie automatycznego skryptu do ProcDumpa

Oryginał tekstu napisany przez Gustawa dostępny pod adresem http://www.crackpl.site.pl/exe/exepack4.htm

Wstęp

Minęło trochę czasu odkąd pisałem o rozpakowywaniu plików uruchomieniowych spakowanych różnymi exepackerami. Przez ostatnie miesiące, lata pojawiło się wiele nowych packerów i crypterów. Pojawiło się także dużo narzędzi wspomagających rozpakowywanie. IMHO najbardziej uniwersalnymi i praktycznymi narzędziami są nadal SoftIce i ProcDump, dołączył do nich także znakomity debuger TRW2000. Ostatnio pojawił się ciekawy packer/crypter firmy http://www.bit-arts.com/ o nazwie Crunch 1.0. Pierwsze spotkanie z nim sprawiło, że postanowiłem się nim zająć i spróbować go rozpakować ponieważ zauważyłem kilka ciekawostek w kodzie i z biegu nie udało mi się go rozpakować uniwersalnymi narzędziami. Za przykład użyjemy samego Crunch'a, który jest spakowany sobą.

Tutorial

Postaram się wam przedstawić jak zbudować uniwersalny skrypt do ProcDump'a rozpakowujący Crunch'a, gdyż na razie nie ma żadnego dedykowanego unpackera a uniwersalne nie radzą sobie z nim. Z uwagi na to, że program wywala się w obecności SoftIce (ma to robić wg. autorów) do debugowania użyjemy TRW2000. Podczas debugowania okazuję się, że w kodzie jest kilka interesujących miejsc, które mocno utrudniają jego debugowanie i muszą być uwzględnione przy tworzeniu skryptu do ProcDumpa. Dlatego też proces tworzenia skryptu będę przeplatał z fragmentami kodu Crunch'a w celu lepszego zrozumienia zagadnienia i ewentualnego szybkiego znalezienia tego kodu na podstawie adresów czy ciągu bajtów podczas debugowania. Polecam także zmienić od razu nazwy sekcji spakowanego Crunch'a (wszystkie mają tą samą nazwę), ponieważ będzie nam łatwiej się zorientować kiedy przeskakujemy z jednej sekcji do drugiej, Oki, startujemy śledzenie crunch.exe. Na starcie EIP=0067E00 pojawia się na mniej więcej taki kod:

017F:0067E000 55                PUSH    EBP
017F:0067E001 E800000000        CALL    0067E006
017F:0067E006 5D                POP     EBP
017F:0067E007 83ED06            SUB     EBP,00000006
...
017F:0067E0C0 8BC8              MOV     ECX,EAX
017F:0067E0C2 F3A4              REP     MOVSB  !!!!!
017F:0067E0C4 8B07              MOV     EAX,[EDI]
017F:0067E0C6 D5                AAD     
017F:0067E0C7 81C2F3080E00      ADD     EDX,000E08F3
017F:0067E0CD 52                PUSH    EDX
017F:0067E0CE 33C0              XOR     EAX,EAX

Tu już pojawia się pierwsza zasadzka w instrukcji REP MOVSB. Otóż ta instrukcja powoduje kopiowanie fragmentu kodu akurat w miejsce następnej instrukcji i po jej wykonaniu kod będzie wyglądać tak:

017F:0067E0C0 8BC8              MOV     ECX,EAX
017F:0067E0C2 F3A4              REP     MOVSB
017F:0067E0C4 8BD5              MOV     EDX,EBP
017F:0067E0C6 81C2F3080000      ADD     EDX,000008F3
017F:0067E0CC 52                PUSH    EDX
017F:0067E0CD 33C0              XOR     EAX,EAX

Tu jest pierwszy moment, który musimy uwzględnić przy tworzeniu skryptu. Ponieważ po instrukcji REP MOVSB dalszy kod się zmienia należy pozwolić by ProcDump znalazł miejsce kiedy to nastąpi:

LOOK F3,A4 / ADD 2 / BP / OBJR

ProcDump przeszuka kod za bajtami REP MOVSB i do EIP ze znalezionymi bajtami doda 2 i na takim adresie założy pułapkę. Musimy to zrobić w ten sposób, ponieważ ProcDump musi się zatrzymać już po wykonaniu REP MOVSB. Dalej znajdujemy podobny kod, który kopiuje fragmenty kodu tym razem w procedurze CALL.

017F:0067E0FE FFD2              CALL    Near EDX
017F:0067E100 CC                INT     03
017F:0067E101 CC                INT     03
017F:0067E102 E8A6080000        CALL    0067E9AD
017F:0067E107 E81C060000        CALL    0067E728

a po wywołaniu CALL kod wygląda:

017F:0067E0FE FFD2              CALL    Near EDX
017F:0067E100 EB05              JMP     0067E107
017F:0067E102 E8A6080000        CALL    0067E9AD
017F:0067E107 E81C060000        CALL    0067E728 

Jeżeli prześledzimy procedurę w wywołaniu CALL znajdziemy ciekawy kod, który wykłada program, jeżeli SoftIce jest w pamięci. Otóż ten fragment kodu: JMP 0067E107 generowany jest na podstawie wartości z tablicy IDT. Jak wiemy gdy SI jest zainstalowany w tablicy są inne wpisy dla przerwań (INT1/IN3) niż w czystym systemie. To właśnie sprawdza Crunch, i jeżeli są tam wartości wpisane przez SI generuje bzdurne wartości powodując niedziałanie programu. TRW nie zmienia wpisów w IDT więc nim możemy spokojnie śledzić taki kod (wracając jeszcze do tego IDT, to jest tutaj obliczana różnica pomiędzy adresami wektorów przerwań. Konkretnie od adresu INT3 jest odejmowany adres INT1 i jeśli wynikiem jest 1Eh to program się ładnie zawiesi. Taka sytuacja występuje gdy SI jest aktywny. W "czystym" systemie różnica ta wynosci 10h - smola). Ten fragment kodu musimy także uwzględnić w naszym skrypcie:

LOOK FF,D2 / BP / WALK /OBJR / LOOK 74,02,58,c3 /ADD 3 /BP / WALK /OBJR

Znajdujemy kod CALL'a i na nim zakładamy pułapkę. Później wykonujemy jedną instrukcję i przypisujemy bazowy EIP do dalszego działania skryptu. Ponieważ jednak ProcDump sam nie chciał mi się zatrzymać po powrocie z CALL, więc poszuka moment powrotu RET z CALL i na nim się zatrzyma, wykona jedną instrukcję czyli wyjdzie z CALL'a i przypisze bazowy EIP już po tym. Dalej debugując kod programu po wielu różnych cudach z kodem dochodzimy do:

017F:00680DA3 E900FFFFFF        JMP     00680CA8
017F:00680DA8 8B8522130000      MOV     EAX,[EBP+00001322]
017F:00680DAE 01858F220000      ADD     [EBP+0000228F],EAX
017F:00680DB4 FFA5F22A0000      JMP     Near [EBP+00002AF2] !!!!
017F:00680DBA C3                RET
017F:0067E107 E81C060000        CALL    0067E728

gdzie interesująco wygląda skok JMP [EBP+2AF2] który skacze do:

017F:0067E0C4 61                POPAD
017F:0067E0C5 5D                POP     EBP
017F:0067E0C6 8B858F220000      MOV     EAX,[EBP+0000228F]
017F:0067E0CC 5D                POP     EBP
017F:0067E0CD FFE0              JMP     Near EAX  !!!

A ten jump EAX jest do :-)) cs:401000 czyli kodu głównego programu.

017F:00401000 A19CA54E00        MOV     EAX,[004EA59C]
017F:00401005 C1E002            SHL     EAX,02
017F:00401008 A3A0A54E00        MOV     [004EA5A0],EAX
017F:0040100D 57                PUSH    EDI
017F:0040100E 51                PUSH    ECX
017F:0040100F 33C0              XOR     EAX,EAX
017F:00401011 BF686C4F00        MOV     EDI,004F6C68 

Spróbujmy dopisać do skryptu szukanie tych jump'ów czyli:

LOOK FF,A5,F2,2A,00,00 / BP

Szukanie jednak bajtów kodów tych skoków przez ProcDumpa w momencie ostatniego zatrzymania skryptu (po wyjściu z CALL) nie daje rezultatu. A raczej daje tylko okazuje się, że kody tych jump'ów znajdują się pod innymi adresami ( kod pierwszego jump jest pod cs:0067F062) niż wynika to z debugera no i mimo ich znalezienia pułapka BP nie zadziała. Co więc robimy? Będąc w debugerze w czasie śledzenia jeszcze pod adresem 017F:0067E100 (czyli w momencie kiedy ProcDump zacznie szukać tego JMP) zaglądamy co jest tam gdzie ma być ten JMP czyli pod adres 017F:00680DB4. Okazuje się, że jest co innego. No więc zakładamy pułapkę na zapisie pod ten adres (BP 017F:00680DB4 W) i puszczamy program dalej. Okazuje się, że ten kod jest kopiowany w to miejsce z innego w tym fragmencie:

017F:0067E2B0 F3A4              REP     MOVSB !!!!
017F:0067E2B2 5F                POP     EDI
017F:0067E2B3 89BD022B0000      MOV     [EBP+00002B02],EDI
017F:0067E2B9 33D2              XOR     EDX,EDX

Wniosek z tego, że skrypt musi najpierw znaleźć miejsce kopiowania, zatrzymać się na nim i szukać JMP'ów dopiero po ich skopiowaniu. A więc:

LOOK F3,A4 / ADD 2 / BP /OBJR

I dopiero po tym poszukać końcowych JMP'ów:

LOOK FF,A5,F2,2A,00,00 / REPL 90,90,90,90,90,90 / LOOK FF,A5,F2,2A,00,00 /BP /WALK /OBJR
LOOK FF,E0 / BP / STEP

ProcDump najpierw znajdzie pierwszą kopię bajtów (którą wcześniej znajdywał), które są już zbędne bo skopiowane pod właściwy adres, więc aby je pominąć zastępujemy je NOP'ami i szukamy ponownie. I to by było praktycznie wszystko. Końcowy pełny skrypt wygląda następująco:

[Crunch]
L1=LOOK F3,A4
L2=ADD 2
L3=BP
L4=OBJR
L5=LOOK FF,D2
L6=BP
L7=WALK
L8=OBJR
L9=LOOK 74,02,58,c3
LA=ADD 3
LB=BP
LC=WALK
LD=OBJR
LE=LOOK F3,A4
LF=ADD 2
L10=BP
L11=OBJR
L12=LOOK FF,A5,F2,2A,00,00
L13=REPL 90,90,90,90,90,90
L14=LOOK FF,A5,F2,2A,00,00
L15=BP
L16=WALK
L17=OBJR
L18=LOOK FF,E0
L19=BP
L1A=STEP
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001
OPTL4=00030000
OPTL5=00000000

Wnioski i uwagi

Prawdopodobnie istnieją inne drogi śledzenia i stworzenia skryptu w inny sposób. To co przedstawiłem jest końcowym efektem mojej pracy bez żadnych optymalizacji. Skrypt działa poprawnie na programach spakowanych Crunch'em więc nie ma co już go poprawiać. O czym świadczy cały ten przykład? Ano o tym, że każdy spakowany czy zaszyfrowany program uruchomieniowy można rozpakować, bez względu na ilość i jakość zabezpieczeń przed tym. Crunch nie jest złym packerem, myślę, że w większości przypadków mógłby uniemożliwić i zniechęcić do modyfikacji i łamania programów nim zabezpieczonych. Mógłby gdyby nie ProcDump, TRW i CrackPL :-). Przykro mi, że tak bezwzględnie potraktowałem Crunch i chłopaków z BitArts ale zrobiłem to tylko dlatego, że ich produkt uznałem za ciekawy i warty poświęcenia mojego czasu. Wszelkie wymienione najnowsze narzędzia i programy można znaleźć na stronach http://www.cookiecrk.z.pl/ , http://www.ptasiek.px.pl/ , http://www.protools.cjb.net/ , http://www.playtools.cjb.net/ i innych, z linków wymienionych stron.

GustawKit - 9 luty 2000


Budowa pliku exe


Nagłówek PE

Nagłówek PE (portable executable header) znajduje się w pliku exe pod offsetm wskazywanym przez członka (member) struktury IMAGE_DOS_HEADER.e_lfanew. Struktura IMAGE_DOS_HEADER jest umieszczona w pliku pod offsetem 0 czyli znajduje się na samym jego początku i zaczyna sie wszystkim chyba znaną dwubajtową sygnaturą 'MZ':

IMAGE_DOS_HEADER STRUCT DWORD
 e_magic	WORD ?
 e_cblp		WORD ?
 e_cp		WORD ?
 e_crlc		WORD ?
 e_cparhdr	WORD ?
 e_minalloc	WORD ?
 e_maxalloc	WORD ?
 e_ss		WORD ?
 e_sp		WORD ?
 e_csum		WORD ?
 e_ip		WORD ?
 e_cs		WORD ?
 e_lfarlc	WORD ?
 e_ovno		WORD ?
 e_res		WORD 4 dup(?)
 e_oemid	WORD ?
 e_oeminfo	WORD ?
 e_res2		WORD 10 dup(?)
 e_lfanew	DWORD ?
IMAGE_DOS_HEADER ENDS

Jako że znamy już offset PE headera to poniżej jego struktura:

IMAGE_NT_HEADERS STRUCT DWORD
 Signature		DWORD ?
 FileHeader 		IMAGE_FILE_HEADER <>
 OptionalHeader		IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS

I co tu widać? Oczywiście sygnaturke pliku (w naszym przypadku znane 'PE') i następne wskaźniki do kolejnych struktur. Na pierwszy ogień idzie IMAGE_FILE_HEADER:

IMAGE_FILE_HEADER STRUCT DWORD
 Machine		WORD ?
 NumberOfSections	WORD ?
 TimeDateStamp		DWORD ?
 PointerToSymbolTable	DWORD ?
 NumberOfSymbols	DWORD ?
 SizeOfOptionalHeader	WORD ?
 Characteristics	WORD ?
IMAGE_FILE_HEADER ENDS

Znaczenie poszczególnych członków tej struktury:

Machine	- określa pod jakim systemem ma się uruchamiać kod tego execa:
	IMAGE_FILE_MACHINE_I386 (0x14c) - Intel 80386 procesor lub lepszy
	0x014d - Intel 80486 procesor lub lepszy
	0x014e - Intel Pentium procesor lub lepszy
	0x0160 - R3000 (MIPS) procesor, duży indianin (big endian), z tymi
		indianinami chodzi o zapis liczb w pamięci, intel zapisuje
		liczbę 12345678h jako 78563412h, natomiast motorola normalnie
		czyli 12345678h, niepytajcie się tylko który jest który :)
	IMAGE_FILE_MACHINE_R3000 (0x162) - R3000 (MIPS) procesor, mały indianin (little endian)
	IMAGE_FILE_MACHINE_R4000 (0x166) - R4000 (MIPS) procesor, mały indianin
	IMAGE_FILE_MACHINE_R10000 (0x168) - R10000 (MIPS) procesor, mały indianin
	IMAGE_FILE_MACHINE_ALPHA (0x184) - DEC Alpha AXP procesor
	IMAGE_FILE_MACHINE_POWERPC (0x1F0) - IBM Power PC, mały indianin
NumberOfSections - informuje o ilości sekcji w pliku a dokładniej o ilości
	nagłówków sekcji (to własnie w nagłówkach sekcji są zawarte m.in.
	informacje o ich położeniu, wielkości i "słynnych" :) characteristics
TimeDateStamp - określa czas kiedy plik został stworzony
PointerToSymbolTable oraz NumberOfSymbols - używane do przechowywania informacji
	dla debuggera, ze względu na brak danych najlepiej ustawiać je na wartość 0
SizeOfOptionalHeader - rozmiar struktury IMAGE_OPTIONAL_HEADER32 równy 224 bajtom
Characteristics	- charakterystyka pliku czyli atrybuty, część z tych flag
	jest ważna tylko w przypadku plików object lub bibliotek
	(szczegółowa rozpiska poszczególnych bitów jest zawarta w pliku PE.txt)

Dobrze, wiemy już jak wygląda struktura IMAGE_FILE_HEADER więc obejrzyjmy kolejną strukturę wskazywaną przez członka IMAGE_NT_HEADERS.OptionalHeader:

IMAGE_OPTIONAL_HEADER equ <IMAGE_OPTIONAL_HEADER32>
IMAGE_OPTIONAL_HEADER32 STRUCT DWORD
 Magic				WORD ?
 MajorLinkerVersion		BYTE ?
 MinorLinkerVersion		BYTE ?
 SizeOfCode			DWORD ?
 SizeOfInitializedData		DWORD ?
 SizeOfUninitializedData	DWORD ?
 AddressOfEntryPoint		DWORD ?
 BaseOfCode			DWORD ?
 BaseOfData			DWORD ?
 ImageBase			DWORD ?
 SectionAlignment		DWORD ?
 FileAlignment			DWORD ?
 MajorOperatingSystemVersion	WORD ?
 MinorOperatingSystemVersion	WORD ?
 MajorImageVersion		WORD ?
 MinorImageVersion		WORD ?
 MajorSubsystemVersion		WORD ?
 MinorSubsystemVersion		WORD ?
 Win32VersionValue		DWORD ?
 SizeOfImage			DWORD ?
 SizeOfHeaders			DWORD ?
 CheckSum			DWORD ?
 Subsystem			WORD ?
 DllCharacteristics		WORD ?
 SizeOfStackReserve		DWORD ?
 SizeOfStackCommit		DWORD ?
 SizeOfHeapReserve		DWORD ?
 SizeOfHeapCommit		DWORD ?
 LoaderFlags			DWORD ?
 NumberOfRvaAndSizes		DWORD ?
 DataDirectory			IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER32 ENDS

Znaczenie poszczególnych członków tej struktury:

(to jeszcze nie koniec)

Magic -
MajorLinkerVersion -
MinorLinkerVersion -
SizeOfCode -
SizeOfInitializedData -
SizeOfUninitializedData -
AddressOfEntryPoint -
BaseOfCode -
BaseOfData -
ImageBase -
SectionAlignment -
FileAlignment -
MajorOperatingSystemVersion -
MinorOperatingSystemVersion -
MajorImageVersion -
MinorImageVersion -
MajorSubsystemVersion -
MinorSubsystemVersion -
Win32VersionValue -
SizeOfImage -
SizeOfHeaders -
CheckSum -
Subsystem -
DllCharacteristics -
SizeOfStackReserve -
SizeOfStackCommit -
SizeOfHeapReserve -
SizeOfHeapCommit -
LoaderFlags -
NumberOfRvaAndSizes -
DataDirectory - IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)

 

IMAGE_DATA_DIRECTORY STRUCT DWORD
 VirtualAddress DWORD ?
 isize DWORD ?
IMAGE_DATA_DIRECTORY ENDS
IMAGE_EXPORT_DIRECTORY STRUCT DWORD
 Characteristics DWORD ?
 TimeDateStamp DWORD ?
 MajorVersion WORD ?
 MinorVersion WORD ?
 nName DWORD ?
 nBase DWORD ?
 NumberOfFunctions DWORD ?
 NumberOfNames DWORD ?
 AddressOfFunctions DWORD ?
 AddressOfNames DWORD ?
 AddressOfNameOrdinals DWORD ?
IMAGE_EXPORT_DIRECTORY ENDS
IMAGE_DIRECTORY_ENTRY_EXPORT equ 0 
IMAGE_DIRECTORY_ENTRY_IMPORT equ 1 
IMAGE_DIRECTORY_ENTRY_RESOURCE equ 2 
IMAGE_DIRECTORY_ENTRY_EXCEPTION equ 3 
IMAGE_DIRECTORY_ENTRY_SECURITY equ 4 
IMAGE_DIRECTORY_ENTRY_BASERELOC equ 5 
IMAGE_DIRECTORY_ENTRY_DEBUG equ 6 
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE equ 7 
IMAGE_DIRECTORY_ENTRY_GLOBALPTR equ 8 
IMAGE_DIRECTORY_ENTRY_TLS equ 9 
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG equ 10 
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT equ 11 
IMAGE_DIRECTORY_ENTRY_IAT equ 12 
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT equ 13 
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR equ 14 

Nagłówek sekcji


Tabela importów

 


Dodatkowe informacje


Słownik pojęć

 


Lista przydatnych tekstów

Poniżej spis materiałów które można namierzyć w sieci tytuł/nazwa pliku/rozmiar:

smola

 


Linki do stron

www.crackpl.site.pl


copyright (c) 2000
smola.crackpl.2ooo