GodeZip 98 by Ptasiek

Autor:	Ptasiek
Cel:	GodeZip 98
Skad:	Enter 5/99
Czym:	SI
Efekt:	serial&keyGenerator

Wstep:

Wielu newbies crackujac progi z prostymi wrecz sztandarowymi zabezpieczeniami zazwyczaj szuka poprawnego seriala w pamieci. Niestety nie zawsze program jest tak uprzejmy i podaje go nam jak na tacy w oknie danych SI. Sa tez progi, w ktorych poprawnosc seriali sprawdza sie poprzez przeprowadzenie na nich jakichs operacji matematycznych i operowania wynikiem. Jeden z takich progow zostal opisany przeze mnie wczesniej(BannerShow2). Dzis mam zaszczyt przedstawic kolejny produkt nie generujacy poprawnego seriala.

GodeZip jest progiem do zarzadzania zzipowanymi plikami. Posiada licznik uruchomien - limit 25. Rejestruje sie go przez podanie nr licencji i kodu odblokowujacego. Brzmi groznie, ale w rzeczywistosci algorytm jest banalny.

Uruchamiamy proga z zaladowanym SI. Przechodzimy do okienka rejestracyjnego i wpisujemy jakies dane:

licencja:	123123123123
kod	:	qwerty

Wchodzimy do SI (CTRL+D) i ustawiamy breakpointy na standardowe funkcje API pobierania textu:

bpx getwindowtexta
bpx getdlgitemtexta

Wychodzimy z SI (CTRL+D) i klikamy OK. Zadzialala pulapka na Getdlgitemtexta. Spoko, widzimy, ze funkcja ta wywolywana jest dwa razy - pobieraja one licencje i kod.

Idziemy dalej - krok po kroku, wchodzac do najblizszej procedury(F8 - gdy step na instrukcji call):

* Referenced by a CALL at Addresses:
|:00402CCA   , :00402F30   
|
:004027CC 55                      push ebp
:004027CD 89E5                    mov ebp, esp
:004027CF 57                      push edi
:004027D0 56                      push esi
:004027D1 53                      push ebx
:004027D2 8B5D08                  mov ebx, dword ptr [ebp+08]
:004027D5 BE1CD34300              mov esi, 0043D31C;(nasza licencja)

* Possible StringData Ref from Code Obj ->"G1111111"
                                  |
:004027DA BF91254000              mov edi, 00402591
:004027DF B809000000              mov eax, 00000009
:004027E4 89C1                    mov ecx, eax
:004027E6 FC                      cld
:004027E7 A800                    test al, 00
:004027E9 F3                      repz
:004027EA A6                      cmpsb;porownanie jej z G1111...
:004027EB 0F843D020000            je 00402A2E;jezeli rowne to skacz

Takich porownan jest jeszcze kilka. W ten prymitywny sposob autor chcial sie bez watpienia zabezpieczyc przed crackerami. No coz nie na wiele mu sie to zdalo. Idziemy dalej:

:00402825 E85AFFFFFF              call 00402784;dziwna procka - uzywa dodatkowego
;rejestru segmentowego - chyba jakis antidebug - ale nie dziala na SI 
;(moze sie myle)
:0040282A 85C0                    test eax, eax
:0040282C 0F8501020000            jne 00402A33
:00402832 803B44                  cmp byte ptr [ebx], 44;w [EBX] nasz kod, a
;konkretnie jego 1-y znak jest porownywany z 'D'
:00402835 0F94C0                  sete al;nadaj al wartosc flagi Z
;jezeli ostatnio porownywane wartosci so rowne to Z=1 w przeciwnym razie
;Z=0
:00402838 0FB6D0                  movzx edx, al
:0040283B 8B4D0C                  mov ecx, dword ptr [ebp+0C];wpisz do [ECX]
;nasza licencje
:0040283E 803947                  cmp byte ptr [ecx], 47;i porownaj 1-y znak licencji
;z 'G' dalej analogicznie jw
:00402841 0F94C0                  sete al
:00402844 25FF000000              and eax, 000000FF;EAX:=EAX AND FF
:00402849 85D0                    test eax, edx;EAX AND EDX - ale zmienia
;tylko znacznik - ww rejestry bez zmian.
:0040284B 0F84D7010000            je 00402A28;jesli Z=1 to skacz
:00402851 E82EFFFFFF              call 00402784

Spostrzezenia: procka ta, wywolywana jest dwa razy. Prawdopodobnie ten drugi CALL przy starcie proga, co by znaczylo, ze seriale nie sa przechowywane w postaci zaszyfrowanej Dalej 1-y znak licencji porownywany jest z 'G', a 1-y kodu z 'D' potem wykonywane jest EAX AND FF

AND jest logiczna operacja na bitach:

argument1(bit_nr_X)=1 gdy argument1(bit_nr_X)=1 oraz argument2(bit_nr_X)=1.

W kazdym innym przypadku daje zero.

Przyklady:
0 	AND 	255	=	0
00000000	11111111	00000000
1	AND	255	=	1
00000001	11111111	00000001
128	AND	63	=
10000000	00111111	00000000

