
Ein Trace-Explorer für Reverse Engineers
Tenet ist ein IDA Pro-Plugin zum Durchsuchen von Ausführungs-Traces. Das Ziel dieses Plugins ist es, natürlichere, menschliche Steuerungen für die Navigation durch Ausführungs-Traces in einer gegebenen Binärdatei bereitzustellen. Die Grundlage dieser Arbeit entspringt dem Wunsch, neue oder innovative Methoden zu erforschen, um komplexe Ausführungsmuster in Software zu untersuchen und zu destillieren.
Für weitere Informationen zu diesem Projekt lesen Sie bitte den Blogbeitrag über die Erstveröffentlichung.
Besonderer Dank gilt QIRA / geohot et al. für die Inspiration.
Tenet ist ein plattformübergreifendes (Windows, macOS, Linux) Python 3-Plugin. Es benötigt keine Abhängigkeiten von Drittanbietern, was den Code sowohl portabel als auch einfach zu installieren macht.
Führen Sie in der Python-Konsole Ihres Disassemblers den folgenden Befehl aus, um das Plugin-Verzeichnis zu finden:
import idaapi, os; os.path.join(idaapi.get_user_idadir(), "plugins")Kopieren Sie den Inhalt des /plugins/-Ordners dieses Repositorys in das genannte Verzeichnis.
Starten Sie Ihren Disassembler neu.
Dieses Plugin wird nur für IDA 7.5 und neuer unterstützt.
Nach erfolgreicher Installation steht ein neuer Menüeintrag im Disassembler zur Verfügung. Damit können extern gesammelte Ausführungs-Traces in Tenet geladen werden.
Da dies die Erstveröffentlichung ist, akzeptiert Tenet derzeit nur einfache, menschenlesbare Text-Traces. Bitte lesen Sie die Tracing-Readme in diesem Repository für weitere Informationen zum Trace-Format, zu Einschränkungen und zu Referenz-Tracern.
Während der Verwendung von Tenet 'malt' das Plugin Pfade, die den Ausführungsfluss vorwärts (blau) und rückwärts (rot) von Ihrer aktuellen Position im aktiven Ausführungs-Trace anzeigen.
Um step vorwärts oder rückwärts durch die Zeit zu bewegen, scrollen Sie einfach über der Zeitleiste auf der rechten Seite des Disassemblers. Um step over bei Funktionsaufrufen auszuführen, halten Sie SHIFT gedrückt, während Sie scrollen.
Die Trace-Zeitleiste wird auf der rechten Seite des Disassemblers angedockt. Dieses Widget dient zur Visualisierung verschiedener Ereignistypen entlang der Trace-Zeitleiste und zur grundlegenden Navigation wie oben beschrieben.
Durch Klicken und Ziehen über die Zeitleiste kann ein bestimmter Abschnitt des Ausführungs-Traces vergrößert werden. Diese Aktion kann beliebig oft wiederholt werden, um die gewünschte Granularität zu erreichen.
Ein Doppelklick auf den Befehlszeiger im Registerfenster hebt ihn rot hervor und zeigt alle Stellen an, an denen der Befehl entlang der Trace-Zeitleiste ausgeführt wurde.
Um zwischen Ausführungen zu springen, scrollen Sie nach oben oder unten, während Sie über den hervorgehobenen Befehlszeiger fahren.
Zusätzlich können Sie einen Rechtsklick in der Disassembly-Liste ausführen und einen der navigationsbasierten Menüeinträge auswählen, um schnell zur Ausführung eines interessierenden Befehls zu springen.
Der native F2-Shortcut von IDA kann ebenfalls verwendet werden, um Breakpoints auf beliebige Befehle zu setzen.
Durch Doppelklicken auf ein Byte in der Stack- oder Speicheransicht sehen Sie sofort alle Lese-/Schreibzugriffe auf diese Adresse, die über die Trace-Zeitleiste visualisiert werden. Gelb kennzeichnet einen Lese-Zugriff, blau einen Schreib-Zugriff.
Speicher-Breakpoints können mit der gleichen Technik wie Ausführungs-Breakpoints navigiert werden. Doppelklicken Sie auf ein Byte und scrollen Sie, während Sie über dem ausgewählten Byte fahren, um den Trace zu jedem seiner Zugriffe zu springen.
Ein Rechtsklick auf ein interessierendes Byte bietet Ihnen Optionen, um zwischen Speicher-Lese-/Schreib-/Zugriffen zu springen, falls Sie eine bestimmte Navigationsaktion im Sinn haben.
Um die Speicheransicht zu einer beliebigen Adresse zu navigieren, klicken Sie auf die Speicheransicht und drücken Sie G, um entweder eine Adresse oder ein Datenbanksymbol einzugeben, zu dem die Ansicht springen soll.
Es ist möglich, einen Speicher-Breakpoint über einen Speicherbereich zu setzen, indem Sie einen Speicherblock markieren und doppelklicken, um einen Zugriffs-Breakpoint zu setzen.
Wie bei normalen Speicher-Breakpoints kann durch Überfahren des Bereichs und Scrollen zwischen den Zugriffen auf den ausgewählten Speicherbereich navigiert werden.
Beim Reverse Engineering trifft man häufig auf Situationen, in denen man sich fragt: 'Welcher Befehl hat dieses Register auf seinen aktuellen Wert gesetzt?'
Mit Tenet können Sie mit einem einzigen Klick zu diesem Befehl zurückspringen.
Das Zurückspringen ist bei weitem die häufigste Navigationsrichtung bei Registeränderungen ... aber der Geschicklichkeit halber können Sie auch vorwärts zur nächsten Registerzuweisung springen, indem Sie den blauen Pfeil rechts neben dem Register verwenden.
Eine einfache 'Shell' wird bereitgestellt, um zu bestimmten Zeitstempeln im Trace zu navigieren. Das Einfügen (oder Eingeben ...) eines Zeitstempels in die Shell mit oder ohne Kommas ist ausreichend.
Mit einem Ausrufezeichen können Sie auch zu einem bestimmten 'Prozentsatz' im Trace springen. Die Eingabe von !100 springt zum letzten Befehl im Trace, während !50 ungefähr zur Hälfte des Tracks springt. !last springt zum letzten navigierbaren Befehl, der im Disassembler angezeigt werden kann.
Tenet wird mit zwei Standard-Designs ausgeliefert – einem 'hellen' und einem 'dunklen'. Abhängig von den aktuell von Ihrem Disassembler verwendeten Farben versucht Tenet, das am besten geeignete Design auszuwählen.
Die Design-Dateien werden als einfaches JSON auf der Festplatte gespeichert und sind hochgradig konfigurierbar. Wenn Sie mit den Standard-Designs oder -Farben nicht zufrieden sind, können Sie Ihre eigenen Designs erstellen und sie einfach in das Benutzer-Design-Verzeichnis legen.
Tenet merkt sich Ihre Design-Präferenz für zukünftige Ladevorgänge und Verwendungen.
Zeit und Motivation Finanzierung vorausgesetzt, könnten zukünftige Arbeiten Folgendes umfassen:
Ich begrüße externe Beiträge, Issues und Feature-Requests. Bitte stellen Sie Pull-Requests an den develop-Branch dieses Repositorys, wenn Sie möchten, dass sie für eine zukünftige Version berücksichtigt werden.
Markus Gaasedelen (@gaasedelen)