SuperJPG 3.2 by Ptasiek

Co:	SuperJPG 3.2
Skad:	ENTER 6/99
Czym:	SI+W32Dasm(listingi)
Efekt:	keyGen
Witam!

Text ten ma sluzyc celom wylacznie edukacyjnym. Jego autor (czyli ja) nie odpowiada za jakielkolwiek uzycie zawartych tu informacji w sposob niezgodny z prawem, jak rowniez za wszelkie straty poniesione przez uzytkownika, na skutek niewlasciwego wykozystania informacji tu zawartych!!!!!!!!!!!!!!!!!:-)

SuperJPG jak sama nazwa mowi jest progiem sluzacym do administrowania JPeGami. W wersji SHAREWARE mamy limit czasowi - 30 dni lub uruchomieniowy: 60 razy. Na szczescie prog udostepnia mozliwosc rejestracji.

Spostrzezenia:

Autor nie staral sie zbytnio zabezpieczyc programow pod katem crackingu: uruchamia sie przy zaladowanym SI bez zadnych problemow. Opcja rejestracji jest pod File/Register, so klikamy i przed naszymi oczyma rysuje sie piekny formularz rejestracyjny. Po kliknieciu srodkowego buttona mamy za zadanie wpisac nasz name oraz dwuczesciowy password. Oczywiscie wchodzimy do SI(CTRL+D) i ustawiamy standardowe breakpointy na GetWindowTexta i GetDlgItemTexta:

bpx Getwindwotexa
bpx getdlgitemtexta

Ok, w name wpisujamy naszego nicka, powiedzmy 'Ptasiek'. W passwd nr 1 wpisujemy nasz ulubiony nr '300919', a w passwd nr 2 szczesliwe numery z ToTka:).

Zaraz, jesli uaktywniles pulapki w SI przed rozpoczeciem wpisywania danych to przy przejsciu do passwd nr 2 SI zatrzyma wykonywanie proga i znajdziesz sie w kodzie funkcji GetWindowTextA. Wniosek: w tym editcie, prog pobiera texcik po jednej literze. Dobra wpiszmy co tam mamy wpisac np: '123321' i wcisnijmy OK.

Oczywiscie zatrzymujemy sie na funkcji GetWindowTextA - pobiera nasz name, puszczamy progra dalej F5 i ladujemy w drugiej, ktora pobiera passwd nr 1. Wychodzimy z tej funkcji i zaczynamy szukac po pamieci dokad nasze stringi zostaly zaladowane:

s ds:0 l ffffff 'Ptasiek'

I znajdujemy go pod 1011ff0.(widzimy ten fragment pamieci w oknie danych). Uwaga, niekiedy adres ten moze byc inny! Ustawiamy pulapke na ten adres pamieci, tak aby kazde odwolanie do niego bylo przechwytywane:

bpm dataaddr 

dataaddr to zmienna wewnetrzna SI, ktora wskazuje na aktualny adres w oknie danych. W naszym przypadku taki zapis jest rownowazny z:

bpm 1011ff0.

Zrobmy to samo z passwd nr 1.

Po ustawiemiu pulapki puszczamy proga, aby sam sie wykonywal F5. Zatrzymalismy sie, ale w okolicy nie ma nic ciekawego, so idzmy dalej instrukcja po instrukcji F10. przechodzimy przez ret i jestesmy w:

:0048EB0F 56                      push esi
:0048EB10 8BF1                    mov esi, ecx
:0048EB12 E898FAFFFF              call 0048E5AF
:0048EB17 FF36                    push dword ptr [esi]
;esi - wskaznik do naszego name
* Reference To: USER32.CharUpperA, Ord:0028h
                                  |
:0048EB19 FF15382C5100            Call dword ptr [00512C38]
:0048EB1F 5E                      pop esi
:0048EB20 C3                      ret

Funkcja CharUpperA, jak sama nazwa wskazuje, sluzy do konwersji malych liter stringu na duze. Wiec zamieni 'Ptasiek' na 'PTASIEK'. Idac dalej krok po kroku F10, dochodzimy do ciekawego fragmentu kodu:

:00424C1B 8B85D0FEFFFF            mov eax, dwordptr [ebp+FFFFFED0]
:00424C21 8B8DCCFEFFFF            mov ecx, dword ptr [ebp+FFFFFECC]
:00424C27 50                      push eax
:00424C28 51                      push ecx
:00424C29 E8C2F9FFFF              call 004245F0
:00424C2E 83C408                  add esp, 00000008
:00424C31 8B8DC8FEFFFF            mov ecx, dword ptr [ebp+FFFFFEC8]
:00424C37 3BC1                    cmp eax, ecx
:00424C39 0F85BE000000            jne 00424CFD
:00424C3F 8B85D0FEFFFF            mov eax, dword ptr [ebp+FFFFFED0]

podejrzana jest procedura 4245f0. Aby sprawdzic nasze domysly looknijmy co siedzi pod eax i ecx w momencie ich odkladania na stos: Gdy pasek kodu jest na adresie 424C28 sprawdzamy: d eax, pozniej d ecx.

