Entry point object for data related to a transition.

A transition is anything that changes the state of the virtual machine, from `context_before` to `context_after`. Most of the time, that would be an instruction executed by the CPU. Sometimes, it will be an exception (CPU fault or IRQ) instead. In that case, an instruction might still be related to the exception, if for instance it is the source of the fault. In that case, the instruction has not been fully executed by the CPU.

Warnings

This object is not meant to be constructed directly. Use Trace.transition instead.

Examples

Spawning: >>> # From a trace >>> tr = reven_server.trace.transition(id) >>> >>> # From a context >>> tr = context.transition_before(transition_id) >>> >>> # From a transition >>> tr = reven_server.trace.transition(id) >>> next_tr = tr + 1 >>> prev_tr = tr - 1 >>> other_tr = tr + 10000

Usage: >>> print(tr) >>> if tr.type == TransitionType.Instruction: >>> print(tr.instruction)

Method __init__ Undocumented
Method id Property: Unique ID of this transition.
Method type Property: The transition's type.
Method instruction Property: The associated Instruction if one exists.
Method exception Property: The associated CPUException if one exists.
Method context_before Get the Context object before this transition was executed
Method context_after Get the Context object after this transition was executed
Method memory_accesses Get a generator over the reven2.memhist.MemoryAccesses at this transition.
Method find_inverse This method is a helper to get the transition that performs the inverse operation to this transition.
Method __str__ Undocumented
Method __repr__ Undocumented
Method __eq__ Undocumented
Method __ne__ Undocumented
Method __lt__ Undocumented
Method __le__ Undocumented
Method __gt__ Undocumented
Method __ge__ Undocumented
Method __add__ Undocumented
Method __sub__ Undocumented
Class Method _unique_id Undocumented
Method _trace Undocumented
Method _data Undocumented
Method _repr_html_ Representation used by Jupyter Notebook when an instance of the Transition class is displayed in a cell.
def __init__(self, trace, _data_source, _ossi_data_source, transition_id):
Undocumented
@classmethod
def _unique_id(cls):
Undocumented
@property
def _trace(self):
Undocumented
@property
def id(self):

Property: Unique ID of this transition.

Can be used to spawn the object from the corresponding `Trace` object.

Information

ReturnsAn integer.
@property
def type(self):

Property: The transition's type.

The type of a transition can be one of the following:

  • TransitionType.Instruction means this transition is a fully instruction executed.
  • TransitionType.Exception means this transition is an exception raised by the CPU or a peripheral.

Information

ReturnsA TransitionType instance.
@property
def instruction(self):

Property: The associated Instruction if one exists.

If this transition is not of type Instruction of TransitionType, None will be returned.

Information

ReturnsAn Instruction, or None.
@property
def exception(self):

Property: The associated CPUException if one exists.

If this transition is not of type Exception of TransitionType, None will be returned.

Information

ReturnsAn CPUException, or None.
def context_before(self):

Get the Context object before this transition was executed

>>> Context before -> This transition

Information

ReturnsA Context.
def context_after(self):

Get the Context object after this transition was executed

>>> This transition -> Context after

Information

ReturnsA Context.
def memory_accesses(self, operation=None):

Get a generator over the reven2.memhist.MemoryAccesses at this transition.

Examples

>>> # Getting all accesses as a list at transition 42 (can be long if there are a lots of accesses):
>>> list(trace.transition(42).memory_accesses())
[MemoryAccess(transition=Transition(id=42), physical_address=PhysicalAddress(offset=0x7fc03eb8), size=8,
    operation=MemoryAccessesOperation.Write, virtual_address=LinearAddress(offset=0xffff88007fc03eb8))]
>>> # Getting the first memory access at transition 14
>>> next(trace.transition(14).memory_accesses())
MemoryAccess(transition=Transition(id=14), physical_address=PhysicalAddress(offset=0x1f270a2), size=1,
    operation=MemoryAccessesOperation.Read, virtual_address=LinearAddress(offset=0xffffffff81f270a2))
>>> # Getting all addresses that are read at transition 0.
>>> addresses = set()
>>> for access in trace.transition(0).memory_accesses(operation=reven2.memhist.MemoryAccessesOperation.Read):
>>>     physical_offset = access.physical_address.offset
>>>     for address in range(physical_offset, physical_offset + access.size)
>>>         addresses.add(address)
>>> for address in addresses:
>>>     print reven2.address.PhysicalAddress(address)
phy:0x36f05080
phy:0x36f05081
phy:0x36f05082
phy:0x36f05083
phy:0x36f05084
phy:0x36f05085
phy:0x36f05086
phy:0x36f05087

Information

ParametersoperationOnly return accesses whose operation equals the specified reven2.memhist.MemoryAccessOperation. If None, return all accesses.
Returnsa generator of reven2.memhist.MemoryAccess.
RaisesRuntimeErrorif the memory history resource has not been generated
def find_inverse(self):

This method is a helper to get the transition that performs the inverse operation to this transition.

Inverse operations

The transition switches between user and kernel land. Examples:

  • a syscall transition => the related sysret transition
  • a sysret transition => the related syscall transition
  • a exception transition => the related iretq transition
  • a iretq transition => the related exception transition

The transition does memory accesses:

  • case 1: a unique access. The access is selected.
  • case 2: multiple write accesses. The first one is selected.
  • case 3: multiple read accesses. The first one is selected.
  • case 4: multiple read and write accesses. The first write access is selected. This enable to get the matching ret transition on an indirect call transition e.g. call [rax + 10].

If the selected access is a write then the next read access on the same memory range is searched for.

If the selected access is a read then the previous write access on the same memory range is searched for.

Example find_inverse on:

  • a call transition => the related ret transition.
  • a ret transition => the related call transition.
  • a push transition => the related pop or mov transition.
  • a pop transition => the related push transition.
  • a store transition => the related load transition.
  • a load transition => the related store transition.

Note

Due to the fact that find_inverse matches with memory accesses to find the inverse instruction, in some special cases, such as ROP chain, the inverse of e.g. a ret will not be a call instruction, but could be a mov to the memory, for example.

Dependencies

This method requires that the REVEN2 server have the Memory history enabled.

Usage

It can be combined with other features like backtrace to obtain interesting results.

Example

For example, to jump to the end of the current function:

>>> import reven2
>>> reven_server = reven2.RevenServer('localhost', 13370)
>>> current_transition = reven_server.trace.transition(10000000)
>>> ret_transition = current_transition.find_inverse()

Information

Returnsreven2.trace.Transition or None if no inverse found.
@property
def _data(self):
Undocumented
def __str__(self):
Undocumented
def __repr__(self):
Undocumented
def _repr_html_(self):

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

The transition is returned as a clickable link containing the transition id, that publishes the transition to all tracked reven2.session.Sessions.

def __eq__(self, other):
Undocumented
def __ne__(self, other):
Undocumented
def __lt__(self, other):
Undocumented
def __le__(self, other):
Undocumented
def __gt__(self, other):
Undocumented
def __ge__(self, other):
Undocumented
def __add__(self, other):
Undocumented
def __sub__(self, other):
Undocumented
API Documentation for reven2, generated by pydoctor at 2020-09-17 15:57:23.