Frage

Gibt es trotzdem kann dies geschehen? Ich habe verwendet objdump aber nicht produzieren Bestückungsleistung, die von jedem Assembler akzeptiert werden, die ich kenne. Ich möchte in der Lage sein, Anweisungen zu ändern innerhalb einer ausführbaren Datei und dann danach testen.

War es hilfreich?

Lösung

Ich glaube nicht, es eine zuverlässige Möglichkeit, dies zu tun. Maschinencode-Formate sind sehr kompliziert, komplizierter als Baugruppendateien. Es ist nicht wirklich möglich, ein kompilierte binären zu nehmen (etwa im ELF-Format) und eine Quellenanordnung Programm zu erzeugen, das auf die gleiche (oder ähnlich genug) binären kompilieren. Um ein Verständnis der Unterschiede zu gewinnen, zu vergleichen, die Ausgabe von GCC direkt an Assembler (gcc -S) im Vergleich zu dem Ausgang des objdump auf dem ausführbaren Datei (objdump -D) kompiliert wird.

Es gibt zwei große Komplikationen ich denken kann. Erstens sich der Maschinencode ist kein 1-zu-1-Entsprechung mit Assembler-Code, weil der Dinge wie Zeiger-Offsets.

Betrachten wir zum Beispiel den C-Code zu Hallo Welt:

int main()
{
    printf("Hello, world!\n");
    return 0;
}

Dies kompiliert auf den x86-Assembler-Code:

.LC0:
    .string "hello"
    .text
<snip>
    movl    $.LC0, %eax
    movl    %eax, (%esp)
    call    printf

Wo .LCO ist eine benannte Konstante und printf ist ein Symbol in einer gemeinsamen Bibliothek Symboltabelle. Vergleichen Sie mit dem Ausgang des objdump:

80483cd:       b8 b0 84 04 08          mov    $0x80484b0,%eax
80483d2:       89 04 24                mov    %eax,(%esp)
80483d5:       e8 1a ff ff ff          call   80482f4 <printf@plt>

Zuerst wird die Konstante .LC0 ist jetzt nur einige zufällig im Speicher irgendwo Offset - wäre es schwierig, eine Assembly-Quelldatei zu erstellen, die diese Konstante in der richtigen Stelle enthält, da der Assembler und Linker sind frei Standorte zu wählen, für diese Konstanten.

Zum anderen bin ich nicht ganz sicher über diese (und es hängt von Dingen wie Position unabhängigen Code), aber ich glaube, dass der Verweis auf printf tatsächlich nicht an der Zeigeradresse codiert in diesem Code überhaupt da, aber die ELF Header enthält eine Lookup-Tabelle, die ihre Adresse zur Laufzeit dynamisch ersetzt. Daher wird der demontierten Code nicht ganz entspricht den Source-Assembler-Code.

Insgesamt Quellenanordnung hat Symbole , während kompilierte Maschinencode hat Adressen , die nur schwer rückgängig zu machen.

Die zweite große Komplikation ist, dass eine Assembly-Quelldatei nicht alle Informationen enthalten kann, die in den ursprünglichen ELF-Datei-Header vorhanden waren, wie die Bibliothek dynamisch Link gegen und andere Metadaten dort durch den ursprünglichen Compiler platziert. Es wäre schwierig, diese zu rekonstruieren.

Wie ich schon sagte, es ist möglich, dass ein spezielles Werkzeug all diese Informationen manipulieren kann, aber es ist unwahrscheinlich, dass man einfach Assembler-Code erzeugen kann, die wieder an die ausführbaren Datei wieder zusammengebaut werden können.

Wenn Sie bei der Änderung nur einen kleinen Ausschnitt der ausführbaren Datei interessiert sind, habe ich eine viel subtiler Ansatz empfehlen als die gesamte Anwendung neu kompilieren. Verwenden Sie objdump, um den Assembler-Code für die Funktion zu erhalten (s), die Sie interessieren. Konvertieren Sie es auf „Quellenanordnung Syntax“ von Hand (und hier möchte ich es ein Werkzeug war, dass tatsächlich Demontage hergestellt in der gleichen Syntax wie die Eingabe) , und ändern Sie es, wie Sie wollen. Wenn Sie fertig sind, recompile nur jene Funktion (en) und verwenden objdump, um herauszufinden, den Maschinencode für Ihr geändertes Programm. Dann einen Hex-Editor verwenden, um manuell den neuen Maschinencode über die Oberseite des entsprechenden Teils des ursprünglichen Programms einfügen, wobei darauf geachtet, dass Ihr neuer Code ist genau die gleiche Anzahl von Bytes wie der alten Code (oder alle der Offsets falsch wären ). Wenn der neue Code kürzer ist, können Sie Pad es aus NOP-Befehle verwenden. Wenn es länger ist, können Sie in Schwierigkeiten sein, und vielleicht müssen neue Funktionen erstellen und nennen sie statt.

