Faq crackerskie #4 by mNICH

THIS TUT IS DEDICATED FOR TWO COOL GUYS : HuffYk & _TRY_ !!! ESPECIALLY FOR U HUF - U'R REALLY KEWL GUY - THX FOR EVERYTHING !!! IT'S FOR YA MATES !!!

23.12.98 BIELSKO-BIALA (w ramach propagowania utrzymania wojewodztwa Bielskiego) :)) (ufff ... Uwinalem sie przed swietami)

HEY All !!!

Gee ... to to juz 4 wydanie ... jak ten czas leci ;) Ekhm, napisalem, ze tym razem zlamiemy cos bez debuggera ... jednak po dluzszym namysle zdecydowalem sie ze uzyjemy debuggera ... moze nastepnym razem ............. No ale zasadnicze pytanie co tym razem zlamiemy ??? Hehehe ... TAK ! ... zgadles ! ... CrackMe 3.0 ;))) Ma on takie zabezpieczenie, ze wymaga pliku z numerem rejestracyjnym ... do pewnego mementu podchodzimy do zabezpieczenia w inny sposob niz do dwoch poprzednich, ale potem okaze sie, ze w zasadzie jest ono podobne do swych poprzednikow ... zatem przeczytaj kilka pierwszych punktow, a dalej SAM !!! ... ten FAQ jest w zasadzie takim uzupelnieniem bo chce omowic (prawie) wszystkie sposoby zabezpieczen (SERIAL..) ... nie wiem czy czesto bedziesz spotykal zabezpieczenia wlasnie tego typu ... no ale ...

Co potrzebne :

No chyba juz wiesz - S-ice !!! oczywiscie kartka papieru i olowek tez sie przydadza ;)

Uwierz Mi !!! Kartka bardzo sie przydaje ... zawsze jak lamie jakies zabezpieczenie (trudniejsze) to kolo mojego kompa leza stosy kartek z jakimis offsetami i innymi wartosciami.

hmmm ... piractwo ? ... czy to dobrze czy zle ? ... wedlug mnie to nie jest ani dobrze ani zle ! ... Ci co chca wyeliminowac calkowicie piractwo to nie zdaja sobie chyba sprawy z konsekwencji !!! A Ci co chcieliby zeby bylo legalne to tak samo !!! ... Wszystko musi byc z umiarem ! ... fakt, ze nie moge sobie pozwolic na zakup JBuildera za 100 baniek ... ale takze nie zamawiam na plytach pelno programow ktore i tak mialbym uzytkowac w 10% !!! Takze zastanow sie przed zakupem nastepnej plyty z *nielegalnym* programem czy jest on Ci naprawde NIEZBEDNY !!! ... Nie lepiej zmienic system na Linuxa i uzywac tam bezplatnych zastepcow programow z W95/98 ??? Przemysl to ! ... Pirackiej plyty nie kupilem juz chyba od roku ...i nie zamierzam kupowac ... chyba, ze bede zmuszony do wykorzystania jakiegos giganta za 100 baniek !!! ... Wiec pirackie plyty staraj sie kupowac tylko w przypadkach BEZ WYJSCIA ... przeciwnicy jak i zwolennicy beda szczesliwsi ;) ...

Jeszcze krotka odpowiedz dla tych ktorzy zadaja mi pytanie "Czy jestes crackerem ?" ... nie nie martw sie ze zaczne gledzic jakim to ja jestem genialnym crackerem ;) ... odp. na pytanie brzmi : "A czy zebra ma czarne czy biale paski ???" ... hehe ... Wszystko zalezy od punktu widzenia dla jednego moge byc crackerem, a dla innego totalnym ... ekhm ... (nie lubie tego slowa no ale...) lamerem.

Z tego co wiem to nie macie problemow ze zrozumieniem tego co pisze ... Dziwne ... ani jednego glosu krytyki ;) ... no, moze ...

KONTAKT :tomroy@kki.net.pl tomroy@polbox.com lub tomroy@friko6.onet.pl;)

++++++++++++++++++++++++++++++++++
TO FAQ MOZE BYC ROZPOWSZECHNIANE
KOMUKOLWIEK I GDZIEKOLWIEK
TYLKO NIE ZMIENIAJAC TRESCI
++++++++++++++++++++++++++++++++++

