Axion Views

Trace view

The Trace view represents the flow of system state transitions in the recorded scenario under analysis.

Trace view screenshot

Most of the time, a transition is simply an executed instruction. However, sometimes a transition can be:

  • A partially executed instruction (normal execution of the instruction was interrupted by a fault).
  • An interrupt.
  • A fault or an exception.

Transitions are numbered from 0, the first transition in the trace, to T, the last transition in the trace.

The trace is divided into basic blocks. Basic blocks contain transitions occurring on contiguous code addresses. In the Trace view, each basic block is identified by the number of its first transition, the name of the symbol in which the transition occurs and the offset within that symbol.

NOTE: symbol information is only displayed if the OSSI information sources have been previously configured for the scenario's VM and files.

Tips

  • You can select any item in the trace, such as an instruction or a register for example. All similar items will be displayed with a yellow background.
  • You can select any operand in the trace and, if appropriate, open a corresponding Hexdump view.

Trace Filter view

The Trace Filter view represents a high level view used to filter the trace. It displays a list of all the processes present in the trace.

Filter view screenshot

The trace can be filtered by checking/unchecking the processes in the list, and by selecting which rings are of interest: User space, Kernel space, or both. In the Trace view, transitions that do not match the filter are displayed with a gray background.

In the Trace view, navigation from one transition matching the filter to the next one, skipping the transitions outside the filter, can be done either using the filter navigation buttons in the toolbar, or the dedicated shortcuts (F6/F7 by default). It is also possible to move from a range of transitions matching the filter to the previous/next range by using the filter range navigation buttons in the toolbar, or the dedicated shortcuts (Alt+F6/Alt+F7 by default).

Trace filter toolbar: Toolbar filter buttons screenshot

A filtered trace view is displayed as the following:

Filtered trace view

Search view

The Search view allows to search some points of interest in the Trace view. Points of interests can be:

  • Any transition.
  • A transition with a given code address executed.
  • A transition with a given binary executed.
  • A transition with a given symbol executed.
  • A transition with a call to a given symbol.

The Search view is composed of:

  • A filter form to select points of interest to search.
  • A zoomable timeline representing the whole set of transitions in the scenario and displaying where results are found in the trace.
  • An exhaustive list of results.

Search view screenshot

Using the timeline

Going to some place in the trace

The Timeline allows to go directly to some place in the trace just by clicking on it. A vertical red bar represents the current location in the Trace view.

Manipulating the zoom

The Timeline can be zoomed-in/out using:

  • the keyboard with the zoom-in/zoom-out sequence key, usually Ctrl++/Ctrl+-.
  • the mouse with Ctrl+WheelUp/Ctrl+WheelDown and Left-click + drag and drop to select the zoom area.

When zoomed in, the background of the zoomed area is white.

The zoomed area can be translated left or right using:

  • the keyboard with the Up key, the Left key or the PageUp key (faster) to move to the left and the Down key, the Right key and the PageDown key (faster) to move to the right.
  • the mouse with Wheel Up to move to the left and Wheel Down to move to the right.

The zoom can be reset using Ctrl+0.

Searching a sub-range of the trace

On large traces, a sub-range can be selected in the Timeline to reduce the scope of a search:

  1. Right-click + drag and drop in the timeline: a green line represents the currently defined sub-range.

Going to a bookmark

The Timeline also displays bookmarks set in the Trace. Click on the bookmark icon in the timeline to get to the bookmark in the trace.

Searching and browsing some points of interest

  1. Fill the search form with your search parameters.
  2. Click the Search button and wait for the results to appear in the timeline and in the result dropbox.

Framebuffer view

The Framebuffer view provides a view of the machine's screen state for a given transition selected in the Trace view.

NOTE: the Metadata replay must have been run for the Framebuffer view to be available.

Framebuffer view screenshot

Calltree view

The Calltree view provides a tree representation of the ancestor and sibling calls around the currently selected transition in the Trace view. This calltree is dependent on the stack currently in use, and as such is local to the current process and thread.

