-
Notifications
You must be signed in to change notification settings - Fork 99
/
exe2hex.py
718 lines (588 loc) · 26.2 KB
/
exe2hex.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
#!/usr/bin/env python3
# Name: exe2hex v1.5.2 (2020-04-24) ~ Codename: hEXE
# Author: g0tmilk ~ https://blog.g0tmi1k.com/
# Licence: MIT License ~ http://opensource.org/licenses/MIT
# Credit to: exe2bat.exe & https://github.com/acjsec/exe2bam
# Notes: Could use certutil for base64...
import os
import shutil
import signal
import subprocess
import sys
import tempfile
from optparse import OptionParser
import urllib.parse
version = '1.5.2'
###################
# Functions start #
###################
# Use standard error message and exit
def error_exit(msg):
error_msg(msg)
sys.exit(1)
# Standard error message (Red)
def error_msg(msg):
sys.stderr.write("\033[01;31m[!]\033[00m ERROR: %s\n" % msg)
# Standard success message (Green)
def success_msg(msg):
print("\033[01;32m[+]\033[00m %s" % msg)
# Verbose message (Yellow)
def verbose_msg(msg):
if verbose:
notification_msg(msg)
# Standard notification message (Yellow)
def notification_msg(msg):
print("\033[01;33m[i]\033[00m %s" % msg)
# Banner information (Blue)
def banner_msg(msg):
print("\033[01;34m[*]\033[00m %s" % msg)
# CTRL + C
def signal_handler(signal, frame):
print('Quitting...')
sys.exit(0)
#################
# Functions End #
#################
###########################
# Start BinaryInput class #
###########################
class BinaryInput:
# Initialization object configuration
def __init__(self, exe_file, output_file, method):
self.exe_file = exe_file # Full path of the binary input
self.output_file = output_file # Full path of output file
self.telnet_file = None # Full path of the telnet file out
self.winexe_file = None # Full path of the winexe file out
self.exe_filename = "" # Filename of binary input
self.output_filename = "" # Filename of output file
self.short_file = "" # Short filename of bat output (8.3 filename)
self.telnet_filename = "" # Filename of telnet output
self.winexe_filename = "" # Filename of winexe output
self.exe_bin = b'' # Binary input (data read in)
self.bin_size = 0 # Binary input (size of data)
self.byte_count = 0 # How many loops to read in binary
self.output_hex = "" # hex format output
self.method = method # EXE conversion method
# Extract the input filename from the input path (if there was one)
if self.exe_file:
self.exe_file = os.path.abspath(self.exe_file)
self.exe_filename = os.path.basename(self.exe_file)
else:
self.exe_filename = "binary.exe"
verbose_msg("Output EXE filename: %s" % self.exe_filename)
# debug.exe has a limitation when renaming files > 8 characters (8.3 filename)
self.short_file = os.path.splitext(self.exe_filename)[0][:8]
verbose_msg("Short filename: %s" % self.short_file)
self.output_filename = os.path.basename(self.output_file)
verbose_msg("Output filename: %s" % self.output_filename)
# Make sure the input file exists
def check_exe(self):
if not os.path.isfile(self.exe_file):
error_exit("The input file was not found (%s)" % self.exe_file)
# Make sure the binary size <= 64k when using bat files (limitation with debug.exe)
def check_bat_size(self):
verbose_msg('Binary file size: %s bytes' % self.bin_size)
if self.bin_size > 65536:
verbose_msg('Input is larger than 65536 bytes')
# Try and use strip and/or upx to compress (useful for bat)
def compress_exe(self):
notification_msg('Attempting to clone and compress')
tf = tempfile.NamedTemporaryFile(delete=False)
notification_msg('Creating temporary file %s' % tf.name)
try:
if (self.exe_file):
shutil.copy2(self.exe_file, tf.name)
else:
with open(tf.name, 'wb') as out:
out.write(self.exe_bin)
except:
error_exit("A problem occurred while trying to clone into a temporary file")
# Compress the new temp file
self.compress_exe_strip(tf)
# Don't do it if its not needed. (AV may detect this)
if compress == 2:
self.compress_exe_upx(tf)
# Set the temp file as the main file
self.exe_file = os.path.abspath(tf.name)
# Use strip to compress (useful for bat)
def compress_exe_strip(self, tf):
if shutil.which("strip"):
verbose_msg('Running strip on %s' % tf.name)
# Get the size before compression
before_size = os.path.getsize(tf.name)
# Program to run to compress
command = "strip -s %s" % tf.name
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
process.wait()
# Size after compression
after_size = os.path.getsize(tf.name)
diff_size = before_size - after_size
# Feedback for the user
success_msg("Compression (strip) was successful! (%s saved)" % ("{:.1%}".format(diff_size / before_size)))
verbose_msg('Binary file size (after strip) %s' % os.path.getsize(tf.name))
else:
error_msg("Cannot find strip. Skipping...")
# Use UPX to compress (useful for bat). Can be flag'd by AV
def compress_exe_upx(self, tf):
if shutil.which("upx"):
verbose_msg('Running UPX on %s' % tf.name)
# Get the size before compression
before_size = os.path.getsize(tf.name)
# Program to run to compress
command = "upx -9 -q -f %s" % tf.name
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
process.wait()
# Size after compression
after_size = os.path.getsize(tf.name)
diff_size = before_size - after_size
# Feedback for the user
success_msg("Compression (UPX) was successful! (%s saved)" % ("{:.1%}".format(diff_size / before_size)))
verbose_msg('Binary file size (after UPX) %s' % os.path.getsize(tf.name))
else:
error_msg("Cannot find UPX. Skipping...")
# Get the contents of the input file
def read_bin_file(self):
# Feedback for the user, to know where they are
verbose_msg('Reading binary file')
# Read the input file
try:
with open(self.exe_file, "rb") as f:
self.exe_bin = f.read()
except:
error_exit("A problem occurred while reading the input file (%s)" % self.exe_file)
# Set the size of the input file
self.bin_size = os.path.getsize(self.exe_file)
# Get the contents of STDIN input
def read_bin_stdin(self):
# Feedback for the user, to know where they are
notification_msg('Reading from STDIN')
# Read from STDIN
f = ""
try:
f = sys.stdin.buffer.read()
except:
error_exit('A problem occurred while reading STDIN')
# Get the length of data read
stdin_bytes = len(f)
# Did something go wrong?
if stdin_bytes == 0:
error_exit('Zero bytes read from STDIN')
# Set the size from STDIN
self.bin_size = stdin_bytes
# Add the read byte into the byte string
self.exe_bin = f
# Convert binary data to a bat file
def bin_to_bat(self):
# Feedback for the user, to know where they are
verbose_msg('Converting to BATch (DEBUG.exe)')
# Number of 64k+/max_size loops will be the number of parts made/
x = -1
# What is tha max size we can use for the loop
max_size = 65536 - (hex_len * 2)
# Loop through binary bytes per 65536 (Debug.exe limitation)
for exeloop in range(0, len(self.exe_bin), max_size):
# Increase the loop counter (incase the input file is 64k+)
x += 1
# Start fresh. Empty the value
self.byte_count = 0
# Loop through binary input file for this section
for i in range(exeloop, exeloop + max_size, hex_len):
# Is there any more data? Are we at the end?
if not (self.exe_bin[i:i + hex_len]):
break
# Numbering for the hex position in this loop
hex_size = (i - (max_size * x)) + (hex_len * 2)
# Convert to hex and debug.exe format
self.output_hex += '%secho e %s>>%s.hex%s\r\necho ' % (
prefix, '{:04x}'.format(hex_size), self.short_file, suffix)
self.output_hex += ' '.join('%02x' % y for y in self.exe_bin[i:i + hex_len])
self.output_hex += '>>%s.hex%s\r\n' % (self.short_file, suffix)
# Save the amount of data converted - aka byte counter (debug.exe needs it at the end)
self.byte_count += hex_len
# Save the bat file
self.save_bat(x)
# Start fresh. Empty the value
self.output_hex = ""
# Finish off the BATch file (in-case there's multiple parts)
self.finish_bat(x)
# Write resulting bat file
def finish_bat(self, loop=0):
# Is there more than one part? Going to be using this for the copy fu
if loop > 0:
# Loop them all, start with the first
parts = '%s.0' % self.short_file
for i in range(1, loop + 1, 1):
parts += '+%s.%s' % (self.short_file, i)
# Command fu, to join all the parts together
output = '%scopy /B /Y %s %s%s\r\n' % (prefix, parts, self.exe_filename, suffix)
else:
# Single file, just move it
output = '%smove /Y %s.%s %s%s\r\n' % (prefix, self.short_file, loop, self.exe_filename, suffix)
# Select every temp file used, so it can be deleted
parts = '%s.hex' % self.short_file
for i in range(0, loop + 1, 1):
parts += ' %s.%s' % (self.short_file, i)
# Some times the del command will not remove it (as it is still in use), so let's just null it!
output += '%secho. >%s.hex%s\r\n' % (prefix, self.short_file, suffix)
# The final few things
output += '%sdel /F /Q %s%s\r\n' % (prefix, parts, suffix)
output += '%sdir %s%s\r\n\r\n' % (prefix, self.exe_filename, suffix)
#if self.telnet_file == None:
# output += '%sstart /wait /b %s%s\r\n\r\n' % (prefix, self.exe_filename, suffix)
# Write the file out
self.write_file(self.output_file, output, "BATch (DEBUG.exe)", False)
# Convert binary data to a PoSh file
def bin_to_posh(self):
# Null any previous files
#self.posh_hex += '%secho|set /p="">%s.hex%s\r\n' % (prefix, self.short_file, suffix)
self.output_hex += '%secho|set /p="">%s.hex%s\r\n' % (prefix, self.short_file, suffix)
# Loop through binary bytes
for i in range(0, len(self.exe_bin), hex_len):
self.output_hex += '%secho|set /p="' % (prefix)
self.output_hex += ''.join('%02x' % i for i in self.exe_bin[i:i + hex_len])
self.output_hex += '">>%s.hex%s\r\n' % (self.short_file, suffix)
# Write resulting bat file
def save_bat(self, loop=0):
# Create bat file!
output = ""
output += '%sdebug /?%s\r\n' % (prefix, suffix)
output += '%sif NOT %%ERRORLEVEL%% == 0 echo &echo &echo &echo **** **** **** **** ****&echo *** Missing DEBUG.exe ***&echo **** **** **** **** ****&exit /b%s\r\n' % (prefix, suffix)
output += '%secho n %s.%s>%s.hex%s\r\n' % (prefix, self.short_file, loop, self.short_file, suffix)
output += self.output_hex
output += '%secho r cx>>%s.hex%s\r\n' % (prefix, self.short_file, suffix)
output += '%secho %s>>%s.hex%s\r\n' % (prefix, '{:04x}'.format(self.byte_count), self.short_file, suffix)
output += '%secho w>>%s.hex%s\r\n' % (prefix, self.short_file, suffix)
output += '%secho q>>%s.hex%s\r\n' % (prefix, self.short_file, suffix)
output += '%sdebug<%s.hex%s\r\n' % (prefix, self.short_file, suffix)
# Write file out (Do we need need to overwrite?)
if loop > 0:
self.write_file(self.output_file, output, "BATch - DEBUG.exe", False)
else:
self.write_file(self.output_file, output, "BATch - DEBUG.exe", True)
# Write resulting PoSh file
def save_posh(self):
# Create PoSh file!
output = ""
#output += '%spowershell /?%s\r\n' % (prefix, suffix)
#output += '%sif NOT %%ERRORLEVEL%% == 0 echo &echo &echo &echo **** **** **** **** ****&echo *** Missing Powershell ***&echo **** **** **** **** ****&exit /b%s\r\n' % (prefix, suffix)
output += self.output_hex
output += "%spowershell -Command \"" % (prefix)
output += "$h=Get-Content -readcount 0 -path './%s.hex';" % (self.short_file)
output += "$l=$h[0].length;"
output += "$b=New-Object byte[] ($l/2);"
output += "$x=0;"
output += "for ($i=0;$i -le $l-1;$i+=2)"
output += "{$b[$x]=[byte]::Parse($h[0].Substring($i,2),[System.Globalization.NumberStyles]::HexNumber);"
output += "$x+=1};"
output += "set-content -encoding byte '%s' -value $b;" % (self.exe_filename)
output += "Remove-Item -force %s.hex;" % (self.short_file)
#output += "Get-ChildItem %s;" % (self.exe_filename)
output += "\"%s\r\n\r\n" % (suffix)
#output += '%sstart /wait /b %s%s\r\n\r\n' % (prefix, self.exe_filename, suffix)
# Write file out
self.write_file(self.output_file, output, "PoSh", True)
# Write resulting certutil BATch file
def save_certutil_bat(self):
# Create bat file!
output = ""
output += self.output_hex
output += "%scertutil -f -decodeHex %s.hex %s >nul%s\r\n" % (prefix, self.short_file, self.exe_filename, suffix)
output += '%sdel /F /Q %s.hex%s\r\n' % (prefix, self.short_file, suffix)
output += '%sdir %s%s\r\n\r\n' % (prefix, self.exe_filename, suffix)
# Write file out
self.write_file(self.output_file, output, "BATch - certutil.exe", True)
# Write resulting expect file
def save_expect(self, mode=''):
port = '0'
cmd = ""
file = ""
infilename = ""
infile = ""
if mode == "telnet":
port = "23"
#cmd = "telnet -l $username $ip"
cmd = "telnet $ip"
file = self.telnet_file
verbose_msg("Telnet filename: %s" % self.telnet_filename)
elif mode == "winexe":
cmd = "winexe -U $username%$password //$ip cmd.exe"
file = self.winexe_file
verbose_msg("WinEXE filename: %s" % self.winexe_filename)
else:
error_exit("Unexpected mode: %s" % mode)
infilename = self.output_filename
infile = self.output_file
output = ("""#!/usr/bin/expect -f
set timeout 10
set ip [lindex $argv 0]
#set port {0}
set username [lindex $argv 1]
set password [lindex $argv 2]
set file_out {1}
set file_in {2}
set prompt "C:"
## Read in command arguments
if {{ [llength $argv] < 3 }} {{
set name [file tail $argv0]
send_user "Usage: ./$name <ip> <username> <password>\\n"; exit 1
}}
## Check to see if the input file is there
if {{ ! [file exist $file_in] }} {{
send_user "\\n\\n\\[!\\] $file_in is missing\\n"; exit 1
}}
## Connect
send_user "\\n"
spawn {3}
send_user "\\n"
""").format(port, infilename, infile, cmd)
if mode == "telnet":
output += ("""## If there is a user name prompt (as -l doesn't always work)
expect "login: " { send "$username\\r" }
## Wait for password prompt
expect {
"password: " { send "$password\\r" }
timeout { send_user "\\n\\n\\[!\\] Failed to get password prompt\\n"; exit 1 }
}
""")
output += ("""## Move to a commonly writeable folder
expect "$prompt" { send "cd %TEMP%\\r" }
## Test write access
set rand [ expr floor( rand() * 999900 ) ]
expect "$prompt" { send "echo $rand>$file_out\\r" }
expect "$prompt" { send "type $file_out\\r" }
expect {
"$rand" { send_user "\\n\\n\\[i\\] Writeable folder!\\n" }
timeout { send_user "\\n\\n\\[!\\] Failed to write out\\n"; exit 1 }
}
""")
if mode == "telnet":
output += ("""## Restore prompt
expect "$prompt" { send "\\r\\n" }
""")
output += ("""## Clean up
expect "$prompt" {{ send "del /F $file_out\\r" }}
## Read in our file
set f [open "$file_in"]
set data [read $f]
close $f
## Set counters
set i 0
set total [llength [split $data \\n]]
## For each line, wait for a prompt
foreach line [ split $data \\n ] {{
## Skip over empty lines
if {{ $line eq {{}} }} continue
## Increase counter
incr i
## Double carriage return here (don't ask)
expect "$prompt" {{ send "$line\\r\\r" }}
## Fix a telnet issues due to its output (don't ask) - progress isn't required
expect "$prompt" {{ send_user " (Progress: $i/$total)\\n" }}
}}
## Show output
#expect "$prompt" {{ send "dir {0}" }}
send_user "\\n\\n\[i\] Done\\n"
## Start
#expect "$prompt" {{ send "start /wait /b {0}" }}
""").format(self.exe_filename)
if mode == "telnet":
output += ("""## Restore prompt
expect "$prompt" { send "\\r\\n" }
""")
output += ("""## Give control back to user afterwards
interact
""")
# Write file out
self.write_file(file, output, "Expect", True)
# Make the file executable
os.chmod(file, 0o755)
# Write output
def write_file(self, filepath, contents, type, overwrite=True):
# Do we need to HTML encode it?
if encode:
contents = urllib.parse.quote_plus(contents).replace("%0D%0A", "\r\n")
if os.path.isfile(filepath) and overwrite:
verbose_msg("File already exists. Overwriting %s" % filepath)
# Try and write the file out to disk
try:
if overwrite:
f = open(filepath, 'w')
else:
f = open(filepath, 'a')
f.write(contents)
f.close
if overwrite:
success_msg("Successfully wrote (%s) %s" % (type, os.path.abspath(filepath)))
except:
error_msg("A problem occurred while writing (%s)" % filepath)
# Main action
def run(self):
# Read binary data (file or STDIN?)
if self.exe_file != None:
# If there is a EXE input, check its valid
self.check_exe()
# If we are to compress, now is the time!
if compress:
self.compress_exe()
self.read_bin_file()
else:
self.read_bin_stdin()
# If we are to compress, now is the time & re-read it in
if compress:
self.compress_exe()
self.read_bin_file()
# Make BATch file (DEBUG.exe)
if self.method == "1":
self.check_bat_size()
self.bin_to_bat()
# Make BATch file (certutil.exe)
if self.method == "2":
# Feedback for the user, to know where they are
verbose_msg('Converting to BATch (certutil.exe)')
self.bin_to_posh()
self.save_certutil_bat()
# Make PoSh file
if self.method == "3":
# Feedback for the user, to know where they are
verbose_msg('Converting to PoSh')
self.bin_to_posh()
self.save_posh()
# Make Expect/Telnet file
if telnet:
# Are we to make a telnet file (bat)?
if self.output_file != None:
if self.method == 1:
self.telnet_filename = "%s-bat-telnet" % (self.short_file)
self.telnet_file = os.path.abspath(self.output_file.replace(self.output_filename, self.telnet_filename))
self.save_expect('telnet')
# Are we to make a telnet file (PoSh)?
if self.posh_file != None:
self.telnet_filename = "%s-posh-telnet" % (self.short_file)
self.telnet_file = os.path.abspath(self.output_file.replace(self.output_filename, self.telnet_filename))
self.save_expect('telnet')
# Make Expect/WinEXE file
if winexe:
# Are we to make a winexe file (bat)?
if self.bat_file != None:
self.winexe_filename = "%s-bat-winexe" % (self.short_file)
self.winexe_file = os.path.abspath(self.output_file.replace(self.output_filename, self.winexe_filename))
self.save_expect('winexe')
# Are we to make a winexe file (PoSh)?
if self.posh_file != None:
self.winexe_filename = "%s-posh-winexe" % (self.short_file)
self.winexe_file = os.path.abspath(self.output_file.replace(self.output_filename, self.winexe_filename))
self.save_expect('winexe')
#########################
# End BinaryInput class #
#########################
signal.signal(signal.SIGINT, signal_handler)
################
# Main Program #
################
# Only run if we are being used as stand-alone script
if __name__ == "__main__":
# Display banner
banner_msg('exe2hex v%s' % version)
# Configure command-line option parsing
parser = OptionParser()
parser.add_option("-x", dest="exe",
help="The EXE binary file to convert", metavar="EXE")
parser.add_option("-s", dest="stdin",
help="Read from STDIN", action="store_true", metavar="STDIN")
parser.add_option("-m", dest="method",
help="""METHOD to convert the EXE:\t\t\t
1 - DEBUG.exe method (.bat) - x86\t\t
2 - certutil.exe method (.bat) - x86/x64 (DEFAULT)\t
3 - PowerShell method (.cmd) - x86/x64""",
default='2',
choices=['1','2','3'],
metavar="METHOD")
parser.add_option("-o", dest="output_file",
help="Output file", metavar="output")
parser.add_option("-e", dest="encode", default=False,
help="URL encode the output", action="store_true", metavar="ENCODE")
parser.add_option("-r", dest="prefix", default='',
help="pRefix - text to add before the command on each line", metavar="TEXT")
parser.add_option("-f", dest="suffix", default='',
help="suFfix - text to add after the command on each line", metavar="TEXT")
parser.add_option("-l", dest="hex_len", default=128,
help="Maximum HEX values per line", metavar="INT")
parser.add_option("-c", dest="compress", default=False,
help="Clones and compress the file before converting (-cc for higher compression)",
action="count", metavar="COMPRESS")
parser.add_option("-t", dest="telnet", default=False,
help="Create a Expect file, to automate to a Telnet session.",
action="store_true", metavar="TELNET")
parser.add_option("-w", dest="winexe", default=False,
help="Create a Expect file, to automate to a WinEXE session.",
action="store_true", metavar="WINEXE")
parser.add_option("-v", dest="verbose", default=False,
help="Enable verbose mode", action="store_true", metavar="VERBOSE")
# Store command-line options and arguments in variables
(options, args) = parser.parse_args()
exe = options.exe
stdin = options.stdin
method = options.method
output_file = options.output_file
encode = options.encode
prefix = options.prefix
suffix = options.suffix
try:
hex_len = int(options.hex_len)
except:
error_exit('Invalid length for -l %s' % options.hex_len)
compress = options.compress
telnet = options.telnet
winexe = options.winexe
verbose = options.verbose
# Being helpful if they haven't read -h...
if len(sys.argv) == 2:
exe = sys.argv[1]
print('')
notification_msg("Next time use \"-x\". e.g.: %s -x %s" % (sys.argv[0], exe))
print('')
# Are there any arguments?
elif len(sys.argv) <= 1:
print('')
print("Encodes an executable binary file into ASCII text format")
print("Restore using different methods (BATch or PoSh)")
print('')
print("Quick Guide:")
print(" + Input binary file with -s or -x")
print(" + Output with -o")
print("Example:")
print(" $ %s -x /usr/share/windows-binaries/sbd.exe" % sys.argv[0])
print(" $ %s -x /usr/share/windows-binaries/nc.exe -m 2 -o /var/www/html/nc.txt -cc" % sys.argv[0])
print(" $ cat /usr/share/windows-binaries/whoami.exe | %s -s -m 3 -o ps.cmd" % sys.argv[0])
print('')
print('--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---')
print('')
parser.print_help()
sys.exit(1)
# Any input methods?
if exe == None and stdin == None:
error_exit("Missing a executable file (-x <file>) or STDIN input (-s)")
# Too many input methods?
if exe != None and stdin != None:
error_exit('Cannot use both a file and STDIN for inputs at the same time')
# If output file was not provided, create one based on the selected method
if output_file == None:
if method == "1":
exe_filename = os.path.splitext(os.path.basename(exe))[0]
output_file = '%s.bat' % os.path.abspath(exe_filename)
notification_msg("Outputting to %s (BATch - DEBUG.exe)" % (output_file))
if method == "2":
exe_filename = os.path.splitext(os.path.basename(exe))[0]
output_file = '%s.bat' % os.path.abspath(exe_filename)
notification_msg("Outputting to %s (BATch - certutil.exe)" % (output_file))
if method == "3":
exe_filename = os.path.splitext(os.path.basename(exe))[0]
output_file = '%s.cmd' % os.path.abspath(exe_filename)
notification_msg("Outputting to %s (PoSh)" % (output_file))
# Is someone going to overwrite what they put in?
if stdin != None and (exe == output_file):
error_exit('Cannot use the same input as output')
# Read in file information
x = BinaryInput(exe, output_file, method)
# GO!
x.run()