OK. ... ZACZYNAMY :

1. Uruchamiamy Crackme 3.0 ... wiemy, ze program bedzie szukal pliku z numerem rejestracyjnym (wiemy to z krotkiego pliku dolaczonego do programu) ... Oczywiscie jesli bedziesz lamal jakis komercyjny program to nie bedzie pliku z informacja, ze "program szuka pliku z numerem rejestracyjnym, patche nie dozwolone ..." ;)) ... Ale wystarczy zazwyczaj zajrzec do helpa (zawsze to rob - moga tam byc ciekawe dla nas informacje np. moze nawet ile znakow powinien miec SERIAL albo cos rownie idiotycznego ;) ) powinno znalezc sie tam cos takiego : "Jesli przeslesz kase, dostaniesz plik z serialem, umiescic go trzeba w katalogu z programem ... ble, ble, ble" No dobra wiemy, ze trzeba pliku ... ale jak sie do tego zabrac ???

2. Przypomnij sobie funkcje API ktora otwiera jakis plik ... czekam ! ... OK. ... juz wiesz, ze jest nia "CreateFileA" !!! No wiec to co zwykle :

bpx createfilea

Teraz przy kazdej PROBIE (Probie ! ... bo oczywiscie otwarcie moze sie nie udac !) otwarcia jakiegos pliku S-ice sie nam pojawi ! UWAGA ! powyzszy breakpoint musisz ustawic przed otwarciem programu ! ... dlaczego ??? ... otoz dlatego, ze gdy juz go otwarles widzisz napis na gornym pasku "CrackMe v3.0 - Uncracked" ... aha ! ... wiec program musial juz sprawdzic czy jest zlamany czy nie !!!

3. Mamy juz ustawiony breakpoint na otwarcie pliku ... uruchamiamy program i ... S-ice sie pojawil ... wychodzimy z funkcji (F11) zaczynamy analizowac kolejne linijki ... analizujemy ... analizujemy ... analizujemy ... dochodzisz do pewnego krytycznego momentu i wykrzykujesz "A po cholere to wszystko jest robione, jeszcze nie zobaczylem nic ciekawego !!!" ... oczywiscie masz racje ... zauwaz, ze S-ice przerywa na KAZDEJ probie otwarcia pliku !!! ... tzn. ze tez przy otwarciu pliku programu (CRACKME3.EXE) !!! ... a nam zalezy na tym aby S-ice przerwal na probie otwarcia pliku z numerem rejestracyjnym, wiec wtedy kiedy nacisnelismy F11, zamiast niego naciskamy F5 (F5 = <x> = Ctrl+d) !

4. S-ice znowu przerwal ... naciskamy F11 (aby dostac sie do miejsca w programie gdzie zostala wywolana funkcja CreateFileA) OK. widzimy tam naszego CALL-a ... wiadomo ze aby funkcja mogla otworzyc jakis plik to musi znac jego nazwe ! ... a wiec ktorys argument (PUSH) musi miec w sobie wskaznik (adres) do miejsca w pamieci gdzie jest ukryta ta nazwa ! ... przeszukujemy kolejne argumenty PUSH-ow (komenda <d>) ... w koncu przy ostatnim jesli damy :

d 004020d7

to zobaczymy ze pod tym adresem kryje sie wiele mowiaca nazwa pliku do otwarcia ... czyli "CRACKME3.KEY" !!! ... Teraz zobaczmy co jest zaraz pod tym CALL-em ... sa tam takie instrukcje :

             CMP   EAX,-01            (1)
             JNZ   00401043           (2)

(1) Tutaj trzeba powiedziec ze CreateFileA zwraca w EAX wartosc -01 (FFFFFFFF) jesli otwarcie pliku sie nie powiodlo !!! , a jakas tam inna wartosc jesli sie powiodlo. Jak widac u nas sie nie powiodlo ;) ... a dlaczego ? ... no bo przeciez my nie mamy takiego pliku i program nie moze odczytac zadnego SERIALA ;) ... oczywiscie warunek JNZ (2) (skok jesli nie zero) NIE zostanie spelniony i wykona sie procedura uruchamiana w wypadku zlego SERIALU w pliku.

5. Teraz opuszczamy S-ice, wychodzimy z CrackMe 3.0 i tworzymy plik "Crackme3.key" ... robimy od nowa to wszystko co przed chwila ... i teraz widzimy, ze nastapi skok (2) bo w EAX siedzi liczba rozna od –01 (FFFFFFFF) !!!

6. No dobra ... przechodzimy przez JNZ (F10) ... malutki skok ... teraz przechodzimy przez kilka instrukcji ... nizbyt waznych ... oprocz tej :

MOV   EAX,00000012

Niby nic szczegolnego, ale zaraz bedzie ... znowu kilka F10 ... i oto mamy :

             PUSH   00
             PUSH   004021A0
             PUSH   EAX
             PUSH   EBX
             PUSH   DWORD PTR [004020F5]
             CALL   KERNEL32!ReadFile

Okay ... Widzimy ze jest tu wywolanie funkcji ReadFile, a PUSH-e to sa jej parametry ... funkcja ReadFile odczytuje ilosc bajtow okreslone trzecim parametrem (PUSH EAX) z jakiegos pliku - w tym przypadku z naszego CRACKME3.KEY, jak latwo sie domyslic ;) ... Teraz wazne jest to MOV EAX... bo program wklada do EAX wartosc 12h (12h = 18d !!!) i potem dzieki PUSH EAX chce odczytac z CRACKME3.KEY te 18 bajtow ... Bedzie odczytywal dopoki nie napotka znaku EOF (koniec pliku) ... czyli np. jesli w pliku beda zapisane tylko 4 pierwsze bajty to funkcja odczyta tylko je i zakonczy dzialanie ... teraz przechodzimy przez wszystkie PUSH-e i CALL ... i ladujemy w tym miejscu :

             CMP   DWORD PTR [004021A0],12       (1)
             JNZ   00401137                      (2)

hmmm ... cos tu jest porownywane z 12h (18d) ... heh ta 12-stka wyglada znajomo ...

wiec zobaczmy co kryje sie za 004021A0 ? ...

d 004021a0 

heh ... mogles pomyslec ze nic szczegolnego - zwykle 0 ... ale to ma duze znaczenie zauwaz, ze masz pusty plik CRACKME3.KEY (jesli juz go wypelniles czyms tam i SAM poszles dalej - to sie ciesze ;) ), a jesli pusty to ReadFile nie odczyta zadnego bajtu, bo od razu napotka EOF ... a teraz uwaga ! ... pod adresem 004021A0 funkcja ReadFile zwraca ilosc odczytanych bajtow !!! ... a ze nasz plik byl pusty to bedzie tam siedzialo ZERO ... proste, nie ? ... wiec instrukcja (1) sprawdza czy funkcja ReadFile odczytala wszystkie 18 bajtow (12h) ... jaki z tego wniosek ??? ... ano taki, ze SERIAL, ktory znajduje sie w pliku MUSI miec conajmniej 18 znakow !!! - moze miec wiecej ale ReadFile i tak to zignoruje (pamietasz - MOV EAX,12) ... jesli nie ma tych conajmniej 18 znakow to skok w (2) nastapi i oczywiscie program UNCRACKED ;)

7. hehe ... wiesz co teraz musisz zrobic ? ... oczywiscie wychodzimy z S-ice, otwieramy plik CRACKME3.KEY (lepiej wylacz wczesniej bpx na CreateFileA - <bd>) i wpisujemy jakis 18-znakowy SERIAL np. taki : 321123321123321123 ... i robimy wszystko to co przed chwila (od punktu 2) ... hehe ... akurat przy tym programiku nie musimy sie natrudzic robiac "wszystko od nowa", ale przy jakies duzej aplikacji ... mozemy zmarnowac troche pracy wychodzac na chwile z S-ice'a ... wiec kiedy wiesz, ze juz duzo zrobiles i nie chce Ci sie od nowa, a musisz na chwile wyjsc z S-ice'a to zrob sobie takiego "save'a" komenda <bpx> ... hmmm ... BPX nie sluzy tylko do stawiania breakpointow na jakis standardowych funkcjach ... mozesz ustawic breakpoint na adresie jakiejs instrukcji do wykonania ... tzn. ustaw sobie breakpoint na instrukcji, ktora wlasnie jest podswietlona (do wykonania) czyli jesli jest takie cos :

