Program		: Flash32 2.32a
Opis		: Screen dumper
URL		: http://pro.wanadoo.fr/chass/indexe.htm
Narzedzia	: SoftIce,W32dsm,hiew

Oki, program ma nastepujace ograniczenia w ver evaluation:
- nag na zakonczenie programu
- 30 dni po ktorych nie da sie dalej uruchomic progsa
- do kazdego zdumpowanego screena dodaje text "Flash 32 - Evaluation"
- texty w oknach Evaluation(unicode) ale to chyba nie problem...

Uno, jak zwykle ladujemy flasha do W32dsm chyba, ze ktos woli IDE
(jak wynika z votek na cookiecrk.z.pl :) bo deadlisting to b.przydatna rzecz.

1.Nag na koncu
Uruchamiamy program, ustawiamy w si breakpointa na DialogBoxParamA
zamykamy flasha, bum jestesmy w si, F11 potem klikamy OK i znowu jestesmy w si
widzimy kod:

:0040F952 A1CCC64800	mov eax, dword ptr [0048C6CC]
:0040F957 55		push ebp
:0040F958 68504E4300	push 00434E50			; <-- adres procedury obslugi okna dialogowego
:0040F95D 56		push esi			; <-- uchwyt okna wywolujacego
:0040F95E 6805010000	push 00000105			; <-- ID okna dialogowego
:0040F963 50		push eax			; <-- module base, czyli adres pod jaki zostal zaladowany exek w win
							; ustawiony w naglowku PE, przewaznie 400000h,staly dla PE EXE,zmienny dla
							; DLLi
* Reference To: USER32.DialogBoxParamA, Ord:0095h
                                  |
:0040F964 FF15C8B54400	Call dword ptr [0044B5C8]	; <-- wywolanie nagscreena
:0040F96A 85C0		test eax, eax			; <-- eax parametr podany funkcji EndDialog
:0040F96C 0F843B0D0000	je 004106AD
:0040F972 56		push esi

Jest mnostwo sposobow aby sprawic zeby program juz nie wyswietlal naga
a) zanopowac calosc kodu od .0040F957 do .0040F972
b) "przeskoczyc" cale wywolanie funkcji DialogBoxParamA
c) przywrocic wartosc ESP zanim zostanie wykonany call dword ptr[__imp__DialogBoxParamA@20]
d) podanie blednych parametrow procedurze wywolujacej
e) zmienic atrybuty sekcji w ktorej znajduje sie kod ktory chcemy zmienic(no chyba,
ze znajduje sie w sekcji z atrybutami READ-WRITE-EXECUTABLE), nastepnie zmienic RVA
entrypointu na adres naszej procki patchujacej znajdujacej sie w jakiejs szczelnie(najlepiej
na koncu pliku gdzie jest zapisane wyrownanie ostatniej sekcji do wartosci file align
zapisanej w naglowku PE), procka patchujaca po zakonczeniu patchowania skacze z powrotem
do oryginalnego entrypointu programu).Ten sposob b.dobrze sprawdza sie na patchowanie
spakowanych plikow(testowalem na UPX,ASPACK 2000.1,SHRINKER), tyle tylko ze nie zmieniamy
entrypointu programu, tylko zmieniamy fragment kodu np.ASPACKAa gdzie jest wykonywany skok do
oryginalnego entrypointu zastepujac go skokiem do wlasnej procki patchujacej i dalej
tak samo procka patchuje odpowiednie VA a nastepnie skacze do entrypointu programu(ale nie
do kodu UPXa!)


AD a) Chyba nic prostszego, otwieramy flash32.exe w hiew-ie, naciskamy F5 i wpisujemy
adres .0040F957(kropka przed adresem oznacza, ze idziemy pod adres witrualny, ten ktory
widzimy w SI), przechodzimy do trybu hex(F4 hex) ,F3 i wpisujemy 90(nop) az do .40F972

AD b) Otwieramy flasha w hiew-ie, zmieniamy tryb na decode, idziemy pod .40F957 gdzie
zapamietywany jest 1 parametr funkcji DialogBoxParamA, nastepnie zmieniamy tryb wyswietlania
offsetow ALT-F1(przelacza wyswitlanie offsetow miedzy VA i adresem fizycznym) na
wyswietlanie adresow rzeczywistych w pliku, naciskamy F3 potem F2 co umozliwia nam
bezposrednie wpisywanie instrukcji asemblera, widzimy kod

