REVEN-Axion 2015v1.1-r3
percent.py

The percent script simulates the % key in VI command mode, more stack memory items. Basically this means that for a push, this makes you jump to the associated pop. For a call, this makes you jump to the corresponding ret, and so on.

This will demonstrate the use of the following services:

It is built as an Axion script, so this also shows the use of a callback in Axion.

1 from axion_api import axion
2 from PythonQt.Qt import *
3 
4 import reven
5 
6 def pick_memory_access(client, point):
7  "Return first non null logical address accessed by instruction at given execution point or None"
8  null_logical = reven.logical_address(0, 0)
9  result = None
10 
11  accesses = client.memory_get_history_instruction(point)
12  for access in accesses:
13  if access.logical != null_logical:
14  if not (result and result.write and not access.write):
15  result = access
16  return result
17 
18 def get_matching_instruction(client, point):
19  "Return execution point of matching instruction for given execution point or None if not found."
20 
21  # create a range of size 1 to query context before and after selected instruction
22  point_range = reven.execution_range(point.run_name, point.sequence_identifier, 1, point.instruction_index)
23  # give an empty vector of logical address range to ignore memory for we don't nedd any memory here
24  context = client.run_get_running_context_between(point_range, reven.vector_of_logical_address_range())
25 
26  # ss values before and after selected instruction
27  ss_before = context.before.numeric_registers['ss'].value
28  ss_after = context.after.numeric_registers['ss'].value
29 
30  # ss basic heuristic to handle sysenter/sysexit
31  if ss_before != ss_after:
32  # ss is modified by instruction, search next or previous write for ss and return corresponding execution point
33  return client.run_search_next_register_use(point, forward=(ss_before > ss_after), read=False, write=True, register_name="ss")
34 
35  # memory heuristic
36  access = pick_memory_access(client, point)
37  if access != None:
38  if access.write:
39  return client.run_search_next_memory_use(point, forward=True, read=True, write=False, address=access.logical)
40 
41  if access.read:
42  return client.run_search_next_memory_use(point, forward=False, read=False, write=True, address=access.logical)
43 
44  # esp values before and after selected instruction
45  esp_before = context.before.numeric_registers['esp'].value
46  esp_after = context.after.numeric_registers['esp'].value
47 
48  # esp heuristic
49  if esp_before != esp_after:
50  if esp_before > esp_after:
51  stack = reven.logical_address(ss_after, esp_after)
52  return client.run_search_next_memory_use(point, forward=True, read=True, write=False, address=stack)
53 
54  if esp_before < esp_after:
55  stack = reven.logical_address(ss_before, esp_before)
56  return client.run_search_next_memory_use(point, forward=False, read=False, write=True, address=stack)
57 
58 
59 
60 def axion_callback():
61  # get current selected instruction from axion
62  run, seq, instr = axion.selected_sequence()
63 
64  # connect to Reven server project instance for latter service calls
65  host, port = axion.connection_info()
66  client = reven.reven_connection(host.encode(), port)
67 
68  # get reven execution point corresponding to selected instruction (for reven service calls take execution point)
69  point = reven.execution_point(run.encode(), seq, instr)
70 
71  # retrieve data from Reven and use custom heuristic to find an instruction matching the current one
72  result = get_matching_instruction(client, point)
73 
74  if result == None or not result.valid():
75  axion.status_message("No matching instruction recorded for [%s@%d:%d]" % (run, seq, instr))
76  else:
77  # select matching instruction in axion
78  axion.select_sequence(result.run_name, result.sequence_identifier, result.instruction_index)
79  axion.status_message("Jumped to matching instruction at [%s@%d:%d] from [%s@%d:%d]" % (result.run_name, result.sequence_identifier, result.instruction_index, run, seq, instr))