Co: ToolBar v 5.2 Skad: ENTER 5/99 Czym: SI Efekt: keyGenWitam
Tym razem zajmiemy sie programem o dosc prostym algorytmie generowania seriala na podst name i company.
Uruchamiamy proga, oczywiscie 30 days left i nagscreen UNREGISTERED USER. Po krotkim obejrzeniu funkcji programu nastepujace wnioski:
Right Click na nazwie paska ujawnia menu - wchodzimy HELP/Register. Trzy textboxy - na wpisanie name, company i seriala. No to do dziela.
Zastawiamy breakpointy textowe w SI:
bpx GetWindowTextA i bpx GetDlgItemTextA.
Wpisujemy nasze wymyslone dane:Ptasiek, CrackPL, 30091981 i wciskamy enter. Si zatrzymuje wykonanie zadania na funkcji GetDlgItemTextA trzy razy. Wychodzimy z ostatniego wywolania funkcji (F12)
Idziemy dalej (F10) i docieramy do:
:00412E28 51 push ecx :00412E29 E8B14D0000 call 00417BDF :00412E2E 56 push esi :00412E2F 8BD8 mov ebx, eax :00412E31 E8DA3C0000 call 00416B10 :00412E36 83C408 add esp, 00000008 :00412E39 3D92A71901 cmp eax, 0119A792 :00412E3E 7518 jne 00412E58
Ciekawe. puscmy program jeszcze raz i na 412e3e zmienmy flage zerowa(aby odwrocic warunek skoku): r fl z i (F5) - boom program zarejestrowany: ale na czyje dane: Wyglada na toze autor testowal procke rejestracyjna na sobie 8-).
No tak, ale chcemy wiadomo miec nasze dane w oknie ABOUT, wiec sprawdzmy gdzie program zapisuje dane usera. Uruchamiamy regmona i ToolBar. Na widoku pokazuja sie ladnie nasze dane:
[HKEY_CURRENT_USER\Software\Software by Design\ToolBar for Windows 95/NT\Registration]
So wymazmy regeditem wartosc [...\Code] i przystapmy od nowa do dziela: Tym razem oczywiscie nie zmieniamy skoku i idziemy dalej:
:00412E58 3D3CCE5F0D cmp eax, 0D5FCE3C :00412E5D 750C jne 00412E6B
Uaa, kolejne porownanie, i zmieniamy flage po raz kolejny r fl z. Program tym razem poprawnie sie zarejestrowal na nasz username. Niektorzy skonczyliby na tym robote, ale my zrobimy inaczej - znajdziemy procke generujaca serial i napiszemy keyGena. Cofamy sie do calla pod adresem 412e31 i sprawdzamy co w nim siedzi(F8):
:00416B10 51 push ecx
:00416B11 53 push ebx
:00416B12 8B5C240C mov ebx, dword ptr [esp+0C]
:00416B16 56 push esi
:00416B17 33F6 xor esi, esi
:00416B19 53 push ebx;nasz username
:00416B1A 8974240C mov dword ptr [esp+0C], esi
* Reference To: KERNEL32.lstrlenA, Ord:0308h
|
:00416B1E FF15B0104200 Call dword ptr [004210B0]
:00416B24 85DB test ebx, ebx
:00416B26 744F je 00416B77
:00416B28 85C0 test eax, eax;eax=dlugosc username
:00416B2A 744B je 00416B77
:00416B2C 33D2 xor edx, edx;edx=0
:00416B2E 85C0 test eax, eax
:00416B30 7E45 jle 00416B77
:00416B32 55 push ebp
:00416B33 57 push edi
* Possible StringData Ref from Data Obj ->"|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw9"
->"4cmqpfhw"
|
:00416B34 BECC804200 mov esi, 004280CC;przeliczenia aby
:00416B39 BF01000000 mov edi, 00000001;eax+edx+428094 wskazywaly
:00416B3E 2BF3 sub esi, ebx;na drugi string, a
:00416B40 8BCB mov ecx, ebx;edi+ecx na kolejny cyfry: 1,2,3...
:00416B42 2BFB sub edi, ebx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00416B6D(C)
|
:00416B44 0FBE1C0E movsx ebx, byte ptr [esi+ecx];ebx=string1[nr]
:00416B48 0FBEAC1094804200 movsx ebp,byte ptr
[eax+edx+00428094];ebp=string2[nr+dlugosc_username]
:00416B50 0FAFDD imul ebx, ebp;mnozenie w ebx wynik
:00416B53 8D2C0F lea ebp, dword ptr [edi+ecx];ebp=nr znaku w ;username aktualnie obrabianego
:00416B56 0FAFDD imul ebx, ebp;jw
:00416B59 0FBE29 movsx ebp, byte ptr [ecx];ebp=username[nr]
:00416B5C 0FAFDD imul ebx, ebp;jw
:00416B5F 8B6C2410 mov ebp, dword ptr [esp+10];ebp=jakas dana
:00416B63 03EB add ebp, ebx;ebp=ebp+ebx
:00416B65 42 inc edx
:00416B66 41 inc ecx
:00416B67 3BD0 cmp edx, eax;czy ostatni znak juz byl?
:00416B69 896C2410 mov dword ptr [esp+10], ebp;dana=ebp
:00416B6D 7CD5 jl 00416B44;jesli nie to skacz
:00416B6F 8BC5 mov eax, ebp;eax=dana
:00416B71 5F pop edi
:00416B72 5D pop ebp
:00416B73 5E pop esi
:00416B74 5B pop ebx
:00416B75 59 pop ecx
:00416B76 C3 ret
Taak ciekawa procka, ale nie ma tu nic o serialu. Czyzby wiec niektore numery byly stale?
Wyjdzmy z procki(F12) i przy naszym drugim skoku(tym gdzie rejestrowalismy sie na nasze dane) Nie zmieniajmy flagi, az dojdziemy do takiego codu:
:00412E6B 57 push edi :00412E6C 56 push esi :00412E6D E80E230000 call 00415180 :00412E72 83C408 add esp, 00000008 :00412E75 3BD8 cmp ebx, eax;w ebx nasz falszywy serial :00412E77 5F pop edi :00412E78 741D je 00412E97;jesli eax=ebx to skacz
No tak, widac, ze poprawna rejestracja zalezy od eax, w ktorym bez watpienia jest wynik procedury spod adresu: 412e6d. Zajrzyjmy do niej:
:00415180 8B442404 mov eax, dword ptr [esp+04] :00415184 56 push esi :00415185 8B3560F14200 mov esi, dword ptr [0042F160] :0041518B 50 push eax :0041518C 81CE78030000 or esi, 00000378;esi=808883f8 :00415192 E879190000 call 00416B10; nie brzmi znajomo?,eax=dana1 :00415197 8B4C2410 mov ecx, dword ptr [esp+10] :0041519B 03F0 add esi, eax;esi=esi+eax :0041519D 51 push ecx :0041519E E86D190000 call 00416B10;eax=dana2; :004151A3 83C408 add esp, 00000008 :004151A6 03C6 add eax, esi;eax=eax+esi; :004151A8 5E pop esi :004151A9 C3 ret
call 416b10 - ta procke wylistowalismy juz wczesniej so nie ma potrzeby jej przytaczania. Widac, ze w eax=dana_z_pierwszej_procki+dana_z_drugiej_procki+(dword ptr[0042f160] or 378)
Pod dword ptr[0042f160] zawsze znajduje sie 80888088 co po or'owaniu z 378 daje 808883f8
So wzor na serialname wyglada tak: serial=dana1+dana2+808883f8.
Dlaczego ta sama procka jest wywolywana dwa razy? przyjrzyjmy sie parametrom w I-ym i w II-im wywolaniu: Gdy pasek wykonania kodu na 00416B16 to: d ebx(nasz string). najpierw mielony jest nasz name, a potem company. Napiszmy wiec schemat tej procki bardziej po ludzku:
for i=1 to length(string3) ebx=string1[i];string1 to ten ww staly ciag ebp=string2[i+length(string3)];string2 to drugi string pomocniczy niewidoczny w zasobach pliku ebx=ebx*ebp ebp=i ebx=ebx*ebp ebp=string3[i] ebx=ebx*ebp dana1=ebx
To samo dla dana2 i dalej: serial=dana1+dana2+808883f8
Jak widac algorytm banalny, a procka krociutka. Ponizej listing keyGena w TP:
const string1:string='|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw';
string2:string=chr($23)+chr($73)+chr($65)+chr($72)+chr($42)+chr($26)+chr($6e)+chr($7a)+chr($7c)+chr($6d)+chr($66)+
chr($4d)+chr($31)+chr($2f)+chr($35)+chr($28)+chr($21)+chr($73)+chr($64)+chr($24)+chr($4d)+chr($71)+chr($2e)+
chr($7b)+chr($73)+chr($5d)+chr($2b)+chr($73)+chr($46)+chr($6a)+chr($74)+chr($4b)+chr($70)+chr($7a)+chr($53)+
chr($64)+chr($74)+chr($7a)+chr($6f)+chr($58)+chr($71)+chr($6d)+chr($62)+chr($5e)+chr($41)+chr($6c)+chr($40)+
chr($64)+chr($76)+chr($3a)+chr($73)+chr($3f)+chr($78)+chr($2f)+chr($0)+chr($0)+chr($7c)+chr($62)+chr($21)+chr($70)
+chr($7a)+chr($2a){+chr($7a)+chr($7a)};
var string3:string;
string4:string;
index:byte;ebx,edi,ebp,dana:longint;esi:real;
begin;
dana:=0;
esi:=0;
writeln('ToolBar 5.2 for W95 by Ptasiek');
writeln('Enter your name:');
readln(string3);
if length(string3)=0 then exit;
writeln('Enter the name of your company:)');
readln(string4);
for index:=1 to length(string3) do
begin;
ebx:=ord(string1[index]);
ebp:=ord(string2[index+length(string3)]);
ebx:=ebx*ebp;
ebp:=index;
ebx:=ebx*ebp;
ebp:=ord(string3[index]);
ebx:=ebx*ebp;
dana:=dana+ebx;
end;
esi:=dana+2156430328.0;
dana:=0;
if length(string4)<>0 then
for index:=1 to length(string4) do
begin;
ebx:=ord(string1[index]);
ebp:=ord(string2[index+length(string4)]);
ebx:=ebx*ebp;
ebp:=index;
ebx:=ebx*ebp;
ebp:=ord(string4[index]);
ebx:=ebx*ebp;
inc(dana,ebx);
end;
esi:=esi+dana;
writeln(esi:0:0);
end.
Oczywiscie mozna wydluzyc string2 przepisujac bajty z okna danych SI. No i to wszystko. jezeli masz jakies sugestie, problemy ze zrozumieniem tego textu tradycyjnie skontaktuj sie ze mna.
Na razie
Ptasiek
dreadpl@polbox.com
21.05.1999