Użycie IDR do szybkiego przeanalizowania aplikacji napisanej w Delphi.

 

Tym razem tutorial opisujący w jaki sposób możemy szybko poprawić skompilowany pod Delphi program aby nieco usprawnić jego działanie i ułatwić korzystanie z niego. Wykorzystam do tego celu program Interactive Delphi Reconstructor (IDR), który polecił mi swego czasu Bartek z secnews.pl za co bardzo mu dziękuję, ponieważ to narzędzie bardzo mi się przydaje, i jak się za chwilę przekonacie bardzo ułatwia analizowanie oprogramowania napisanego w wielu wersjach Delphi. Modyfikowanym programem będzie JEDI Code Format służący do automatycznego formatowania kodu w plikach z kodem.Do wykonania modyfikacji przyda się oczywiście HIEW i Total Commander do wygodnych operacji na plikach. O programach tych wspominam w jednym z moich poprzednich wpisów Analiza gry „Max Payne” (patch v1.05) w celu stworzenia Trainera. Poza tym oczywiście przyda się sam modyfikowany program JEDI Code Format w wersji 2.43. A przede wszystkim skorzystamy na początku ze wspomnianego IDR autorstwa crypto. Można go wraz z dokumentacją i „bazami wiedzy” definiującymi obsługę poszczególnych wersji Delphi z tej strony. Jak pewnie wiedzą Ci z Was, którzy zajmowali się kiedykolwiek patchowaniem programów czy reverse engineeringiem do analizy programów napisanych w Delphi można było się kiedyś wspomóc dekompilatorem o nazwie DeDe. Jednak jest on od bardzo wielu lat nierozwijany i do nowszych programów napisanych w Delphi nie udało by się nam z niego skorzystać w taki sposób jak z IDR.

Cel modyfikacji.

Program JEDI Code Format GUI którym szybko możemy zmodyfikować pliki z kodami źródłowymi Delphi po ustawieniu go prezentuje się tak jak na zrzucie ekranu poniżej.

Zwróćcie tutaj uwagę na wybrane opcje pod „Files” oraz „Backup”. Teraz jeżeli naciśniemy klawisz F9 albo wybierzemy z menu „File” polecenie „Run” zostanie wyświetlony monit, w którym musimy potwierdzić czy na pewno chcemy dokonać zmian w znalezionych plikach bez kopii zapasowej. Z moich testów wynika, że dobrze ustawiony formatter się sprawdza i jeżeli nie korzystamy na przykład z Lazarusa czy dodatku GExperts dla Delphi, a chcemy szybko sformatować wiekszą ilość kodu śmiało możemy z tego programu skorzystać, a takie okienko jak poniżej i klikanie na „Yes” czy naciskanie klawisza Enter jest (według mnie) trochę wprost pisząc: upierdliwe.

Analiza miejsca koniecznego do modyfikacji.

Jeszcze zanim cokolwiek przeanalizujemy to wspomnę, że program JEDI Code Format posiada akurat kod źródłowy i można by oczywiście dokonać tej modyfikacji na poziomie kodu źródłowego i przekompilować program. Ale teraz bawienie się z kodem w sensie instalacja IDE Delphi najlepiej w odpowiedniej wersji czy ewentualne doinstalowanie niestandardowych komponentów może być mozolne, poza tym prawdziwy reverser czasem woli szybciej coś zreversować niż bawić się w zmienianie kodu. A przy okazji mam nadzieję, że niektórzy czytający ten wpis chcą się czegoś dowiedzieć.

Ok, do rzeczy. Uruchamiamy IDR i wczytujemy plik jcfgui.exe. Chwile to może potrwać. Jeżeli w międzyczasie otrzymamy komunikat z pytaniem „Build full Tree of Classes?” możemy odpowiedzieć przecząco bo w tym przypadku nam to nie będzie potrzebne i nie ma sensu za bardzo wydłużać procesu analizowania kodu przez IDR. Kiedy IDR skończy analizować przełączamy się na zakładkę Forms (klawisz F5). Wybieramy RadioButton „Form”. u góry I na liście odszukujemy TFrmMain. Jak wiadomo jeżeli koder to nie dziecko neo tworzący bałaganiarskie trojany i inny pseudo malware na ogół z użyciem pakietu Indy do komunikacji po HTTP i trzyma się on pewnych zasad, które wpoił mu ktoś (lub on sobie sam czytając kursy kiedy zaczynał naukę Delphi) to raczej sensownie nazwie wszelkie elementy kodu jak: stałe, zmienne, funkcje,  procedury, moduły, po nazwach klas kończąc. Czyli pewnie nazwie formatkę frmMain lub MainForm. Zresztą dzięki wizualnemu podglądowi wiemy z jaką formatką mamy do czynienia. Widać to na poniższym ekranie.

I tutaj możemy poruszać się wygodniej niż po wspomnianym DeDe. Klikając prawym przyciskiem myszki na widocznej elementach formatki jak i wolnym polu możemy wybierać dane zdarzenia. My jednak najszybciej znajdziemy wspomniane konieczne miejsce do modyfikacji jeżeli zachowamy się tak jakbyśmy używali normalnie uruchomiony program. Czyli klikamy na menu „File” i polecenie „Run”. Widzimy kod:

_Unit87::TfrmMain.aFormatExecute
0054BDD8 call 0054B7A4
0054BDDD ret

Klikamy dwukrotnie na ten call i mamy listing assemblera jak na dłoni. Wystarczy się mu przejrzeć. Widzimy wiele mówiący fragment komunikatu, który pokazywałem na zrzucie ekranowym powyżej.

 _Unit87::sub_0054B7A4
(...)
>0054B898 jmp 0054B8C6
0054B89A cmp byte ptr [esi+33],0
>0054B89E jne 0054B8C6
0054B8A0 push 54BA9C; 'Are you sure you want to convert '
0054B8A5 push dword ptr [ebp-8]
0054B8A8 push 54BAEC; ' without backup?'
0054B8AD lea eax,[ebp-0C]
0054B8B0 mov edx,3
0054B8B5 call @UStrCatN
0054B8BA mov eax,dword ptr [ebp-0C]
0054B8BD call 0054B768
0054B8C2 test al,al
>0054B8C4 je 0054B906
0054B8C6 mov eax,dword ptr [ebx+420]; TfrmMain.?f420:TFileConverter
0054B8CC add eax,14; TFileConverter.?f14:string
0054B8CF mov edx,dword ptr [ebp-4]
0054B8D2 call @UStrAsg
0054B8D7 mov eax,dword ptr [ebx+400]; TfrmMain.frBasic:TfrBasic
0054B8DD call 0052500C
0054B8E2 mov edx,dword ptr [ebx+420]; TfrmMain.?f420:TFileConverter
0054B8E8 mov byte ptr [edx+10],al; TFileConverter.?f10:byte
0054B8EB mov eax,dword ptr [ebx+400]; TfrmMain.frBasic:TfrBasic
0054B8F1 call 0052501C
0054B8F6 mov esi,dword ptr [ebx+420]; TfrmMain.?f420:TFileConverter
0054B8FC mov byte ptr [esi+11],al; TFileConverter.?f11:byte
0054B8FF mov eax,esi
0054B901 call 004EF2B8
 
(...)

Pod adresem:  0054B89E widzimy skok warunkowy do kodu pod  0054B8C6, a w linii  0054B8C6 tekst TFileConverter, co może sugerować że dalej wywoływany jest kod jakiejś klasy do konwertowania plików. Chyba wiadomo co musimy zrobić by osiągnąć żałożony cel modyfikacji? Jeżeli nie wiesz to oczywiście podpowiem 🙂 Należy tak zmienić kod aby skok z pod adresu 0054B89E zawsze się wykonał, a tym samym pominął pytanie o to czy na pewno wykonać backup. Czyli oczywiście zmieniamy skok jne (jump if not equal) na jmps (jump short). Kto się bawił już kiedykolwiek w jakiekolwiek patchowanie to z pewnością wie jak wykonać ostatni krok. Oczywiście. Najwygodniej będzie skorzystać do tego celu ze wspomnianego na początku edytora HIEW.

Finałowe patchowanie.

Przed dokonaniem zmian dla pewności wykonaj kopię zapasową pliku który chcesz modyfikować. Na przykład skopiuj pod Total Commanderem (Shift+F5) pod nazwę jcfgui.ex – wygodniej nam później będzie szybko zmienić jego nazwę dodając tylko literę „e” na końcu rozszerzenia i nadpisując zmodyfikowany plik jeżeli coś by poszło nie tak jak trzeba. Uruchamiamy HIEW z plikiem jcfgui.exe. Naciskamy klawisz F4 i wybieramy widok „Decode” (jeśli aktywny był inny po starcie możemy to zmienić odpowiednio modyfikując plik hiew8.ini z ustawieniami HIEW w jego katalogu). Teraz naciskamy klawisz F5 i wpisujemy lub wklejamy jeśli mamy w schowku adres do zmiany czyli . 0054B89E – oczywiście koniecznie z kropką na początku ponieważ jak wiadomo modyfikujemy adres wirtualny, a nie fizyczny offset w pliku. Naciskamy klawisz Enter. Jesteśmy we właściwym miejscu. Teraz pora na modyfikację. Naciskamy klawisz F3 i jeśli znamy podstawowe opcody – możemy wpisać zamiast: 75 – EB. Podstawowe opcody wypada znać lub pogooglować sobie ich spis i przyswoić sobie tę wiedzę. Oczywiście podejrzewam, że nawet wprawni reverserzy, a nie takie lamki jak ja (chociaż ja jestem jedyną aż taką totalną lamą jaką znam ;)) nikt nie uczy się ich na pamięć, a czasami skok wymaga na przykład przesunięcia się o wiele linijek wyżej lub niżej także nikt nie będzie dokonywał niepotrzebnych tutaj akurat obliczeń – tym bardziej że HIEW pozwala po naciśnięciu klawisza F3 nacisnąć klawisz F2 i wprowadzać instrukcje assemblera. Możemy więc sprawnie zamienić jnz na jmps. Po zmianie naciskamy F9 aby zaktualizować plik. Wygląda to teraz tak jak na zrzucie ekranu poniżej.

Zamykamy HIEW klawiszem F10 lub ESC. Uruchamiamy jcfgui.exe naciskamy F9 i mamy elegancko sformawany kod bez konieczności oglądania dodatkowych pytań. Oczywiście IDR możemy już zamknąć, ewentualnie zapisując projekt jeżeli będziemy chcieli w przsszłości pracować dalej z tym plikiem exe i móc szybciej załądować go do analizy.

Podsumowując. Zmiana nie była trudna. Zwłaszcza, że program nie był skompresowany czy dodatkowo zabezpieczony. Co w przypadku programu z dostępnym kodem źródłowym nie było by chyba i tak celowe, może jedynie spakowanie w celu zmniejszenia plików wykonywalnych, które jak wiemy Delphi po wersji 3 IDE, a szczególnie już po wersji 7 standardowo tworzy niestety coraz większe wrzucając tam mnóstwo zbędnych elementów. Dlatego przy okazji mogę zachęcić to prób pisania w WinAPI 🙂 I to co opisałem powyżej to był oczywiście tylko przykład zastosowania technik reverse engineeringingu. Nie jestem w temacie ekspertem, ale mam nadzieję, że pomimo mojej tendencji do rozpisywania się wytrwaliście czytając do końca ten wpis i niektórzy z Was się czegoś dowiedzieli. Na koniec dodam jeszcze tylko, że możemy na przyszłość stworzyć sobie patcha do dokonanej zmiany. Można oczywiście takowy zakodować w mnóstwie języków, ale prawdziwy reverser koduje raczej jeśli już to pod WinAPI i najlepiej w assemblerze (taki beginner jak ja wspomaga się Delphi, jak przy tworzeniu wspomnianego trainera do gry Max Payne, bo tak szybciej i łatwiej, a przynajmniej dla mnie 🙂 Jednak w celu szybkiego stworzenia patcha polecam wygodny patcher dUP2 z dużymi możliwościami, do pobrania z tej strony.

Comments (2)

  1. 17:07, 04.07.2012Grzonu  / Odpowiedz

    No wygląda to całkiem ciekawie. Przyznam, że nie znałem tego programu a programy pisane w Delphi albo reversowalem jak kazdy inny program, albo wspomagałem się DeDe i generowalem mapy do ollyego. Ale z tego co widac tutaj, to może być naprawde przydatne 😉

  2. 08:59, 05.07.2012bw  / Odpowiedz

    Dobry tutorial, czekam na następne 🙂

Dodaj komentarz

Allowed Tags - You may use these HTML tags and attributes in your comment.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Pingbacks (0)

› No pingbacks yet.