-
Notifications
You must be signed in to change notification settings - Fork 18
/
util.py
66 lines (56 loc) · 1.89 KB
/
util.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
"""
Util.py
Various helper functions
"""
import re
import idc
import idautils
import idaapi
def instr_size(ea):
""" Get the size of the instr at ea or 1 """
instr = idautils.DecodeInstruction(ea)
#If invalid, return 1 to consume this byte
#XXX: Fixed-width instr sets should add instr size
return instr.size if instr else 1
def get_pos():
""" Get the selected area """
start, end = idc.SelStart(), idc.SelEnd()
if start == idc.BADADDR:
start = idc.ScreenEA()
end = idc.ScreenEA() + instr_size(start)
return start, end
def read_data(ea, sz):
""" Read bytes from idb """
return idaapi.get_many_bytes(ea, sz)
def write_data(ea, blob, reanalyze=True):
""" Write bytes to idb """
if reanalyze: idc.MakeUnknown(ea, len(blob), 0)
idaapi.patch_many_bytes(ea, blob)
if reanalyze: idc.MakeCode(ea)
def save_file(output_file):
""" Save the patched file """
DIFF_RE = re.compile(r'([A-F0-9]+): ([A-F0-9]+) ([A-F0-9]+)')
idc.GenerateFile(idaapi.OFILE_DIF, output_file, 0, idc.MaxEA(), 0)
diff_file = open(output_file, "rb").read()
orig_file = open(idc.GetInputFilePath(), "rb").read()
print "OK"
diff_file = diff_file.split("\n")
total = 0
success = 0
for line in diff_file:
match = DIFF_RE.match(line)
if match:
groups = match.groups()
total += 1
offset = int(groups[0], 16)
orig_byte = groups[1].decode('hex')
new_byte = groups[2].decode('hex')
if orig_file[offset] == orig_byte:
orig_file = orig_file[:offset] + new_byte + orig_file[offset + 1:]
success += 1
else:
print "Error matching %02x at offset %x..." % (groups[1], offset)
new_file = open(output_file, 'wb')
new_file.write(orig_file)
new_file.close()
print "%i/%i patches applied" % (success, total)