Czy kiedykolwiek czułeś pragnienie, aby rozebrać jakiś mechanizm na części, aby dowiedzieć się, jak działa? Cóż, kto nie ma. To pragnienie jest wiodącą siłą w inżynierii odwrotnej. Umiejętność ta jest przydatna do analizy bezpieczeństwa produktu, poznania przeznaczenia podejrzanego pliku .exe bez jego uruchamiania, odzyskania utraconej dokumentacji, opracowania nowego rozwiązania opartego na starszym oprogramowaniu itp.
W tym artykule omawiamy podstawy wiedzy potrzebnej do przeprowadzenia inżynierii wstecznej, podstawowe zasady inżynierii wstecznej oprogramowania Windows, dezasemblery i narzędzia. Przedstawiamy również przykład inżynierii wstecznej aplikacji krok po kroku.
Written by
Sergii Bratus,
Development Coordinator,
Network Security Team
and
Anton Kukoba,
Lider badań nad bezpieczeństwem
Treść
Co to jest odwracanie oprogramowania?
Czego potrzebujemy do inżynierii odwrotnej?
Wiedza teoretyczna. Proces inżynierii odwrotnej oprogramowania
Przydatne narzędzia do inżynierii odwrotnej oprogramowania Windows
Disassemblery
Windows Sysinternals
Narzędzia do monitorowania sieci
Debuggery
Przykłady real-przykład inżynierii odwrotnej oprogramowania
Jak przeprowadzić inżynierię odwrotną sterownika
Zakończenie
- Co to jest odwracanie oprogramowania?
- Czego potrzebujemy do inżynierii odwrotnej?
- Wiedza teoretyczna. Proces inżynierii odwrotnej oprogramowania
- Przydatne narzędzia do inżynierii wstecznej oprogramowania Windows
- Dezasemblery
- Windows Sysinternals
- Narzędzia do monitorowania sieci
- Debuggery
- Przykład inżynierii odwrotnej oprogramowania z prawdziwego życia
- Jak odwrócić inżynierię sterownika
- Wnioski
Co to jest odwracanie oprogramowania?
Inżynieria wsteczna jest procesem odkrywania zasad kryjących się za kawałkiem sprzętu lub oprogramowania, takich jak jego architektura i struktura wewnętrzna. Pytanie, które napędza inżynierię odwrotną, brzmi: Jak to działa?
Oczywiście, jeśli masz dokumentację, cały proces staje się dużo prostszy. Ale często zdarza się, że nie ma dokumentacji i musisz znaleźć inny sposób, aby dowiedzieć się, jak działa kawałek oprogramowania.
Kiedy możesz potrzebować inżynierii wstecznej kawałka oprogramowania i jak może ci to pomóc?
Istnieje wiele zastosowań inżynierii wstecznej w dziedzinie informatyki, w tym:
- Badanie protokołów komunikacji sieciowej
- Znajdowanie algorytmów używanych w złośliwym oprogramowaniu, takim jak wirusy komputerowe, trojany, ransomware itp.
- Badanie formatu plików używanych do przechowywania dowolnego rodzaju informacji, na przykład baz danych e-maili i obrazów dysków
- Sprawdzanie zdolności własnego oprogramowania do oparcia się inżynierii wstecznej
- Poprawa kompatybilności oprogramowania z platformami i oprogramowaniem stron trzecich
- Używanie nieudokumentowanych funkcji platform
Legalność inżynierii wstecznej zależy od jej celu i sposobu, w jaki oprogramowanie będzie używane. Wszystkie cele wymienione powyżej są całkowicie legalne, zakładając, że zdobyłeś kopię oprogramowania legalnie. Ale jeśli zamierzacie, na przykład, odtworzyć pewną cechę zamkniętej aplikacji, a następnie zaimplementować ją w innej aplikacji, prawdopodobnie wpadniecie w kłopoty.
W odniesieniu do dokumentacji prawnej, inżynieria wsteczna jest często zabroniona przez umowy licencyjne użytkownika końcowego (EULA). Ale US Digital Millenium Copyright Act określa, że odwrócenie kawałka oprogramowania jest legalne, jeśli to” zrobione w celu poprawy kompatybilności z innymi produktami.
Wymagania prawne różnią się w zależności od kraju, więc poświęć swój czas na ich zbadanie przed rozpoczęciem.
Teraz zobaczmy, jak odwrócić inżynierię oprogramowania.
Czego potrzebujemy do inżynierii odwrotnej?
Aby rozpocząć inżynierię odwrotną oprogramowania, potrzebujesz:
- wiedzy w dziedzinie, w której chcesz zastosować inżynierię odwrotną
- narzędzi, które pozwolą ci zastosować twoją wiedzę podczas próby demontażu oprogramowania.
Rozważmy ogólny przykład, który nie jest związany z oprogramowaniem. Powiedzmy, że masz zegarek i chcesz się dowiedzieć, czy jest on mechaniczny, kwarcowy czy automatyczny.
Mając wiedzę z tej dziedziny powinieneś wiedzieć, że istnieją trzy rodzaje zegarków. Dodatkowo, należy wiedzieć, że jeśli jest bateria, to znajduje się wewnątrz zegarka, i można go zobaczyć, jeśli go otworzyć. Powinieneś również mieć podstawową wiedzę na temat wewnętrznej struktury zegarka, jak wygląda bateria i jakich narzędzi potrzebujesz, aby otworzyć obudowę zegarka. Posiadanie narzędzi do zastosowania swojej wiedzy oznacza, że musisz mieć śrubokręt lub inne dedykowane narzędzie, które da ci szansę na otwarcie zegarka.
Tak jak inżynieria odwrotna zegarka wymaga specyficznego zestawu umiejętności i narzędzi, inżynieria odwrotna oprogramowania wymaga własnej wiedzy i narzędzi specyficznych dla tej dziedziny.
Wiedza teoretyczna. Proces inżynierii odwrotnej oprogramowania
Do różnych zadań inżynierii odwrotnej oprogramowania, potrzebujesz różnych rodzajów wiedzy. Oczywiście, istnieje wspólna wiedza, która pomoże ci w większości zadań inżynierii odwrotnej: wiedza o wspólnych strukturach aplikacji, językach programowania, kompilatorach i tak dalej. Jednak bez specjalnej wiedzy teoretycznej nie można rozwiązać konkretnych zadań inżynierii odwrotnej.
Jeśli… |
Potrzebujesz wiedzy o… |
inżynierii odwrotnej dowolnych aplikacji sieciowych |
zasad komunikacji międzyprocesowej, struktury sieci, połączeń, pakietów sieciowych itp. |
odwrócenie algorytmów kryptograficznych |
kryptografia i najpopularniejsze algorytmy stosowane w tej dziedzinie |
badanie struktur plików struktury |
podstawowe pojęcia związane z plikami oraz jak różne systemy lub komponenty współpracują z plikami |
Szczególne techniki mogą zaoszczędzić wiele czasu podczas odwracania specjalnych typów oprogramowania. W przypadku interakcji plików, wykonanie testu, który zapisuje unikalne wartości typu do pliku, jednocześnie rejestrując przesunięcia i rozmiar danych do rzeczywistego pliku przechowywania, może pomóc w znalezieniu wspólnych wzorców w przesunięciach. To da ci wskazówkę na temat wewnętrznych struktur tych plików.
Podczas rozpoczynania procesu inżynierii wstecznej, programiści oprogramowania zazwyczaj używają disassemblera w celu znalezienia algorytmów i logiki programu w miejscu. Istnieje wiele różnych formatów plików wykonywalnych, kompilatorów (które dają różne dane wyjściowe) i systemów operacyjnych. Ta różnorodność technologii wyklucza użycie jednej technologii do odwrócenia wszystkich typów oprogramowania.
Aby zrozumieć zdekompilowany kod, potrzebna jest pewna wiedza o języku asemblera, konwencjach wywoływania funkcji, strukturze stosu, koncepcji ramek stosu, itp.
Znajomość wyjścia asemblera dla różnych próbek kodu może pomóc w odkryciu oryginalnej funkcjonalności. Rozważmy kilka przykładów dla platformy Windows x86.
Powiedzmy, że mamy następujący kod:
Jeśli skompilujemy ten kod do pliku wykonywalnego, zobaczymy to w disassemblerze:
Jak widać, zwykły cykl zamienił się w kod asemblera z porównaniami i skokami. Zauważmy, że kod asemblerowy nie używa zwykłej pętli asemblerowej z licznikiem w rejestrze ecx. Ponadto zmienne lokalne są tu określane jako i odpowiednio.
Zobaczmy, co się stanie, jeśli skompilujemy ten kod przy użyciu release build:
Ten fragment kodu w niczym nie przypomina poprzedniego. Jest to spowodowane tym, jak kod został zoptymalizowany. Technicznie rzecz biorąc, pętla została usunięta, ponieważ nie robi ona nic wartościowego poza inkrementowaniem zmiennej count do 10. Tak więc optymalizator zdecydował się po prostu zachować końcową wartość zmiennej count i umieścić tę wartość bezpośrednio jako argument dla operatora wyjścia count.
Kompilatory, których używamy obecnie, są bardzo dobre w optymalizacji kodu. Dlatego podczas inżynierii wstecznej lepiej jest zrozumieć ideę stojącą za kodem (zasady kodu), niż próbować uzyskać sam oryginalny kod. Jeśli zrozumiesz ideę stojącą za kodem, możesz po prostu napisać swój własny prototyp, który pasuje do oryginalnego zadania.
Bardzo przydatna będzie wiedza, jaki kod asemblera otrzymasz, jeśli skompilujesz różne operatory, struktury i inne konstrukcje językowe. Zrozumienie wynikowego kodu asemblera jest dobrym sposobem na rozpoczęcie procesu inżynierii wstecznej C++, ale nie będziemy tutaj wchodzić w szczegóły techniczne tego procesu.
Przydatne narzędzia do inżynierii wstecznej oprogramowania Windows
Opisaliśmy już kilka narzędzi inżynierii wstecznej, w tym ProcessMonitor i ProcessExplorer, w naszych badaniach architektury aplikacji. Te narzędzia są absolutnie niezbędne do inżynierii wstecznej.
W tej sekcji przejrzymy najpopularniejsze dezasemblery i kilka innych narzędzi, których używamy w naszych projektach inżynierii wstecznej.
Więcej szczegółów i przykładów użycia można uzyskać w naszym artykule na temat najlepszych narzędzi do inżynierii wstecznej oprogramowania.
Dezasemblery
Dezasembler to program, który tłumaczy plik wykonywalny na język asemblera. Najpopularniejszym z nich jest IDA Pro
IDA Pro
IDA Pro
IDA Pro jest wygodnym i potężnym narzędziem do demontażu. Posiada ogromną ilość narzędzi, które pozwalają na szybki demontaż oprogramowania. Może pokazywać drzewo wywołań funkcji, parsować import i eksport pliku wykonywalnego, oraz pokazywać informacje o nich. Może nawet pokazać kod w C. Ponadto, obsługuje wiele architektur procesorów, więc możliwe jest użycie IDA Pro do inżynierii wstecznej kodu dla ARM, AVR, M68k i wielu innych architektur.
Radare
Radare
Dezasembler Radare jest alternatywą dla IDA. W zasadzie ma wszystkie cechy IDA, ale nie jest tak solidny i stabilny. Ale jest darmowy i open source. Sam Radare jest narzędziem konsolowym, ale ma interfejs Cuttera, co czyni go prawdziwą alternatywą dla IDA.
Windows Sysinternals
Przyborniki Windows Sysinternals są generalnie używane do zarządzania, diagnostyki, rozwiązywania problemów i monitorowania środowiska Microsoft Windows. Ale są one również odpowiednie do inżynierii wstecznej oprogramowania Windows.
TCPView jest snifferem sieciowym, który pokazuje wszystkie informacje o pakietach TCP/UDP ze wszystkich procesów. To narzędzie jest przydatne do odwracania protokołów sieciowych.
PortMon jest monitorem portów systemu fizycznego. Monitoruje on porty szeregowe i równoległe oraz cały ruch, który przez nie przechodzi.
WinObj pokazuje wszystkie globalne obiekty w systemie w strukturze hierarchicznej. To narzędzie może być przydatne podczas odwracania aplikacji, która pracuje z prymitywami synchronizacji, takimi jak muteksy i semafory, a także podczas inżynierii wstecznej sterowników trybu jądra.
Narzędzia do monitorowania sieci
Wireshark
Wireshark
Wireshark jest jednym z najpotężniejszych snifferów sieciowych. Nie tylko pozwala na przechwytywanie ruchu sieciowego, ale także zawiera parsery dla różnych protokołów sieciowych, począwszy od naprawdę niskiego poziomu, jak Ethernet, TCP i IP, do protokołów specyficznych dla aplikacji, jak WebSockets i XMPP.
Fiddler
Fiddler
Fiddler jest proxy internetowym, które rejestruje ruch z przeglądarek i pozwala analizować żądania HTTP/HTTPS. W przeciwieństwie do Wiresharka, pokazuje on sesje HTTP zamiast pojedynczych pakietów sieciowych. Fiddler pozwala również analizować skompresowane dane przesyłane przez HTTP i analizować dane JSON i XML podczas monitorowania żądań SOAP, REST i AJAX.
Monitor API
Monitor API
Monitor API jest użytecznym narzędziem do odkrywania, które API są wywoływane przez aplikację i jakiego zachowania aplikacja oczekuje od tych API. Narzędzie to posiada potężną bazę danych i pozwala zobaczyć wywołania do ogromnej liczby funkcji API nie tylko kernel32 i ntdll, ale także COM, środowiska zarządzanego i innych. Ponadto, API Monitor zapewnia wygodne mechanizmy filtrowania.
Debuggery
Debugger jest nieoceniony dla każdego programisty, ponieważ pozwala zobaczyć, co program robi w danej chwili. Uzyskujesz takie same korzyści z debugowania podczas cofania aplikacji, jak z debugowania aplikacji na żywo.
Najpopularniejsze debuggery to OllyDbg, WinDbg i Windbg Preview.
OllyDbg
OllyDBG
OllyDbg (i jego następca x64dbg) jest prawdopodobnie najlepszym debuggerem jeśli chodzi o inżynierię wsteczną oprogramowania. Został stworzony specjalnie na potrzeby odwracania i posiada wszystkie potrzebne do tego narzędzia:
- wbudowany disassembler z możliwością analizy i identyfikacji kluczowych struktur danych
- funkcja analizy importu i eksportu
- wbudowany silnik asemblera i patchowania
Możliwość parsowania funkcji API i ich parametrów ułatwia odwracanie interakcji z systemem. Widok stosu dostarcza wielu informacji o stosie wywołań. Jeszcze jedną ważną zaletą jest to, że możesz używać OllyDbg z aplikacjami chronionymi przed debugowaniem, kiedy zwykłe debuggery po prostu nie mogą nic zrobić.
WinDbg
Windbg
Pomimo prostego interfejsu, WinDbg posiada potężne narzędzia do debugowania. Posiada wbudowany disassembler, różne komendy, które pozwalają dowiedzieć się prawie wszystkiego o procesie/systemie, który debugujesz, oraz możliwość debugowania w trybie jądra, co jest prawdopodobnie najcenniejszą cechą. Jest to duża zaleta przy odwracaniu sterowników, sterowników w trybie jądra w szczególności.
Windbg Preview
Windbg Preview
Windbg Preview jest nową wersją Windbg opracowaną przez Microsoft. Jest ona dystrybuowana wyłącznie przez Windows Store. Posiada wszystkie cechy klasycznego Windbg w połączeniu z nowym UI i kilka nowych funkcji. Jedną z tych nowych funkcji jest Time Travel Debugging, która pozwala nagrać pewien okres wykonywania programu, a następnie odtworzyć go tyle razy, ile potrzebujesz. W ten sposób można wykonać interesujące fragmenty kodu metodą krokową, nie obawiając się przypadkowego uruchomienia jakiegoś kodu i utraty kontekstu lub wszystkich danych.
Czytaj także:
9 Najlepszych narzędzi do inżynierii odwrotnej na 2018 rok
Przykład inżynierii odwrotnej oprogramowania z prawdziwego życia
Teraz zobaczymy przykład, jak przeprowadzić inżynierię odwrotną kawałka oprogramowania. Wyobraźmy sobie, że masz podejrzany plik wykonywalny. Musisz dowiedzieć się, co robi ten program i czy jest bezpieczny dla użytkowników.
Rozważając ten scenariusz, dobrze jest nie uruchamiać tego pliku wykonywalnego na komputerze służbowym, ale użyć maszyny wirtualnej. Uruchommy aplikację w naszej maszynie wirtualnej.
Proces tworzy usługę
Jak widzimy, ten plik tworzy usługę Windows o nazwie TestDriver. Ma ona typ kernel, więc wiemy, że jest to sterownik. Ale skąd bierze plik sterownika, aby móc go uruchomić? Możemy użyć ProcessMonitora z pakietu Sysinternals Suite, aby się tego dowiedzieć. Kiedy otworzymy ProcessMonitora, możemy ustawić filtry tak, aby pokazywał nam tylko aktywność plików z interesującego nas procesu. Jego dziennik aktywności wygląda tak:
Informacje FileMon
Plik sterownika jest tworzony przez proces, który odwracamy, a proces ten umieszcza ten plik w katalogu tymczasowym użytkownika. Nie ma potrzeby szukania pliku w folderze tymczasowym, ponieważ widzimy, że proces usuwa go zaraz po użyciu. Co więc proces robi z tym plikiem? Jeśli rozpakowuje plik, możemy spróbować znaleźć go w sekcji zasobów procesu, gdyż jest to częste miejsce przechowywania tego typu danych. Zajrzyjmy tam. Do zbadania zasobów użyjemy innego narzędzia – Resource Hacker. Uruchommy je:
Examine resources with Resource Hacker
Bingo! Jak widzimy po zawartości znalezionego zasobu, jest to prawdopodobnie plik wykonywalny Windows, ponieważ zaczyna się od sygnatury MZ i ma ciąg „Ten program nie może być uruchomiony w trybie DOS”. Sprawdźmy, czy jest to plik naszego sterownika. W tym celu rozpakowujemy zasób za pomocą Resource Hackera i otwieramy go w disassemblerze.
Ekran disassemblera
Jak wiemy, DriverEntry jest punktem wejścia dla sterowników trybu jądra w systemach Windows. Możemy kontynuować nasze badania, ponieważ wygląda na to, że znaleźliśmy właściwy sterownik.
Jak odwrócić inżynierię sterownika
Aby rozpocząć odwrotną inżynierię sterownika, sprawdzamy po kolei funkcje, które są wywoływane z DriverEntry. Jeśli przejdziemy do sub_14005, nie znajdziemy nic interesującego, więc kontynuujemy od sub_110F0 i znajdujemy ten kod:
Kod fragmentu 1
Kod fragmentu 2
Kod fragmentu 3
Kod fragmentu 4
Niektóre linie zostały tu pominięte dla uproszczenia.
W pierwszym listingu tworzony jest ciąg znaków unicode, który wskazuje na ścieżkę C:hello.txt. Następnie struktura OBJECT_ATTRIBUTES jest wypełniana zwykłymi wartościami; wiemy, że ta struktura jest często potrzebna przy wywoływaniu funkcji takich jak ZwCreateFile.
Na drugim listingu widzimy, że ZwCreateFile jest rzeczywiście wywoływany, co daje nam pewność, że sterownik tworzy plik – i wiemy, gdzie ten plik znajduje się po utworzeniu.
Z trzeciego i czwartego listingu widzimy, że sterownik pobiera łańcuch unicode i zapisuje go do bufora (dzieje się to w funkcji sub_11150), a bufor zostanie zapisany do pliku za pomocą funkcji ZwWriteFile. Na koniec sterownik zamyka plik za pomocą API ZwClose.
Podsumujmy. Dowiedzieliśmy się, że oryginalny program wyciąga plik sterownika z jego zasobów, umieszcza go w folderze temp bieżącego użytkownika, tworzy usługę Windows dla tego sterownika i uruchamia ją. Po tym program zatrzymuje się i usuwa usługę oraz oryginalny plik sterownika z katalogu tymczasowego. Z tego zachowania oraz z analizy demontażu wynika, że sterownik nie robi nic poza utworzeniem pliku na dysku C o nazwie hello.txt i zapisaniem w nim ciągu znaków „Hello from driver”.
Teraz musimy sprawdzić, czy mamy rację. Uruchommy program i sprawdźmy dysk C:
Ekran aplikacji
Cudownie! Przeprowadziliśmy inżynierię wsteczną tego prostego programu i teraz wiemy, że jest on bezpieczny w użyciu.
Mogliśmy osiągnąć ten wynik na wiele różnych sposobów – używając debugowania lub API Mon, pisząc testy, itp. Możesz znaleźć swoje własne sposoby inżynierii wstecznej oprogramowania, które działają dla Ciebie.
Wnioski
Inżynieria wsteczna oprogramowania Windows wymaga solidnego wykształcenia i doświadczenia w programowaniu. Aby wykonać inżynierię odwrotną, musisz połączyć umiejętności w zakresie demontażu, monitorowania sieci, debugowania, integracji API, kilku języków programowania, kompilatorów itp. Musisz również być bardzo ostrożny podczas odwracania oprogramowania, aby nie złamać praw autorskich lub nie uszkodzić systemu.
W Apriorit mamy doświadczony zespół inżynierów odwrotnych. Jeśli chcesz zastosować umiejętności inżynierii odwrotnej do swojego projektu, skontaktuj się z nami!
W Apriorit mamy doświadczony zespół inżynierów odwrotnych.