
Enlaces de Python para el IR VEX de Valgrind.
PyVEX son los bindings de Python para el IR de VEX.
Repositorio del proyecto: https://github.com/angr/pyvex
Documentación: https://api.angr.io/projects/pyvex/en/latest/
PyVEX se puede instalar con 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])
Ten en cuenta que esta es una representación sintáctica de un bloque básico. Es decir, te dirá qué significa el bloque, pero no tienes ningún contexto para decir, por ejemplo, qué datos reales escribe una instrucción de almacenamiento.
Para tratar con arquitecturas ampliamente diversas, es útil llevar a cabo análisis sobre una representación intermedia. Un IR abstrae varias diferencias de arquitectura al tratar con diferentes arquitecturas, permitiendo que un único análisis se ejecute sobre todas ellas:
rax de AMD64 se almacena comenzando en la dirección 16 en este espacio de memoria).Hay muchas opciones para un IR. Usamos VEX, ya que la elevación de código binario a VEX está bastante bien soportada. VEX es una representación agnóstica de la arquitectura y libre de efectos secundarios de varios lenguajes de máquina objetivo. Abstrae el código máquina en una representación diseñada para facilitar el análisis de programas. Esta representación tiene cinco clases principales de objetos:
t0. Estas temporales están fuertemente tipadas (es decir, "entero de 64 bits" o "float de 32 bits").El IR de VEX está en realidad bastante bien documentado en el archivo libvex_ir.h (https://github.com/angr/vex/blob/dev/pub/libvex_ir.h) en el repositorio de VEX. Para los perezosos, detallaremos algunas partes de VEX con las que probablemente interactuarás con bastante frecuencia. Para empezar, aquí hay algunas Expresiones IR:
| Expresión IR | Valor evaluado | Ejemplo de salida de VEX |
|---|---|---|
| Constant | Un valor constante. | 0x4:I32 |
| Read Temp | El valor almacenado en una variable temporal de VEX. | RdTmp(t10) |
| Get Register | El valor almacenado en un registro. | GET:I32(16) |
| Load Memory | El valor almacenado en una dirección de memoria, con la dirección especificada por otra Expresión IR. | LDle:I32 / LDbe:I64 |
| Operation | Un resultado de una Operación IR especificada, aplicada a argumentos de Expresión IR especificados. | Add32 |
| If-Then-Else | Si una Expresión IR dada se evalúa a 0, devuelve una Expresión IR. De lo contrario, devuelve otra. | ITE |
| Helper Function | VEX usa funciones auxiliares de C para ciertas operaciones, como calcular los registros de flags de condición de ciertas arquitecturas. Estas funciones devuelven Expresiones IR. | function_name() |
Estas expresiones se usan, a su vez, en Sentencias IR. Aquí hay algunas comunes: