class documentation

Entry point object for data related to a context.

A context represents the full state of the VM at a point in time. You can access contexts before or after a transition:

    ... -> Context Before #N -> Transition #N -> Context After #N -> ...

A context can usually be referenced as both a context before and a context after:

    ... -> Transition #N-1 -> Context After #N-1 / Before #N -> Transition #N -> ...

Except at the trace's begin and end:

    Context Before #0 -> Transition #0 -> ... -> Transition #M -> Context After #M}

Warnings

This object is not meant to be constructed directly. Use Trace.context_before, Trace.context_after, Transition.context_before or Transition.context_after instead.

Examples

>>> # From a transition
>>> reven_server.trace.transition(id).context_before()
>>> reven_server.trace.transition(id).context_after()
>>> # From a trace directly
>>> reven_server.trace.context_before(transition_id)
>>> reven_server.trace.context_after(transition_id)
>>> # From a context
>>> ctx = reven_server.trace.context_before(transition_id)
>>> next_ctx = ctx + 1
>>> prev_ctx = ctx - 1
>>> other_ctx = ctx + 10000
Method __add__ Undocumented
Method __eq__ Compares the instance for equality with an object.
Method __ge__ Undocumented
Method __gt__ Undocumented
Method __hash__ Returns the hash for this value.
Method __init__ Undocumented
Method __le__ Undocumented
Method __lt__ Undocumented
Method __ne__ Compares the instance for equality with an object.
Method __repr__ Undocumented
Method __str__ Undocumented
Method __sub__ Undocumented
Method deref Dereferences a pointer and read the value read as a pointing type.
Method deref_all Recursively dereferences a pointer and read the value read as a pointing type.
Method find_register_change Find the next/previous context in which the content of the register is modified.
Method format_as_html This method gets an html formatting string representation for this class instance.
Method is64b Undocumented
Method physical_memory_regions Get all the physical memory regions that are accessible.
Method read Reads the value contained in a register or in memory.
Method search_in_memory Iterate the search range looking for the specified pattern. Search range is:
Method transition_after Get Transition that will execute right after this context:
Method transition_before Get Transition that led to this context:
Property ossi Property: OSSI information related to the context
Property stack Property: The active stack linked to the context.
Static Method _next_stop_point Undocumented
Method _read_as Undocumented
Method _read_raw Undocumented
Method _read_register Undocumented
Method _read_size Undocumented
Method _read_st_register Undocumented
Method _repr_html_ Representation used by Jupyter Notebook when an instance of this class is displayed in a cell.
Instance Variable __trace Undocumented
Instance Variable _cpu_context Undocumented
Instance Variable _data_source Undocumented
Instance Variable _id Undocumented
Instance Variable _ossi_data_source Undocumented
Property _rvn Undocumented
Property _trace Undocumented
def __add__(self, other):

Undocumented

Parameters
other:intUndocumented
Returns
ContextUndocumented
def __eq__(self, other):

Compares the instance for equality with an object.

  • if the object is not a Context, returns False.
Parameters
other:_AnyUndocumented
Returns
boolUndocumented
def __ge__(self, other):

Undocumented

Parameters
other:ContextUndocumented
Returns
boolUndocumented
def __gt__(self, other):

Undocumented

Parameters
other:ContextUndocumented
Returns
boolUndocumented
def __hash__(self):

Returns the hash for this value.

Returns
intUndocumented
def __init__(self, trace, _data_source, _ossi_data_source, context_id):

Undocumented

Parameters
trace:TraceUndocumented
_data_source:_data_source.DataSourceUndocumented
_ossi_data_source:_ossi._DataSourceUndocumented
context_id:intUndocumented
def __le__(self, other):

Undocumented

Parameters
other:ContextUndocumented
Returns
boolUndocumented
def __lt__(self, other):

Undocumented

Parameters
other:ContextUndocumented
Returns
boolUndocumented
def __ne__(self, other):

Compares the instance for equality with an object.

  • if the object is not a Context, returns True.
Parameters
other:_AnyUndocumented
Returns
boolUndocumented
def __repr__(self):

Undocumented

Returns
strUndocumented
def __str__(self):

Undocumented

Returns
strUndocumented
def __sub__(self, other):

Undocumented

Parameters
other:intUndocumented
Returns
ContextUndocumented
def deref(self, source, ptr_ty):

Dereferences a pointer and read the value read as a pointing type.

This method allows to directly returns the pointed-to value when passed a pointer type and a source from which read the pointer address.

A (simplified) desugaring of this method can be thought of like the following:

>>> def deref_simple_case(self, source, ptr_ty):
...     addr = self.read(source, ptr_ty)
...     return self.read(addr, ptr_ty.elem_type)

Example

Reading the stack pointer:

>>> hex(context.deref(reven2.arch.x64.rsp, types.Pointer(types.USize)))
'0xfffff801653ff072'

Information

Parameters
sourceThe source where to read the address of the pointer. Can be an address (virtual or physical) or a register.
ptr_tyA reven2.types.Pointer.
Returns
The data interpreted as the requested type. If the pointer points to an unmapped memory, None is returned.
Raises
TypeErrorif 'source' is not supported.
TypeErrorif 'ptr_ty' is not a Pointer.
ValueErrorif 'source' is a Register and there is not enough bytes to read the pointer address in it.
RuntimeErrorif 'source' is an unavailable register.
def deref_all(self, source, ptr_ty):

Recursively dereferences a pointer and read the value read as a pointing type.

This method allows to directly returns the pointed-to value when passed a pointer type and a source from which read the pointer address.

A (simplified) desugaring of this method can be thought of like the following:

>>> def deref_simple_case(self, source, ptr_ty):
...     addr = self.read(source, ptr_ty)
...     return self.read(addr, ptr_ty.elem_type)

Note, however that the actual implementation will recursively remove all levels of indirection, e.g. if the type is Pointer(Pointer(U64)), then the implementation will do the following:

>>> def deref_unrolled(self, source, ptr_ty):
...     addr1 = self.read(source, Pointer(Pointer(U64)))
...     addr2 = self.read(addr1, Pointer(U64))
...     return self.read(addr2, U64)

Example

Reading the stack pointer:

>>> hex(context.deref_all(reven2.arch.x64.rsp, types.Pointer(types.USize)))
'0xfffff801653ff072'

Looks like an address, let's try to dereference twice:

>>> hex(context.deref_all(reven2.arch.x64.rsp, types.Pointer(types.Pointer(types.USize))))
'0x7c894828247c894c'

Doesn't look like an address anymore, show raw:

>>> [hex(x) for x in context.deref_all(reven2.arch.x64.rsp, types.Pointer(types.Pointer(types.RawBuffer(8))))]
['0x4c', '0x89', '0x7c', '0x24', '0x28', '0x48', '0x89', '0x7c']

Information

Parameters
sourceThe source where to read the address of the pointer. Can be an address (virtual or physical) or a register.
ptr_tyA reven2.types.Pointer.
Returns
The data interpreted as the requested type. If the pointer points to an unmapped memory, None is returned.
Raises
TypeErrorif 'source' is not supported.
TypeErrorif 'ptr_ty' is not a Pointer.
ValueErrorif 'source' is a Register and there is not enough bytes to read the pointer address in it.
RuntimeErrorif 'source' is an unavailable register.
def find_register_change(self, register, is_forward=True, fetch_count=10000):

Find the next/previous context in which the content of the register is modified.

Warning

In the current implementation, this function does not return changes that occur on the context right after the specified context.

Information

Parameters
register:_arch.Registerreven2.arch.register.Register
is_forward:boolIf True return next context. Otherwise return previous context.
fetch_count:int

