class Context(object):
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
This object is not meant to be constructed directly. Use Trace.context_before
, Trace.context_after
, Transition.context_before
or Transition.context_after
instead.
>>> # 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 | __init__ |
Undocumented |
Method | transition_before |
Get Transition that led to this context |
Method | transition_after |
Get Transition that will execute right after this |
Property | ossi |
Property: OSSI information related to the context |
Property | stack |
Property: The active stack linked to the context. |
Method | is64b |
Undocumented |
Method | physical_memory_regions |
Get all the physical memory regions that are accessible. |
Method | read |
read(register [, raw=False]) -> read bytes from a register read(source, size[, raw=False]) -> read bytes from a register or a memory read(source, type) -> read bytes from a register or a memory |
Method | deref |
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 | search_in_memory |
No summary |
Method | __str__ |
Undocumented |
Method | __repr__ |
Undocumented |
Method | format_as_html |
This method gets an html formatting string representation for this class instance. |
Method | __eq__ |
Undocumented |
Method | __ne__ |
Undocumented |
Method | __lt__ |
Undocumented |
Method | __le__ |
Undocumented |
Method | __gt__ |
Undocumented |
Method | __ge__ |
Undocumented |
Method | __add__ |
Undocumented |
Method | __sub__ |
Undocumented |
Instance Variable | __trace |
Undocumented |
Instance Variable | _data_source |
Undocumented |
Instance Variable | _ossi_data_source |
Undocumented |
Instance Variable | _id |
Undocumented |
Instance Variable | _cpu_context |
Undocumented |
Property | _trace |
Undocumented |
Static Method | _next_stop_point |
Undocumented |
Method | _read_size |
Undocumented |
Method | _read_as |
Undocumented |
Method | _read_raw |
Undocumented |
Method | _read_st_register |
Undocumented |
Method | _read_register |
Undocumented |
Method | _repr_html_ |
Representation used by Jupyter Notebook when an instance of this class is displayed in a cell. |
Property | _rvn |
Undocumented |
Get Transition that led to this context
>>> Transition Before -> This context
Returns | A Transition . | |
Raises | IndexError | if called on the context before the first transition |
Get Transition that will execute right after this
>>> This context -> Transition After
Returns | A Transition . | |
Raises | IndexError | if called on the context after the last transition |
Property: OSSI information related to the context
>>> # the current symbol >>> print(context.ossi.location()) 'ntoskrnl!KiIsrLinkage+0x10'
Returns | A reven2.ossi.OssiContext . |
Property: The active stack linked to the context.
>>> # the active stack >>> print(context.stack.backtrace) [0] #2753249448 - ntoskrnl!KeZeroPages [1] #2753249199 - ntoskrnl!MiZeroPhysicalPage [2] #2753248836 - ntoskrnl!MiResolveDemandZeroFault [3] #2753248607 - ntoskrnl!MmAccessFault [4] #2753248552 - ntoskrnl!KiPageFault [5] ??? - ntoskrnl!KiSystemCall64+0x15
Returns | A reven2.stack.Stack . |
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.
>>> for (start, size) in ctx.physical_memory_regions(): >>> print("{} - {}".format(start, start + size)) phy:0x0 - phy:0x80000000 phy:0xfd000000 - phy:0xfe000000
Returns | A generator of tuples composed of the start physical address of a region and its size. |
read(register [, raw=False]) -> read bytes from a register read(source, size[, raw=False]) -> read bytes from a register or a memory 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
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'
Parameters | source | From where the bytes are read. Can be an address (virtual or physical) or a Register . |
args | Undocumented | |
kwargs | Undocumented | |
type | A reven2.types.Type . See the reven2.types package documentation for more information on types. | |
size | The byte size to read. If no 'size' and 'source' is a reven2.arch.register.Register , then the Register.size_bytes is used. | |
raw | Force the return type to be a raw buffer of 'size' bytes. | |
Raises | TypeError | if 'source' is not supported. |
TypeError | if 'type' is not a Type . | |
ValueError | if 'source' is an address and 'size' or 'type' are not provided. | |
ValueError | if 'source' is a Register and 'size' is bigger than the register byte size. | |
RuntimeError | if 'source' is an unavailable register. | |
RuntimeError | if 'source' is a virtual address and is not mapped in the current context. | |
RuntimeError | if 'source' is a physical address and is outside the physical memory. |
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:
>>> 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:
>>> addr1 = self.read(source, Pointer(Pointer(U64))) >>> addr2 = self.read(addr1, Pointer(U64)) >>> return self.read(addr2, U64)
Reading the stack pointer:
>>> hex(context.deref(reven2.arch.x64.rsp, types.Pointer(types.USize))) '0xfffff801653ff072L'
Looks like an address, let's try to dereference twice:
>>> hex(context.deref(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(reven2.arch.x64.rsp, types.Pointer(types.Pointer(types.RawBuffer(8))))] ['0x4c', '0x89', '0x7c', '0x24', '0x28', '0x48', '0x89', '0x7c']
Parameters | source | The source where to read the address of the pointer. Can be an address (virtual or physical) or a register. |
ptr_ty | A reven2.types.Pointer . | |
Returns | The data interpreted as the requested type. If the pointer points to an unmapped memory, None is returned. | |
Raises | TypeError | if 'source' is not supported. |
TypeError | if 'ptr_ty' is not a Pointer . | |
ValueError | if 'source' is a Register and there is not enough bytes to read the pointer address in it. | |
RuntimeError | if 'source' is an unavailable register. |
Find the next/previous context in which the content of the register is modified.
Parameters | register | reven2.arch.register.Register |
is_forward | If True return next context. Otherwise return previous context. | |
fetch_count | Technical parameter indicating how many contexts the server should handle per query. Modifying this parameter allows to fine-tune performance:
NOTE: Modifying this parameter does not modify the results of the query | |
Returns | A reven2.trace.Context or None if no context was found. | |
Raises | ValueError | if fetch_count is not positive. |
Iterate the search range looking for the specified pattern. Search range is:
This method returns a generator of addresses corresponding to the addresses where the searched pattern matches.
Parameters | pattern | A str or bytearray . The pattern to look for in memory. Note: str pattern is converted to bytearray using ascci encoding. |
address | a 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. | |
size | an Integer representing the size, in bytes, of the search range. | |
is_forward | bool , 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 | TypeError | if address is not a Integer or one of the address classes on reven2.address . |
RunTimeError | If the address is a virtual address that is not aligned to its corresponding physical address. |
This method gets an html formatting string representation for this class instance.
Returns | String |