-------------------------------------------------------- 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