A wiec jak wynika z powyzszego numery musza sie zaczynac na wskazane litery. Wyjdzmy wiec z SI i uzupelnyjmy nasze nr o te znaki - i wsio od poczatku

G123123123123
Dqwerty

Ok, nastepnie zaczyna sie proces sprawdzania zgodnosci licencji z kodem:

:00402858 0F85CA010000            jne 00402A28
:0040285E 0FBE5306                movsx edx, byte ptr [ebx+06];EDX=kod[7]
:00402862 8B4D0C                  mov ecx, dword ptr [ebp+0C]
:00402865 0FBE4101                movsx eax, byte ptr [ecx+01];EAX=licencja[2]
:00402869 83C01E                  add eax, 0000001E;EAX=EAX+1e
:0040286C 39C2                    cmp edx, eax;porownaj EAX i EDX
:0040286E 0F85B4010000            jne 00402A28;jesli rozne to skacz
:00402874 E80BFFFFFF              call 00402784;nic waznego

W tym fragmencie listingu prog bierze siodmy znak kodu i porownuje go z drugim znakiem licencji powiekszonym o 1e. Konkretnie porownuje ich cody ASCII So tutaj i ponizej sa zaleznosci wymagane przez procke, aby numery byly poprawne. Idziemy w dol zmieniajac flage przy kazdym skoku az dojdziemy do:

:00402A15 7511                    jne 00402A28
:00402A17 E868FDFFFF              call 00402784
:00402A1C 85C0                    test eax, eax
:00402A1E 7508                    jne 00402A28
:00402A20 B801000000              mov eax, 00000001;EAX=1
:00402A25 EB0E                    jmp 00402A35;skocz do dziekczynnego messageboxa

Cala filozofia opiera sie na spisaniu wszystkich zaleznosci znakow licencji od znakow kodu i napisac maly keyGen, aby dokonczyc dziela. Komu nie chce sie zmudnie spisywac dzialan ten ma je spisane ponizej w zalaczonym source keyGena.: Generuje on licencje na podstawie kodu, a wiec Twoj nick nie bedzie widoczny w oknie About.. Mozna opierajac sie na tym source'u napisac odwrotna funkcje, ale jej wynikami beda znaki ASCII spoza zakresu widzialnosci wINSHITA.

uses crt;
var licencja,kod:string;i:byte;
begin;
licencja[1]:='D';
writeln('The GodeZip98 keyGenerator made by Ptasiek. Enjoy it!');
writeln('Polish crack rulz');
writeln('Enter string');
readln(kod);

insert('D',kod,1);
if length(kod)<16 then
for i:=length(kod)+1 to $f do kod[i]:='a';

licencja[2]:=chr(ord(kod[7])-$1e);
licencja[3]:=chr(ord(kod[6])-$17);
licencja[4]:=chr(ord(kod[3])-$1f);
licencja[5]:=chr(ord(kod[8])-$11);
licencja[6]:=chr(ord(kod[4])-$13);
licencja[7]:=chr(ord(kod[2])-$15);
licencja[8]:=chr(ord(kod[5])-$1d);
licencja[9]:=chr(ord(kod[9])-$1e);
licencja[$e]:=chr(ord(kod[$a])-$1c);
licencja[$f]:=chr(ord(kod[$b])-$18);
licencja[$c]:=chr(ord(kod[$c])-$15);
licencja[$d]:=chr(ord(kod[$d])-$16);
licencja[$b]:=chr(ord(kod[$e])-$1b);
licencja[$a]:=chr(ord(kod[$f])-$1d);
licencja[1]:='G';
clrscr;
writeln;
write('Kod      : ');
for i:=1 to $f do
begin;
write(kod[i]);
gotoxy(wherex-1,wherey-1);
write('_');
gotoxy(wherex,wherey+1);
end;
writeln;
writeln;
write('licencja : ');
for i:=1 to $f do
write(licencja[i]);
end.

Dobra, teraz dla sprawdzenia uruchamiamy proga poraz drugi i... Unregistered - co sie stalo - czyzby nie docenilismy autora, ktory wyposazyl proga w opcje falszywej rejestracji - A niech sie tam cracker ucieszy. Ale nigdzie nie wywolywana jest innna procka sprawdzajaca. Wobec tego ustalmy gdzie przechwywany jest serial. Uruchamiamy regmona i nasz prog. Ciekawie wyglada plik godezip.ini Przejrzyjmy go:

(..)
licencenum=
licencekey=
(..)

Co jest?, brakuje danych. Tak jakby prog ich nie wpisal. Chwila zastanowienia(no, moze dwie chwile) olsnienie - setup proga polegal jedynie na skopiowaniu plikow z CD so looknijmy w attrybuty tego pliku - no tak tylko_do_odczytu. Usunmy ow attrybut i zarejestrujmy prog jeszcze raz. Super dziala! Oto przyklad na banalne rozwiazanie skomplikowanego z pozoru problemu. Na dzis to juz wszystko tradycyjnie jesli masz jakies pytania, uwagi sugestie pisz:

dreadpl@polbox.com
Ptasiek