Érzett már valaha vágyat arra, hogy szétszedjen egy mechanizmust, hogy megtudja, hogyan működik? Nos, ki ne érezte volna. Ez a vágy a vezető erő a reverse engineeringben. Ez a készség hasznos a termékbiztonság elemzéséhez, egy gyanús .exe fájl céljának kiderítéséhez annak futtatása nélkül, elveszett dokumentáció visszaszerzéséhez, régi szoftverekre épülő új megoldás kifejlesztéséhez stb.

Ez a cikk a reverse engineering elvégzéséhez szükséges tudásbázisról, egy Windows szoftver reverse engineeringjének alapelveiről, disassemblerekről és eszközökről szól. Emellett lépésről-lépésre bemutatunk egy példát egy alkalmazás visszafejtésére.

A cikket

Sergii Bratus,

fejlesztés koordinátor,

hálózatbiztonsági csoport

és

Anton Kukoba írta,

Biztonsági kutatási vezető

Tartalom

Mi az a szoftver visszafordítás?

Mire van szükségünk a visszafejtéshez?

Elméleti ismeretek. Szoftver visszafejtés folyamata

Hasznos eszközök a Windows szoftverek visszafejtéséhez

Disassemblerek

Windows Sysinternals

Hálózati felügyeleti eszközök

Debuggerek

Real-életbeli szoftver-visszafejtési példa

Hogyan kell visszafejteni egy illesztőprogramot

Következtetés

Mi a szoftver-visszafejtés?

A reverse engineering egy hardver vagy szoftver mögötti elvek, például az architektúra és a belső felépítés feltárásának folyamata. A kérdés, amely a visszafejtést vezérli: Hogyan működik?

Nyilvánvaló, hogy ha van dokumentáció, az egész folyamat sokkal egyszerűbbé válik. De gyakran előfordul, hogy nincs dokumentáció, és más módot kell találni arra, hogy megtudjuk, hogyan működik egy szoftver.

Mikor lehet szükségünk egy szoftver visszafejtésére, és miben segíthet ez?

A reverse engineeringnek számos felhasználási területe van az informatika területén, például:

  • Hálózati kommunikációs protokollok kutatása
  • A rosszindulatú szoftverekben, például számítógépes vírusokban, trójai vírusokban, zsarolóprogramokban stb. használt algoritmusok megtalálása.
  • A bármilyen információ tárolására használt fájlformátum kutatása, például e-mailek adatbázisok és lemezképek
  • A saját szoftverek visszafejtésnek való ellenálló képességének ellenőrzése
  • A szoftverek platformokkal és harmadik féltől származó szoftverekkel való kompatibilitásának javítása
  • A nem dokumentált platformfunkciók használata

A visszafejtés jogszerűsége a céltól és a szoftver felhasználásának módjától függ. A fent említett célok mindegyike teljesen jogszerű, feltéve, hogy a szoftver másolatát legálisan szerezte be. Ha azonban például egy zárt alkalmazás egy bizonyos funkcióját kívánja visszafejteni, majd egy másik alkalmazásban megvalósítani, akkor valószínűleg bajba kerül.

A jogi dokumentáció tekintetében a visszafejtést gyakran tiltják a végfelhasználói licencszerződések (EULA). Az amerikai Digital Millennium Copyright Act azonban kimondja, hogy egy szoftver visszafejtése legális, ha az más termékekkel való kompatibilitás javítása érdekében történik.

A jogi követelmények országonként eltérőek, ezért szánjon időt arra, hogy utánanézzen, mielőtt belevág.

Most lássuk, hogyan kell visszafejteni egy szoftvert.

Mire van szükségünk a visszafejtéshez?

A szoftverek visszafejtésének megkezdéséhez szükségünk van:

  1. ismeretekre azon a területen, ahol a visszafejtést alkalmazni akarjuk
  2. eszközökre, amelyek lehetővé teszik, hogy a tudásunkat alkalmazzuk, miközben megpróbáljuk szétszerelni a szoftvert.

Nézzünk egy általános példát, amely nem kapcsolódik szoftverekhez. Tegyük fel, hogy van egy órád, és meg akarod tudni, hogy mechanikus, kvarc vagy automata.

Az ismeretek birtokában tudnod kell, hogy háromféle óra létezik. Továbbá tudnia kell, hogy ha van elem, akkor az az óra belsejében található, és ha kinyitja, akkor láthatja. Alapvető ismeretekkel kell rendelkeznie az óra belső felépítéséről is, arról, hogyan néz ki az akkumulátor, és milyen eszközökre van szüksége az óraház kinyitásához. Az ismeretek alkalmazásához szükséges szerszámok megléte azt jelenti, hogy szükséged van egy csavarhúzóra vagy más speciális szerszámra, amellyel ki tudod nyitni az órát.

Mint ahogyan az óra visszafejtéséhez is speciális készségekre és eszközökre van szükség, a szoftverek visszafejtéséhez is szükség van a saját területére jellemző ismeretekre és eszközökre.

Elméleti ismeretek. Szoftver visszafejtési folyamat

A különböző szoftver-visszafejtési feladatokhoz különböző típusú ismeretekre van szükség. Természetesen vannak olyan általános ismeretek, amelyek a legtöbb reverse engineering feladatban segítenek: az általános alkalmazási struktúrák, programozási nyelvek, fordítók stb. ismerete. Speciális elméleti ismeretek nélkül azonban nem tudsz speciális reverse engineering feladatokat megoldani.

Ha…

Szükséged van ismeretekre…

viszont bármilyen hálózati alkalmazást

a folyamatok közötti kommunikáció alapelvei, a hálózatok felépítése, a kapcsolatok, a hálózati csomagok stb.

reverzális kriptográfiai algoritmusok

kriptográfia és a területen használt legnépszerűbb algoritmusok

kutatási fájl. struktúrák

alapvető fájlfogalmak és az, hogy a különböző rendszerek vagy komponensek hogyan dolgoznak a fájlokkal

A speciális technikák sok időt takaríthatnak meg a speciális típusú szoftverek visszafordítása során. A fájlok kölcsönhatása esetén egy olyan teszt elkészítése, amely egyedi típusértékeket ír egy fájlba, miközben naplózza az eltolásokat és az adatméretet a tényleges tárolófájlba, segíthet megtalálni az eltolások közös mintáit. Ez támpontot ad az ilyen fájlok belső struktúrájáról.

A szoftverfejlesztők a visszafejtési folyamat megkezdésekor általában disszamblert használnak, hogy megtalálják az algoritmusokat és a programlogikát a helyükön. Sokféle futtatható fájlformátum, fordító (amelyek különböző kimeneteket adnak) és operációs rendszer létezik. A technológiák ilyen sokfélesége kizárja egyetlen technológia használatát az összes szoftvertípus visszafordításához.

A dekompilált kód megértéséhez szükség van bizonyos ismeretekre az asszembler nyelvéről, a függvényhívási konvenciókról, a veremszerkezetről, a veremkeretek fogalmáról stb.

A különböző kódminták asszembler-kimenetének ismerete segíthet az eredeti funkcionalitás feltárásában. Nézzünk néhány példát a Windows x86 platformra.

Tegyük fel, hogy a következő kódunk van:

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

Ha ezt a kódot lefordítjuk egy futtatható fájlba, a disassemblerben ezt látjuk:

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 

Mint látjuk, a szabályos ciklusból assembly kód lett, összehasonlításokkal és ugrásokkal. Vegyük észre, hogy az assembly kód nem használja a szabályos assembly ciklust az ecx regiszterben lévő számlálóval. Ráadásul a helyi változókra itt ennek megfelelően and-ként hivatkozunk.

Lássuk, mi történik, ha ezt a kódot a release build segítségével fordítjuk le:

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

Ez a kódrészlet egyáltalán nem hasonlít az előzőhöz. Ez a kód optimalizálásának módja miatt van. Gyakorlatilag a ciklus eltávolításra került, mivel semmi értékeset nem csinál azon kívül, hogy a count változót 10-re növeli. Így az optimalizáló úgy döntött, hogy egyszerűen megtartja a count változó végső értékét, és az értéket közvetlenül a count kimeneti operátor argumentumaként helyezi el.

A manapság használt fordítóprogramok nagyon jók a kód optimalizálásában. Ezért a reverse engineering során jobb, ha megértjük a kód mögötti ötletet (a kód alapelveit), mintha magát az eredeti kódot próbálnánk megszerezni. Ha megértjük a kód mögötti ötletet, akkor egyszerűen megírhatjuk a saját prototípusunkat, amely megfelel az eredeti feladatnak.

Nagyon hasznos lesz tudni, hogy milyen assembly kódot kapunk, ha különböző operátorokat, struktúrákat és más nyelvi konstrukciókat fordítunk le. Az eredményül kapott assembly kód megértése jó kiindulópont a C++ fordított tervezéséhez, de ennek technikai részleteibe itt nem megyünk bele.

Hasznos eszközök a Windows-szoftverek fordított tervezéséhez

Az alkalmazásarchitektúra kutatásunkban már több fordított tervezési eszközt, köztük a ProcessMonitor-t és a ProcessExplorer-t is ismertettük. Ezek az eszközök teljesen nélkülözhetetlenek a reverse engineeringhez.

Ebben a részben áttekintjük a legnépszerűbb disassemblereket és néhány további eszközt, amelyeket mi is használunk a reverse engineering projektjeinkhez.

További részleteket és használati példákat a legjobb szoftver reverse engineering eszközökről szóló cikkünkben találhat.

Disassemblerek

A disassembler egy olyan program, amely egy futtatható fájlt assembly nyelvre fordít. A legnépszerűbb az IDA Pro

IDA Pro

IDA Pro

Az IDA Pro

egy kényelmes és hatékony eszköz a szétszereléshez. Rengeteg olyan eszközzel rendelkezik, amelyek lehetővé teszik egy szoftver gyors szétszerelését. Képes megjeleníteni a függvényhívásfát, elemezni a futtatható fájl importját és exportját, és információkat mutatni róluk. Még a kódot is képes megmutatni C-ben. Emellett több CPU architektúrát is támogat, így az IDA Pro segítségével ARM, AVR, M68k és sok más architektúra kódját is visszafejthetjük.

Radare

Radare

A Radare disassembler az IDA alternatívája. Alapvetően rendelkezik az IDA összes funkciójával, anélkül, hogy olyan robusztus és stabil lenne. De ingyenes és nyílt forráskódú. Maga a Radare egy konzolos eszköz, de van egy Cutter frontendje, ami az IDA valódi alternatívájává teszi.

Windows Sysinternals

A Windows Sysinternals segédprogramokat általában a Microsoft Windows környezet kezelésére, diagnosztikájára, hibaelhárítására és felügyeletére használják. De alkalmasak a Windows szoftverek visszafejtésére is.

ATCPView egy hálózati szimatoló, amely minden folyamat TCP/UDP csomagjairól minden információt megjelenít. Ez az eszköz hasznos a hálózati protokollok visszafordításához.

APortMon egy fizikai rendszerportfigyelő. Figyeli a soros és párhuzamos portokat és az ezeken keresztülmenő összes forgalmat.

A WinObj hierarchikus struktúrában mutatja a rendszer összes globális objektumát. Ez az eszköz hasznos lehet egy olyan alkalmazás visszafordításakor, amely szinkronizációs primitívekkel, például mutexekkel és szemaforokkal dolgozik, valamint a kernelmódú illesztőprogramok visszafordításakor.

Hálózatfigyelő eszközök

Wireshark

Wireshark

Aireshark az egyik legerősebb hálózati szimatoló. Nemcsak a hálózati forgalom rögzítését teszi lehetővé, hanem különböző hálózati protokollok elemzőit is tartalmazza, kezdve az igazán alacsony szintűektől, mint az Ethernet, TCP és IP, egészen az alkalmazásspecifikus protokollokig, mint a WebSockets és XMPP.

Fiddler

Fiddler

A Fiddler egy webproxy, amely rögzíti a böngészők forgalmát, és lehetővé teszi a HTTP/HTTPS kérések elemzését. A Wiresharkkal ellentétben különálló hálózati csomagok helyett HTTP munkameneteket mutat. A Fiddler lehetővé teszi továbbá a HTTP-n keresztül küldött tömörített adatok elemzését, valamint a SOAP, REST és AJAX kérések figyelése során a JSON és XML adatok elemzését.

API Monitor

API Monitor

Az API Monitor hasznos eszköz annak feltárására, hogy egy alkalmazás milyen API-kat hív meg, és az alkalmazás milyen viselkedést vár el ezektől az API-któl. Ez az eszköz nagy teljesítményű adatbázissal rendelkezik, és lehetővé teszi, hogy ne csak a kernel32 és az ntdll, hanem a COM, a menedzselt környezet és mások API-funkcióinak hatalmas számú hívását is láthassuk. Emellett az API Monitor kényelmes szűrési mechanizmusokat is biztosít.

Hibakeresők

A hibakereső minden fejlesztő számára felbecsülhetetlen értékű, hogy lássa, mit csinál éppen egy program. A hibakeresésből az alkalmazások visszafordításakor ugyanolyan előnyök származnak, mint az éles alkalmazások hibakereséséből.

A legnépszerűbb hibakeresők az OllyDbg, a WinDbg és a Windbg Preview.

OllyDbg

OllyDBG

Az OllyDbg (és utódja, az x64dbg) valószínűleg a legjobb debugger, ha szoftverek visszafejtéséről van szó. Kifejezetten a visszafejtés igényeihez fejlesztették ki, és rendelkezik az ehhez szükséges összes eszközzel:

  • egy beépített disassembler, amely képes a kulcsfontosságú adatstruktúrák elemzésére és azonosítására
  • egy import és export elemző funkció
  • egy beépített összeszerelő és foltozó motor

Az API függvények és paramétereik elemzésére való képesség megkönnyíti a rendszerrel való interakciók visszafejtését. A verem nézet sok információt nyújt a hívási veremről. További fontos előnye, hogy az OllyDbg-et használhatjuk debug-védett alkalmazásoknál, amikor a szokásos debuggerek egyszerűen nem tudnak mit kezdeni.

WinDbg

Windbg

A WinDbg egyszerű felülete ellenére erős eszközökkel rendelkezik a hibakereséshez. Van egy beépített disassembler, különböző parancsok, amelyek segítségével szinte mindent megtudhatunk a hibakeresés alatt álló folyamatról/rendszerről, és képes kernel-módú hibakeresésre, ami talán a legértékesebb funkciója. Ez nagy előny a meghajtók, különösen a kernel-módú meghajtók visszafordításánál.

Windbg Preview

Windbg Preview

A Windbg Preview a Microsoft által kifejlesztett Windbg új verziója. Kizárólag a Windows Store-on keresztül kerül terjesztésre. A klasszikus Windbg összes funkciójával rendelkezik, új felhasználói felülettel és számos új funkcióval párosítva. Az egyik ilyen új funkció az időutazásos hibakeresés, amely lehetővé teszi, hogy a program végrehajtásának bizonyos időszakát rögzítsük, majd annyiszor játsszuk le újra, ahányszor csak szükséges. Így a kód érdekes részeit lépten-nyomon végrehajthatja, nem kell attól tartania, hogy véletlenül lefuttat valamilyen kódot, és elveszíti a kontextust vagy az összes adatot.

Olvass még:
9 Best Reverse Engineering Tools for 2018

Valós szoftver reverse engineering példa

Most egy példát fogunk látni arra, hogyan lehet egy szoftvert visszafejteni. Képzeljük el, hogy van egy gyanús futtatható fájlunk. Ki kell derítenie, hogy mit csinál ez a program, és hogy biztonságos-e a felhasználók számára.

A forgatókönyvet figyelembe véve jó ötlet, ha ezt a futtatható fájlt nem a munkahelyi számítógépén futtatja, hanem inkább egy virtuális gépet használ. Indítsuk el az alkalmazást a virtuális gépünkön.

A folyamat létrehoz egy szolgáltatást

Amint látjuk, ez a fájl létrehoz egy Windows szolgáltatást TestDriver néven. Típusa kernel, tehát tudjuk, hogy ez egy meghajtó. De honnan veszi az illesztőprogram fájlt a futtatáshoz? A Sysinternals Suite ProcessMonitor segítségével kideríthetjük. Amikor megnyitjuk a ProcessMonitor-t, szűrőket állíthatunk be, hogy csak a minket érdeklő folyamat fájlaktivitását mutassa meg. A tevékenységi naplója így néz ki:

FileMon information

A vezérlőfájlt az általunk visszafordított folyamat hozza létre, és ez a folyamat ezt a fájlt a felhasználó temp könyvtárába helyezi. Nincs szükség arra, hogy megkeressük a fájlt a temp mappában, mivel látjuk, hogy a folyamat használat után azonnal törli azt. Mit csinál tehát a folyamat ezzel a fájllal? Ha kicsomagolja a fájlt, akkor megpróbálhatjuk megtalálni a folyamat erőforrás szekciójában, mivel ez egy gyakori hely az ilyen adatok tárolására. Nézzük meg ott. Az erőforrások vizsgálatához egy másik eszközt – Resource Hacker – fogunk használni. Futtassuk le:

