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

The slicer script make use of REVEN data tainting capabilities to display a list of instructions that manipulate tainted data.

It uses services run_search_tainted_instructions to retrieve the list of interesting instruction locations, then for each point, it prints the instructions themselves.

1 #!/usr/bin/env python
2 
3 import reven
4 
5 host = raw_input('Enter the reven host [localhost]: ')
6 if not host:
7  host = "localhost"
8 
9 try:
10  port = int(raw_input('Enter the reven port [13370]: '))
11 except ValueError as e:
12  port = 13370
13 
14 try:
15  rvn = reven.reven_connection(host, port)
16 except:
17  print("[!] Reven not found on port %d" % port)
18  sys.exit(1)
19 
20 print("[+] Connected to reven on %s:%d" % (host, port))
21 runs = rvn.run_get_all()
22 
23 if len(runs) == 0:
24  sys.stderr.write("[!] No run detected.\n")
25  sys.exit(1)
26 
27 # Usually the interesting run will always be the first one, unless we are using the fuzzer.
28 run = runs[0]
29 
30 try:
31  start_sequence = int(raw_input("Enter the initial sequence [0]: "))
32 except ValueError as e:
33  start_sequence = 0
34 
35 try:
36  start_instruction = int(raw_input("Enter the initial instruction [0]: "))
37 except ValueError as e:
38  start_instruction = 0
39 
40 try:
41  stop_sequence = int(raw_input("Enter the ending sequence [1]: "))
42 except ValueError as e:
43  stop_sequence = 1
44 
45 stop_instruction = 0
46 
47 reg = raw_input("Enter the initialy tainted register [eax]: ")
48 if not reg:
49  reg = "eax"
50 
51 # Here we only taint one register, we could create more of them if desired.
52 register_tainted = [reg]
53 
54 # We can also taint some memories by uncommenting the last part of the following lines:
55 # Memory range (last is excluded)
56 first_memory_tainted = reven.logical_address(0,0) #reven.logical_address(0x7b,0xbffff55c)
57 last_memory_tainted = reven.logical_address(0,0) #reven.logical_address(0x7b,0xbffff58c)
58 
59 initial_taint = reven.vector_of_symbolic()
60 
61 #####################################################################################################
62 
63 
64 start_point = reven.execution_point(run, start_sequence, start_instruction)
65 stop_point = reven.execution_point(run, stop_sequence, stop_instruction)
66 
67 # Create the list of registers to taint. We just convert any item in register_tainted to the proper format.
68 for sym in register_tainted:
69  smem = reven.symbolic()
70  smem.name = reg
71  smem.type = reven.symbolic_type.register_all_purpose
72  initial_taint.append(smem)
73 
74 # Append memories
75 offset_tainted = first_memory_tainted.offset
76 
77 # We do exactly the same for memories. In the memories case, we also have to get their physical address
78 # because the tainter works by physical addresses.
79 segment = first_memory_tainted.segment
80 for offset in range(first_memory_tainted.offset, last_memory_tainted.offset):
81  smem = reven.symbolic()
82  smem.name = "0x%x:0x%x" % (segment, offset)
83  smem.type = reven.symbolic_type.memory_physical
84  smem.physical_address = rvn.memory_get_physical_address(start_point, reven.logical_address(segment, offset))
85 
86  initial_taint.append(smem)
87 
88 # Propagate taint, may took some times
89 print "[*] Tainting ..."
90 tainted_points = rvn.run_search_tainted_instructions(start_point, stop_point, 5000, initial_taint, False)
91 
92 print("[*] Tracking ")
93 for i in initial_taint:
94  print("%s, " % (i.name), '', None)
95 print("from #%d:%d to #%d:%d" % (start_sequence,
96  start_instruction,
97  stop_sequence,
98  0))
99 print("-----------------------------------------------\n")
100 
101 
102 
103 # Now, in tainted_points, we have all points where the taint is changed.
104 
105 for entry in tainted_points:
106  k = entry.key()
107  v = entry.data()
108 
109  if not len(v.new) and not len(v.old):
110  # Ignore when the taint hasn't changed
111  continue
112 
113  # Request the instructions of the point
114  sequences = rvn.run_get_instructions_range(reven.execution_range(run, k.sequence_identifier, 1, 0))
115  seq = sequences[0]
116  ins = seq.instructions[k.instruction_index]
117 
118 
119  # Print the instruction itself
120  mnemonic = " "
121  if ins.prefixes: mnemonic = "%s " % ins.prefixes
122  mnemonic += ins.mnemonic
123  if ins.operand_one: mnemonic += " " + ins.operand_one
124  if ins.operand_two: mnemonic += ", " + ins.operand_two
125  if ins.operand_three: mnemonic += ", " + ins.operand_three
126 
127  symbol = "%s+%x" % (seq.sequence.symbol.name, seq.sequence.symbol.offset)
128  print("%-32s: #%d_%d: %s" % (symbol, k.sequence_identifier, k.instruction_index, mnemonic))