Corporate

Announcing esReven version 2023.01

Mathieu Favréaux
|
-
|
Jan 2023
Back to all articles
SHARE

eShard is pleased to announce the release of **esReven version 2023.01**! It is the first version released by eShard, and a major step forward in the life of the product.[esReven](https://eshard.com/esreverse) is a Timeless Debugging and Analysis (TDnA) platform for experts in reverse engineering. Technically, esReven captures a time slice of a full system execution (CPU, memory, hardware events from a virtual machine), then provides a trace of that recording for analysis. It comes batteries-included: - Fully UI-enabled workflow, from environment preparation to recording to analysis.- Unique analysis features such as Memory History or forward & backward data flow tainting, that speed up and scale the reverse engineering process. - Comprehensive APIs to speed up and automate your analysis & power your algorithms. - Knowledge-base platform to guide you all the way by providing theoretical knowledge and practical know-how.This article covers the other important changes introduced in this release. Here is a summary:- **Reven is now esReven**, and leverages eShard's platform. What changed? - **Expertise modules**: following eShard's strengths and practices, esReven provides more knowledge & practical know-how about its usage and use cases. Two knowledge-base modules now come bundled with esReven: "Getting Started" and "Vulnerability Analysis". Read more below. - A **more comprehensive web platfrom**, which brings JupyterLab and other improvements, and includes the existing Project Manager. Read more below. - Deployment is now based on **Docker Compose**, for a simplified installation on any Linux distribution - see the [online documentation](https://doc.esreven.eshard.com/enterprise/2023.01/Installation/Index.html). - Finally, versioning is now **calendar based**, following the "Year.Month" scheme.- **API improvements:** to even better support the JupyterLab environment, and following the trend set by the previous 2.11.0 version, multiple API objects have been introduced: you can now easily parse the call tree, or display the framebuffer, among others. Read more below.*Note: esReven applies to the Enterprise license only - read more at the end.*## Reven is now esRevenWith esReven, we strive to make the product even more usable and accessible than before.### Knowledge modulesThis is a very important direction for us.eShard has a history of providing both the platform for studying targets (hardware & software) and the knowledge & experience for doing so. This expertise is then packaged to be provided to our customers as knowledge modules.Each knowledge module is a set of interactive JupyterLab notebooks produced by experts that mixes theoretical knowledge, tutorials and practical guides about a subject. What they cover can vary from basic tooling tutorials, to introductions about a topic, to practical how-to guides about a specific attack or vulnerability.![Example of a module](/uploads/Example_of_a_module_c29da365bd.png)This approach has been very successful, and we are working on bringing it to esReven as well.The result of this work so far is a set of two modules that we decided to include with this version of esReven for free:- The "Getting started" module to on-board new (or existing, but rusty!) users.- A "Vulnerability Analysis" module, which takes the user on the ride of recording and analyzing a CVE in Google Chrome.We want to continue on this path: expect more work on this side in the future!### A more comprehensive web platformThis is of course the most visible element - esReven implements eShard's platform for a better web interface.![eShard framework](/uploads/e_Shard_framework_dbf464f28d.png)The existing Reven components have been integrated in the more generic eShard framework, which is now the top-most UI. It gracefully integrates the following elements:- ![My notebooks icon](/uploads/My_notebooks_icon_64a8b48ce6.png) The **My notebooks app**, a JupyterLab instance, which replaces Reven's Jupyter and powers the knowledge modules.- ![Project Manager icon](/uploads/Project_Manager_icon_79c887cd7d.png) The existing **Project Manager**.- ![Offline doc icon](/uploads/Offline_doc_icon_9e9f1a00f5.png) The **searchable offline documentation**, for a better experience on air-gapped servers.Existing Reven users need not worry, they will feel right at home!![Familiar UI](/uploads/Familiar_UI_fd04e7662e.png)## New APIsFollowing the trend set by the previous 2.11.0 version, we kept on improving working from the Python API, making algorithms easier to build, and in general making the experience of exploring a trace from Python smoother. For this, we strive to make APIs that provide access to high-level objects while keeping the complexity as low as possible.### Type APIFirst of all, we have improved our `Type` API, which allows a user to parse high-level data in the target's memory such as typed structures, arrays, etc.:- It is now easier to browse the content of instances of typed object in memory: - using `StructInstance.fields()` we can now parse all members of a struct without having to fetch member's names first. - `ArrayInstance` now reliably contains `PointerInstance` objects, while they would sometimes contain addresses instead.- There is now a dedicated `__format__` method for `StructInstance` objects. Supported by proper `format` methods in all objects that can be contained (`FieldInstance`, `ArrayInstance`, etc.), this allows for very straightforward formatting: - Here is an example of the default formatting: ```python >>> print(f"{instance}") struct _RTL_AVL_TREE /* 0x8 */ { /* 0x0 */ Root : _RTL_BALANCED_NODE* = (...)* @ds:0xffffe00013174e80, } ``` - Alternatively, you can choose to display the inner structures, up to a certain depth (default is 1): ```python >>> print(f"{instance:max_depth=2}") struct _RTL_AVL_TREE /* 0x8 */ { /* 0x0 */ Root : _RTL_BALANCED_NODE* = (struct _RTL_BALANCED_NODE /* 0x18 */ { /* 0x0 */ Children : [_RTL_BALANCED_NODE*; 2] = [...], /* 0x0 */ Left : _RTL_BALANCED_NODE* = (...)* @ds:0xffffe000138fa510, /* 0x8 */ Right : _RTL_BALANCED_NODE* = (...)* @ds:0xffffe00012818bc0, /* 0x10 */ Red : U8[0..1] = 0, /* 0x10 */ Balance : U8[0..2] = 0, /* 0x10 */ ParentValue : U64 = 0, })* @ds:0xffffe00013174e80, } ```- If more than one type share an identical name, we can now get them all by using the `Binary.types` method. Notably, this allows fetching the proper `_KPCR` structure type on Windows 11.### Stack Events and Call TreeWe have introduced the "Stack Events" data into the Python API under the `reven2.stack` objects (accessible through `ctx.ossi.stack`). In this API, a Frame represents the time span one function call lives in, and what it does.- `stack.frame` gives access to the current `StackFrame`, while `stack.frames()` still gives all parent frames as was the case in previous version.- Each frame's exact time boundaries are explicit, and allow not only a display that is on-par with Axion, but precise control for your algorithms: - `first_context` and `last_context` give you the natural start and stop of the frame. However, there are plenty of edge-cases possible, so we also added: - `first_executed_context` gives the first time a frame appears if it has started before the beginning of the trace - `function_start` and `function_location` gives the resolved function start (in time) and location (in memory) (taking everything into account, such as trampolines or out-of-trace starts).- You can easily parse all calls made in a Frame with `children`, or access the Frame's parents with `ancestors`. Using this API recursively is possible, so you can imagine displaying a call tree as such: ```python >>> def print_children(ctx: reven2.trace.Context) -> None: ... active_frame: reven2.stack.StackFrame = ctx.stack.frame() ... print(active_frame) ... for child in active_frame.children(): ... print(f"|- {child}") ... >>> print_children(server.trace.first_context + 200_000) #199862 - usbhub!UsbhDecHubBusy |- #199886 - ntoskrnl!KeWaitForSingleObject |- #200032 - ntoskrnl!ExFreePoolWithTag |- #200239 - ntoskrnl!KiAcquireKobjectLockSafe |- #200269 - ntoskrnl!KiExitDispatcher ```- Moreover, we need to handle the fact that there can be many different situations when analyzing a function: we might be interested in its own code only, skipping its children. Or we might want the children's code, up to certain binaries. Finally, we often want to skip external code such as kernel code, or of other processes that might get scheduled between `first_context` and `last_context`. In order to handle all these various situations easily, we introduced another call: `descendant_events`. It yields all the relevant events from a frame: - `FrameStart`: a child frame starts. From this point, I can check the child's symbol, binary, etc. - `FrameEnd`: a child frame end, allowing me to resume my analysis if I skipped over the child call. - `StackLeave`: I am entering a portion of the trace where I'm no longer executing from on this particular Stack, for instance I've entered kernel code, or another process. I should really ignore everything that is going on. - `StackEnter`: I am back into my stack, so into my frame or a child.- We also know that the complexity of this call tree can rapidly grow out of control, so for these situations we ensure the iterator from `descendant_events` could skip entire frames with `skip_children()`. For example, you can control the display depth as such: ```python >>> def print_descendants(ctx: reven2.trace.Context) -> None: ... depth = 0 ... it = ctx.stack.frame().descendant_events() ... for event in it: ... if isinstance(event, reven2.stack.FrameStart): ... # [...] Do something ... depth += 1 ... if depth >= 3: ... # Skip any child this call may have and skip to its return ... it.skip_children() ... elif isinstance(event, reven2.stack.FrameEnd): ... depth -= 1 ```### Framebuffer APIThere is now a framebuffer entry point in the `Context` object! Use it to get a straight `PIL.Image` object representing the VM screen at this point in time. For example, fetch the screen at the start of the trace with: `server.trace.first_context.framebuffer.image()`. This is also very convenient to use in notebooks, as you can for instance constraint the resulting image's size with `resize((width, height))`:![Showing the framebuffer](/uploads/Showing_the_framebuffer_9bfa1b94b3.png)### OSSI APIYou can now access information about the OS running in the trace from `server.ossi.os()`. For instance:```python>>> print(server.ossi.os())Windows x64 10.0.17763 (Windows 10)```### Workflow APIFinally, there have been improvements on the side of managing scenarios and archives:- You can now open a scenario by uuid or by name, using `ProjectManager.get_server_by` and specifying either `name` or `uuid` argument.- You can now upload a scenario archive from the API with `ProjectManager.upload_scenario`## LicensingesReven covers the Enterprise license only. While the REVEN Professional & REVEN Free Editions stills exist for the moment, they are likely to be deprecated in the coming months. Other options may replace them in the future.## And what now?And that's it for this release! You can find the full list of improvements and fixes in the version's [release notes](https://doc.esreven.eshard.com/enterprise/2023.01/Release-Notes/Versions/2023.01.html).**Want to try the product?** - We provide an [extensive set of online demos](https://www.tetrane.com/demos.html), which constitute a good first step with tutorials available in most. However, they are based on the previous REVEN version for the time being. - Want to try the new esReven? [Contact us!](https://eshard.com/contact)