No tak w EAX siedzi nasz passwd nr 1, a w ECX nasz name. Sprawdzmy wiec co bedzie, gdy zmienimy flage skoku na 424C39: Gdy pasek kodu na tym adresie:

r fl z

I wciskamy F5. Cool! Prog zarejestrowany, podziekowania sie sypia z ekranu. W rzeczywistosci po restarcie proga wszystko jest po staremu. Ale juz wiemy czego sie trzymac. Interesuje nas procka 4245f0. Jej listing to ponad 6 kb so przypuszczam, ze zamieszczajac go zanudzilbym was na smierc so oto niewielki fragment:

:0042460C 8A1A                    mov bl, byte ptr [edx]
:0042460E 80FB61                  cmp bl, 61
:00424611 7C08                    jl 0042461B
:00424613 80FB7A                  cmp bl, 7A
:00424616 7F03                    jg 0042461B
:00424618 80EB20                  sub bl, 20

w edx nasz name - konwersja na duze litery jak CharUpperA. Dalej mamy przeliczenia algortymu kodujacego. uwaga! lea ebx, dword ptr [edx+8*edx] - taki zapis to nic innego jak skrocona wersja wpisywania do ebx wyniku dzialan edx+8*edx. Gdyby uzyto tradycyjnej metody w przyblizeniu wygladaloby to tak:

mov ebx edx
imul ebx,8
add ebx,edx

Oba te fragmentu oznaczaja: ebx=edx+8*edx. Analogiczne przeliczenia sa wykonywane dla passwd nr 1. Wszystkie dzialania jasno widac w souece so tutaj tylko wyjasnienie jednej instrukcji:

:004246E0 C1F807                  sar eax, 07

sar 7= przesuniecie 7 bitow w prawo, najstarszy bit zostaje, a najmlodszy ustawia flage CF. Poniewaz Delphi nie uwzglednia tej instrukcji(niewiem jak z wersja 4.0) so zapisalem ja we wstawce assemblerowej.

Wyjdzmy teraz z tej procedury i przyjrzyjmy sie porownaniu, ktore decyduje o rejestracji: 424C37 EAX czyli wynik przeliczen naszej procki jest porownywany z jakas dana obliczona wczesniej. Przyjrzyjmy sie rejestrowi ECX, chwila na myslenie i przeblysk naszego intelektu - ecx to nic innego jak tylko passwd nr 2. Znakomicie, mamy juz wszystkie elementy ukladanki, so pora na napisanie keyGena.

Tym razem uzyjemy Delphi, gdyz Tp, ktory mialem tylko na twardzielu poszedl na przemial razem z nim. So: tworzymy na formie 3 Edity i jeden Button. Wklejamy zawartosc procki tam, gdzie trzeba, ew dodajemy opisy Editow, obsluge I/O itp.

procedure TForm1.Button1Click(Sender: TObject);
var eax,ebx,ecx,edx,temp:longint;name,sn:string;i:byte;
begin
name:=edit2.text;
name:=uppercase(name);
eax:=$07D2284D;ecx:=0;
for i:= 1 to length(name) do
begin;
edx:=ord(name[i]);
ecx:=edx;
ebx:=edx+8*edx;
edx:=ecx+2*ebx;
edx:=edx shl 7;
edx:=edx+ecx;
ebx:=edx+4*edx;
edx:=ecx+8*ebx;
ecx:=eax;
ecx:=ecx shl 5;
edx:=edx+ecx;
ecx:=eax;
temp:=eax;
asm
sar temp,7
end;
eax:=temp;
ecx:=ecx and $7f800;
ecx:=ecx shr $b;
eax:=eax shl $10;
edx:=edx xor ecx;
edx:=edx xor eax;
edx:=edx and $FFFFFF;
eax:=edx;
end;

sn:=edit3.text;
for i:=1 to length(sn) do
begin;
edx:=ord(sn[i]);
ecx:=edx;
ebx:=edx+8*edx;
edx:=ecx+2*ebx;
edx:=edx shl 7;
edx:=edx+ecx;
ebx:=edx+4*edx;
edx:=ecx+8*ebx;
ecx:=eax;
ecx:=ecx shl 5;
edx:=edx+ecx;
ecx:=eax;
temp:=eax;
asm
sar temp,7
end;
eax:=temp;
ecx:=ecx and $7f800;
ecx:=ecx shr $b;
eax:=eax shl $10;
edx:=edx xor ecx;
edx:=edx xor eax;
edx:=edx and $ffffff;
eax:=edx;
end;
eax:=eax or $A00000;
edit1.text:=inttostr(eax);
end;
edit1.text zawiera passwd nr 2.
CopyRight 1999 Text ten mozesz zamiescic na swojej stronie o ile:
1. przeslesz mi krotkie info o tym
2. Text pozostaje niezmieniony

Jesli chcesz uzyc powyzszego source do wygenerowania kodu dla siebie to nie ma problemu, jesli chcesz go wlaczyc do jakiejs bazy seriali, crackow itp. to nie zapomnij o creditsach, oraz poinformuj mnie o tym.

Ptasiek
ptasiek1@friko.internet.pl
6.6.1999