0000F957: 55		push      ebp			; <-- tu jestesmy
0000F958: 68504E4300	push      000434E50 ;" CNP"
0000F95D: 56		push      esi
0000F95E: 6805010000	push      000000105 ;"  "
0000F963: 50		push      eax
0000F964: FF15C8B54400	call      DialogBoxParamA ;USER32.dll
0000F96A: 85C0		test      eax,eax
0000F96C: 0F843B0D0000	je        0000106AD   -------- (1)
0000F972: 56		push      esi

po F2 piszemy jmps 0F972 zapamietujemy zmiany F9, naga nie ma

AD c) a wiec znowu hiew, idziemy pod .0040F964 gdzie jest wywolanie call DialogBoxParamA.
Wiemy, ze funkcja DialogBoxParamA zanim zostanie wywolana "dostaje" poprzez stos liste
parametrow(5 parametrow), a wiec pod .0040F964 parametry sa juz zapamietane, bardzo wazna
rzecza jest aby wskaznik stosu ESP po wywolaniu fuckji DialogBoxParamA byl taki sam jak
przed zapamietaniem 1 parametru(push ebp), poniewaz potem jest kaszana z wyjsciem z call-ow.
Funkcja DialogBoxParamA nalezy do funkcjj , ktore same przywracaja wartosc esp taka jaka byla
przed zapamietaniem 1 parametru, funkcje po ktorych trzeba samemu przywracac wartosc
poprzednia esp okresla sie mianem cdecl(np._wsprintfA).Czyli trzeba zrobic tak aby pod
.0040F964 byla przywrocona wartosc esp jaka jest przed zapamietaniem 1 parametru,
jak dziala push&pop chyba kazdy wie , zamiast 5x pop eax i 1 nopa mozemy napisac w
hiew pod .0040F964 add esp,14 (4rozmiar_liczby_typu_dword*5parametrow=20d=14h)
instrukcja add esp,14 zajmuje 3 bajty, zostaja nam 3 bajty(instrukcja
call DialogBoxParamA zajmuje 6 bajtow(3bajty okupuje add esp,4*5)), mozna zamiast tych
3 bajtow wpisac sub eax,eax(2bajty) i inc eax(1bajt) co spowoduje dodatkowo, ze nie zostanie
wykonany skok spod .040F96C

AD d) Funkcje api oczekuja, ze parametry podane im przed wywolaniem sa poprawne,
ale co sie dzieje gdy np. wpiszemy parametry niepoprawnie np.

push	MB_ICONHAND		; <-- typ okienka
push	offset szCaption
push	offset szText
push	0			; <-- uchwyt okna wywolujacego(okno to bedzie
call	MessageBoxA		; nieaktywne dopoki nie nacisniemy ok na messageboxie)

program po kompilacji wyswietli okienko, sprobujmy teraz jako parametr
window handle(ostatni push) zapisac wartosc -1

push	MB_ICONHAND		; <-- typ okienka
push	offset szCaption
push	offset szText
push	-1			; <-- niepoprawna wartosc parametru
call	MessageBoxA

w tym przypadku po kompilacji i uruchomieniu, program wywola funkcje MessageBoxA
ale nie wyswietli okna!Wlasnie ze wzgledu na bledny parametr.
Ok, ale co nam po tym, ano mamy wywolanie:

push      ebp
push      000434E50 ;" CNP"
push      esi
push      000000105 ;"  "	<-- ID okna dialogowego
push      eax
call      DialogBoxParamA ;USER32.dll

co sie stanie gdy zamiast poprawnego ID wpiszemy ID jakiegos innego okna?
To inne okno zostanie wyswietlone, a co jesli zamiast poprawnego ID wpiszemy
wartosc 0FFFFFFFFh, system bedzie szukal w strukturach zasobow exeka okna
dialogowego o numerku 0FFFFFFFFh, jesli okno takie nie istnieje, to funkcja
DialogBoxParamA zostanie wywolana,parametry zostana zdjete ze stosu natomiast
wartosc zwrocona w eax bedzie kodem bledu, w przypadku funkcji DialogBoxParamA
w eax w przypadku bledu zwracana jest wartosc 0FFFFFFFFh(-1).A wiec w hiew
pod adresem gdzie jest push 105 wpisujemy push 0FFFFFFFFh zapisujem zmiany.
Po wszystkim trzeba jeszcze sprawdzic czy program czasem nie sprawdza wartosci
zwracanych przz funkcje,niekiedy moze sie zdarzyc ze nie wyswietli nagscreena
ale za to wyswietli msgboxa z textem ze wystapil blad podczas otwierania okna.

AD e) opisze ten sposob przy okazji jakiegos spakowanego proga

2.Limit 30 dni
Program po uplywie 30 dni wyswietla message ze czas sie skonczyl i konczy swoje dzialnie.
Zanim uruchomimy program zastawimy pulapke w si bpx MessageBoxA do "p ret;", uruchamiamy
program, okno softica mignie na sekunde(p ret to F11), klikamy na OK i jestesmy w SI.
Spisujemy sobie na kartce skad nastapilo wywolanie MessageBoxA, idziemy w W32dsm pod
ta lokacje:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00410C87(C)					; <-- stad nastapil skok
|

* Possible StringData Ref from Data Obj ->"The evaluation period is finished."
                                  |
:00410CA1 6868934500	push 00459368		; <-- 1 parametr dla wsprintfA

* Possible StringData Ref from Data Obj ->"%s"
                                  |
:00410CA6 682C544500	push 0045542C		; <-- ciag formatujacy %s oznacza ze parametrem jest string
:00410CAB 6820D14700	push 0047D120		; <-- bufor gdzie bedzie zapisany wypadkowy text

* Reference To: USER32.wsprintfA, Ord:02B2h
                                  |
:00410CB0 FF1510B64400	Call dword ptr [0044B610]
:00410CB6 83C40C	add esp, 0000000C	; <-- funkcja typu cdecl, add esp,4*3parametry
:00410CB9 6A10		push 00000010		; <-- typ okna (MB_ICONHAND)

* Possible StringData Ref from Data Obj ->"Flash 32"
                                  |
:00410CBB 6870504500	push 00455070		; <-- text z paska tytulowego
:00410CC0 6820D14700	push 0047D120		; <-- bufor gdzie jest zapisany wypadkowy text,"The evaluation perio...
:00410CC5 6A00		push 00000000		; <-- uchwyt okna glownego(wywolujacego MessageBoxA),jesli nie ma
						; okna glownego to podajemy parametr 0
* Reference To: USER32.MessageBoxA, Ord:01C3h
                                  |
:00410CC7 FF1500B64400	Call dword ptr [0044B600]	; <-- pokaz info ze czas sie skonczyl
:00410CCD 5E		pop esi
:00410CCE 33C0		xor eax, eax
:00410CD0 5B		pop ebx
:00410CD1 C21000	ret 0010

Widzimy, ze skok do wywolania messaga nastapil spod adresu .00410C87,a wiec klikamy na nim
2 razy prawym klawiszem myszy

:00410C5B C705A0C8470000010000    mov dword ptr [0047C8A0], 00000100
:00410C65 C705F0C04700FFFFFFFF    mov dword ptr [0047C0F0], FFFFFFFF
:00410C6F 8915FCC94700            mov dword ptr [0047C9FC], edx
:00410C75 A3B0CC4700              mov dword ptr [0047CCB0], eax
:00410C7A E8316C0200              call 004378B0
:00410C7F 83C440                  add esp, 00000040
:00410C82 48                      dec eax
:00410C83 5F                      pop edi
:00410C84 744E                    je 00410CD4	; <-- 1jump
:00410C86 48                      dec eax
:00410C87 7418                    je 00410CA1	; <-- 2jump (stad nastapil jmp)
:00410C89 6A00                    push 00000000
:00410C8B 68D0D54000              push 0040D5D0
:00410C90 6A00                    push 00000000

* Possible Reference to Dialog: DialogID_009C 
                                  |