The following is a code block with its corresponding calltree. The calltree widget adds a hole item when there are many siblings. This hole item contains buttons that can be used to request more siblings. In the example below, the hole item represents hidden calls to function_bottom, made by function_b in a for loop.

void function_top() {
    function_a();
    function_b();
    function_c();
}

void function_a() {}
void function_b() {
    for(int i=0; i < 1000; ++i) {
        function_bottom();
    }
}
void function_c() {}

void function_bottom() {}

Calltree example

The Calltree view is initialized with a minimal call tree that can be enriched by the user.

List of actions available in the Calltree view:

  • Display more sibling Calltree request sibling buttons
  • Display children Calltree request children button
  • Display more ancestors Calltree request ancestor button

The Calltree view displays several other important pieces of information:

  • A horizontal red line representing the current selected transition.
  • The calls belonging to the current backtrace are displayed with bold font.
  • Binary names are displayed at the right side of the view. Only binary changes are displayed. The destination binary of a call is displayed beside the call if its children are hidden.

By default, the Calltree view is updated every time the active transition is changed. This behavior can be disabled by clicking on the lock button Calltree lock button. To re-enable it, click on the unlock button Calltree unlock button. Only the tree will be locked, the location of the active transition and the current backtrace will still be updated. Note that if the current transition is not using the stack where the call tree view is locked in, no current transition will be displayed.

Double clicking on a call item will change the active transition to the one that make the call. This will not update the tree, even if the widget is unlocked.

Calltree view screenshot

NOTE This view represents an attempt at rebuilding this information from the trace's content, and sometimes cannot be comprehensive. In that case, information from earliest calls may be missing or partial. Therefore double clicking certain entries is not possible.

NOTE: the Stack Events resource must have been replayed for the Calltree view to be available.

Backtrace view

The Backtrace view provides a list of nested calls for the currently selected transaction in the Trace view, akin to what would be expected in a debugger. This backtrace is dependent on the stack currently in use, and as such is local to the current process and thread.

Backtrace view screenshot

On the upper part of the widget are two links which, when possible, provide a quick way to navigate between stack switches (i.e. when the stack pointer points to a different stack) - these moments can be process switches, ring changes, process creations, etc. The left link points to the previous stack switch, and the right link to the next stack switch.

Below these links is a list of calls, sorted from latest to earliest. You can double click an entry to get to that call.

NOTE This view represents an attempt at rebuilding this information from the trace's content, and sometimes cannot be comprehensive. In that case, information from earliest calls may be missing or partial. Therefore double clicking certain entries is not possible.

NOTE: the Stack Events resource must have been replayed for the Backtrace view to be available.

Trampolines

The backtrace as well as the Calltree widgets support trampoline calls. Trampolines are situations where the program calls an intermediary address that in turn jumps to the actual function code. See an example below:

Trampoline example

In this case, the selected transition is after both the call the trampoline jmp, so the backtrace displays the target function. However, if the selected transition is between the call and the trampoline jmp, the backtrace will show the call destination:

Between call and trampoline

The detection of these trampolines is a heuristic and can sometimes be wrong. It is possible to ignore that information and only show the call destination by unchecking Replace calls with detected trampolines in Axion's Settings dialog window.

CPU view

The CPU view displays the state of CPU registers:

Axion CPU view

  • By default, when a transition is selected in the Trace view, it shows the CPU registers values before and after the transition.
  • From the Timeline, you can also compare the CPU contexts between any two transitions in the trace.

Registers whose value has been modified by a transition or between two transitions are displayed with a yellow background. A checkbox allows you to display only modified registers.

The contextual menu provides the following actions:

  • Select memory/register can be used to:
    • Browse the register changes with the Trace view Prev and Next buttons.
    • Open a new Hexdump view at the selected address.
  • Open an new Hexdump view.
  • Configure which registers must be displayed.

Hexdump view

The Hexdump view shows the content of the memory starting at a given address, before or after a given transition in the trace. By default, the Hexdump view that had the focus last will be reused when changing the memory location. Several Hexdump views can also be opened at the same time for different memory locations by clicking the "duplicate" button.

If a memory location is not mapped at the selected execution point, ? characters will be displayed instead of its content.

The "previous/next" arrow buttons of a Hexdump view can be used to go back and forth between visited memory locations, similar to a browser history.

Hexdump view screenshot

Memory history

The Memory History view displays the history of the accesses to the selected memory buffer.

NOTE: the Memory History replay must have been run for the Memory History data to be available.

Hexdump Memory History view screenshot

To display the history of a memory buffer:

  1. In a Hexdump view, select a Byte, DWord, QWord or any continuous range of memory.
  2. Check Show access history of selection.

The list of Read and Write accesses to the buffer in the trace will then be displayed, centered on neighboring accesses. Each access is described with:

  • A transition number in the trace.
  • The access type R for read, W for write.
  • The start address of the accessed memory.
  • The size of the memory accessed.

To go to the transition in the trace corresponding to a given memory access, double-click its entry in the list.

Note this history reflects the activity of the physical region that the selected virtual area points to. This means that it can contain accesses to this area made through other virtual addresses if for example this area is:

  • Shared with another process.
  • Mapped elsewhere in the same process.
  • Accessed via a physical address directly (by peripherals for instance).
  • Reused later on in a different context.

Advanced details

There are a few specific details that are good to know, as they could otherwise be confusing:

  1. The history may not track internal accesses, such as those performed by the MMU itself while resolving accesses.
  2. The history does not track failed access attempts leading to page faults - unless if said access spans over more than one page and the first page is mapped but the rest is not, in which case there will be an entry for the first part of this access.
  3. What would intuitively be expected as a single access may appear sliced into consecutive smaller ones in various cases (access is more than 8 byte large, access spans over more than one page, etc.). This is tracer dependent.
  4. Certain instructions might generate counter-intuitive accesses: for instance, BTS (bit test and set) may access a whole 8-byte region. Again, this is tracer dependent.

Strings view

The Strings view allows to display and filter all accessed memory buffers in the trace that look like valid strings.

Strings view screenshot

Each accessed buffer is described with:

  • A transition number in the trace.
  • The memory address of the buffer.
  • The string value.

To view the access history of a buffer:

  1. Select the buffer in the list by clicking on it + Enter or double-clicking on it.

Each entry in the access history shows:

  • A transition number in the trace. Double-click on the entry to get to the transition in the Trace view.
  • The access type R for read, W for write.
  • The Symbol that performed the access, if known.

NOTE: the Strings replay must have been run for the Strings data to be available.

Taint view

The taint view allows to follow the data flow in the trace, either forward or backward.

The taint analysis automates the task of following some data from memory buffers and registers to other buffers. When performing a backward taint, it allows to find the origin of the tainted data.

Taint view screenshot

Specifying taint parameters

On the upper part of the widget are some input controls that allow to specify the taint parameters:

  • From indicates the first transition to taint.
  • To indicates the first transition not in the taint.
  • Tag0 and Tag1 indicate which data should be marked. Different data can be marked in Tag0 and Tag1, in order to follow their propagation in parallel. For more information on what data can be tainted, please refer to the Taint data format section.

To perform a backward taint, the transition number in the To control should be lower than in the From control (e.g., From = 2968405, To = 0). Otherwise, the taint will be forward. The Reverse button allows to swap the content of From and To, switching between a forward and a backward taint.

Browsing taint results

On the middle part of the widget are several tabs. The Tag0 and Tag1 tabs each contain a table indicating all changes to tainted data that occurred during the taint. The Tag0 tab indicates changes that involve data marked with Tag0, and similarly for Tag1.

For each taint change in the list, the following information is provided:

  • Transition: the transition number of the change.
  • New: shows data newly tainted.
  • Lost: shows data that just lost taint. You can double click any entry in that list to display the transition where the change occurred in the Trace view.

NOTE: If you encounter any problem with the taint, you can check the Warnings tab to see some information about what happened during the taint process. The warnings are also displayed as a clickable Warning icon next to the affected change in the change view. It is recommended to manually check changes when there is a warning icon displayed next to them.

