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?

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:

  1. wiedzy w dziedzinie, w której chcesz zastosować inżynierię odwrotną
  2. 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:

int count = 0;for (int i = 0; i < 10; ++i){count++;}std::cout << count;

Jeśli skompilujemy ten kod do pliku wykonywalnego, zobaczymy to w disassemblerze:

004113DE loc_4113DE:004113DE mov eax, 004113E1 add eax, 1004113E4 mov , eax004113E7 loc_4113E7:004113E7 cmp , 0Ah004113EB jge short loc_4113F8004113ED mov eax, 004113F0 add eax, 1004113F3 mov , eax004113F6 jmp short loc_4113DE004113F8 loc_4113F8:004113F8 mov ecx, ds:004113FE push eax00411400 call ds:<<(int)00411404 xor eax, eax00411406 retn 

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:

00401000 main proc near00401000 mov ecx, ds:00401006 push 0Ah00401008 call ds:<<(int)0040100E xor eax, eax00401010 retn00401010 main endp

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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.