Reading values or structs from registers or memory
Common imports for easy access
from reven2.address import LinearAddress, LogicalAddress, LogicalAddressSegmentIndex, PhysicalAddress
from reven2.arch import x64 as regs
from reven2.types import *
Getting the current ring
def current_ring(ctx):
return ctx.read(regs.cs) & 3
Reading as a type
Integer types
ctx.read(regs.rax, U8)
ctx.read(regs.rax, U16)
ctx.read(regs.rax, I16)
ctx.read(regs.rax, BigEndian(U16))
Sample output:
96
35680
-29856
24715
String
ctx.read(LogicalAddress(0xffffe00041cac2ea), CString(encoding=Encoding.Utf16,
max_character_count=1000))
Sample output:
u'Network Store Interface Service'
Array
list(ctx.read(LogicalAddress(0xffffe00041cac2ea), Array(U8, 4)))
Sample output:
[78, 0, 101, 0]
Dereferencing pointers, reading the stack
Reading [rsp+0x20]
manually:
addr = LogicalAddress(0x20) + ctx.read(regs.rsp, USize)
ctx.read(addr, U64)
Reading [rsp+0x20]
using deref
:
ctx.deref(regs.rsp, Pointer(U64, base_address=LogicalAddress(0x20)))
Sample output:
10738
Retrieving struct definitions from PDB
Getting a struct
type from a binary:
object_attributes_ty = next(server.ossi.executed_binaries("ntoskrnl")).exact_type("_OBJECT_ATTRIBUTES")
Sample output of printing object_attributes_ty
:
StructKind.Struct _OBJECT_ATTRIBUTES /* 0x30 */ {
/* 0x0 */ Length : U32,
/* 0x8 */ RootDirectory : void*,
/* 0x10 */ ObjectName : _UNICODE_STRING*,
/* 0x18 */ Attributes : U32,
/* 0x20 */ SecurityDescriptor : void*,
/* 0x28 */ SecurityQualityOfService : void*,
}
Reading struct values
Reading a struct instance from a source (register, memory, etc):
# Reading structure from pointer stored in r8
object_attributes = ctx.read(reven2.address.LogicalAddress(0xffffe00041cac2ea), object_attributes_ty)
# Read one field according to declared type
object_attributes.field("Length").read()
Sample output:
48
You can also:
# Read one field, forcing its type to int-like. Useful for IDE type hints
object_attributes.field("Attributes").read_int()
# Get whole struct content as bytes
object_attributes.as_bytes()
# Dereferences a pointer-like field, read it as an inner struct, display its type
print(object_attributes.field("ObjectName").deref_struct().type)
Sample output:
0
b'0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\xd1]\x06\x00\x00\x00\x00B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
StructKind.Struct _UNICODE_STRING /* 0x10 */ {
/* 0x0 */ Length : U16,
/* 0x2 */ MaximumLength : U16,
/* 0x8 */ Buffer : U16*,
}
Defining a struct manually
Creating a struct:
my_struct = Struct(
StructKind.Struct, 10, "MyStruct", None,
[
RegularField("start", 0x0, Pointer(U16)),
RegularField("value", 0x8, U16),
],
)
You can also create structs that contain forward mentions to yet-undefined structs (useful with recursive links for instance). In this case, you must use a TypeResolver
:
type_resolver = TypeResolver()
struct_a_ty = Struct(
StructKind.Struct, 10, "A", None,
[
RegularField("b", 0x0, Pointer(UnresolvedStruct(StructKind.Struct, "B", None))),
RegularField("value", 0x8, U16),
],
type_resolver,
)
type_resolver["A"] = struct_a_ty
struct_b_ty = Struct(
StructKind.Struct, 10, "B", None,
[
RegularField("a", 0x0, Pointer(UnresolvedStruct(StructKind.Struct, "A", None))),
RegularField("value", 0x8, U16),
],
type_resolver,
)
type_resolver["B"] = struct_b_ty
Sample output of printing struct_a_ty
:
struct A /* 0x8 */ {
/* 0x0 */ b : B*,
/* 0x8 */ value : U16,
}
Parsing a raw buffer as a type
U16.parse(b"\x10\x20")
BigEndian(U16).parse(b"\x10\x20")
Array(U8, 2).parse(b"\x10\x20")
Sample output:
8208
4128
[16, 32]
Accessing the framebuffer memory to take a screenshot
image = ctx.framebuffer.image()
# save the screenshot as a png file
image.save("/tmp/framebuffer.png")
# display the screenshot in the default image viewer
image.show()
# display the screenshot in a Jupyter Notebook
display(image)
# access RGB values from a pixel as a tuple
image.getpixel((123, 42))