The bottom part of the widget can be activated by checking the Display state checkbox. It presents the current state of all tainted data (regardless of Tag0 and Tag1) at the transition that is currently selected in the trace.

NOTE: Although, internally, the taint works using physical addresses, the taint attempts to rebuild linear addresses in the taint state view. These linear addresses are clickable links that will open a new hexdump.

Taint data format

Various kinds of data can be tainted, here is a list:

  • A register: rax, rbx, eax, ah
  • A slice of register: rax[0:3] (is the same as eax), rax[2]
  • A byte of logical memory (implicit ds segment): [0x4242] taints ds:0x4242
  • A range of logical memory (implicit ds segment): [0x4242; 2] taints ds:0x4242 and ds:0x4243
  • A byte of logical memory (segment register): [gs:0x4242] taints gs:0x4242
  • A range of logical memory (segment register): [gs:0x4242; 2] taints gs:0x4242 and gs:0x4243
  • A byte of logical memory (numeric segment index): [0x23:0x4242] taints 0x23:0x4242
  • A range of logical memory (numeric segment index): [0x23:0x4242; 2] taints 0x23:0x4242 and 0x23:0x4243
  • A byte of linear memory: [lin:0x4242] taints linear address 0x4242
  • A range of linear memory: [lin:0x4242; 2] taints linear addresses 0x4242 and 0x4243
  • A byte of physical memory: [phy:0x4242] taints 0x4242
  • A range of physical memory: [phy:0x4242; 2] taints 0x4242 and 0x4243

NOTE: Several pieces of data can be tainted at once for each tag.

Example: Tag0: [0x2523808; 24], rax[4], rsp, [phy:0x1234f] will tag ds:0x2523808 through ds:252381f, the fourth byte of rax, the entirety of rsp and the physical byte at address 0x1234f.

Known limitations

  • The taint may fail to propagate the taint on some instructions (notably, swapgs). The corresponding warning message is unable to lift instruction.
  • The taint may fail to propagate correctly on FPU instructions. The corresponding warning message is X87 FPU access in forward taint analysis.
  • The taint uses information obtained at the basic-block level to infer local simplifications (for instance, it can infer that in the instruction sequence {mov rax, rbx; xor rax, rbx}, the xor always resets rax to 0.). This inference may result in surprising displays in the table views, in backward (some register may lose the taint at one instruction, and some memory may "regain" the taint, apparently from nowhere). This is simply a display limitation and does not otherwise affect the correctness of the taint.
  • Tainting large ranges of memory (several MB) may result in a very slow taint that uses a lot of CPU.
  • Only a single taint can run concurrently per REVEN server: currently, starting a second taint, even from a different Axion, will cancel the first running taint. Besides, if two Axion sessions are involved, the first Axion session may display mixed taint results.

Bookmarks view

The Bookmarks view lists bookmarks that you can create on any transition in the trace, together with a name and a comment.

Bookmarks view screenshot

To create a bookmark:

  1. Select a transition in the Trace view.
  2. Click right to get to the contextual menu and select Add bookmark (or use the corresponding keyboard shortcut).

Memory watchers view

The Memory watchers view lists watchers that you can create on any virtual memory range in the trace, together with a name, a basic type information and a description.

In order to be as light as possible during the analysis, the view only displays the watchers' name and their value in memory at the current transition in the trace. To see the description, click right to get the contextual menu and select Edit.

The value in memory:

  • will be updated at each transition change.
  • is formatted according to the basic type the memory watcher is assigned.

Memory watchers view screenshot

There is 3 ways to create a memory watcher:

  1. Manual creation:

    1. Select the View menu
    2. Select Create Memory Watcher
  2. From a memory operand in the Trace view:

    1. Double click on an operand
    2. Click right to get the contextual menu and select Watch memory
  3. From a Hexdump view:

    1. Select the memory range to watch.
    2. Click right to get the contextual menu and select Watch memory

Logs view

The Logs view displays information, warning, error messages encountered by the Axion GUI.

It is a good idea to check this view when something unexpected occurs in the GUI.