Examine resources with Resource Hacker

Bingo! Amint a talált erőforrás tartalmából láthatjuk, ez valószínűleg a Windows futtatható fájlja, mivel MZ aláírással kezdődik, és a “Ez a program nem futtatható DOS módban” sztringet tartalmazza. Ellenőrizzük, hogy ez a mi driver fájlunk-e. Ehhez az Resource Hacker segítségével kicsomagoljuk az erőforrást, és megnyitjuk a disassemblerben.

Disassembler képernyő

Mint tudjuk, a DriverEntry a Windows rendszerekben a kernel-módú driverek belépési pontja. Folytathatjuk a kutatást, mivel úgy tűnik, megtaláltuk a megfelelő illesztőprogramot.

Hogyan kell visszafejteni egy illesztőprogramot

Az illesztőprogram visszafejtésének megkezdéséhez egyesével megvizsgáljuk a DriverEntry-ből meghívott függvényeket. Ha a sub_14005-re megyünk, nem találunk semmi érdekeset, ezért a sub_110F0-val folytatjuk, és ezt a kódot találjuk:

Code piece 1

Code piece 2

Code piece 3

Code piece 4

Az egyszerűség kedvéért néhány sort itt kihagyunk.

Az első felsorolásban egy unicode karakterláncot hozunk létre, és ez a karakterlánc a C:\hello.txt elérési útvonalra mutat. Ezután az OBJECT_ATTRIBUTES struktúra feltöltődik szabályos értékekkel; tudjuk, hogy erre a struktúrára gyakran van szükség az olyan függvények hívásakor, mint a ZwCreateFile.

A második listában látjuk, hogy a ZwCreateFile valóban meghívásra kerül, ami eléggé biztossá teszi számunkra, hogy a meghajtó létrehozza a fájlt – és tudjuk, hogy ez a fájl hol található a létrehozása után.

A harmadik és negyedik listából láthatjuk, hogy az illesztőprogram átveszi az unicode karakterláncot, és a pufferbe írja (ez a sub_11150 függvényben történik), és a puffer a ZwWriteFile függvény segítségével íródik a fájlba. A végén az illesztőprogram bezárja a fájlt a ZwClose API használatával.

Foglaljuk össze. Megállapítottuk, hogy az eredeti program kiveszi az illesztőprogram fájlját az erőforrásokból, az aktuális felhasználó temp mappájába helyezi, létrehozza a Windows szolgáltatást ehhez az illesztőprogramhoz, és futtatja azt. Ezután a program leáll, és törli a szolgáltatást és az eredeti driverfájlt a temp könyvtárból. Ebből a viselkedésből és a szétszerelés elemzéséből úgy tűnik, hogy az illesztőprogram nem csinál semmit, csak létrehoz egy hello.txt nevű fájlt a C meghajtón, és kiírja a “Hello from driver” sztringet.

Most ellenőriznünk kell, hogy igazunk van-e. Futtassuk a programot, és ellenőrizzük a C meghajtót:

Az alkalmazás képernyője

Nagyszerű! Visszafejtettük ezt az egyszerű programot, és most már tudjuk, hogy biztonságosan használható.

Ezt az eredményt sokféleképpen elérhettük volna – hibakereséssel vagy API Mon használatával, tesztek írásával stb. Ön is megtalálhatja a saját módját a szoftverek visszafejtésének, ami Önnek megfelel.

Következtetés

A Windows szoftverek visszafejtéséhez szilárd iskolai háttér és programozási tapasztalat szükséges. A reverse engineering elvégzéséhez kombinálni kell a szétszerelés, a hálózatfigyelés, a hibakeresés, az API-integráció, több programnyelv, a fordítóprogramok stb. ismereteit. A szoftverek visszafordítása során is nagyon óvatosnak kell lennie, hogy ne sértse meg a szerzői jogokat, és ne okozzon kárt a rendszerben.

Az Aprioritnál tapasztalt fordított mérnökökből álló csapattal rendelkezünk. Ha szeretné alkalmazni a fordított mérnöki készségeket a projektjében, forduljon hozzánk bizalommal!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.