0300:03038428  MOV   EBX,12345678

To taki breakpoint ustawiamy komenda :

<bpx 03038428>

Teraz gdy wyjdziemy z S-ice'a to latwo mozemy wrocic do poprzedniego miejsca w debugowanym programie ;).

8. No wiec juz jestesmy w poprzednim miejscu - z wypelnionym plikiem CRACKME3.KEY ... Teraz warunek (1) zostanie spelniony i skok w (2) nie nastapi !!! Popatrzmy na nastepne instrukcje :

             PUSH 00402008
             CALL 00401311

hmmm ... jakis CALL ... zobaczmy co oznacza jego argument :

<d 00402008>

ACHA ! ... to nasz SERIAL !!!

odtad mozesz swobodnie dalej probowac SAM

Dobra ... wchodzimy do CALL-a (F8) ... i oto co nastepuje :

             XOR   ECX,ECX          (1)
             XOR   EAX,EAX          (2)
             MOV   ESI,[ESP+04]     (3)
             MOV   BL,41            (4)
             MOV   AL,[ESI]         (5)  <----------|
             XOR   AL,BL            (6)             |
             MOV   [ESI],AL         (7)             |
             INC   ESI              (8)             |
             INC   BL               (9)             |} Petle
             ADD   [004020F9],EAX   (10)            |
             CMP   AL,00            (11)            |
             JZ    00401335         (12) <----------|
             INC   CL               (13)            |
             CMP   BL,4F            (14)            |
             JNZ   0040141B         (15) <----------| 
             MOV   [00402149],ECX   (16)
             RET                    (17)

(1) to zerowanie ECX, (2) zerowanie EAX ... (3) Do ESI wkladana jest wartosc [ESP+4] ... sprawdzamy co jest pod adresem ESP+4 :

<d esp+4>

hmmm ... jakas "pozornie_nic_nie_mowiaca_wartosc" ... to co zobaczyles w oknie danych to : 08 20 40 00 ... heh ... sprawdzamy dalej co sie kryje pod ta wartoscia (adresem) :

<d 402008>

Oczywiscie zobaczymy nasz SERIAL !!!

A wiec pod ESP+4 kryl sie pointer (wskaznik) do jakiejs innej wartosci ! Zauwaz ze jesli chcemy sprawdzic co sie kryje pod jakas wartoscia uzyskana z okna danych musimy odwrocic ta wartosc ... czyli np. jesli w oknie danych jest wartosc 11 22 33 44 to "przeksztalcamy" to na 44 33 22 11 ... wynika to z organizacji pamieci w trybie protected ... czyli np. w ulubionym W95 czy jeszcze bardziej lubianym W98 ;) ... mniej wiecej polega to na tym, ze wartosci "poukladane" sa od adresow rosnacych do malejacych ... i z tad wynika ta "odwrotnosc" ... nie bede sie rozwodzil nad ta organizacja bo nie mam miejsca ... przeczytaj w jakis ksiazkach, czy gdziekolwiek ;) ... A wiec teraz w ESI siedzi adres naszego SERIALA (3) ... w (4) do BL idzie 41 ... hehe ... chyba nie musze mowic co oznacza wartosc 41h ??? ... oczywiscie ze to w ASCII 'A' (duze A !!!) ... nastepnie w (5) do AL ida kolejne znaki z naszego SERIALA przy kazdym obiegu petli ... w (6) zostaja zXOR-owane wartosci AL (kolejne znaki z naszego SERIALA) i BL (kolejne litery "duzego" alfabetu ... A,B,C,D... ), i wynik umieszczony w AL ... (7) pod oryginalny SERIAL (adres w ESI) podkladane sa kolejne wyniki XOR-owan ... (8) inkrementowane jest ESI - czyli teraz ESI wskazuje na kolejny znak w SERIALU ... (9) inkrementowane BL - hmmm ... przed petla BL bylo 41 ('A') ... czyli przy kazdym obiegu petli w BL jest kolejna litera "wielkiego alfabetu" ... (10) pod adres 004020F9 wkladana jes suma wszystkich z XOR-owanych wartosci ze wszystkich obiegow petli ... (11) sprawdzane jest czy nie ma konca naszego SERIALA (czy znak=00 (NULL) )... (12) jesli koniec SERIALA to skok "w dal" ;), a dokladniej mowiac o 3-4 instrukcje - do (16) ;) ... (13) inkrementowane jest CL ... (14) BL jest porownywane z 4Fh ... hmmm ... 4Fh ??? ... tak ... BL na poczatku ma wartosc 41h, a wiec 'A' ... potem BL jest kazdorazowo (przy obiegu petli) inkrementowane, czyli bedzi miec wartosci 'A','B','C','D' itd. ... natomiast 4Fh to jest 'O' (duze O, nie zero) ... z tego wynika, ze petla albo zXOR-uje 14 pierwszych wartosci z SERIALA (14), albo skonczy szybciej gdy SERIAL ma mniej niz 14 znakow (11) ... heh ... dlaczego 14 ??? ... latwo obliczyc, ze od 'A' do 'O' jest 14 liter (albo jak wolisz to odejmij 4Fh - 41h) ... (15) tu nastapi skok gdy juz zXOR-ujemy te 14 pierwszych znakow z 'A','B','C' itd. ... (16) zapisywanie wartosci ECX pod adres 00402149 - przy czym w ECX jest ilosc znakow z SERIALA ktore udalo sie zXOR-owac (czyli powinno byc 0Eh (14d) )!!! ... No i (17) to powrot z funkcji ...

