
Python-Bindings für Valgrinds VEX IR.
PyVEX sind Python-Bindings für die VEX IR.
Projekt-Repository: https://github.com/angr/pyvex
Dokumentation: https://api.angr.io/projects/pyvex/en/latest/
PyVEX kann per pip installiert werden:
pip install pyvex
import pyvex
import archinfo
# translate an AMD64 basic block (of nops) at 0x400400 into VEX
irsb = pyvex.lift(b"\x90\x90\x90\x90\x90", 0x400400, archinfo.ArchAMD64())
# pretty-print the basic block
irsb.pp()
# this is the IR Expression of the jump target of the unconditional exit at the end of the basic block
print(irsb.next)
# this is the type of the unconditional exit (i.e., a call, ret, syscall, etc)
print(irsb.jumpkind)
# you can also pretty-print it
irsb.next.pp()
# iterate through each statement and print all the statements
for stmt in irsb.statements:
stmt.pp()
# pretty-print the IR expression representing the data, and the *type* of that IR expression written by every store statement
import pyvex
for stmt in irsb.statements:
if isinstance(stmt, pyvex.IRStmt.Store):
print("Data:", end="")
stmt.data.pp()
print("")
print("Type:", end="")
print(stmt.data.result_type)
print("")
# pretty-print the condition and jump target of every conditional exit from the basic block
for stmt in irsb.statements:
if isinstance(stmt, pyvex.IRStmt.Exit):
print("Condition:", end="")
stmt.guard.pp()
print("")
print("Target:", end="")
stmt.dst.pp()
print("")
# these are the types of every temp in the IRSB
print(irsb.tyenv.types)
# here is one way to get the type of temp 0
print(irsb.tyenv.types[0])
Beachten Sie, dass dies eine syntaktische Darstellung eines Basisblocks ist. Das heißt, sie sagt Ihnen, was der Block bedeutet, aber Sie haben keinen Kontext, um beispielsweise zu sagen, welche tatsächlichen Daten von einer Store-Anweisung geschrieben werden.
Um mit sehr unterschiedlichen Architekturen umzugehen, ist es nützlich, Analysen auf einer Zwischendarstellung durchzuführen. Eine IR abstrahiert mehrere Architekturunterschiede beim Umgang mit verschiedenen Architekturen und ermöglicht es, eine einzige Analyse auf allen von ihnen auszuführen:
rax wird beginnend bei Adresse 16 in diesem Speicherraum gespeichert).Es gibt viele Möglichkeiten für eine IR. Wir verwenden VEX, da das Uplifting von Binärcode nach VEX recht gut unterstützt wird. VEX ist eine architekturunabhängige, nebenwirkungsfreie Darstellung einer Reihe von Zielmaschinensprachen. Sie abstrahiert Maschinencode in eine Darstellung, die darauf ausgelegt ist, Programmanalysen zu erleichtern. Diese Darstellung hat fünf Hauptklassen von Objekten:
t0. Diese Temporären sind stark typisiert (d. h. „64-Bit-Ganzzahl“ oder „32-Bit-Gleitkommazahl“).VEX IR ist tatsächlich recht gut dokumentiert in der Datei libvex_ir.h (https://github.com/angr/vex/blob/dev/pub/libvex_ir.h) im VEX-Repository. Für die Faulen werden wir einige Teile von VEX detailliert beschreiben, mit denen Sie wahrscheinlich recht häufig interagieren werden. Zunächst einmal hier einige IR-Ausdrücke:
| IR-Ausdruck | Ausgewerteter Wert | VEX-Ausgabebeispiel |
|---|---|---|
| Constant | Ein konstanter Wert. | 0x4:I32 |
| Read Temp | Der in einer VEX-temporären Variablen gespeicherte Wert. | RdTmp(t10) |
| Get Register | Der in einem Register gespeicherte Wert. | GET:I32(16) |
| Load Memory | Der an einer Speicheradresse gespeicherte Wert, wobei die Adresse durch einen anderen IR-Ausdruck angegeben wird. | LDle:I32 / LDbe:I64 |
| Operation | Ein Ergebnis einer angegebenen IR-Operation, angewendet auf angegebene IR-Ausdrucksargumente. | Add32 |
| If-Then-Else | Wenn ein gegebener IR-Ausdruck zu 0 ausgewertet wird, wird ein IR-Ausdruck zurückgegeben. Andernfalls wird ein anderer zurückgegeben. | ITE |
| Helper Function | VEX verwendet C-Hilfsfunktionen für bestimmte Operationen, wie die Berechnung der Bedingungsflag-Register bestimmter Architekturen. Diese Funktionen geben IR-Ausdrücke zurück. | function_name() |
Diese Ausdrücke werden dann wiederum in IR-Anweisungen verwendet. Hier sind einige häufige: