2.11.0
Highlights
Reven version 2.11 is packed with new features, with the following highlights:
- A fuzzing and triage platform to analyze crashes found by a fuzzer using Reven's powerful features such as semantic tainting.
- A new WinDbg-assisted workflow to perform fine-grained recording of Windows scenarios, whether applicative or full-system, at the breakpoint level.
- The most "featureful" release of the Analysis Python API since Reven 2.2 (which introduced the API)! This release introduces:
- Essential vocabulary types such as
MemoryRange
,RegisterSlice
. - Helpers for the Taint API that facilitate the implementation of semantic tainting.
- A new API to inspect handles inside the trace of a Windows scenario.
- An extension of the Type API to read data structures in the trace of a Windows scenario, directly after their description in the PDBs.
- Essential vocabulary types such as
In more details:
-
Fuzzing & Triage Platform: this release includes a first iteration of the vision we shared in the dedicated blog article and on our stand at Offensive Con 2022. The platform monitors a directory for crash reproduction files, produced by the fuzzer of your choice. Then for each such file, it records a scenario by passing the file as input for the target binary, then it replays, analyzes and performs some initial triage of the recorded crashes. Note that the analysis is provided for Windows scenarios only so far: you will need to either fuzz directly on Windows, or to cross-compile your target binary to fuzz it on Linux and analyze crashes on Windows. Find more in the user documentation. The platform's crash analyzer is available in all Reven Editions and can be manually run against any existing replayed scenario, while the platform's workflow itself (monitor, record, replay, analyze) is exclusive to the Enterprise Edition.
-
Fine-grained recording with WinDbg: in all editions, you can now use WinDbg to finely control a Windows scenario's VM for start and stop recording points. We recently demonstrated the capability with GDB, allowing you to make records shorter and to the point, using GDB's familiar breakpoint interface. Additionally in the WinDbg integration, you can apply breakpoints directly on function names at record time. This technology combines the QEMU Virtual Machine Introspection (VMI) technology with Reven's OSSI. A dedicated blog article on using WinDbg and VMI to make fine-grained recordings will follow, so stay tuned! Meanwhile, you can already refer to the user documentation for the feature.
-
New "vocabulary" types for the Analysis API: up to now, most of the API would model a range of memory by accepting two parameters (start address and size) and returning tuples in the functions manipulating such objects. The
MemoryRange
concept is often needed to keep track of the raw information (address, size) and add additional functionality on top (such as range intersection, union, concatenation, ...). This led to multiple, custom, similar implementations of the concept in users' scripts, which is indicative thatMemoryRange
is a "vocabulary" type: a type that is always implemented in a similar fashion and that is frequently useful. Providing a "canonical" implementation in the API spares users from the multiple reimplementations and makes it easier to communicate between scripts, that would previously need to convert between the various implementations of the type. This release also implements aRegisterSlice
type that allows to express that you only want a subslice of the bits of a register (for exampleeax
israx[0:32]
), andMemoryRangeMap
/RegisterSliceMap
types that store non-overlapping ranges associated with arbitrary data, very useful for some applications such as the new Taint helpers. -
More powerful Taint API: speaking of the new Taint helpers, we now provide easier ways to query what is tainted in a state, and to add or remove tainted data from a taint state. You can then restart a new Taint from the modified taint state. This simplifies the implementation of semantic tainting in the fuzzing platform, that often requires checking that some registers or memory areas are tainted, and then modify the state before restarting the Taint.
-
Windows Handle inspection: we provide a new
reven2.preview.windows
module that contains some Windows-specific API entries, the main one for this release being thereven2.preview.windows.Context.handle
andreven2.preview.windows.Context.handles
methods. They allow to fetch the object corresponding to each OS handle in a Reven scenario, so that you can easily get e.g. the filename corresponding to the handle parameter in aNtReadFile
call. -
Revamped
types
API package, now with Windows structure information from PDBs: the API always provided a way to read from a source (register, memory) at any context, and interpret the result as some type such as signed or unsigned integers, floats, or even strings. In addition to these primitive types, this API has now been extended to support structure and enumeration types, such as the types defined by the programmers of the recorded programs. For Windows scenarios, these types are fetched from the PDBs, so that you can ask any binary executed in a Reven scenario for any named type defined by this binary. Here is a quick example of using the newtypes
API package to find all files created byNtCreateFile
in a scenario:>>> import reven2 >>> from reven2 import types >>> # Connecting to a reven server >>> hostname = "localhost" >>> port = 13370 >>> server = reven2.RevenServer(hostname, port) >>> # Getting the first binary named "ntoskrnl.exe" in the list of executed binaries in the trace >>> ntoskrnl = next(server.ossi.executed_binaries("ntoskrnl.exe")) >>> # Getting the exact symbol "NtCreateFile" in "ntoskrnl.exe" >>> nt_create_file = next(ntoskrnl.symbols("^NtCreateFile$")) >>> # Finding all files that are created in a call to NtCreateFile >>> def read_filename(ctx) -> str: ... # The third argument to the call is an _OBJECT_ATTRIBUTES structure, the filename is stored in: ... # _OBJECT_ATTRIBUTES->ObjectName.Buffer ... ty : types.Struct = ntoskrnl.exact_type("_OBJECT_ATTRIBUTES") ... object_attribute: StructInstance = ctx.deref(reven2.arch.x64.r8, types.Pointer(ty)) ... unicode_string = object_attribute.field("ObjectName").deref_struct() ... return unicode_string.field("Buffer").deref_str( ... types.CString(encoding=types.Encoding.Utf16, max_size=unicode_string.field("Length").read_int()) ... ) ... >>> for (index, ctx) in enumerate(server.trace.search.symbol(nt_create_file)): ... if index > 5: ... break ... print("{}: {}".format(ctx, read_filename(ctx))) ... Context before #14771105: \??\C:\Windows\SystemApps\ShellExperienceHost_cw5n1h2txyewy\resources.pri Context before #14816618: \??\PhysicalDrive0 Context before #16353064: \??\C:\Users\reven\AppData\Local\...\AC\Microsoft Context before #16446049: \??\C:\Users\reven\AppData\Local\...\AC\Microsoft\Windows Context before #16698900: \??\C:\Windows\rescache\_merged\2428212390\2218571205.pri Context before #26715236: \??\C:\Windows\system32\dps.dll
Improvements
Reven
- It is now possible to record interactions with some USB devices configured as USB passthrough.
- Linux kernel debug symbols are now correctly retrieved if the Linux kernel debug binary is present in the prepared file system. As a result of this change, the name of the executed binary corresponding to the kernel in a trace is now its actual name on disk (e.g.
/boot/vmlinuz-<kernel version>
) rather thankernel
like it used to be. - Searching for executed binaries in the trace is now faster when using the "Not Match" operator.
- This version improves performance of replaying the Memory History resource by about 10%.
Project Manager
- The VM's full path is now displayed when registering a new VM, to disambiguate VMs with the same name in different directories.
Axion
- When hovering over a transition in a widget, its location is displayed in timeline.
Analysis Python API
types
package
- Add
reven2.types.Struct
,reven2.types.Enumeration
,reven2.types.UnresolvedStruct
,reven2.types.UnresolvedEnumeration
to model user-defined types. - Add
reven2.types.ErrorType
andreven2.types.VoidType
that respectively represent types that couldn't be parsed from a debug object and the void type. - Add
reven2.types.StructInstance
,reven2.types.EnumerationInstance
,reven2.types.ArrayInstance
,reven2.types.PointerInstance
to represent values read from these types. - Add
reven2.ossi.Binary.exact_type
to get a named type from a debug object for Windows scenarios. - Add
reven2.types.F16
. reven2.types.Pointer
now accepts an explicitsize
arguments. Pointers created this way don't have a context-dependent size.- Add
reven2.trace.Context.deref_all
to explicitly ask dereferencing nested pointer types. - Add
reven2.types.Pointer.cast_inner
to cast the inner type of a pointer.
Taint helpers
- You can now modify a
reven2.preview.taint.TaintState
to add or remove elements of the state, and restart a new taint from this modified state usingreven2.preview.taint.Tainter.taint_from_state
.
Register slices
- Building a
reven2.RegisterSlice
by indexing a register, e.g.reven2.arch.x64.rax[0:-3]
is now possible. - The following items have been added:
reven2.arch.helpers.is_flag_register
andreven2.arch.helpers.is_condensed_flags_register
.reven2.RegisterSlice
to build bitwise slices of areven2.Register
.reven2.register_slice.RegisterSliceMap
andreven2.register_slice.RegisterSliceSet
to store multiplereven2.RegisterSlice
s.reven2.Register.root
andreven2.Register.children
to retrieve the base register/children registers of a register.
reven2.preview.taint.TaintedRegisterSlice
now accepts areven2.RegisterSlice
as tainted data.reven2.arch.register.Register
andreven2.arch.register.Category
are now exposed asreven2.arch.Register
andreven2.arch.Category
.
Memory ranges
- Add
reven2.MemoryRange
to model ranges of memory address. - Add
reven2.memory_range.MemoryRangeMap
andreven2.memory_range.MemoryRangeSet
to store multiplereven2.MemoryRange
- Add memory range support to various types of the API.
OSSI
- Add support of data symbol:
reven2.ossi.Symbol
is now an abstract class- Add
reven2.ossi.FunctionSymbol
andreven2.ossi.DataSymbol
to ossi reven2.ossi.Ossi.symbols
andreven2.ossi.Binary.symbols
return an iterator ofreven2.ossi.FunctionSymbol
andreven2.ossi.DataSymbol
- Add new methods
reven2.ossi.Binary.function_symbols
andreven2.ossi.Binary.data_symbols
- Add
reven2.ossi.BinaryMapping
andreven2.ossi.OssiContext.kernel_mappings
to access to the kernel mapping at a context. - Add the
reven2.ossi.Thread.owner_process
method to find the process owning a the current thread, when available. On Windows, threads can be detached from their owner process to execute in the context of different processes.
Python API type annotations
- Add marker file indicating that the API is typed. This results in type checkers no longer ignoring types of the API when typechecking scripts that use the API.
- Typing: Expose
reven2.address.AddressType
to represent any address type to the type checker andreven2.address.VirtualAddress
to represent virtual addresses to the type checker.
Miscellaneous
- Add
preview.windows
package containing Windows 10 utilities (e.g to parse handles and objects) - Add string representations for classes in the
reven2.types
package. - Classes in the
reven2.types
package are now comparable for equality. - Made the following classes hashable:
reven2.arch.Register
reven2.trace.Context
reven2.trace.Transition
- classes in the
reven2.types
package - classes in the
reven2.address
module
Analysis Python API script library
- Added
examples/analyze/memory/symbols_access_memory_range.ipynb
andmemory_ranges_accessed_by_a_symbol.ipynb
scripts that demonstrate how to search the trace for the symbols that access a given memory range and for the memory accesses made during the execution of a symbol, respectively.
Fixed issues
Reven
- Forward tainting
rep
-prefixed instructions no longer causes overtaint in some situations. - Fixed display of operands that only consist of an absolute address in the API and in Axion.
- When running a VM, the
I/O thread spun for 1000 iterations
condition is no longer encountered. - Filters would not return a range when the last context was included in the query.
Project Manager
- Scenario deletion no longer fails with an error in some cases.
- When attempting to replay a kernel description for a Linux kernel version that is outside of the supported range, the supported range is now correctly displayed.
- In some cases, failing to download a PDB would preclude from downloading the others from the PDB server.
- VM download from a URL no longer fails in some cases
- The Light Filesystem resource is no longer marked as "not compatible" on imported scenarios (where it cannot be regenerated).
- Sometimes artifacts from older automatic records would interfere with newer automatic records during the Light Filesystem generation, leading to wrong or missing symbols.
- Replayers would sometimes output
terminate called recursively
multiple times in the logs when failing.
Axion
- The Memory Watcher View no longer triggers the save confirmation dialog when the memory range wasn't edited/modified.
- Calltree view improvements:
- Better display of binary name
- Enable horizontal scrolling in the view
- Fix vertical scrolling when adding new items
- The Search Symbol completion no longer freezes for a long time on binaries that contain a lot of symbols.
- The Calltree view no longer requires multiple clicks to respond when clicking on sibling and level up buttons.
Analysis Python API
reven2.trace.Trace.filter
would raise an exception ifto_context == from_context + 1
.- Equality comparisons of objects
reven2.ossi.Binary
,reven2.ossi.BinaryMapping
,reven2.ossi.Symbol
,reven2.trace.Context
,reven2.trace.Transition
andreven2.memhist.MemoryAccess
now all returnFalse
when comparing against an object of a different type. Previously the behavior was unspecified. - Fixed an issue where reading a
reven2.types.Array
of e.g. areven2.types.CString
, areven2.types.Pointer
or a nestedreven2.types.Array
would return values of incorrect types. As a result of this fix, reading a value as areven2.types.Array
will now return areven2.types.ArrayInstance
.
Analysis Python API Compatibility Notes
-
The Python packages installed system-wide are no longer available in the Reven virtual environment. This is to prevent possible conflicts between Reven requirements and the system packages. You can install any needed Python package in the Reven virtual environment using
pip
. -
reven2.preview.taint.Tainter.simple_taint
no longer attempts to convert the passed tag argument toint
when it doesn't match any of the supported types. -
Comparing an address with another type for equality no longer raise a
ValueError
, but returnsFalse
instead. -
Calling
Trace.memory_accesses
with a size of 0 now raises aValueError
. -
reven2.ossi.FunctionSymbol.prototype
is deprecated. Usereven2.ossi.FunctionSymbol.demangled_name
instead -
Since
reven2.ossi.Ossi.symbols
andreven2.ossi.Binary.symbols
now returnreven2.ossi.DataSymbol
in addition toreven2.ossi.FunctionSymbol
, indiscriminately callingreven2.ossi.FunctionSymbol.name_only
orreven2.ossi.FunctionSymbol.prototype
on its returned values may now raise an exception. If you have code like the following:>>> for symbol in binary.symbols(): >>> symbol.prototype
Modify it to use the
reven2.ossi.Binary.function_symbols
function instead:>>> for symbol in binary.function_symbols(): >>> symbol.prototype
-
Constructing a
reven2.preview.taint.TaintedRegisterSlice
with a non-positive size now raises aValueError
. -
reven2.trace.Context.deref
is now deprecated when the target is a type containing nested pointers. Either usereven2.trace.Context.deref_all
to explicitly ask for nested-pointer dereference, or replace the inner Pointer types withUSize
. In the futurereven2.trace.Context.deref
will only dereference the outermost pointer. -
reven2.trace.Context.read
is now deprecated when the target is a pointer type. To compute an address, add the base address of the pointer type to the offset computed by reading as a USize. In the future,reven2.trace.Context.read
will return areven2.types.PointerInstance
when reading a pointer. -
Reading a value as a
reven2.types.Array
will now return areven2.types.ArrayInstance
rather than alist
. The former can be converted into the latter by passing it to thelist
constructor.