MemTurbo 1.0a by GustawKit

Program : MemTurbo 1.0a
Gdzie   : Enter CD 1A/99
Tools   : SoftIce, Wdasm, Customiser

Dla rozgrzania komórek wzialem sie za programik MemTurbo 1.0a. Program sluzy do optymalizacji pamieci pod win95. Program jest wersja shareware i nie posiada mozliwosci wpisania danych rejestracyjnych. Po uplywie 30-dni trial uzytkowania programu pojawia sie komunikat o wersji demo i program sie nie uruchamia. Jezeli cofniemy zegar, program wykrywa to i zglasza komunikat o zmianach zegara.

Na poczatek musimy zdisasamblowac kod programu (Wdasm32). Poniewaz cofalem zegar program zglasza mi komunikat "It looks as though your clock has been set backward....". Poszukajmy wiec tego komunikatu w kodzie. Przegladajac kod powyzej znalezionego fragmentu widzimy kilka ciekawych wywolan funkcji API :

ADVAPI32.RegQueryValueExA
KERNEL32.GetSystemTime
KERNEL32.SystemTimeToFileTime
KERNEL32.CompareFileTime
ADVAPI32.RegCloseKey

Widzimy wiec, ze program pobiera dane z rejestrów i porównuje czas instalacji z aktualnym czasem itp. W kazdym razie nie bedziemy sie bawic z tymi porównaniami. Spróbujmy pominac procedure sprawdzania czasu. Analizujemy kod przed wywolaniami tych funkcji i znajdujemy interesujacy skok warunkowy :

:00407C69 E8E29C0000    call 00411950
:00407C6E 83C40C        add esp, 0000000C
:00407C71 85DB          test ebx, ebx
:00407C73 7407          je 00407C7C     <--- skok do porównan czasu
:00407C75 6A51          push 00000051
:00407C77 E962010000    jmp 00407DDE

No wiec co zapuszczamy memturbo.exe pod softice i zakladamy pulapke na 407c73 aby dowiedziec sie co sie stanie jezeli zmienimy ten skok. Oki. puszczamy program, SI przejal nam kontrole nad kodem w interesujacej na linijce. Widzimy, ze flaga jest ustawiona na skok a wiec zmieniamy flage zerowa (r fl z) i puszczamy dalej program. Upsss....... program zglasza komunikat "Unable to verify evaluation period....". No wiec dobra, puszczamy jeszcze raz program, zmieniamy flage na skoku warunkowym i sledzimy instrukcja po instrukcji. Program wykonuje push 51 i jmp 00407DDE do kodu:

:00407DDE 5E            pop esi
:00407DDF FF75FC        push [ebp-04]
:00407DE2 FF1500304300  Call dword ptr [00433000]
:00407DE8 8BC6          mov eax, esi
:00407DEA 5F            pop edi
:00407DEB 5E            pop esi
:00407DEC 5B            pop ebx
:00407DED C9            leave
:00407DEE C3            ret

a pózniej wraca z wywolania CaLL do kodu :

:00405C81 E8301D0000    call 004079B6  <---- tu wracam !!!!
:00405C86 83F807        cmp eax, 00000007
:00405C89 0F84BC000000  je 00405D4B    <---- !!!! goooood
:00405C8F 83F809        cmp eax, 00000009
:00405C92 0F8485000000  je 00405D1D
:00405C98 83F813        cmp eax, 00000013
:00405C9B 7444          je 00405CE1
:00405C9D 8B0DAC2B4400  mov ecx, dword ptr [00442BAC]
:00405CA3 894DF0        mov dword ptr [ebp-10], ecx
:00405CA6 50            push eax
:00405CA7 8D45F0        lea eax, dword ptr [ebp-10]

* Possible StringData Ref from Data Obj ->"Unable to verify evaluation period                                   |
:00405CAA 6844254400              push 00442544

Ups..... widzimy ciekawe skoki warunkowe na podstawie zawartosci rejestru EAX. Patrzymy co mamy w EAX, no mamy tam 51 (fakt bo bylo push 51) no i program pomija skoki warunkowe zglaszajac nieszczesliwy komunikat "Unable.....".

Krotka analiza kodu ze zmianami flag na skokach warunkowych pozwala nam stwierdzic, ze przy EAX=7 program uruchamia sie dalej, przy EAX=9 program zglasza komunikat o konczacym sie czasie trial a przy EAX=13 zglasza komunikat o skonczonym czasie trial i sie nie uruchamia.

No to zcrackujmy to, sposobów jest kila. Ja proponuje tak, zmienmy skok warunkowy przy EAX=7 je 00405D4B na skok bezwarunkowy jmp 00405D4B. Uruchamiamy program, ups... program zglasza komunikat o modyfikacji czasu ale sie uruchamia po zmianie skoku. Dobra, pasuje usunac sprawdzanie czasu. Proponuje usunac skok warunkowy, który modyfikowalismy na poczatku je 00407C7C i wtedy program wróci z wywolania call 004079B6 bez sprawdzania czasu.

Uruchamiamy zmodyfikowany program, który pieknie sie uruchamia. Co prawda okienko startowe pisze o trial i unregistered ale kogo to obchodzi, jak co to mozna zmodyfikowac sobie HexEdytorem i wpisac tam cokolwiek. :-)

Dobra dobra.....jeszcze nie koniec. Kazdy szanujacy sie cracker nim pusci w obieg swoja crackerska prace powinien przeanalizowac program czy wszystko dziala (o czym zapomina wielu naszych zachodnich kolegów wypuszczajac niepelne cracki). Uruchamiamy program i sprawdzamy czy wszystkie opcje dzialaja. Upsss... okienko CacheTuning posiada wylaczone opcje i suwaki i komunikat "Chace tuning is only available in the registered version". No to ladnie, czeba zabrac sie za dalsza ciezka prace.

Dlugo sie zastanawialem jak opisac wam sposób znalezienia i wlaczenia wylaczonych opcji w okienkach dialogowych. Najczesciej program sprawdza jakas komórke czy reg czy trial i odpowiednio wylacza niektóre opcje. Wtedy latwo jest znalezc ta komórke i ja zmodyfikowac.

W tym programie jest inaczej, program na stale ma wylaczone opcje ale posiada odpowiednie procedurych ich obslugi.

Na poczatek przy takim problemie proponuje sprawdzic czy program faktycznie posiada procedury i czy warto go dalej crackowac. Do tego celu wspaniale nadaje sie Customiser ze stron iczeljon.cjb.net. Umozliwia on nam wlaczenie nieaktywnych (greyed) elementow w okienkach dialogowych. No wiec wlaczamy te elementy i okazuje sie, ze one dzialaja i program zmienia swoje ustawienia. Dobra, wezmy sie wiec za zcrackwanie. Problem tylko jak znalezc interesujacy nas kod wylaczajacy te elementy. Opisze wam jak do tego dojsc.

Na poczatku sprawdzilem, czy poszczegolne elementy nie maja ustawionych opcji 'disabled' juz na poziomie zasobow programu co by szybko rozwiazalo nasz problem. Nie bede sie wglebial w szczegoly, wszystkie zasoby maja swoja wlasna strukture i opcje zapisane kodami. W tym przypadku 'enable' to bajt 50h a 'disable' to 58h. Podgladnijcie edytorem zasoby w programi to zobaczycie, ze interesujace nas elemety maja jednak bajt 50 w swojej strukturze czyli sa aktywne. Wniosek z tego, ze wylaczane sa one na poziomie kodu.

Na poczatku nie bardzo wiedzialem jak znalezc kod wylaczajacy te elementy. Ale z pomoca przyszedl mi Customiser, który wlacza nieaktywne elementy. Dlaczego by nie przesledzic jak on to robi. No wiec zaznaczam sobie element nieaktywny. Customiser podaje mi uchwyt (hwnd) elementu np. 6e3h. Przechodza pod SoftIce, zastawiam pulapke na wiadomosci elementu o uchwycie hwnd czyli bmsg 6e3h (najlepiej zastawic na elemencie ComboBox bo na tekstach ciagle przesylane sa jakies wiadomosci). Dobra przechodzimy do Customisera i uruchamiamy opcje 'enable' wybrany element. SI przechwytuje wiadomosci wysylane do tego wybranego elementu. Jest ich kilka ale SI ladnie nam podaje jakie msg i jakie parametry. Kilka razy puszczamy dalej i chwytamy bardzo interesujaca nas wiadomosc WM_ENABLE.

Zapisujemy sobie z jakimi parametrami wyslana jest ta wiadomosc.

Hwnd=6e3 Lparam=1 Rparam=0 kodmsg=000A WM_ENABLE

Teraz mozemy zmienic nasza pulapke w SI aby nie lapala wszystkich msg tylko WM_ENABLE, czyli zmieniamy na bmsg 6e3 WM_ENABLE i bawimy sie dalej w zmienianie Customiserem enable/disable nasz wybrany element. Zauwazymy, ze przy wylaczaniu elementu tez wysylana jast WM_ENABLE tyle ze z innym parametrem Lparam :

Hwnd=6e3 Lparam=0 Rparam=0 kodmsg=000A WM_ENABLE

Oki.. wiemy juz od czego mozna zaczac szukania w kodzie programu. Wyladowywujemy z pamieci Customiser, zostawiamy pulapke w SI na uchwycie 6e3 W_ENABLE, i przeladowywujemy program memturbo.exe. Progam startuje i w pewnym momencie SI przejmuje kontrole nad wiadomoscia WM_ENABLE z paramerem Lparam=0 czyli disable. Co prawda uchwyt naszego ComboBox jest inny ale SI i tak wychwytuje to wiadomosc (jak przypuszczam kazden typ elementu ma pewnie swoj zakres wartosci hwnd albo cos w tym stylu)

