- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshellcode_gen.py
More file actions
Latest commit
142 lines (113 loc) · 4.25 KB
/
Copy pathshellcode_gen.py
File metadata and controls
142 lines (113 loc) · 4.25 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
""" Built-in modules """
importos
importre
importshlex
importsys
frompathlibimportPath
fromsubprocessimportPopen, TimeoutExpired
defobjdump_run(filename: str, tmp_file: Path):
"""
Takes the passed in binary executable, runs objdump utility, and writes the output to file.
:param filename: The file to be run through the objdump utility.
:param tmp_file: The temp file where the objdump output will be saved to.
:return: Nothing
"""
# Shell escape filename for execution #
file=shlex.quote(filename)
try:
# Open the temp file in write mode #
withtmp_file.open('w', encoding='utf-8') asout_file:
# Create objdump command process, storing output in open file #
withPopen(['objdump', '-M', 'intel', '-D', file], stdout=out_file,
stderr=out_file) ascommand:
command.communicate()
# If error occurs during file operation #
exceptOSErrorasio_err:
print_err(f'Error occurred writing {file} objdump to {tmp_file}: {io_err}')
sys.exit(2)
defprint_err(msg: str):
"""
Prints a timed error message via stderr.
:param msg: The error message to be displayed.
:return: Nothing
"""
print(f'\n* [ERROR]: {msg} *\n', file=sys.stderr)
defprompt_user(re_exe) ->str:
"""
Prompt the user for input, handle errors accordingly.
:param re_exe: The regular expression match format.
:return: Validated user input.
"""
cmd=shlex.quote('clear')
whileTrue:
# Clear the display #
os.system(cmd)
# Prompt user for input #
prompt=input('[+] Invalid or no args provided .. enter file to grab bytes: ')
# If input validation regex fails #
ifnotre.search(re_exe, prompt):
print_err('Improper input .. try again')
continue
returnprompt
defmain():
"""
Take input file, run in objdump, and parse output into shellcode.
:return: Nothing
"""
# Compile path regex #
re_exe=re.compile(r'[a-zA-Z\d_\"\' .,\-]{1,20}')
# If an arg was passed in #
iflen(sys.argv) >1:
# Check if arg was passed in #
arg_check=re.search(re_exe, sys.argv[1])
# If regex did not match #
ifnotarg_check:
# Prompt the user for input #
filename=prompt_user(re_exe)
else:
# Set the passed in arg as filename #
filename=sys.argv[1]
# If no args were passed in #
eliflen(sys.argv) ==1:
# Prompt the user for binary tp execute on #
filename=prompt_user(re_exe)
# If unexpected error occurs parsing args #
else:
print_err('Unknown error occurred on program startup')
# Exit program on error #
sys.exit(1)
out_path=Path('/tmp')
# Set temp file name for pre-parsing #
tmp_file=out_path/f'{filename}.txt'
# Run objdump utility on binary file and save to tmp file #
objdump_run(filename, tmp_file)
# Compile regular expression for byte formatting #
re_byte=re.compile(r'\s([a-f\d]{2}\s){1,7}')
re_space_strip=re.compile(r'\s[^\S\r\n]')
re_raw_byte=re.compile(r'\s|\t')
shellcode=''
try:
# Open the temporary file in read mode #
withtmp_file.open('r', encoding='utf-8') asre_file:
# Iterate through file line by line #
forlineinre_file:
# Attempt to match bytes in line #
byte_grab=re.search(re_byte, line)
# If regex matches #
ifbyte_grab:
# Strip whitespace from match #
strip=re.sub(re_space_strip, r'', byte_grab.group(0))
# Format raw byte like \xXX #
raw_byte=re.sub(re_raw_byte, r'\\x', strip)
# Append raw byte to shellcode string #
shellcode+=raw_byte[:-2]
print(f'Shellcode: {shellcode}')
# If error occurs during file operation #
exceptOSErrorasio_err:
print_err(f'Error occurred writing shellcode to {tmp_file.name}: {io_err}')
sys.exit(3)
# Unlink the temporary parsing file #
tmp_file.unlink()
sys.exit(0)
if__name__=='__main__':
main()