forked from maddiestone/IDAPythonEmbeddedToolkit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
data_offset_calc.py
121 lines (106 loc) · 6.95 KB
/
data_offset_calc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# data_offset_calc.py
# Resolves the references to indirect offsets of a variable, register, or memory location
# whose value is known. Changes the display of the operand in the instruction (OpAlt function),
# creates a data cross references (add_dref), and creates a comment of the resolved address
# (MakeComment). User nees to define the following:
# offset_var_string: The string representation of the variable, register, or memory
# location to be replaced by the resolved value
# offset_var_value: The value of the variable defined in offset_var_string
# reg_ex_indirect: A regular expression of how indirect offset accesses to the variable
# reg_ex_immediate: A regular expression of how the immediate offset value is represented
# new_opnd_display: A string representation of how the calculated and resolved
# value should be displayed as the operand in the instruction
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
#
##############################################################################################
import re
################### USER DEFINED VALUES ###################
# String of the variable/register/location used as the indirect variable
offset_var_str = "fp"
# The defined offset_var_str's value
offset_var_value = 0x808000
# Regular expression for out offset_var_str is referenced indirectly in the IDA Disassembly
# @(-0x(1-8 hex chars), fp )
reg_ex_indirect = re.compile(r"@\(-?0x[0-9A-Fa-f]{1,8}, "+ offset_var_str +"\)")
# Regular expression for how immediate values are shown in the indirect reference
# For this example, it's 0x1044, but some architectures would show that as 1044h
regex_immediate = re.compile(r"0x[0-9A-Fa-f]{1,8}")
# String expression for how the newly calculated instruction should be displayed within the instruction
new_opnd_display = '@[0x%x]'
# OPTIONAL ---- EXAMPLE FOR ADDING OTHER INSTRUCTIONS TO THE PROCESSING
# If you'd like to add other instructions to be processed for resolving indirect offset accesses,
# update the regular expression here and use it as shown in the "else" block below
reg_ex_add3 = re.compile(r"add3 \w\w, fp, #-?0x[0-9A-Fa-f]{1,8}")
#############################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the data to be analyzed.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the data to be analyzed.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
print "[data_offset_calc.py] STARTING. Looking for indirect accesses across 0x%x to 0x%x" % (start_addr, end_addr)
curr_addr = start_addr;
while curr_addr < end_addr:
operand = GetOpnd(curr_addr, 1) # Operand = 2nd Operand in the Instruction at curr_addr
if reg_ex_indirect.match(operand):
print ('[data_offset_calc.py] 0x%x Operand: ' % curr_addr) + operand
# This checks if there are any immediate values also in the 2nd operand with the variable. For example, mov R3, @(0x10, fp)
offset = re.findall(regex_immediate, operand)
if (offset):
print "[data_offset_calc.py] 0x%x Offset: 0x%x" % (curr_addr, int(offset[0],16))
# Check if Immediate Operand is Neg or Pos
if '-' in operand :
new_opnd = offset_var_value - int(offset[0], 16)
else:
new_opnd = offset_var_value + int(offset[0], 16)
print ("[data_offset_calc.py] 0x%x: Offset + " + offset_var_str + " = 0x%0x") % (curr_addr, new_opnd)
OpAlt(curr_addr, 1, new_opnd_display % new_opnd) # Changes Display of Instruction
result = add_dref(curr_addr, new_opnd, dr_T) # Create Data Ref -- Using dref_T because not checking if read or write
print ("[data_offset_calc.py] Creating dref from 0x%x to 0x%x: " % (curr_addr, new_opnd)) + str(result)
# Using dr_O (O as in Offset, not 0) because we are not check if this a "write" or "read"
else:
print "[data_offset_calc.py] 0x%x: No immediate offset identified." % curr_addr
#####################################################################################
# This block is optional but shows how to add additional regular expressions for other instructions
# you'd like to match besides the general indirect offset acceses. For M32R we are also matching
# the add3 instruction that take the form "add3 Reg, fp, 0xNUM"
else:
instruct = GetDisasm(curr_addr)
if reg_ex_add3.match(instruct):
print ('[data_offset_calc.py] 0x%08x Instruct: ' % curr_addr) + instruct
immed_opnd = GetOpnd(curr_addr, 2) # Getting the 3rd Operand Based on the reg_ex_add3 defined above
offset = re.findall(regex_immediate, immed_opnd);
if offset:
if '-' in immed_opnd:
new_opnd = offset_var_value - int(offset[0], 16)
else:
new_opnd = offset_var_value + int(offset[0], 16)
print '[data_offset_calc.py] 0x%x: Offset + fp = 0x%08x' % (curr_addr, new_opnd)
MakeComm(curr_addr, '0x%08x' % new_opnd) # Add comment with new operand instead of overwriting instruction as done above
result = add_dref(curr_addr, new_opnd, dr_T) # Creates Data XREF from Instruct to Calculated Val
print ("[data_offset_calc.py] Creating dref from 0x%x to 0x%x: " % (curr_addr, new_opnd)) + str(result)
else:
print "[data_offset_calc.py] 0x%x: No immediate offset identified." % curr_addr
########################################################################################
prev = curr_addr
curr_addr = NextHead(curr_addr, 0xFFFFF)
if (curr_addr == BADADDR):
print "[data_offset_calc.py] EXITING."
break
else:
print "[data_offset_calc.py] QUITTING. Invalid values entered for starting and ending addresses."