Andere Tipps

Code innerhalb eines binären ändernden Montag gibt es im Allgemeinen drei Möglichkeiten, es zu tun.

  • Wenn es nur einige triviale Sache wie eine Konstante ist, dann ändern Sie einfach den Standort mit einem Hex-Editor. Angenommen, Sie können es finden beginnen.
  • Wenn Sie alten Code benötigen, nutzt dann die LD_PRELOAD eine Funktion in Ihrem Programm zu überschreiben. Das funktioniert nicht, wenn die Funktion aber nicht in den Funktionstabellen ist.
  • Hack der Code an der Funktion, die Sie korrigieren möchten ein direkter Sprung zu einer Funktion, die Sie über LD_PRELOAD laden und dann auf die gleiche Stelle zurückspringen (Dies ist eine Kombi der beiden oben genannten)

Natürlich steht nur der zweite ein funktionieren wird, wenn die Montage tut jede Art von Selbstintegritätsprüfung.

Edit:. Wenn es nicht offensichtlich ist, dann mit binären Baugruppen um zu spielen, ist sehr High-Level-Entwickler Sachen, und Sie werden eine harte Zeit, darüber hier gefragt haben, es sei denn, es wirklich bestimmte Dinge, die Sie fragen,

@mgiuca hat korrekt adressiert diese Antwort aus technischer Sicht. In der Tat ist disassemblying ein ausführbares Programm in eine einfach zu recompile Montage Quelle keine leichte Aufgabe.

Um einige Bits zur Diskussion hinzufügen, es gibt ein paar Techniken / Werkzeuge, die interessant sein könnten zu erkunden, obwohl sie technisch komplex sind.

  1. statisch / dynamisch Instrumentierung . Diese Technik beinhaltet die ausführbare Datei-Format zu analysieren, Einfügen / Löschen / Ersetzen spezifische Montageanleitung für einen bestimmten Zweck, fixieren Sie alle Verweise auf Variablen / Funktionen in der ausführbaren Datei und die emit eine neue ausführbare Datei modifiziert. Einige Werkzeuge, die ich kenne, sind: PIN , Hijacker , PEBIL , DynamoRIO . Bedenken Sie, dass die Konfiguration solcher Werkzeuge zu einem anderen Zweck als dem, was sie entworfen wurden für schwierig sein könnte, und erfordert Verständnis beider ausführbaren Formate und Befehlssätze.
  2. Voll ausführbare Dekompilierungsprozeß . Diese Technik versucht, eine vollständige Montage Quelle aus einer ausführbaren Datei zu rekonstruieren. Sie können einen Blick auf die Online Disassembler geben wollen, was zu tun versucht, die Arbeit. Sie verlieren sowieso Informationen über die verschiedenen Quellenmodule und möglicherweise Funktionen / Variablennamen.
  3. Retargetable Dekompilierungsprozeß . Diese Technik versucht, mehr Informationen aus der ausführbaren Datei zu extrahieren, mit Blick auf Compiler Fingerabdrücke (das heißt, Muster von Code generiert durch bekannte Compiler) und andere deterministische Sachen. Das Hauptziel ist geordnete Quellcode zu rekonstruieren, wie C-Quelle, von einer ausführbaren Datei. Dies ist manchmal die Lage, Informationen über Funktionen / Variablen-Namen wieder zu erlangen. Bedenken Sie, dass Quellen mit -g bietet oft bessere Ergebnisse zu kompilieren. Vielleicht möchten Sie geben die Retargetable Decompiler versuchen.

Die meisten davon stammen aus vulnerbility Beurteilung und Durchführung Analyse Forschungsgebieten. Sie sind komplexe Techniken und oft sind die Werkzeuge nicht sofort aus der Box verwendet werden. Dennoch liefern sie wertvolle Hilfe bei dem Versuch, einige Software Reverse Engineering.

