Decompiler - Decompiler

Dekompilátor je počítačový program , který překládá spustitelný soubor na vysoké úrovni zdrojového souboru, který může být recompiled úspěšně. Jedná se tedy o opak kompilátoru , který překládá zdrojový soubor do spustitelného souboru. Decompilery obvykle nejsou schopny dokonale zrekonstruovat původní zdrojový kód, takže často vytvářejí zmatený kód . Nicméně, dekompilátory zůstává důležitým nástrojem v reverzní inženýrství z počítačového softwaru .

Úvod

Termín dekompilátor se nejčastěji používá pro program, který překládá spustitelné programy (výstup z kompilátoru ) do zdrojového kódu v (relativně) vysokém jazyce, který při kompilaci vytvoří spustitelný soubor, jehož chování je stejné jako původní spustitelný soubor. program. Pro srovnání, disassembler překládá spustitelný program do jazyka sestavení (a pro jeho sestavení zpět do spustitelného programu lze použít assembler).

Dekompilace je akt použití dekompilátoru, i když tento termín může také odkazovat na výstup dekompilátoru. Může být použit pro obnovu ztraceného zdrojového kódu a je také užitečný v některých případech pro zabezpečení počítače , interoperabilitu a opravu chyb . Úspěch dekompilace závisí na množství informací přítomných v dekompilovaném kódu a náročnosti analýzy na něm provedené. Formáty bajtkódu používané mnoha virtuálními stroji (například Java Virtual Machine nebo .NET Framework Common Language Runtime ) často obsahují rozsáhlá metadata a funkce na vysoké úrovni, díky nimž je dekompilace docela proveditelná. Aplikace ladicích dat , tj. Ladicích symbolů, může umožnit reprodukci původních názvů proměnných a struktur a dokonce i čísel řádků. Strojový jazyk bez takových metadat nebo ladicích dat je mnohem těžší dekompilovat.

Některé kompilátory a nástroje po kompilaci produkují zmatený kód (to znamená, že se pokoušejí vytvořit výstup, který je velmi obtížné dekompilovat, nebo který dekompiluje na matoucí výstup). To se provádí, aby bylo obtížnější zpětně analyzovat spustitelný soubor.

Přestože se dekompilátory běžně používají k (opětovnému) vytváření zdrojového kódu z binárních spustitelných souborů, existují také dekompilátory, které mění konkrétní binární datové soubory na zdroje čitelné a upravitelné pro člověka.

Design

Decompilery lze považovat za složené ze série fází, z nichž každá přispívá specifickými aspekty celkového dekompilačního procesu.

Nakladač

První fáze dekompilace načte a analyzuje binární formát vstupního strojového kódu nebo programu středně pokročilého jazyka . Měl by být schopen objevit základní fakta o vstupním programu, jako je architektura (Pentium, PowerPC atd.) A vstupní bod. V mnoha případech by měl být schopen najít ekvivalent funkce programu C , což je začátek uživatelem psaného kódu. To vylučuje inicializační kód runtime, který by neměl být dekompilován, pokud je to možné. Pokud jsou k dispozici, načtou se také tabulky symbolů a data ladění. Frontend může být schopen identifikovat použité knihovny, i když jsou propojeny s kódem, což poskytne rozhraní knihovny. Pokud dokáže určit kompilátor nebo použité kompilátory, může poskytnout užitečné informace při identifikaci idiomů kódu. main

Demontáž

Další logickou fází je rozebrání instrukcí strojového kódu na strojově nezávislou střední reprezentaci (IR). Například strojová instrukce Pentium

mov    eax, [ebx+0x04]

může být přeloženo do IR

eax  := m[ebx+4];

Idiomy

Idiomatické sekvence strojového kódu jsou sekvence kódu, jejichž kombinovaná sémantika není bezprostředně zřejmá z individuální sémantiky instrukcí. Buď jako součást fáze demontáže, nebo jako součást pozdějších analýz je třeba tyto idiomatické sekvence převést do známého ekvivalentního IR. Například kód sestavení x86 :

    cdq    eax             ; edx is set to the sign-extension≠edi,edi +(tex)push
    xor    eax, edx
    sub    eax, edx

by se dalo přeložit do

eax  := abs(eax);

Některé idiomatické sekvence jsou nezávislé na stroji; některé zahrnují pouze jednu instrukci. Například vymaže registr (nastaví jej na nulu). To lze implementovat pomocí pravidla zjednodušení nezávislého na stroji, jako je například . xor eax, eaxeaxa = 0

Obecně je nejlepší odložit detekci idiomatických sekvencí, pokud je to možné, na pozdější fáze, které jsou méně ovlivněny uspořádáním instrukcí. Fáze plánování plánovače kompilátoru může například vložit další instrukce do idiomatické sekvence nebo změnit pořadí instrukcí v sekvenci. Proces shody vzoru ve fázi demontáže by pravděpodobně nepoznal změněný vzor. Pozdější fáze seskupují výrazy instrukcí do složitějších výrazů a upravují je do kanonické (standardizované) formy, takže je pravděpodobnější, že i změněný idiom bude později v dekompilaci odpovídat vzoru vyšší úrovně.

Je obzvláště důležité rozpoznat idiomy kompilátoru pro volání podprogramů , zpracování výjimek a příkazy přepínače . Některé jazyky mají také rozsáhlou podporu řetězců nebo dlouhých celých čísel .

Analýza programu

Na IR lze použít různé programové analýzy. Zejména propagace výrazu kombinuje sémantiku několika instrukcí do složitějších výrazů. Například,

    mov   eax,[ebx+0x04]
    add   eax,[ebx+0x08]
    sub   [ebx+0x0C],eax

po šíření výrazu může mít za následek následující IR:

m[ebx+12]  := m[ebx+12] - (m[ebx+4] + m[ebx+8]);

Výsledný výraz je spíše jazykem vysoké úrovně a také eliminoval použití strojového registru eax. Pozdější analýzy mohou ebxregistr odstranit .

Analýza toku dat

Místa, kde je definován a používán obsah registru, musí být vysledovány pomocí analýzy toku dat . Stejnou analýzu lze použít na místa, která se používají pro dočasná a místní data. Pro každou takto připojenou sadu definic a použití hodnot pak lze vytvořit jiný název. Je možné, že stejné umístění lokální proměnné bylo použito pro více než jednu proměnnou v různých částech původního programu. Ještě horší je, že analýza toku dat může identifikovat cestu, po které může hodnota proudit mezi dvěma takovými způsoby použití, i když by se to ve skutečnosti nikdy nestalo nebo na tom ve skutečnosti nezáleželo. To může ve špatných případech vést k potřebě definovat umístění jako sjednocení typů. Dekompiler může uživateli umožnit výslovně prolomit takové nepřirozené závislosti, které povedou k jasnějšímu kódu. To samozřejmě znamená, že proměnná je potenciálně použita, aniž by byla inicializována, a znamená to problém v původním programu.

Typová analýza

Dobrý strojový kódový dekompilátor provede analýzu typu. Zde způsob použití registrů nebo paměťových míst vede k omezením možného typu umístění. andInstrukce například znamená, že operand je celé číslo; programy nepoužívají takovou operaci na hodnotách s pohyblivou řádovou čárkou (kromě speciálního kódu knihovny) nebo na ukazatelích . An addvýsledky instrukcí ve třech omezení, od operandů mohou být jak celé číslo, nebo jedno celé číslo a jeden ukazatel (s celočíselnými a ukazatele výsledků respektive, třetí omezení pochází z uspořádání dvou operandů, když typy se liší).

Lze rozpoznat různé výrazy na vysoké úrovni, které spouští rozpoznávání struktur nebo polí. Je však obtížné rozlišit mnoho z těchto možností, protože svoboda, kterou strojový kód nebo dokonce některé jazyky na vysoké úrovni, jako je C, umožňují s házením a aritmetikou ukazatele.

Příklad z předchozí části může mít za následek následující kód vysoké úrovně:

struct T1 *ebx;
    struct T1 {
        int v0004;
        int v0008;
        int v000C;
    };
ebx->v000C -= ebx->v0004 + ebx->v0008;

Strukturování

Předposlední fáze dekompilace zahrnuje strukturování IR do konstruktů vyšší úrovně, jako jsou whilesmyčky a if/then/elsepodmíněné příkazy. Například strojový kód

    xor eax, eax
l0002:
    or  ebx, ebx
    jge l0003
    add eax,[ebx]
    mov ebx,[ebx+0x4]
    jmp l0002
l0003:
    mov [0x10040000],eax

lze přeložit do:

eax = 0;
while (ebx < 0) {
    eax += ebx->v0000;
    ebx = ebx->v0004;
}
v10040000 = eax;

Nestrukturovaný kód je těžší přeložit do strukturovaného kódu než již strukturovaný kód. Řešení zahrnují replikaci nějakého kódu nebo přidání logických proměnných.

Generování kódu

Poslední fází je vygenerování kódu vysoké úrovně na zadním konci dekompilátoru. Stejně jako kompilátor může mít několik back -endů pro generování strojového kódu pro různé architektury, dekompilátor může mít několik back -endů pro generování kódu vysoké úrovně v různých jazycích vysoké úrovně.