Posumujmy co tu sie stalo :

Pod adres gdzie sie znajdowal uprzednio nasz SERIAL zostaly zapisane zXOR-owane wartosci znakow w SERIALU i wielkich liter od 'A' do 'O' ... natomiast pod adresem 004020F9 zostala zapisana suma tych zXOR-owanych wartosci ... a tutaj 00402149 ilosc liter z SERIALA ktore program zXOR-owal (w zasadzie zawsze powinno tu byc 0Eh - chyba ze bedziesz modyfikowal jakies rejestry albo COS podczas debuggowania).

9. Gdy wyszlismy juz z poprzedniej funkcji widzimy takie cos :

XOR   DWORD PTR [004020F9],12345678

Powinienes wiedziec co sie kryje pod adresem 004020F9, chyba ze masz skleroze ;) ... no dobra jesli nie wiesz to jest to suma zXOR-owanych wartosci z poprzedniego punktu !!! No wiec ta wlasnie suma zostaje znowu zXOR-owana z wartoscia 12345678h (jak ja "lubie" takie mieszanie ;) ) i wynik jest zapisywany z powrotem pod adres 004020F9 !!!

10.Przechodzimy dalej :

             ADD   ESP,04    (1)
             PUSH  00402008  (2)
             CALL  0040133C  (3)

(1) nie ma specjalnego znaczenia - jak mozna zauwazyc, w poblizu [ESP] jest kilka miejsc gdzie sa bajty 08 20 40 00 - zeby sie przekonac wystarczy komenda <d esp> i rozgladnac sie (ALT+strzalka dol/gora) a jak wiemy jest to wskaznik do naszego SERIALA ... ups ! ... juz nie SERIALA tylko zXOR-owanego SERIALA ;) ... ale jak juz mowilem nie ma to znaczenia ... (2) no juz wiadomo co jest argumentem PUSH-a ... nie wiesz ? ... nie uwazales ! ... oczywiscie to wskaznik do naszego zXOR-owanego SERIALA !!! ... A wiec trzeba wejsc w tego CALL-a (3) ...

11.Wchodzimy w CALL-a (F8) i widzimy :

             MOV   ESI,[ESP+04]    (1)
             ADD   ESI,0E          (2)
             MOV   EAX,[ESI]       (3)
             RET                   (4)

(1) do ESI wkladany jest wskaznik do naszego zXOR-owanego SERIALA ... (2) Teraz do ESI dodawane jest 0Eh (14d), to teraz na co bedzie wskazywal adres w ESI ??? ... TAK ! na 15 znak z naszego SERIALA ... dlaczego ? ... no bo po wykonaniu (1) ESI wkazywal na pierwszy znak z naszego zXOR-owanego SERIALA ... przy czym nasz SERIAL (nawet ten zXOR-owany) ma 18 znakow ... czyli 1 (bo pierwszy znak) + 14 (bo (2) ) = 15 (15 znak w zXOR-owanym SERIALU) ... UWAGA !!! ... tylko pierwszych 14 znakow zostalo zXOR-owane z 'A','B', itd. ... natomiast ostatnie 4 (bo wszystkich 18) pozostaly nienaruszone !!! ostatnie 4 to w moim przypadku : 3321 (33 33 32 31) ... (3) Te ostatnie 4 znaki (ich wartosci hexadecymalne) zostaja zapisane do EAX, czyli teraz EAX=31323333 (znowu odwrotnie niz w oknie danych - zob. wyjasnienie wczesniej) (4) no i RET - powrot z funkcji.

12.Gdy juz wyszlismy z funkcji obserwujemy taki kawalek kodu :

             ADD   ESP,04             (1)
             CMP   EAX,[004020F9]     (2)
             SETZ  AL                 (3)
             PUSH  EAX                (4)
             TEST  AL,AL              (5)
             JZ    00401137           (6)

(1) Raczej nie ma znaczenia ... (2) mmmm ... to wyglada na zasadnicze porownanie !!! ... jak wiemy w EAX mamy ostatnie 4 znaki z naszego SERIALA ... natomiast w 004020F9 ... wiesz chyba co tam jest ??? ... no dobra wiem masz skleroze ;) ... a wiec pod 004020F9 znajduje sie suma zXOR-owanych znakow (pierwszych 14) z naszego SERIALA ... (3) SETZ ustawia AL na 1 jesli wynik CMP wypadl pomyslnie to znaczy argumenty CMP sa rowne ... (4) nie ma znaczenia ... (5) teraz nastepuje sprawdzenie AL - jesli jest tam jeden to skok w (6) nie nastapi a jesli zero to nastapi ... Latwo sie domyslic ze EAX musi byc rowne [004020F9] aby SERIAL w pliku byl prawidlowy !!!!!

13.Okay ... Zabezpieczenie omowione ;) ... teraz zastanowmy sie jak go zlamac ? ... hmmm ... moglibysmy sie zastanawiac jak odwrocic to 31323333 aby otrzymac pierwsze 14 znakow, ale raczej do niczego bysmy nie doszli, i tylko utrudnilibysmy sobie zycie heh ... rozwiazanie sie samo nasuwa i jest bardzo proste ;) ... dlaczego by nie zrobic tak : ostatnie 4 znaki z seriala zastapis wlasnie ta suma z [004020F9] !!! i wtedy EAX bedzie rowne temu [004020F9] i warunek z (5) zostanie spelniony i po robocie ;) No dobra ... ale powiesz, jak mamy zapisac w pliku ta sume jako 4 ostatnie znaki, skoro ta sume (u mnie FE 50 34 12) nie da sie przedstawic w formie ASCII ??? ... Nic prostszego !!! ... ladujemy plik CRACKME3.KEY do jakiegos HEXedytora czy edytora ktory umozliwia zapisywanie w trybie HEXadecymalnym i pierwsze 14 znakow zapisujemy normalnie jako ASCII a w ostatnich 4 zapisujesz ta sume jaka Ci wyszla ... oczywiscie wiadomo, ze bedzie ona uzalezniona od 14 pierwszych znakow w twym SERIALU !!!

14.Zapisujemy zmiany w pliku ... uruchamiamy CRACKME.EXE ... i ukazuje nam sie message z info : "Cracked by: pppwwwvzzzyy}|" ... huh ? ... co to ma byc to pppww... ??? odp: jest to ten zXOR-owany SERIAL (14 znakow) (u Ciebie napis bedzie inny - jesli dales inny SERIAL w pliku !!!) ... hehe ... chyba wiesz jakie masz zadanie ??? ... musisz tak wpisac SERIAL w pliku aby program ladnie wyswietlil komunikat np. "Cracked by: Mirek" ... a do tego czasu mozemy sie rozkoszowac napisem "CRACKED !!!" na okienku z programem ;) ...

END !!!

PS. na zadanie macie tez CrueMe (CRUEME.EXE)... UWAGA !!! ... on juz nie jest prosty !!! ... przyznam sie bez bicia, ze go (jeszcze) nie zlamalem ;) ... wiec jesli go zlamiesz daj mi znac ! ...

MARRY CHRISTMAS AND HAPPY NEW YEAR(S) ...

Linki :

THE END ... OF MICRO$OFT ... IS COMING .......