:00410C92 689C000000              push 0000009C
:00410C97 56                      push esi
:00410C98 FFD3                    call ebx
...

1jump prowadzi nas do:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00410C84(C)
|
:00410CD4 6A10                    push 00000010

* Possible StringData Ref from Data Obj ->"Flash 32"
                                  |
:00410CD6 6870504500              push 00455070

* Possible StringData Ref from Data Obj ->"Flash 32 is not correctly installed..."
                                  |
:00410CDB 6828934500              push 00459328
:00410CE0 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:01C3h
                                  |
:00410CE2 FF1500B64400            Call dword ptr [0044B600]	; <-- tego raczej nie chcemy ;)

2jump to skok do wczesniej omawianej procedurki wyswietlenia message boxa
z textem o koncu czasu ewaluacji.Aby omiac te "przykre" procki
najlepiej zanopowac, albo lepiej jesli bedziemy pod .00410C84 w hiew, przejsc
do trybu decode i wprowadzic instrukcje asemblera mov eax,1(5bajtow)
Przestawiamy date systemowa w win(tak z 2lata w przod), uruchamiamy
flasha, juz sie nie rzuca o koniec czasu testowania :)

3.Text "Flash 32 - Evaluation" dodawany do kazdego screendumpa
Aby wyswietlic text w danym rejonie(nie mowie o elemencie takim jak np.
okienko edycyjne)okna, stosowane sa funkcje TextOutA,DrawTextA,DrawTextExA,
wszystkie te funkcje jako jeden z parametrow wykorzystuja tzw.display device context,
jest to uchwyt danego obszaru na ktorym cos chcemy rysowac, wyswietlac text.
Uchwyt ten pobiera sie poprzez funkcje API GetDC (GetDeviceContext).
Uruchamiamy flasha, robimy jakiegos screendumpa,idziemy do menu file
nastepnie save as, wybieramy nazwe pliku i zanim klikaniemy na save
ustawiamy w si pulapke na GetDC do " p ret;" , wychodzimy z si, save
flash wywolal funkcje GetDC pod .00427B0D, idziemy w W32dsm pod ten adres:

:00427AE6 6A15			push 00000015	; <-- wczesniej zapamietana dlugosc ciagu
...
:00427B02 8D9424B8030000	lea edx, dword ptr [esp+000003B8]
:00427B09 52			push edx	; <-- adres textu do wyswietlenia
:00427B0A 50			push eax	; <-- Ypos

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00427B00(U)
|
:00427B0B 51			push ecx	; <-- Xpos
:00427B0C 55			push ebp	; <-- uchwyt okna

* Reference To: USER32.GetDC, Ord:0100h
                                  |
:00427B0D FF15BCB54400		Call dword ptr [0044B5BC]	; <<-- tu sie zatrzymalismy
:00427B13 50			push eax	; <-- device context

* Reference To: GDI32.TextOutA, Ord:020Bh
                                  |
:00427B14 FF15D8B24400		Call dword ptr [0044B2D8]

Program najpierw zapamietuje parametry dla f.TextOutA, nastepnie tuz przed jej
wykonaniem pobiera ostatni parametr poprzez GetDC i zapamietuje go dla TextOutA

Aby miec pewnosc, ze funkcja TextOutA nie zaszpeci nam dumpa, postepujemy podobnie jak
w punkcie 1c), wiemy ze TextOutA potrzebuje 5 parametrow(4*5=20d=14h) a wiec w hiew
pod .00427B14 piszemy add esp,14, znowu zostana nam 3 bajty do zapelnienia, sprawdzamy
w Win32.hlp jakie wartosci zwraca TextOutA po poprawnym zadzialaniu, eax musi byc
rozne od zera, wiec sprawa prosta 3 bajty to sub eax,eax & inc eax, zapisujemy zmiany
i gotowe.

4.Texty "Evaluation"
Hmm, polecam HexWorkshopa do zabawy z ciagami(text "Evaluation" jest zapisany
wielokrotnie pod postacia normalnego ciagu i unicode), ale kto by sie tym
przejmowal skoro program jest juz full :)


bart^CrackPl
cryogen@free.net.pl

