REVEN-Axion 2018v1.5.0
ida_name_binding_ida_to_reven.py

This is an example of IDA script using the REVEN Python API. Must be run from IDA!

See the script's documentation below for more information:

1 """
2 Purpose:
3  This script updates symbol names in a REVEN's project using bound names of the
4  corresponding binary analyzed in IDA.
5 
6 Usage:
7  Use IDA to load the binary, and give the following arguments before
8  executing the script:
9  host = your REVEN server name, and
10  port = your REVEN project on this host.
11 
12 Remark:
13  This script takes all basic block names and use them to assign "symbol names"
14  for the corresponding binary in REVEN. We should note that:
15  - the name of the binary must be obtained from REVEN (that is usually the
16  case if "dump process" is executed properly), and be case insentively
17  identical with the one analyzed in IDA (i.e. we do not rename the binary)
18 
19  - only function names are used for binding
20 
21  - if there is several binaries of the same name (but located at different
22  paths), then the first one will be used for name binding only.
23 """
24 
25 
26 import idaapi
27 import idautils
28 import idc
29 
30 import reven
31 
32 
33 def main(host, port):
34  project = reven.Project(host, port)
35  binary_path = get_binary_runtime_path(project)
36 
37  if binary_path is not None:
38  name_binding = get_name_binding()
39  update_binding(binary_path, project, name_binding)
40  print 'binding names from IDA to REVEN done.'
41  else:
42  print 'binary {} not found in the REVEN\'s project'.format(os.path.basename(idc.GetInputFilePath()))
43 
44 
45 def get_binary_runtime_path(reven_project):
46  """
47  Look for current IDA's binary name in the REVEN trace's binaries.
48  If found, return the full path it was located at at runtime, otherwise return None.
49  """
50  binary_basename = os.path.basename(idc.GetInputFilePath()).lower()
51  main_binary_path = None
52  for bin_path in reven_project.binaries():
53  bin_basename = os.path.basename(bin_path).lower()
54  # We will look for the first matched name only...
55  if bin_basename == binary_basename:
56  main_binary_path = bin_path
57  # so break immediately when found
58  break
59  return main_binary_path
60 
61 
62 def update_binding(binary_path, reven_project, name_binding):
63  """
64  Update REVEN project's symbol base with known IDA symbols
65  """
66  base_addr = idaapi.get_imagebase()
67  for offset in name_binding:
68  print "bind 0x{:x} as {:s}".format(base_addr + offset, name_binding[offset])
69 
70  symbols = [reven.Symbol(offset, name_binding[offset]) for offset in name_binding]
71 
72  # Note we add all symbols with a single call to keep overhead low.
73  # If symbols were previously defined, they are overridden.
74  reven_project.add_symbols_to_binary(binary_path, symbols)
75 
76 
77 def get_name_binding():
78  name_binding = {}
79  base_addr = idaapi.get_imagebase()
80  for fun_head in idautils.Functions():
81  fun_name = idc.GetFunctionName(fun_head)
82  if fun_name is not None:
83  name_binding[fun_head - base_addr] = fun_name
84 
85  return name_binding
86 
87 
88 if __name__ == '__main__':
89  host_port_str = idc.AskStr('localhost:13370', "REVEN's project address")
90  if host_port_str is not None:
91  try:
92  host, port_str = host_port_str.split(':')
93  port = int(port_str)
94  print("REVEN's project: {}:{}").format(host, port)
95  main(host, port)
96  except ValueError:
97  print("please give a correct REVEN\'s project address, e.g. localhost:13370")
98  except RuntimeError as e:
99  print('{}').format(e)
100  except:
101  print('unknown error')