W kazdym razie, kilka razy F12 aby dotrzec do kodu w memturbo.exe i znajdujemy taki o to fragment kodu :

:00422EF0 8B4138        mov eax, dword ptr [ecx+38]
:00422EF3 85C0          test eax, eax
:00422EF5 750F          jne 00422F06
:00422EF7 FF742404      push [esp+04] <--- na stos Lparam, Rparam
:00422EFB FF711C        push [ecx+1C] <--- na stos hwnd

* Reference To: USER32.EnableWindow, Ord:00B7h
                                  |
:00422EFE FF15C4354300   Call dword ptr [004335C4]
:00422F04 EB0E           jmp 00422F14

Oki... funkcja API EnableWindow wysyla nasz komunikat WM_ENABLE do poszczegolnych elementow. Poniewaz ten fragment kodu jest jednak wiele razy wywolywany z programu, musimy znalezc skad byl wywolywany w naszym interesujacym nas przypadku. Sledzimy sobie kod i wychodzimy z tej procedury do takiego fragmentu kodu :

:0040130B 6A02          push 00000002
:0040130D FF731C        push [ebx+1C]
:00401310 FFD5          call ebp
:00401312 50            push eax        <--- tu chbyba ? hwnd niepamietam
:00401313 E87FEF0100    call 00420297
:00401318 8BD8          mov ebx, eax
:0040131A 33F6          xor esi, esi    <---- !!!! baaaaaaad.....
:0040131C 3BDE          cmp ebx, esi
:0040131E 740A          je 0040132A
:00401320 56            push esi        <---- tu kladzie lparam, rparam
:00401321 8BCB          mov ecx, ebx
:00401323 E8C81B0200    call 00422EF0   <---- tu jestesmy
:00401328 EBE1          jmp 0040130B

Powiem wam juz teraz...BINGO to jest nasz interesujacy kod. Mozecie sobie poanalizowac ten kod uruchamiajac wiele razy program i sprawdzajac co sie dzieje. W kazdym razie funkcja Enable Window pobiera ze stosu parametry push [esp+04] i push [ecx+1C]. Jezeli sobie zagladniemy co jest w esp+04 to okaze sie, ze 0 czyli wylacza a jak zmienimy na 1 to nasz ComboBox bedzie wlaczony!. Analiza powyzszego kodu da nam info, ze esi to sa wlasnie lparam,rparam. Ale co widzimy xor esi,esi czyli zawsze odklada nam 00000000. Powiem wam juz teraz, ze zmiana tego i wpisanie do ESI 00000001 uaktywni nam wszystkie wylaczone elementy.

Problem tylko z odpowiednia modyfikacja kodu poniewaz w cmp ebx,esi wymaga zeby w esi bylo 0 a musimy przy push esi wstawic na stos 1. Za malo miejsca na zwykla modyfikacje kodu. Nalezy zrobic pewne kombinacje. Poniewaz instrukcja xor esi,esi nie zmienia nam w tym przypadku zadnych flag mozemy ja pominac. W kazdym razie musimy sie zmiescic z bajtami instrukcji pomiedzy 040131A a 401320 czyli mamy do dyspozycji 7 bajtow. Oki... moja modyfikacja wygladala tak :

:00401313 E87FEF0100     call 00420297
:00401318 8BD8           mov ebx, eax
:0040131A 83FB00         cmp ebx,000
:0040131D 740B  (!)      je 0040132A
:0040131F 6A01           push 001
:00401321 8BCB           mov ecx, ebx
:00401323 E8C81B0200     call 00422EF0
:00401328 EBE1           jmp 0040130B

Widzicie, usunalem xor, porownalem ebx z 0 a na stos dalem od razu 1. Musicie bardzo uwaznie modyfikowac kod najlepiej pod HackerView bo mamy na bierzaca kody instrukcji i mnemonike asemblera.

Oki..... uruchamiamy program i zagladamy na dialog Cache Tuning. Oki... wszystkie elementy wlaczone i dzialaja. Ale co to?? srodkowy suwak nie dziala i wogole cos zepsuty :-) nie wiadomo dlaczego :-)

Oki..... analizujemy ponownie nasza procedure i okazuje sie, ze w pierwszym podejsciu w ESI jest jakas tam wartosc np. 8832, ktora caly czas tam pozostaje a wczesniej od razu byla zerowana prze xor esi,esi. Dobra wpiszmy recznie pod SoftIce do ESI 0 i uruchommy program. Wszystko dziala poprawnie. Uff...... Pozostaje tylko zadbac o to aby na starcie naszej modyfikowanej procedurki ESI bylo zerowane. To juz pozostawiam wam, musicie wczesniej przesledzic program i gdzies upchac zerowanie lub cos pozmieniac. Ja mam juz dos tego programu :-)))

No to tyle (I love reverse......_)

GustawKit