Těsně před generováním kódu může být žádoucí umožnit interaktivní úpravu IR, možná pomocí nějaké formy grafického uživatelského rozhraní . To by uživateli umožnilo zadávat komentáře a generické názvy proměnných a funkcí. Ty jsou však téměř stejně snadno zadávány v úpravě po dekompilaci. Uživatel může chtít změnit strukturální aspekty, například převést whilesmyčku na forsmyčku. Ty jsou méně snadno upravovány pomocí jednoduchého textového editoru, i když s tímto procesem mohou pomoci nástroje pro refaktorování zdrojového kódu . Uživatel může potřebovat zadat informace, které se nepodařilo identifikovat během fáze typové analýzy, např. Úpravou výrazu paměti na výraz pole nebo struktury. Nakonec může být nutné opravit nesprávné IR nebo provést změny, aby byl výstupní kód čitelnější.

Zákonnost

Na většinu počítačových programů se vztahují autorská práva. Ačkoli přesný rozsah toho, co je chráněno autorským právem, se liší region od regionu, autorský zákon obecně poskytuje autorovi (programátoru (programátorům) nebo zaměstnavateli) sbírku výhradních práv k programu. Tato práva zahrnují právo pořizovat kopie, včetně kopií vytvořených v paměti RAM počítače (pokud není vytvoření takové kopie nezbytné pro používání programu). Protože proces dekompilace zahrnuje vytváření více takových kopií, je obecně bez povolení držitele autorských práv zakázán. Protože je však dekompilace často nezbytným krokem k dosažení softwarové interoperability , zákony o autorských právech ve Spojených státech i v Evropě umožňují dekompilaci v omezené míře.

Ve Spojených státech byla v případech dekompilace úspěšně uplatněna ochrana poctivého používání autorských práv . Například v rozsudku Sega v. Accolade soud rozhodl, že se Accolade může zákonitě zapojit do dekompilace, aby se obešel mechanismus uzamykání softwaru používaný herními konzolami společnosti Sega. Navíc, Digital Millennium Copyright Act (Public Law 105-304) má správné výjimky jak pro testování bezpečnosti a vyhodnocování v §1201 (i), a reverzní inženýrství v §1201 (f).

V Evropě směrnice o softwaru z roku 1991 výslovně stanoví právo na dekompilaci za účelem dosažení interoperability. Výsledek vášnivé debaty mezi ochranáři softwaru na jedné straně a akademiky a nezávislými vývojáři softwaru na straně druhé umožňuje článek 6 dekompilaci pouze tehdy, je -li splněna řada podmínek:

  • Za prvé, osoba nebo entita musí mít licenci k používání programu k dekompilaci.
  • Za druhé, k dosažení interoperability s cílovým programem nebo jinými programy musí být nutná dekompilace . Informace o interoperabilitě by proto neměly být snadno dostupné, například prostřednictvím příruček nebo dokumentace API . Toto je důležité omezení. Dekompiler musí prokázat nezbytnost. Účelem tohoto důležitého omezení je především poskytnout pobídku vývojářům, aby dokumentovali a zveřejňovali informace o interoperabilitě svých produktů.
  • Zatřetí, proces dekompilace musí být, pokud je to možné, omezen na části cílového programu relevantní pro interoperabilitu. Protože jedním z účelů dekompilace je porozumět struktuře programu, může být obtížné splnit toto třetí omezení. Důkazní břemeno je opět na dekompilátoru.

Kromě toho článek 6 předepisuje, že informace získané dekompilací nelze použít k jiným účelům a že je nelze poskytnout ostatním.

Celkově právo na dekompilaci stanovené v článku 6 kodifikuje to, o čem se tvrdí, že je běžnou praxí v softwarovém průmyslu. Je známo, že z práva na dekompilaci vzešlo několik evropských soudních sporů. To lze interpretovat tak, že to znamená jednu ze tří věcí:

  1. ) právo na dekompilaci není používáno často a právo na dekompilaci proto mohlo být zbytečné,
  2. ) právo na dekompilaci funguje dobře a poskytuje dostatečnou právní jistotu, aby nevznikly právní spory nebo
  3. ) nelegální dekompilace zůstává do značné míry nezjištěna.

Ve zprávě z roku 2000 týkající se implementace softwarové směrnice evropskými členskými státy se zdá , že Evropská komise podporuje druhou interpretaci.

Nástroje

Decompilery se obvykle zaměřují na konkrétní binární formát. Některé jsou nativní sady instrukcí (např. Intel x86, ARM, MIPS), jiné jsou bytecode pro virtuální stroje (Dalvik, soubory třídy Java, WebAssembly, Ethereum).

Kvůli ztrátě informací během kompilace není dekompilace téměř nikdy dokonalá a ne všechny dekompilátory fungují stejně dobře pro daný binární formát. Existují studie porovnávající výkon různých dekompilátorů.

Viz také

Rozkladače Java

Ostatní dekompiléry

Reference

externí odkazy