
Binding Python per l'IR VEX di Valgrind.
PyVEX è un binding Python per il VEX IR.
Repository del progetto: https://github.com/angr/pyvex
Documentazione: https://api.angr.io/projects/pyvex/en/latest/
PyVEX può essere installato tramite pip:
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])
Tieni presente che questa è una rappresentazione sintattica di un basic block. Ovvero, ti dirà cosa significa il blocco, ma non hai alcun contesto per dire, ad esempio, quali dati effettivi vengano scritti da un'istruzione di store.
Per gestire architetture molto diverse tra loro, è utile eseguire analisi su una rappresentazione intermedia. Una IR astrae diverse differenze architetturali quando si ha a che fare con architetture diverse, consentendo di eseguire una singola analisi su tutte:
rax di AMD64 è memorizzato a partire dall'indirizzo 16 in questo spazio di memoria).Ci sono molte scelte per una IR. Noi usiamo VEX, poiché il lifting del codice binario in VEX è supportato piuttosto bene. VEX è una rappresentazione agnostica rispetto all'architettura e priva di effetti collaterali di numerosi linguaggi macchina target. Astrae il codice macchina in una rappresentazione progettata per rendere più semplice l'analisi dei programmi. Questa rappresentazione ha cinque classi principali di oggetti:
t0. Queste variabili temporanee sono fortemente tipizzate (ad esempio, "intero a 64 bit" o "float a 32 bit").Il VEX IR è in realtà piuttosto ben documentato nel file libvex_ir.h (https://github.com/angr/vex/blob/dev/pub/libvex_ir.h) nel repository VEX. Per i pigri, dettaglieremo alcune parti di VEX con cui probabilmente interagirai abbastanza frequentemente. Per iniziare, ecco alcune IR Expression:
| IR Expression | Valore Valutato | Esempio di Output VEX |
|---|---|---|
| Constant | Un valore costante. | 0x4:I32 |
| Read Temp | Il valore memorizzato in una variabile temporanea VEX. | RdTmp(t10) |
| Get Register | Il valore memorizzato in un registro. | GET:I32(16) |
| Load Memory | Il valore memorizzato a un indirizzo di memoria, con l'indirizzo specificato da un'altra IR Expression. | LDle:I32 / LDbe:I64 |
| Operation | Un risultato di una specificata IR Operation, applicata a specificati argomenti IR Expression. | Add32 |
| If-Then-Else | Se una data IR Expression restituisce 0, restituisce un'IR Expression. Altrimenti, ne restituisce un'altra. | ITE |
| Helper Function | VEX usa funzioni helper C per certe operazioni, come il calcolo dei registri dei flag di condizione di certe architetture. Queste funzioni restituiscono IR Expression. | function_name() |
Queste espressioni vengono poi, a loro volta, usate negli IR Statement. Ecco alcuni comuni: