forked from schlafwandler/ghidra_SavePatch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSavePatch.py
75 lines (58 loc) · 2.6 KB
/
SavePatch.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
# Write the selected memory (including patches) back to a copy of the binary file
#@author schlafwandler
#@category Memory
#@keybinding
#@menupath
#@toolbar
import shutil
import jarray
import os
def address_to_file_offset(address):
tested_file_formats = [u'Executable and Linking Format (ELF)',u'Portable Executable (PE)']
if currentProgram.getExecutableFormat() not in tested_file_formats:
print('Warning: this script was not tested for executable format "%s"'%(currentProgram.getExecutableFormat()))
mem = currentProgram.getMemory()
sourceinfo = mem.getAddressSourceInfo(address)
return sourceinfo.getFileOffset()
def getPatchRange():
if currentSelection is not None:
if len(list(currentSelection.getAddressRanges())) != 1:
print("Only patches in one address range are supported. Aborting.")
return
addr_range = currentSelection.getFirstRange()
start_addr = addr_range.getMinAddress()
size = addr_range.getLength()
return start_addr,size
else:
monitor.setMessage("Waiting for user input")
start_addr = askAddress("Patch address","Start of patch:")
size = askInt("Patch size","Patch size (bytes):")
return start_addr,size
def main():
start_addr,size = getPatchRange()
print("Patch starting at 0x%08x (%d bytes)"%(start_addr.getOffset(),size))
imagebase_offset = start_addr.getOffset() - currentProgram.getImageBase().getOffset()
file_offset = address_to_file_offset(start_addr)
if not file_offset:
print("Failed to get file offset. Aborting.")
return
else:
print("Memory offset 0x%08x corresponds to file offset 0x%08x"%(imagebase_offset,file_offset))
monitor.setMessage("Waiting for user input")
orig_path = str(currentProgram.getExecutablePath())
# workaround for https://github.com/NationalSecurityAgency/ghidra/pull/2220
if os.sep == "\\" and orig_path[0] == "/":
orig_path = orig_path[1:]
output_path = str(askFile("Select output file name","Save changes"))
if not os.path.isfile(output_path):
shutil.copy(orig_path,output_path)
with open(output_path,"rb+") as f:
monitor.setMessage("Patching copied file")
print("Writing %d bytes to file offset 0x%08x"%(size,file_offset))
# https://github.com/NationalSecurityAgency/ghidra/issues/858
data_buffer = jarray.zeros(size,"b")
currentProgram.getMemory().getBytes(start_addr,data_buffer)
data_buffer = bytearray(data_buffer)
f.seek(file_offset,0)
f.write(data_buffer)
main()