
IDA-Plugins und Skripte zur Analyse des Register-Nutzungsrahmens

"""
Wofür wird dieses Register verwendet?
Hmm.. Ich benenne es einfach in veryuniquename um, führe eine Textsuche durch und finde alle Referenzen!
Ok.. Warte auf das Ende der Suche.. jeden Moment.. Fertig!
Jetzt muss ich nur noch verstehen, welches der Suchergebnisse für den aktuellen Verwendungsrahmen des Registers relevant ist.
Sollte nicht zu schwer sein, oder?
"""
Wenn Ihnen das passiert ist (vielleicht mehr als einmal), haben Sie etwas zu erwarten!
Einfach Shift-X drücken, und Ihre Probleme verschwinden!
Sie können das Register auch im Verwendungsrahmen umbennen. Einfach Shift-N und den Anweisungen folgen!
Außerdem - anstatt die Typen aller Verwendungen in einen bestimmten Typ zu ändern, drücken Sie einfach einmal Shift-T.
Und zu guter Letzt - wenn Sie einen Offset (wie bei Ctrl-R) auf alle Verwendungen dieses Registers setzen möchten, drücken Sie einfach Shift-R.
Hinweis: Manchmal gibt es bereits ein anderes Plugin, das Shift-T verwendet. Entfernen Sie dieses Plugin - Sie haben es sowieso noch nie benutzt :-).
Dieses Plugin verwendet sark, um bequem mit den IDA-Skripten zu interagieren, und cachetools, um den Frame-Scan zu cachen, was das Ganze erheblich schneller macht.
Oregami unterstützt sowohl IDA 7.x/8.x als auch IDA 9.0+.
Wenn Sie IDA 9 verwenden, stellen Sie sicher, dass Sie eine aktuelle Version von sark haben, die IDA 9 unterstützt.
Hinweis: IDA 9 hat eine eigene Shift-X-Funktionalität eingeführt. Wenn Sie stattdessen die integrierte Shift-X-Funktion von IDA anstelle der von oregami verwenden möchten, sollten Sie die oregami-Verknüpfung in der Plugin-Datei ändern.
[Für python3]
pip3 install sark
[Für python2]
Wenn Sie die python2-Variante von IDA verwenden, führen Sie stattdessen Folgendes aus:
pip2 install -U git+https://github.com/tmr232/[email protected]#egg=Sark
Beachten Sie, dass python2 nicht aktiv unterstützt wird (da IDA hauptsächlich zu python3 gewechselt ist und ich auch), daher funktioniert dies möglicherweise nicht.
git clone https://github.com/shemesh999/oregami
Die sark-Codebasis bietet viele Plugins. Eines davon ist: https://github.com/tmr232/Sark/blob/master/plugins/plugin_loader.py
Wir empfehlen, es in Ihr Plugins-Verzeichnis zu kopieren und dann IDA einmal mit Administratorrechten auszuführen (damit es die plugins.list-Dateien erstellen kann).
Danach können Sie neue Plugins hinzufügen, indem Sie den Pfad zu ihnen zu einer der erstellten plugins.list-Dateien hinzufügen (z.B. eine wird im cfg-Ordner von IDA erstellt).
Jetzt fügen Sie zu einer der plugins.list-Dateien hinzu:
FULLPATH\oregami\oregami_plugin.py
FULLPATH\oregami\regname_plugin.py
FULLPATH\oregami\typeregter_plugin.py
FULLPATH\oregami\offreg_plugin.py
Starten Sie IDA neu, und die Plugins sollten funktionieren.
Alternativ:
Kopieren Sie alle Dateien (einschließlich des internen oregami-Ordners, außer setup.py) in das IDA-Plugins-Verzeichnis.
Neben der Verwendung als Plugins kann oregami auch zum Schreiben eigener Skripte verwendet werden!
Dafür sollten Sie zuerst die enthaltene setup.py-Datei installieren. Das bedeutet, dass Sie Folgendes aufrufen sollten:
'python setup.py develop', und ab dann können Sie die internen Klassen und Funktionen verwenden.
Beachten Sie, dass wir die Verwendung von 'develop' und nicht 'install' empfehlen, damit eine neu gezogene Version von oregami sofort funktioniert.
Zum Beispiel:
-- script.py --
def find_func_usage(func_ea, reg='r0'):
"""
Find and print all usages of a register, including the information of the specific operands
it is in, and what operation it does in the operand.
"""
import oregami
rf = oregami.RegFrame(func_ea, reg)
for insn in rf.get_instructions():
print('Addr:{:x}'.format(insn.ea))
for opnd in insn.operands:
if opnd.uf_is_external:
continue
print('--opnd_idx:{} - {}'.format(opnd.n, oregami.UsageBits(opnd.op_flags)))
Nehmen wir die folgende Sequenz von Opcodes an:
ROM:01000010 e_lis r10, 0x4004 # 0x40040000 # Load Immediate Shifted
ROM:01000014 e_add16i r10, r10, 0x1337 # 0x40041337 # Add Immediate
ROM:01000020 se_mr r30, r31 # Move Register
ROM:01000022 cmplw r11, r10 # Compare Logical Word
ROM:01000026 se_bge loc_1000036 # Branch if greater than or equal
ROM:01000028
ROM:01000028 loc_1000028: # CODE XREF: sub_0100000+144↓j
ROM:01000028 e_stmw r30, 0(r11) # Store Multiple Word
ROM:0100002C e_add16i r11, r11, 8 # Add Immediate
ROM:01000030 cmplw r11, r10 # Compare Logical Word
ROM:01000034 se_blt loc_1000028 # Branch if less than
ROM:01000036
ROM:01000036 loc_1000036: # CODE XREF: sub_0100000+136↑j
ROM:01000036 e_add16i r10, r10, 8 # Add Immediate
ROM:0100003A e_li r11, 0 # Load Immediate
Wenn wir den Verwendungsrahmen des r10-Registers scannen, beginnend bei der Adresse 01000022, werden wir drei Arten von Verwendungen im Verwendungsrahmen finden.
Dies umfasst die Anweisungen, die den Wert des Registers initialisieren.
Wir möchten möglicherweise nur die letzte Anweisung einbeziehen, die den Registerwert geändert hat (Adresse 01000014 im Beispiel), oder eine Sequenz von Operationen, die zum Setzen des Anfangswerts des Registers verwendet werden (Adressen 01000010 und 01000014 im Beispiel).
Die Sequenz von Operationen, die bei der Registerinitialisierung verwendet wird, kann als 'Init-Stage' bezeichnet werden.
Sie können wählen, ob Sie eine Init-Stage unterstützen möchten oder nicht, abhängig vom Parameter init_stage_bool in der RegFrame-Initialisierung.
Dies umfasst die Anweisungen, die den Wert des Registers verwenden und ihn in keiner Weise ändern. Diese entsprechen den Zeilen 01000022 und 01000030 im Beispiel.
Dies umfasst die Anweisungen, die den Wert des Registers verwenden, aber dann seinen Wert ändern. Diese Anweisungen können als in zwei verschiedenen Verwendungsrahmen enthalten betrachtet werden - dem, der zu ihnen führt, und dem, der von ihnen ausgeht.
Dies entspricht der Zeile 01000036.
Beim Scannen des Verwendungsregisters führt das Erreichen einer Init-Operation oder einer Break-Operation dazu, dass wir das Scannen in eine bestimmte Richtung stoppen.
Aber wir können den Scan auch aufgrund von Anweisungen außerhalb des Verwendungsrahmens stoppen.
Zum Beispiel wird das Scannen des Verwendungsrahmens des r11-Registers beginnend bei der Adresse 01000030 in Zeile 0100003A gestoppt.
Dies ist die grundlegende Klasse, die in oregami verwendet wird. Durch Initialisieren auf einer Adresse und einem bestimmten Register scannt sie den Verwendungsrahmen des Registers und erstellt eine UFInstruction für alle relevanten Anweisungen.
get_instruction - holt die Anweisung von der angegebenen Adresse
get_instructions - ein Generator, der die Anweisungen im Verwendungsrahmen zurückgibt.
Sie können auch nach spezifischen Teilmengen der verwendeten Anweisungen fragen:
get_init_instructions - nur Anweisungen vom Typ Init abrufen
get_pure_instructions - nur Anweisungen vom Typ Pure abrufen
get_break_instructions - nur Anweisungen vom Typ Break abrufen
get_nobreak_instructions - nur Anweisungen abrufen, die nicht vom Typ Break sind (d.h. Init + Pure)
get_noinit_instructions - nur Anweisungen abrufen, die nicht vom Typ Init sind (d.h. Pure + Break)
get_outbreak_instructions - nur Anweisungen vom Typ Out Break abrufen
Standardmäßig speichert diese Klasse die Ergebnisse des Scans zwischen und verhindert, dass derselbe Verwendungsrahmen erneut gescannt wird.
Das bedeutet, dass das Anfordern des RegFrame für eine Anweisung, die Teil des Verwendungsrahmens war (insbesondere der Typen Init + Pure. Nicht Break, da das Starten eines Scans auf ihnen den von ihnen ausgehenden Verwendungsrahmen zurückgeben sollte), dieselbe vorberechnete RegFrame-Instanz zurückgibt.
Um einen erneuten Scan zu erzwingen, verwenden Sie das force-Flag beim Initialisieren der Klasse.
Dies ist die von RegFrame zurückgegebene Klasse, die eine Anweisung im Verwendungsrahmen darstellt.
Diese Klasse erbt von der sark-Instruction-Klasse und unterstützt daher dieselben Methoden.
Ein Hauptunterschied besteht darin, dass sie anstelle eines Operanden-Arrays der sark-Operand-Klasse ein Array der UFOperand-Klasse enthält.
Diese Klasse enthält auch Methoden, um den Anweisungstyp (init, pure, break, outbreak) und die Operationsbits (read, write, explicit und verschiedene Arten von implicit) zu verstehen.
Dies ist die Klasse im Operanden-Array innerhalb einer bestimmten UFInstruction.
Diese Klasse erbt von der sark-Instruction-Klasse und unterstützt daher dieselben Methoden.
Zusätzlich zu den sark-Operationen enthält sie Methoden, um die Operationsbits (read, write, explicit und verschiedene Arten von implicit) zu erhalten und zu erfahren, ob der Operand tatsächlich Teil des Verwendungsrahmens ist (nützlich, um zu wissen, welcher Operand in einer Break-Typ-Anweisung Teil des Verwendungsrahmens ist).
Dies ist eine Klasse, die verwendet wird, um eine bestimmte Anweisung zu analysieren und ihre Verwendung in Bezug auf Register zu ermitteln.
Sie tut dies mithilfe von Wissen aus IDA, Textanalyse und prozessorspezifischen Details.
Der Grund für diese Klasse ist, dass die grundlegende IDA-Analyse dazu neigt, über die Menge der verwendeten Register und die Art und Weise ihrer Verwendung in vielen Opcodes zu lügen.
Diese Klasse erbt von der sark-Instruction-Klasse und unterstützt daher dieselben Methoden.
Ein Hauptunterschied besteht darin, dass sie anstelle eines Operanden-Arrays der sark-Operand-Klasse ein Array der RegOperand-Klasse enthält.
Dies ist eine Klasse, die verwendet wird, um einen bestimmten Operanden zu analysieren und seine Verwendung in Bezug auf Register zu ermitteln.
Sie tut dies mithilfe von Wissen aus IDA, Textanalyse und prozessorspezifischen Details.
Der Grund für diese Klasse ist, dass die grundlegende IDA-Analyse dazu neigt, über die Menge der verwendeten Register und die Art und Weise ihrer Verwendung in vielen Opcodes zu lügen.
Diese Klasse erbt von der sark-Operand-Klasse und unterstützt daher dieselben Methoden.