ToolBar v 5.2 by Ptasiek

Co: ToolBar v 5.2
Skad: ENTER 5/99
Czym: SI
Efekt: keyGen
Witam

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