Ich tue dies mit hexdump und einem Texteditor. Sie müssen in die wirklich bequem mit dem Maschinencode und das Dateiformat es, und flexibel mit dem, was zählt als „zerlegen, modifizieren, und dann wieder zusammenbauen“.

Speicher

Wenn Sie mit der Herstellung nur „vor Ort Veränderungen“ weg (Umschreiben Bytes, aber nicht das Hinzufügen noch Bytes zu entfernen), wird es leicht sein (relativ gesehen).

Sie wirklich wollen keine bestehenden Befehle verdrängen, denn dann würden Sie manuell alle betroffenen relativ innerhalb der Maschinencode-Offset einstellen müssen, um, für Sprünge / branches / Lasten / Geschäfte in Bezug auf der Programmzähler, die beide in fest einprogrammiert sofort Werte und diejenigen, berechnet durch Register .

Sie sollten immer in der Lage sein, weg mit nicht Bytes zu entfernen. Hinzufügen von Bytes können für komplexere Modifikationen notwendig sein, und bekommt viel härter.

Schritt 0 (Vorbereitung)

Nachdem Sie wirklich zerlegt die Datei ordnungsgemäß mit objdump -D oder was auch immer Sie normalerweise zuerst tatsächlich verstehen es nutzen und die Punkte, die Sie ändern müssen, finden, müssen Sie bitte die folgenden nehmen Dinge zu Hilfe finden Sie das richtige Bytes zu ändern:

  1. Die „Adresse“ (Offset vom Anfang der Datei) der Bytes, die Sie ändern müssen.
  2. Der Rohwert dieses Bytes, wie sie derzeit sind (die --show-raw-insn Option objdump ist wirklich hilfreich hier).

Schritt 1

Dump die rohe hexadezimale Darstellung der Binärdatei mit hexdump -Cv.

Schritt 2

Öffnen Sie die Datei hexdumped und finden Sie die Bytes an der Adresse, die Sie ändern suchen.

Schnell Crash-Kurs in hexdump -Cv Ausgabe:

  1. Die linke Spalte ist die Adressen des Bytes (relativ zum Anfang der Binärdatei selbst, genau wie objdump bietet).
  2. Die rechte Spalte (von | Zeichen umgeben ist) ist nur „human readable“ Darstellung der Bytes - das ASCII-Zeichen jedes Byte passende dort geschrieben steht, mit einem . im Stehen für alle Bytes, die auf eine Karte nicht druckbare ASCII-Zeichen.
  3. Die wichtigen Sachen sind zwischendurch -. Jedes Byte als zwei hexadezimale Ziffern durch Leerzeichen getrennt, 16 Bytes pro Zeile

Achtung: Im Gegensatz zu objdump -D, mit dem Sie die Adresse jedes Befehls und zeigt die rohe hex des Befehls basierend auf gibt, wie sie als kodierte dokumentiert ist, Dumps hexdump -Cv jedes Byte genau in der Reihenfolge, in der Datei angezeigt wird. Dies kann ein wenig verwirrend, als erste auf Maschinen, bei denen der Befehlsbytes in umgekehrter Reihenfolge sind aufgrund endianness Unterschiede, die auch verwirrend sein können, wenn Sie ein bestimmtes Byte als eine bestimmte Adresse zu erwarten.

Schritt 3

Ändern der diesen Bedarf zu ändern Bytes -. Sie offensichtlich brauchen, um herauszufinden, die Roh-Maschine Befehlscodierung (nicht die Montage Mnemotechnik) und manuell in den richtigen Bytes schreiben

Hinweis: Sie nicht Notwendigkeit, die für Menschen lesbare Darstellung in der rechten Spalte zu ändern. hexdump ignoriert es, wenn Sie "un-dump" es.

Schritt 4

"Un-dump" die modifizierte hexdump Datei mit hexdump -R.

Schritt 5 (Plausibilitätsprüfung)

objdump Ihre neu unhexdumped Datei und stellen Sie sicher, dass die Demontage, dass Sie veränderten Aussehen korrigieren. diff es gegen die objdump des Originals.

Im Ernst, nicht überspringen Sie diesen Schritt. Ich mache einen häufigen Fehler als nicht, wenn die Maschine manuell Code Bearbeitung und das ist, wie ich die meisten von ihnen fange.