Technical parameter indicating how many contexts the server should handle per query. Modifying this parameter allows to fine-tune performance:

  • A large value leads to better performance but may cause the script to block longer while waiting for the server response without being interruptible.
  • A small value leads to a lot of server requests and so reduces performance but ensures the script will not block.
  • The default value should provide sufficient performance in most cases.

NOTE: Modifying this parameter does not modify the results of the query

Returns
_Optional[Context]A reven2.trace.Context or None if no context was found.
Raises
ValueErrorif fetch_count is not positive.
def format_as_html(self):

This method gets an html formatting string representation for this class instance.

Information

Returns
strString
def is64b(self):

Undocumented

Returns
boolUndocumented
def physical_memory_regions(self):

Get all the physical memory regions that are accessible.

These regions are assumed to not change during the entire trace.

Any physical read inside these regions is guaranteed to succeed.

Examples

>>> for (start, size) in ctx.physical_memory_regions():
...     print("{} - {}".format(start, start + size))
phy:0x0 - phy:0x80000000
phy:0xfd000000 - phy:0xfe000000

Informations

Returns
_Iterator[_Tuple[_address.PhysicalAddress, int]]A generator of tuples composed of the start physical address of a region and its size.
def read(self, source, *args, **kwargs):

Reads the value contained in a register or in memory.

Overloads

read(register [, raw=False]) -> read bytes from a register read(source, size[, raw=False]) -> read bytes from a register or a memory read(source_range[, raw=False]) -> read bytes from a memory range read(source, type) -> read bytes from a register or a memory

If 'size' in [1, 2, 4, 8], the bytes are interpreted as an unsigned int. If 'raw' is True, a raw buffer is returned even if 'size' is in [1, 2, 4, 8]. If 'type' is provided (a reven2.types.Type), the bytes are interpreted as the given 'type'. In all other cases, a raw buffer is returned.

If 'source' is a virtual address, then [source; length] must be mapped in the current context, with `length == size` if 'size' was provided, or `length == type.size_bytes(self)` if `type` was provided

If 'source' is a physical address, then [source; length] must be in the available physical memory (see Context.physical_memory_regions), with `length == size` if 'size' was provided, or `length == type.size_bytes(self)` if `type` was provided

Examples

Read rax without size:

>>> hex(context.read(arch.x64.rax))
'0xffffc000e9997ac0'
>>> # Get a raw buffer
>>> context.read(arch.x64.rax, raw=True)
bytearray(b'\xc0z\x99\xe9\x00\xc0\xff\xff')

Read rax with size:

>>> # size not in [1, 2, 4, 8]
>>> context.read(arch.x64.rax, 6)
bytearray(b'\xc0z\x99\xe9\x00\xc0')
>>> # size in [1, 2, 4, 8]
>>> hex(context.read(arch.x64.rax, 4))
'0xe9997ac0'
>>> # Get a raw buffer
>>> hex(context.read(arch.x64.rax, 4, raw=True))
bytearray(b'\xc0z\x99\xe9')

Read rax as a U64 integer:

>>> hex(context.read(arch.x64.rax, types.U64))
'0xffffc000e9997ac0'

Read rax as two U8 integers:

>>> context.read(arch.x64.rax, types.Array(types.U16, 2))
ListContainer([0xe999, 0x7ac0])

Read a buffer in memory at address ds:0x1234:

>>> address = address.LogicalAddress(0x1234)
>>> # size not in [1, 2, 4, 8]
>>> context.read(address, 6)
bytearray(b'\xc0z\x99\xe9\x00\xc0')
>>> # size in [1, 2, 4, 8]
>>> hex(context.read(address, 8))
'0xffffc000e9997ac0'
>>> # Get a raw buffer
>>> context.read(address, 8, raw=True)
bytearray(b'\xc0z\x99\xe9\x00\xc0\xff\xff')

Read a string in memory at address ds:0x1234:

>>> address = address.LogicalAddress(0x1234)
>>> WString1000 = types.CString(encoding=types.Encoding.Utf16, max_character_count=1000)
>>> context.read(address, WString1000)
'Hello World'

Information

Parameters
source

From where the bytes are read.

Can be an address (virtual or physical) or a Register.

*args

Positional arguments that should be either type or size, where:

**kwargsThe raw parameter: Force the return type to be a raw buffer of size bytes.
Raises
TypeErrorif source is not supported.
TypeErrorif type is not a Type.
ValueErrorif source is an address and size or type are not provided.
ValueErrorif source is a Register and size is bigger than the register byte size.
RuntimeErrorif source is an unavailable register.
RuntimeErrorif source is a virtual address and is not mapped in the current context.
RuntimeErrorif source is a physical address and is outside the physical memory.
def search_in_memory(self, pattern, address, size, is_forward=True):

Iterate the search range looking for the specified pattern. Search range is:

  • [address, address + size[ in forward direction
  • [address - size, address[ in backward direction

This method returns a generator of addresses corresponding to the addresses where the searched pattern matches.

Information

Parameters
patternA str or bytearray. The pattern to look for in memory. Note: str pattern is converted to bytearray using ascii encoding.
addressa class from reven2.address the address where the search will be started. an Integer represents the offset of the address where the search will be started.
sizean Integer representing the size, in bytes, of the search range.
is_forwardbool, True to search in forward direction and False to search in backward direction
Returns
a generator of addresses corresponding to the addresses where the searched pattern matches.
Raises
TypeErrorif address is not a Integer or one of the address classes on reven2.address.
RunTimeErrorIf the address is a virtual address that is not aligned to its corresponding physical address.
def transition_after(self):

Get Transition that will execute right after this context:

    This context -> Transition After

Information

Returns
TransitionA Transition.
Raises
IndexErrorif called on the context after the last transition
def transition_before(self):

Get Transition that led to this context:

    Transition Before -> This context

Information

Returns
TransitionA Transition.
Raises
IndexErrorif called on the context before the first transition
@property
ossi: _ossi.OssiContext =

Property: OSSI information related to the context

Examples

>>> # the current symbol
>>> print(context.ossi.location())
'ntoskrnl!KiIsrLinkage+0x10'

Information

Returns
A reven2.ossi.OssiContext.
@property
stack: _stack.Stack =

Property: The active stack linked to the context.

Examples

>>> # the active stack
>>> print(context.stack)
[0] #2753249448 - ntoskrnl!KeZeroPages
[1] #2753249199 - ntoskrnl!MiZeroPhysicalPage
[2] #2753248836 - ntoskrnl!MiResolveDemandZeroFault
[3] #2753248607 - ntoskrnl!MmAccessFault
[4] #2753248552 - ntoskrnl!KiPageFault
[5] ??? - ntoskrnl!KiSystemCall64+0x15

Information

Returns
A reven2.stack.Stack.
@staticmethod
def _next_stop_point(is_forward, start, fetch_count, trans_count):

Undocumented

Parameters
is_forward:boolUndocumented
start:intUndocumented
fetch_count:intUndocumented
trans_count:intUndocumented
Returns
intUndocumented
def _read_as(self, source, ty):

Undocumented

def _read_raw(self, source, size):

Undocumented

def _read_register(self, register, size):

Undocumented

def _read_size(self, source, size, raw):

Undocumented

def _read_st_register(self, register, size):

Undocumented

def _repr_html_(self):

Representation used by Jupyter Notebook when an instance of this class is displayed in a cell.

Returns
strUndocumented
__trace =

Undocumented

_cpu_context =

Undocumented

_data_source =

Undocumented

_id =

Undocumented

_ossi_data_source =

Undocumented

@property
_rvn: _reven_api.reven_connection =

Undocumented

@property
_trace: Trace =

Undocumented