Cel: Wash&Go 1.0a Skad: eNTER 4/2000 Narzedzia: SI Skala trudnosci: [xx----]
Tak sobie siedze przed monitorem wpatrujac sie bezmyslnie w zielony pulpit winshita (mam za slabego kompa na umieszczenie tapety), maturka za miesiac, a ja nawet do podrecznika IV klasy nie zajrzalem bo nie mam. No ale nie ma co sie przejmowac na zapas jakos to bedzie, carpe diem, zyjmy chwila jak mawiali starozytni Grecy. Siedze sobie wygodnie i tak sie zastanawiam, kiedy ostatnio napisalem cosik odkrywczego dla pragnacych wiedzy crackerow. Huh, duzo w rzece wody uplynelo od czasu, gdy ostatni tut opuscil moj komp wedrujac w przesylce emailowej po zakamarkach inetu do zadnych informacji czytaczy, warto wiec sie zabrac do roboty coby nie zostawic na lodzie tych wszystkich biednych newbies czytajacych stare oklaple jush tutory i z zapamietaniem crackujacych produkty firm JZK i MarBitSoftware; dla nieobeznanych w temacie - poziom zabezpieczen w programach ww firm jest zaden, co wiecej ta druga wypuscila na rynek program z bledem uniemozliwiajacym poprawna rejestracje. sic!. Tia, kiepsko wygladaja zabezpieczenia polskiego softu przed crackowaniem. Az plakac sie chce czlowiekowi gdy widzi blyskotliwe rozwiazania zachodnich programistow, o ktore rozbijaja sie wysilki wielu pokolen reverse engineerów. Nie do pomyslenia jest fakt, ze u progu XXI wieku najczesciej spotykanym fragmentem kodu w swojskich produktach jest archaiczny bad/good boy. Polscy programisci, czy tak trudno jest poswiecic pare godzin na pobuszowanie w sieci, tam az roi sie od opisow, schematow i konkretnych przykladow zabezpieczen programowych. Inna sprawa, ze towarzysza im zazwyczaj opisy jak je zlamac, ale w koncu liczy sie szybkosc wykorzystania danej informacji.
Ups. zagalopowalem sie troche, txcior przeznaczony w zamysle do poczatkujacych crackerow zaadresowalem do "profesjonalnych" polskich programistow. Dobrze, ze znaczka nie przykleilem:).No, to zaczynamy, naszym celem bedzie program Wash&Go 1.0a, wypatrzony na JEDYNEJ plycie kwietniowego eNTERA(4/2000). Daje slowo, ta gazeta coraz bardziej schodzi na psy, najpierw kacik dla linuxowcow (jakby nie mieli swojego czasopisma nota bene tez chyba wydawanego przez lUPUSA), teraz brak plyty i jakies badziewne papierowe dodatki do M$Office. It sux. Dobra, koncze to fuckanie, bo czuje, ze emocje w Was narastaja:)
Program sluzy do czyszczenia dysku z nadprogramowych smieci jakie serwuje nam codzien winshit, i imho gdyby doczekal sie polskiej wersji jezykowej to mialby niezle wziecie na naszym rynku. Do łamania bedziemy uzywali tylko SoftIce'a, u mnie 4.0, no i ew. jakiegos komplikatora do zrobienia keygena. Macie jush to wszystko to zaczynamy. Po odpaleniu proga pokazuje sie nam panel z opcjami, klikamy Information i pokazuje nam sie dialog z polem 'Please insert your KEY here!'. Ok, kasujemy ten napisik i wprowadzamy własny, powiedzmy '3312915' (dla tych, ktorzy za duzo pytaja jush wyjasniam - to numer telefonu na sTRAZ mIEJSKA w moim miescie). Po wpisaniu wchodzimy do SI i zastawiamy pulapki na funkcje API pobierajace txt:
bpx GetWindowTextA i bpx GetDlgItemTextA
Ok, po powrocie na powierzchnie naciskamy przycisk 'Use this key' i ladujemy po wywołaniu GetWindowTextA. Wyjdzmy z tej funkcji naciskajac F12. Hm. podejrzany jest rejestr EAX. Jak wiemy wspomniana funkcja zwraca w nim dlugosc pobranego txtu. Po kilku operacjach na kalkulatorze okazuje sie, ze dlugosc naszego s/n to 7 (slownie siedem) znakow, a wiec jestesmy w zlym miejscu choc o o dobrym czasie:) Ale nie ma co rezygnowac, czas poprostu na bron najciezszego kalibru - hmemcpy. 'Let the combat begin'
Hehe, jush widze wasze spocone twarze, rozbiegane oczy, a w nich strach przed przebijaniem sie przez gaszcz bibiotek systemowych. Spox, nie pekajcie to nie VB tutaj raz dwa wrocimy do kodu programu. A wiec kasujemy poprzednie pulapki bc* i ustawiamy nowa: bpx hmemcpy
Nie zapomnijcie przedtem wpisac seriala bo inaczej bedziecie ladowali w debuggerze za kazdym wpisanym znakiem. Jesli wszystko ok to naciskamy przycisk i... wskakujemy do wnetrza funkcji. Teraz naciskamy pare razy F12, az znajdziemy sie w programie glownym(przypominam, ze informuje o tym wyswietlanie przez SI nazwy programu pomiedzy oknem kodu a linia polecem (przy defaultowych ustawieniach of coz). Teraz patrzymy w EAX, jest 7 wiec znalezlismy sie na dobrym tropie, a konkretnie w środku procedury pobierajacej txt z okienka. Poniewaz znajdujemy sie prawie pod koniec (widac koncowe porzadki - przywracanie stosu i RET) to mozemy sobie pozwolic na odrobine fantazji czyli F12 az przestaniemy widziec koncowy fragment jakichs procedur (czyli wspomiane przeze mnie porzadki). Po tym maratonie znajdziemy sie tutaj:
0137:00449C18 MOV EAX,[EBP-01D0]; <<lt;tutaj jestesmy 0137:00449C1E CALL 00403BB0 0137:00449C23 CMP EAX,06 ; dlugosc naszego sn 0137:00449C26 JLE 00449E15 ;czy mniejsza, rowna 6 0137:00449C2C LEA EDX,[EBP-01D0] ;jesli nie to idz dalej 0137:00449C32 MOV EAX,[EBX+00000A50] 0137:00449C38 CALL 0041CB6C 0137:00449C3D MOV EDX,[EBP-01D0] 0137:00449C43 LEA ECX,[EBP-01D4] 0137:00449C49 MOV EAX,00449EA0 ;txt WASHANDGO 0137:00449C4E CALL 00438768 ;procka rejestrujaca? 0137:00449C53 CMP DWORD PTR [EBP-01D4],00 0137:00449C5A JZ 00449E15 ;czy zarejestrowany?
hm. zmiana tego skoku nic nie powoduje, ale rzeczywiscie odpowiada on za stwierdzenie rejestracji, prowadzi on bezposrednio do procedury wyswietlajacej okno 'Wrong key...'. Wiemy jush, ze nasz s/n musi byc dluzszy od 6, przyjrzyjmy sie teraz procedurze spod adresu 449EA0. Jej poczatek to smieci komplilatora, ustawianie obslugi wyjatkow itp. Cos sie zaczyna dziac dopiero odtad:
0137:004387A5 MOV BYTE PTR [EBP-21],01 ;wyglada to jak flaga 0137:004387A9 LEA EAX,[EBP-0C] 0137:004387AC CALL 00403934 0137:004387B1 LEA EAX,[EBP-20] 0137:004387B4 MOV EDX,[EBP-08] 0137:004387B7 CALL 004039CC 0137:004387BC LEA EAX,[EBP-21] 0137:004387BF MOV EDX,[EBP-20] 0137:004387C2 CALL 004385F4 0137:004387C7 MOV EAX,[EBP-20] 0137:004387CA CALL 00403BB0 0137:004387CF MOV ESI,EAX 0137:004387D1 MOV EAX,[EBP-20] 0137:004387D4 CALL 00403BB0 ;w eax dlugosc naszego seriala 0137:004387D9 MOV ECX,00000003 0137:004387DE CDQ 0137:004387DF IDIV ECX ;dlugosc seriala/3 0137:004387E1 TEST EDX,EDX ;czy jest reszta z dzielenia? 0137:004387E3 JNZ 00438838 ;jesli tak to skacz ............. 0137:00438838 MOV BYTE PTR [EBP-21],00 ;tutaj; czyszczenie flagi 0137:0043883C CMP BYTE PTR [EBP-21],00 ; i jej sprawdzenie 0137:00438840 JZ 00438852
Ok, pod adresem 4387DF nasza dlugosc jest dzielona przez 3. Wynik instrukcji IDIV to eax - wynik dzielenia calkowitego, edx - reszta z dzielenia. EDX bedzie rowne zero tylko wtedy gdy dlugosc sn podzieli sie calkowicie przez 3, czyli gdy bedzie wielkokrotnoscia trojki. Ale nie zapominajmy, ze dlugosc s/n musi byc wieksza od 6. Tak wiec wpisujemy nowy 9 znakowy sn: 331291512 i wracamy do sledzenia kodu.
0137:004387E8 CALL 00403934 0137:004387ED LEA EAX,[EBP-1C] 0137:004387F0 CALL 00403934 0137:004387F5 MOV EBX,00000001 0137:004387FA LEA EAX,[EBP-28] [..] 0137:00438831 INC EBX 0137:00438832 CMP ESI,EBX 0137:00438834 JG 004387FA
Petla sprawdza czy s/n nie zawiera niedozwolonych znakow typu ^, ! i jesli stwierdzi ich wystapienie to zeruje flage rejestracji [EBP-21].
0137:00438842 LEA ECX,[EBP-10] 0137:00438845 MOV EDX,[EBP-18] ;string zawierajacy co trzeci 0137:00438848 MOV EAX,00000015 ;znak s/n liczac od pierwszego 0137:0043884D CALL 004386A4 ; procka miejaca nasz s/n 0137:00438852 CMP BYTE PTR [EBP-21],00 0137:00438856 JZ 00438868 0137:00438858 LEA ECX,[EBP-14] 0137:0043885B MOV EDX,[EBP-1C]; jw. ale liczac od trzeciego 0137:0043885E MOV EAX,00000007 0137:00438863 CALL 004386A4 0137:00438868 MOV EAX,[EBP-10] ;porownanie wygenerowanych txt 0137:0043886B MOV EDX,[EBP-14] 0137:0043886E CALL 00403CC0 0137:00438873 JZ 00438879 0137:00438875 MOV BYTE PTR [EBP-21],00 0137:00438879 CMP BYTE PTR [EBP-21],00 0137:0043887D JZ 0043888A ............. 0137:004388BE MOV EDX,[EBP-2C] ;porownanie I znaku I stringa 0137:004388C1 POP EAX ;z litera 'W' 0137:004388C2 CALL 00403CC0
Ok, no to mamy jush praktycznie caly schemat, teraz warto sie przyjrzec prockom przerabiajacym oba stringi. Jak widac jest to jeden i ten sam kawalek kodu, ale pobierajacy rozne parametry 15h i 7. Wnetrze procedury , a raczej jego istotny fragment wyglada tak:
0137:004386E8 JLE 00438731 0137:004386EA MOV EBX,00000001 0137:004386EF MOV EAX,[EBP-10] 0137:004386F2 MOV AL,[EBX+EAX-01] ;do al znak stringu 0137:004386F6 CMP AL,2D 0137:004386F8 JZ 00438720 0137:004386FA MOV EDX,[EBP-10] 0137:004386FD MOV EDI,EAX 0137:004386FF AND EDI,000000FF 0137:00438705 SUB EDI,[EBP-04] ;znak minus 15h lub 7h 0137:00438708 CMP EDI,30 ;czy rowne 30h? 0137:0043870B JGE 00438710 ;jesli wieksze to skacz 0137:0043870D ADD EDI,2B ;jesli nie to dodaj 2bh 0137:00438710 LEA EAX,[EBP-10] 0137:00438713 CALL 00403D80 0137:00438718 MOV EDX,EDI 0137:0043871A MOV [EBX+EAX-01],DL ; i zapisz nowy znak 0137:0043871E JMP 0043872D 0137:0043872D INC EBX 0137:0043872E DEC ESI 0137:0043872F JNZ 004386EF
Oba wygenerowane stringu sa nastepnie porownywane ze soba. Jesli beda one jednakowe, to zostana zapisane jako NAME uzytkownika (bez uwzglednienia pierwszego znaku 'W' of coz). Czyli klucz nie jest taki bezimienny jakby sie moglo wydawac na poczatku nie widzac okienka na wpisanie name. Wszystko jest jush wylozone jak na tacy, teraz tylko wystarczy sprobowac odwrocic algorytm pamietajac, ze pierwszym znakiem wygenerowanej kombinacji musi byc='W'. Ponadto warto zauwazyc, ze co trzeci znak oryginalnego seriala zaczynajac od drugiego jest nieistotny. Ok, schemat generowania znaku pierwszego stringa wyglada tak
petla: i:=i+1 znak_s:=stringI[i] znak_s:=znak_s-15h jesli znak_s<30h znak_s:=znak_s+2bh koniec_jesli przerobiony_string[i]:=znak_s jesli i<dlugosc skok petla koniec_jesli
Zastanowmy sie jak mozna zamienic na bardziej cracker friendly:)
Rozwazmy nastepujace mozliwosci: Pojednynczy znak_s ma wzor:
znak_s:=znak_name+15h ;pierwsza kombinacjalub
znak_s:=znak_name+15h-2bh czyli znak_s:=znak_name-16h ;druga kombinacja
ZNAK
II
druga kombinacja
czy znak jest dopuszczalny (litera,cyfra)
I------------------II------------------I
I I
nie, wyszedl jakis tak, udalo sie
krzaczek ASCII I
wobec tego uzywamy piewszej I
kombinacji po przywroceniu znaku I
Przywracamy oryginalna wartosc I
znaku (czyli dodajemy 16h) I
pierwsza kombinacja I
I I
I------------------II------------------I
zapisz przemielony znak
To samo postepujemy z drugim stringiem pamietajac, ze parametrem zamiast 15h jest 7h. Wezmy dla przykladu name='WPTASIEK'
W(57h)-16h=41h('A')
P(50h)-16h=3Ah(':')+16h+15h=65h('e')
...
AeiVh3Z5
Drugi string:
W(57h)-24h=33h('3')
P(50h)-24h=2ch(',')+24h+7h=57h('W')
...
3W0HZPLR
Teraz sklejamy stringi wstawiajac w nieuzywane miejsca myslniki:
A-3e-Wi-0V-Hh-Z3-PZ-L5-R
No i mamy seriala. Program zapisuje g w pliku licencyjnym WASHANDGO.key w swoim katalogu. Majac tyle danych nie jest jush problemem napisanie keygena.
Niestety sposob zaproponowany przeze mnie ma pewna wade - otoz, nie uwzglednia wszystkich niedozwolonych znakow, dlatego jest lepiej ograniczyc stosowanie tego algorytmu do duzych liter i cyfr. Of coz nic nie stoi na przeszkodzie aby uzupelnic go o te brakujace elementy:)
Uff, dobrnelismy do konca (mam nadzieje, ze ktos to jeszcze czyta?) mysle, ze wszelkie wskazowki tutaj zebrane przedadza sie Wam w crackersiej karierze no i na koniec tradycyjnie za wszelkie szkody spowodowane przez wykorzystanie zawartych informacji do celow innych niz edukacyjne nie odpowiadam. To tak dla formalnosci.
3majcie sie, do nextego razu.
Ptasiek/CrackPL
ptasiek@park.px.pl