Beispiel

Hier ist ein Real-Life arbeitete Beispiel aus, wenn ich geändert kürzlich eine ARMv8 (Little Endian) binär. (Ich weiß, ist die Frage x86 markiert, aber ich habe kein x86 Beispiel praktisch, und die grundlegenden Prinzipien sind the gleich, nur die Anweisungen sind anders.)

In meiner Situation Ich brauchte eine spezifische zu deaktivieren Hand halten check „Sie sollten nicht tun“: in meinem Beispiel binär, in objdump --show-raw-insn -d Ausgang der Linie ich sah gepflegt wie diese (eine Anweisung vor und nach bestimmten für context):

     f40:   aa1503e3    mov x3, x21
     f44:   97fffeeb    bl  af0 <error@plt>
     f48:   f94013f7    ldr x23, [sp, #32]

Wie Sie sehen können, ist unser Programm „helfend“ Verlassen durch Springen in eine error Funktion (die das Programm beendet). Nicht akzeptabel. So werden wir diese Anweisung in eine no-op drehen. So dass wir für den Bytes 0x97fffeeb an der Adresse / file-Offset 0xf44 suchen.

Hier ist die hexdump -Cv Linie enthält, dass gegenüber.

00000f40  e3 03 15 aa eb fe ff 97  f7 13 40 f9 e8 02 40 39  |..........@...@9|

Beachten Sie, wie die relevanten Bytes tatsächlich gekippt (Little-Endian-Codierung in der Architektur gilt für Maschinenbefehle wie auf etwas anderes) und wie diese leicht unintuitively in welchem ??bezieht Byte an, was Byte-Offset:

00000f40  -- -- -- -- eb fe ff 97  -- -- -- -- -- -- -- --  |..........@...@9|
                      ^
                      This is offset f44, holding the least significant byte
                      So the *instruction as a whole* is at the expected offset,
                      just the bytes are flipped around. Of course, whether the
                      order matches or not will vary with the architecture.

Wie auch immer, ich weiß aus der Betrachtung anderer Demontage, dass 0xd503201f Disassembliert zu nop so dass für meine no-op-Befehl wie ein guter Kandidat zu sein scheint. Ich modifiziere die Zeile in der hexdumped Datei entsprechend:

00000f40  e3 03 15 aa 1f 20 03 d5  f7 13 40 f9 e8 02 40 39  |..........@...@9|

Converted zurück in binären mit hexdump -R, zerlegt die neue Binärdatei mit objdump --show-raw-insn -d und verifiziert, dass die Änderung richtig war:

     f40:   aa1503e3    mov x3, x21
     f44:   d503201f    nop
     f48:   f94013f7    ldr x23, [sp, #32]

Dann lief ich die binären und bekam das Verhalten, das ich wollte -. Das entsprechende Kontroll nicht verursacht länger das Programm abbrechen

Maschinencode Änderung erfolgreich.

!!! Achtung !!!

Oder war ich erfolgreich? Haben Sie vor Ort, was ich in diesem Beispiel verpasst?

Ich bin sicher, du hast - da Sie fragen, wie die Maschine manuell Code eines Programms ändern, wissen Sie vermutlich, was du tust. Aber zum Nutzen aller Leser, die lernen könnte zu lesen, ich werde erarbeiten:

ich nur die letzte Anweisung im Fehlerfall Zweig verändert! Der Sprung in die Funktion, die das Problem austritt. Aber wie Sie sehen können, Register x3 wurde knapp oberhalb der mov geändert! In der Tat, insgesamt vier (4) wurden Register als Teil der Präambel Anruf error modifizieren und ein Register war. Hier ist der vollständige Maschinencode für diesen Zweig, ausgehend von dem bedingten Sprung über den if Block und endet, wo der Sprung zu geht, wenn der bedingte if nicht genommen wird:

     f2c:   350000e8    cbnz    w8, f48
     f30:   b0000002    adrp    x2, 1000
     f34:   91128442    add x2, x2, #0x4a1
     f38:   320003e0    orr w0, wzr, #0x1
     f3c:   2a1f03e1    mov w1, wzr
     f40:   aa1503e3    mov x3, x21
     f44:   97fffeeb    bl  af0 <error@plt>
     f48:   f94013f7    ldr x23, [sp, #32]

Alle des Code nach der Verzweigung durch den Compiler auf der Annahme erzeugt wurde, daß der Programmzustand war wie es vor dem bedingten Sprung war ! Aber gerade den letzten Sprung zum error Funktionscode macht einen no-op, habe ich einen Codepfad, wo wir diesen Code erreichen mit inkonsistentem / falsch Programmzustand

In meinem Fall, das ist eigentlich schien keine Probleme verursachen. Also ich hatte Glück. Sehr Glück: erst, nachdem ich meine modifizierten binären bereits lief (was, nebenbei bemerkt, war ein sicherheitskritische binäre : es hatte die Fähigkeit, setuid, setgid und ändern SELinux Kontext !) wurde mir klar, dass ich den Code vergessen zu Wege tatsächlich zu verfolgen, ob diese Register ändert die Codepfade erfolgen, die später kamen!

Das könnte schon katastrophal gewesen - eine dieser Register könnte unter der Annahme, in späterem Code verwendet hat, dass es einen vorherigen Wert enthalten ist, dass jetzt bekam überschrieben! Und ich bin die Art von Person, dass die Menschen für akribisches sorgfältiges Nachdenken über Code kennen und als Pedanten und Stickler für immer gewissenhaft die Computer-Sicherheit zu sein.

Was passiert, wenn ich eine Funktion anrufen, wo die Argumente aus den Registern auf den Stapel verschüttete (wie sehr häufig, zum Beispiel x86)? Was, wenn es tatsächlich mehrere bedingte Anweisungen in der Anweisung set, die den bedingten Sprung voraus (wie zum Beispiel älteren ARM-Versionen üblich ist)? Ich würde, nachdem sie getan recklessly inkonsistenten Zustand in einem noch gewesen ist, dass einfachste anmutende Veränderung!

So diese meine warnende Erinnerung: manuell Fummeln mit Binärdateien ist buchstäblich Abstreifen alle Sicherheit zwischen Ihnen und was die Maschine und Betriebssystem erlauben. Wörtlich alle die Fortschritte, die wir in unseren Tool zum automatischen Fang Fehlern unserer Programme gemacht haben, weg .

Wie beheben wir dies richtig mehr? Lesen Sie weiter.

Entfernen von Code

effektiv / logisch „Entfernen“ mehr als eine Anweisung, können Sie die erste Anweisung ersetzen Sie „löschen“ wollen mit einem unbedingten Sprung auf den ersten Befehl an das Ende der „gelöscht“ Anweisungen. Aus diesem ARMv8 binär, dass so aussah:

     f2c:   14000007    b   f48
     f30:   b0000002    adrp    x2, 1000
     f34:   91128442    add x2, x2, #0x4a1
     f38:   320003e0    orr w0, wzr, #0x1
     f3c:   2a1f03e1    mov w1, wzr
     f40:   aa1503e3    mov x3, x21
     f44:   97fffeeb    bl  af0 <error@plt>
     f48:   f94013f7    ldr x23, [sp, #32]

Grundsätzlich Sie "kill" den Code (schalten Sie ihn in "dead code"). Nebenbei bemerkt: Sie können in der binären eingebettet etwas ähnliches mit Literalzeichenfolgen tun: so lange, wie Sie es mit einem kleineren Zeichenfolge ersetzen möchten, können Sie fast bekommen immer mit dem Überschreiben der Zeichenfolge (einschließlich des abschließenden Null-Byte weg, wenn es sich um eine „C- ist string ") und, wenn notwendig, die hartcodierte Größe der Zeichenfolge in dem Maschinencode, dass Verwendungen es überschrieben wird.

Sie können auch alle unerwünschten Anweisungen ohne-ops ersetzen. Mit anderen Worten, wir können den unerwünschten Code in drehen, was heißt ein „no-op Schlitten“:

     f2c:   d503201f    nop
     f30:   d503201f    nop
     f34:   d503201f    nop
     f38:   d503201f    nop
     f3c:   d503201f    nop
     f40:   d503201f    nop
     f44:   d503201f    nop
     f48:   f94013f7    ldr x23, [sp, #32]

würde ich erwarten, dass die gerade ist relativ über sie zu Springen CPU-Zyklen verschwenden, und es einfacher und somit sicherer gegen Fehler , weil Sie müssen nicht von Hand, um herauszufinden, wie der Sprungbefehl zu codieren, einschließlich der Offset- / Adresse Verwendung darin, herauszufinden, - Sie haben nicht zu denkt, wie viel für ein no-op Schlitten.

Um klar zu sein, Fehler ist einfach: Ich vermassele zwei (2) mal manuell bei der Kodierung, dass unbedingten Sprungbefehls. Und es ist nicht immer unsere Schuld: das erste Mal war, weil die Dokumentation ich hatte, war veraltet / falsch und sagte ein Bit in der Codierung ignoriert wurde, als es eigentlich nicht, so dass ich es auf Null bei meinem ersten Versuch gesetzt

Hinzufügen-Code

Sie könnte theoretisch verwenden diese Technik, um in Maschinenbefehle auch, aber es ist komplizierter, und ich habe es nie zu tun hatte, so habe ich nicht ein Beispiel arbeitete zu diesem Zeitpunkt.

Von einem Maschinencode Perspektive ist es sorta einfach: wählen Sie einen Befehl an der Stelle, die Sie Code hinzufügen möchten, und es in einen Sprungbefehl zu dem neuen Code konvertieren, dass Sie hinzufügen müssen (vergessen Sie nicht die Anweisung (s hinzufügen ) Sie damit in den neuen Code ersetzt, es sei denn, Sie nicht, dass Ihre Logik hinzugefügt brauchten, und auf die Anweisung Sie am Ende wieder zu kommen, um der Zugabe wollen zurück zu springen). Grundsätzlich Sie sind „Spleißen“ der neue Code in.

Aber Sie müssen einen Platz finden, um tatsächlich setzen, dass neue Code, und das ist der schwierige Teil.

Wenn Sie wirklich Glück hat, können Sie hängen Sie einfach den neuen Maschinencode am Ende der Datei, und es wird „nur Arbeit“: Der neue Code wird zusammen mit der geladen werden Ruhe in die gleichen erwarteten Maschinenbefehl, in dem Adressraum Raum, richtig markiert ausführbare in eine Speicherseite fällt.

Nach meiner Erfahrung hexdump -R ignoriert nicht nur die rechte Spalte, aber die linke Spalte zu -. So konnte man buchstäblich setzt nur Null-Adressen für alle manuell hinzugefügten Zeilen und es wird funktionieren

Wenn Sie weniger Glück haben, nach dem Code hinzugefügt werden Sie haben tatsächlich einige Header-Werte innerhalb der gleichen Datei einstellen: wenn der Lader für Ihr Betriebssystem der binären Metadaten, um die Größe des ausführbaren Abschnitts beschreiben zu enthalten erwartet ( aus historischen Gründen häufig den „Text“ Abschnitt) bezeichnet man muss feststellen, dass finden und einzustellen. In den alten Tagen Binärdateien waren nurRoh Maschinencode -. heute die Maschinencode in einem Bündel von Metadaten (zB ELF auf Linux und einige andere) gewickelt ist,

Wenn Sie noch ein wenig Glück haben, können Sie einige „toten“ Punkt in der Datei haben, der als Teil des binären an den gleichen relativen Offsets wie der Rest des Codes geladen bekommt, die in der Datei bereits ist (und der tote Punkt kann den Code passen und richtig ausgerichtet ist, wenn Ihre CPU Wort-Ausrichtung für CPU-Anweisungen erfordert). Dann können Sie es überschreiben.

Wenn Sie wirklich Pech Sie nicht nur Code anhängen und es gibt keine Toträume Sie mit Ihrem Maschinencode füllen. An diesem Punkt müssen Sie grundsätzlich mit dem ausführbaren Format und Hoffnung vertraut sein, dass Sie etwas innerhalb dieser Zwänge herausfinden können, die menschlich möglich ist, manuell innerhalb einer angemessenen Menge fo Zeit abziehen und mit einer vernünftigen Chance, nicht es vermasselt .

Meine „ci Assembler Disassembler“ ist das einzige System, dass ich weiß, ist, dass um das Prinzip ausgelegt ist, dass alles, was die Demontage ist, um es in die Byte für Byte gleiche binäre wieder zusammenbauen muss.

https://github.com/albertvanderhorst/ciasdis

Es gibt zwei Beispiele gegeben von elf-Executables mit ihrer Demontage und Montage. Es wurde ursprünglich in der Lage sein entworfen, um ein Boot-System zu ändern, von Code aus, interpretierten Codes, Daten und grafischer Zeichen, mit solchen Feinheiten als Übergang von realen in dem geschützten Modus. (Es gelang.) Die Beispiele zeigen auch die Extraktion von Text aus den ausführbaren Dateien, die anschließend für Etiketten verwendet wird. Das Debian-Paket ist für Intel Pentium gedacht, aber Plug-Ins sind für Dezember Alpha verfügbar, 6809, 8086 etc.

Die Qualität der Demontage hängt davon ab, wie viel Mühe man hineinsteckt. Zum Beispiel, wenn die Informationen nicht einmal liefern, dass es eine Elf-Datei ist, bestehen die Demontage des einzelnen Bytes und der Remontag ist trivial. In den Beispielen verwende ich ein Skript, dass Auszüge Etikett und sorgt für ein wirklich nutzbares Reverse Engineering-Programm, das veränderbar ist. Sie können oder löschen etwas einfügen und die automatisch generierten symbolische Etiketten neu berechnet wird erhalten.

Keine Annahme überhaupt über die binäre Blob gemacht wird, aber natürlich ein Intel ist die Demontage von geringen Nutzen für eine binäre Dec Alpha.

Miasma

https://github.com/cea-sec/miasm

Dies scheint die vielversprechendste konkrete Lösung. Gemäß der Projektbeschreibung, die Bibliothek kann:

  
      
  • Öffnen / Modifizieren / Erzeugen von PE / ELF 32/64 LE / BE Elfesteem mit
  •   
  • Montage / Demontage X86 / ARM / MIPS / SH4 / MSP430
  •   

So soll es im Grunde:

  • parsen die ELF in eine interne Darstellung (Demontage)
  • ändern, was Sie wollen
  • erzeugt eine neues ELF (Montag)

Ich glaube nicht, es erzeugt eine textuelle Repräsentation Demontage, werden Sie wahrscheinlich durch Datenstrukturen Python gehen haben.

TODO ein minimales Beispiel zu erfahren, wie all das mit der Bibliothek zu tun. Ein guter Ausgangspunkt scheint Beispiel / DISASM / voll zu sein Py , die beim Analysieren eines bestimmten ELF-Datei. Der Schlüssel der obersten Ebene structurei ist Container, die die ELF-Datei mit Container.from_stream liest. Todo, wie es danach wieder zusammenzusetzen? Dieser Artikel scheint, es zu tun: http://www.miasm.re /blog/2016/03/24/re150_rebuild.html

Diese Frage stellt, ob es irgendwelche andere solche Bibliotheken: https://reverseengineering.stackexchange.com/questions/1843/what-are-the-available-libraries-to-statically-modify-elf-executables

Verwandte Fragen:

Ich denke, das Problem ist nicht automatisierbar ist

ich glaube, das allgemeine Problem nicht vollständig automatisierbar ist, und die allgemeine Lösung ist im Grunde gleichbedeutend mit „wie Reverse Engineering“ einem binären.

Um zum Einsetzen oder Entfernen Bytes in einer sinnvollen Art und Weise möchten wir sicherstellen müssen, dass alle möglichen Sprünge Springen zu den gleichen Stellen zu halten.

Formal müssen wir die Kontrollflussgraphen des binären extrahieren.

jedoch mit indirekten Zweigen zum Beispiel https://en.wikipedia.org/wiki/Indirect_branch , es ist nicht leicht, diese Grafik zu bestimmen, siehe auch: Indirekte Sprungzielberechnung

Eine andere Sache, die Sie interessiert sein könnte zu tun:

  • binäre Instrumentierung - Änderung bestehenden Code

Wenn Sie interessiert sind, finden Sie unter: Pin, Valgrind (oder Projekte dies zu tun. NaCl - Googles Native Client, vielleicht QEmu)

Sie können die ausführbare Datei unter Aufsicht von ptrace (in anderen Worten, ein Debugger wie gdb) laufen und auf diese Weise die Steuerung der Ausführung, wie Sie gehen, ohne die eigentliche Datei zu ändern. Natürlich erfordert die üblichen Bearbeitungsfähigkeiten wie die Suche nach dem besonderen Anweisung, die Sie beeinflussen wollen sind in der ausführbaren Datei.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top