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 |
Recursively dereferences a pointer and read the value read as a pointing type. |
Method | find |
Find the next/previous context in which the content of the register is modified. |
Method | format |
This method gets an html formatting string representation for this class instance. |
Method | is64b |
Undocumented |
Method | physical |
Get all the physical memory regions that are accessible. |
Method | read |
Reads the value contained in a register or in memory. |
Method | search |
Iterate the search range looking for the specified pattern. Search range is: |
Method | transition |
Get Transition that will execute right after this context: |
Method | transition |
Get Transition that led to this context: |
Property | framebuffer |
Property: The framebuffer for this context. |
Property | ossi |
Property: OSSI information related to the context |
Property | stack |
Property: The active stack linked to the context. |
Static Method | _next |
Undocumented |
Method | _read |
Undocumented |
Method | _read |
Undocumented |
Method | _read |
Undocumented |
Method | _read |
Undocumented |
Method | _read |
Undocumented |
Method | _repr |
Representation used by Jupyter Notebook when an instance of this class is displayed in a cell. |
Instance Variable | __trace |
Undocumented |
Instance Variable | _cpu |
Undocumented |
Instance Variable | _data |
Undocumented |
Instance Variable | _id |
Undocumented |
Instance Variable | _ossi |
Undocumented |
Instance Variable | _stack |
Undocumented |
Property | _rvn |
Undocumented |
Property | _trace |
Undocumented |
Compares the instance for equality with an object.
- if the object is not a
Context
, returns False.
Parameters | |
other:_Any | Undocumented |
Returns | |
bool | Undocumented |
reven2.preview.windows.context.Context
Undocumented
Parameters | |
trace:Trace | Undocumented |
_data_data_source.DataSource | Undocumented |
_ossi_ossi._DataSource | Undocumented |
_stack_stack._DataSource | Undocumented |
contextint | Undocumented |
Compares the instance for equality with an object.
- if the object is not a
Context
, returns True.
Parameters | |
other:_Any | Undocumented |
Returns | |
bool | Undocumented |
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 | |
source | The source where to read the address of the pointer. Can be an address (virtual or physical) or a register. |
ptr | 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. |
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 | |
source | The source where to read the address of the pointer. Can be an address (virtual or physical) or a register. |
ptr | 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.
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.Register | reven2.arch.register.Register |
isbool | If True return next context. Otherwise return previous context. |
fetchint | 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 | |
_Optional[ | A reven2.trace.Context or None if no context was found. |
Raises | |
ValueError | if fetch_count is not positive. |
This method gets an html formatting string representation for this class instance.
Information
Returns | |
str | String |
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[ | A generator of tuples composed of the start physical address of a region and its size. |
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 |
*args | Positional arguments that should be either type or size, where:
|
**kwargs | The raw parameter: 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. |
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 | |
pattern | A str or bytearray. The pattern to look for in memory. Note: str pattern is converted to bytearray using ascii 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 | 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. |
Get Transition that will execute right after this context:
This context -> Transition After
Information
Returns | |
Transition | A Transition . |
Raises | |
IndexError | if called on the context after the last transition |
Get Transition that led to this context:
Transition Before -> This context
Information
Returns | |
Transition | A Transition . |
Raises | |
IndexError | if called on the context before the first transition |
Property: The framebuffer for this context.
Examples
>>> # Save the current framebuffer as a PNG file >>> context.framebuffer.image().save("framebuffer.png")
Information
Returns | |
A reven2.framebuffer.Framebuffer . |
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: 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 . |
def _next_stop_point(is_forward, start, fetch_count, trans_count):
Undocumented
Parameters | |
isbool | Undocumented |
start:int | Undocumented |
fetchint | Undocumented |
transint | Undocumented |
Returns | |
int | Undocumented |