Ostatnio natrafiłem na aplikację stworzoną w środowisku Visual FoxPro 9, zabezpieczona była kluczem sprzętowym HASP Hardlock, a sam plik wykonywalny aplikacji był zaszyfrowany (tzw. envelope).
Struktura aplikacji Visual FoxPro
Z nielicznych kontaktów z oprogramowaniem Visual FoxPro wiedziałem, że każda taka aplikacja składa się z prostego loadera (który uruchamia cały engine VFP znajdujący się w dodatkowych plikach DLL) oraz właściwej aplikacji, która znajduje się na końcu pliku wykonywalnego (zapisana jako overlay), całość jest więc w jednym pliku wykonywalnym. Tak jest w przypadku programów niezabezpieczonych:

W przypadku zabezpieczenia HASP, na końcu zabezpieczonego pliku faktycznie znajdują się jakieś dane, ale nie są to dane aplikacji VFP, gdyż nie można jej zdekompilować oprogramowaniem ReFox.
Zabezpieczenia dla aplikacji z overlayami
Dane overlay (tak zapisane dane są w aplikacjach Flash, Director, Shockwave etc.) nie są mapowane w pamięci procesu i muszą być odczytane bezpośrednio z dysku. Popularną metodą ochrony takich aplikacji jest szyfrowanie tych danych i hookowanie funkcji systemu plików (np. CreateFile, ReadFile etc.) w samej aplikacji, poprzez podstawienie adresów funkcji zastępczych w tabeli importów aplikacji. Jeśli aplikacja otworzy swój własny plik i będzie probowała czytać dane overlaya, nie zostanie odczytane to co jest na dysku, ale to co zostało wczesniej zaszyfrowane.
Takie rozwiązanie przez hookowanie tabeli importów działa jedynie w przypadku samodzielnych plików (bez dodatkowych bibliotek), w przypadku aplikacji VFP, dane z pliku wykonywalnego czytane są przez dodatkowe biblioteki, więc wymagany byłby system wide hook.
Envelope HASP dla aplikacji VFP
System zabezpieczeń HASP dla takich plików, działa w ten sposób, że sterownik systemowy HASP-a podpina się pod funkcje systemowe Windows odpowiedzialne za czytanie plików i obecność oryginalnego overlaya jest emulowana tylko dla zabezpieczonej aplikacji i jej bibliotek. Wygląda to mniej więcej tak:
Odczytanie overlaya
Jak zatem uzyskać obraz całego overlaya? Z przeprowadzonych eksperymentów wynika, że dane nie są nigdzie czytane w całości, więc nie ma takiego punktu w programie (a grzebanie w engine VFP nie należy do najprzyjemniejszych), gdzie by można było zrzucić pamięć całego overlaya.
Jednak jeśli czytanie danych overlaya jest emulowane dla samej zabezpieczonej aplikacji, można wstrzyknąć kod czytający zawartość całego pliku do zabezpieczonej aplikacji i dzięki temu uzyskać dane odszyfrowanego overlaya.
Jest tutaj kilka problemów. Po pierwsze, aby wstrzyknąc kod należy dojść do OEP zabezpieczonej aplikacji, co może sprawić trochę problemów, ja skorzystałem z OllyDbg i pluginu Phant0m, ponieważ envelope HASP-a wykrywa popularne narzędzia do debuggowania, co można zobaczyć na zrzuconym obrazie zabepieczonego pliku:
Znalezienie OEP jest relatywnie proste, wersja dla leniwych — zrzucić działający program z pamięci i wyszukać standardowego entrypoint-a dla aplikacji skompilowanych pod Visual C++ (szukać funkcji GetStartupInfoA). Potem wgrać na nowo plik i ustawić hardware breakpoint na tym adresie.
Będąc na adresie OEP można teraz wstrzyknąć kod odpowiedzialny za czytanie pliku. Aby zaoszczedzić trochę kodu, ja wykorzystałem fakt, że plik aplikacji jest przez nią otwierany w pewnym momencie, dzięki czemu nie trzeba pobierać jego ścieżki i go otwierać, a od razu mamy jego uchwyt, który można wykorzystać do odczytania overlaya:
Następnie skorzystałem ze skryptu ODBScript, żeby pod adresem 4015EE załadować kod, który odczyta zawartość pliku i zapisze go na dysku:
; usun wszystkie breakpointy bphwcall bc ; ustaw hardware bp na OEP bphws 401873,"x" run ; ustaw hardware bp na kod po _lopen bphws 4015F4,"x" run bphwcall ; kompiluj kod z pliku pod adres EIP asmtxt eip, "C:\fox_dumper.asm" ; pomocniczy bp bphws 401644,"x" run ; zrzuc pamiec pod adresem ESI o rozmiarze EBX dm esi, ebx, "c:\dump.bin" log "VFP dumper zrobione." pause
Kod dumpera ładowany jest z zewnętrznego pliku, a nie jest wykorzystywana funkcja ODBScript wykonująca kod assemblera w przestrzeni adresowej aplikacji, ponieważ to po prostu nie działało (jakby ktoś pytał):
; w EAX jest uchwyt pliku mov edi,eax ; hFile ; nawiguj na koniec pliku (korzystajac z funkcji ; z tabeli importow aplikacji) push 2 ; FILE_END push 0 ; offset push edi ; hFile call [40203C] ;_llseek mov ebx,eax ; eax = current offset = size ; alokuj pamiec na rozmiar overlaya lea eax,[ebx-4] ; na koncu overala zapisany jest DWORD ; ktory wskazuje offset poczatku overlaya ; w pliku push 0 ; FILE_BEGIN push eax ; offset push edi ; hFile call [40203C] ;_llseek ; odczytaj DWORD, ktory okresja polozenie overalaya w pliku push 0 mov eax,esp push 4 ; size push eax ; &memory push edi ; hFile call [402040] ;_lread pop eax ; esi - raw offset overlaya push 0 ; FILE_BEGIN push 0 ; offset push edi ; hFile call [40203C] ;_llseek ; alokuj pamiec na calego overlaya push ebx push 40 ; GMEM_FIXED or GMEM_ZEROINIT call GlobalAlloc mov esi,eax ; odczytaj calego overlaya do nowo zaalokowanej pamieci push ebx ; size push esi ; &memory push edi ; hFile call [402040] ;_lread ; zamknij oryginalny plik push edi call [402038] ;_lclose ; utworz nowy plik sub esp,512 mov eax,esp ; "C:\x" mov edx,785C3A43 mov [eax],edx xor ecx,ecx mov [eax+4],ecx ; esi - ptr ; ebx - size push 0 call ExitProcess
Po wykonaniu skryptu, w pliku C:\x otrzymamy zrzut całego pliku (nie tylko overlaya).
Odbudowa oryginalnego pliku wykonywalnego
Posiadając zrzucony overlay (rozpoznamy jego bajty po sygnaturze FE F2 EE), należy go dokleić do odbudowanego loadera VFP. Sam loader po zabezpieczeniu i zrzuceniu wymaga odbudowy importów, tutaj można trochę oszukać, wszystkie loadery VFP (danej wersji) są takie same, różnią się jedynie wersją językową, ikoną i zasobami z nazwą i numerem wersji aplikacji. Jeśli posiadacie środowisko Visual FoxPro 9, można stworzyć projekt w stylu Hello World, skompilować do pliku wykonywalnego, usunąć oryginalny overlay i wkleić nasz, a aplikacja będzie działała poprawnie (można potem w edytorze zasobów podmienić ikonę i wersję aplikacji).
Wnioski
Było trochę problemów z samą zabezpieczoną aplikacją i jej działaniem w OllyDbg z włączonym pluginem Phant0m (dużo restartów, nie dało się normalnie zamknąć aplikacji), jednak sama metoda jest dosyć szybka i uniwersalna, z późniejszych poszukiwań udało mi się jeszcze znaleźć doskonały artykuł prezentujący szereg innych zabezpieczeń stosowanych w aplikacjach VFP, polecam na koniec:
Security in FoxPro — www.foxpert.com/docs/security.en.htm
PS. Pozdro dla wszystkich burtoniarzy ![]()






Marzec 30th, 2010 o godzinie 10:37 am
Świetny wpis
Będziesz może na SeConference w kwietniu?
Marzec 30th, 2010 o godzinie 11:28 am
Dzięki. A co tam fajnego będzie?
Styczeń 2nd, 2011 o godzinie 12:37 am
[...] DOS-a, ściśle związany z operowaniem na bazach danych, można powiedzieć, że to protoplasta Visual FoxPro.Piszę o tym, ponieważ przed świętami otrzymałem zlecenie na modyfikację starego programu [...]