def pack(self): # names table number_of_dll = len(self.functions) names_table_base = self.base_address + PE.structSize(PE.IMAGE_IMPORT_DESCRIPTOR)*(number_of_dll + 1) # for the last null value names_table = '' names_table_offset = {} offset = names_table_base tmp = '' for (dll_name, functions) in self.functions.items(): # for each dll names_table_offset[dll_name] = offset tmp = dll_name + '\x00' names_table += tmp offset += len(tmp) for function_name in functions: # for each function in this dll names_table_offset[function_name] = offset tmp = '\x00\x00' + function_name + '\x00' names_table += tmp offset += len(tmp) # Original First Thunk table original_first_thunk_table = '' original_first_thunk_base = offset original_first_thunk_offset = {} for (dll_name, functions) in self.functions.items(): # for each dll original_first_thunk_offset[dll_name] = offset for function_name in functions: # for each function in this dll tmp = struct.pack('<I', names_table_offset[function_name]) original_first_thunk_table += tmp offset += len(tmp) original_first_thunk_table += '\x00\x00\x00\x00' offset += 4 # First Thunk Table first_thunk_table = original_first_thunk_table first_thunk_base = offset first_thunk_offset = {} for (dll_name, offset_in_oft) in original_first_thunk_offset.items(): first_thunk_offset[dll_name] = offset_in_oft - original_first_thunk_base + first_thunk_base # IAT Table iat_table = '' for (dll_name, functions) in self.functions.items(): # for each dll function = PE.structDictionary(PE.IMAGE_IMPORT_DESCRIPTOR) function['OriginalFirstThunk'] = original_first_thunk_offset[dll_name] function['TimeDateStamp'] = 0 function['ForwarderChain'] = 0 function['Name'] = names_table_offset[dll_name] function['FirstThunk'] = first_thunk_offset[dll_name] iat_table += PE.packDictionary(PE.IMAGE_IMPORT_DESCRIPTOR, function) function['OriginalFirstThunk'] = 0 function['TimeDateStamp'] = 0 function['ForwarderChain'] = 0 function['Name'] = 0 function['FirstThunk'] = 0 iat_table += PE.packDictionary(PE.IMAGE_IMPORT_DESCRIPTOR, function) iat_table += names_table iat_table += original_first_thunk_table iat_table += first_thunk_table return iat_table
def pack(self, stub_path, output_path, input_file): f = open(stub_path, 'rb') stub_file = f.read() f.close() # encrypt the input key_str = '' for i in range(4): key_str += chr(random.randint(1, 0xFF)) input_encrypted = self.xor_long(input_file, key_str) input_file = key_str + input_encrypted # increment the number of sections dos_header = PE.unpack(PE.IMAGE_DOS_HEADER, stub_file) peHeader_offset = dos_header['e_lfanew'] numberOfSections_offset = peHeader_offset + 0x6 numberOfSections = struct.unpack( '<H', stub_file[numberOfSections_offset:numberOfSections_offset + 2])[0] numberOfSections = numberOfSections + 1 stub_file = stub_file[:numberOfSections_offset] + struct.pack( '<H', numberOfSections) + stub_file[numberOfSections_offset + 2:] # add the section header sectionHeader_offset = peHeader_offset + 0xF8 last_section_offset = sectionHeader_offset + ( (numberOfSections - 2) * 0x28) # last section print 'last section: {0:x}'.format(last_section_offset) last_section = PE.unpack(PE.IMAGE_SECTION_HEADER, stub_file[last_section_offset:]) new_section_header_offset = last_section_offset + 0x28 new_section = PE.structDictionary(PE.IMAGE_SECTION_HEADER) new_section['Name'] = '.rsrc' new_section['Misc_VirtualSize'] = len(input_file) new_section['VirtualAddress'] = PE.align_value( last_section['VirtualAddress'] + last_section['SizeOfRawData'], 0x1000) new_section['SizeOfRawData'] = PE.align_value(len(input_file), 0x200) new_section['PointerToRawData'] = PE.align_value(len(stub_file), 0x200) new_section[ 'Characteristics'] = PE.IMAGE_SCN_CNT_INITIALIZED_DATA | PE.IMAGE_SCN_MEM_READ | PE.IMAGE_SCN_MEM_WRITE | PE.IMAGE_SCN_ALIGN_4BYTES stub_file = stub_file[:new_section_header_offset] + PE.packDictionary( PE.IMAGE_SECTION_HEADER, new_section) + stub_file[new_section_header_offset + 0x28:] # section jam stub_file += '\x00' * (new_section['PointerToRawData'] - len(stub_file)) # append the section stub_file += input_file padding = new_section['SizeOfRawData'] - len(input_file) stub_file += '\x00' * padding # increment SizeOfImage optionalHeader_offset = peHeader_offset + 0x18 optionalHeader_size = PE.structSize(PE.IMAGE_OPTIONAL_HEADER) optional_header = PE.unpack(PE.IMAGE_OPTIONAL_HEADER, stub_file[optionalHeader_offset:]) optional_header['SizeOfImage'] = PE.align_value( new_section['VirtualAddress'] + new_section['SizeOfRawData'], 0x1000) stub_file = stub_file[:optionalHeader_offset] + PE.packDictionary( PE.IMAGE_OPTIONAL_HEADER, optional_header) + stub_file[optionalHeader_offset + optionalHeader_size:] # save the file f = open(output_path, 'wb') f.write(stub_file) f.close()
optional_header['SizeOfHeapReserve'] = 0x100000 optional_header['SizeOfHeapCommit'] = 0x1000 optional_header['NumberOfRvaAndSizes'] = PE.IMAGE_NUMBEROF_DIRECTORY_ENTRIES data_directories = [] for i in range(PE.IMAGE_NUMBEROF_DIRECTORY_ENTRIES): data_directories.append(PE.structDictionary(PE.IMAGE_DATA_DIRECTORY)) data_directories[PE.IMAGE_DIRECTORY_ENTRY_IMPORT][ 'VirtualAddress'] = section_iat['VirtualAddress'] data_directories[ PE.IMAGE_DIRECTORY_ENTRY_IMPORT]['Size'] = section_iat['Misc_VirtualSize'] exe_file = open('stub.exe', 'wb') file_offset = 0 exe_file.write(PE.packDictionary(PE.IMAGE_DOS_HEADER, dos_header)) file_offset += PE.structSize(PE.IMAGE_DOS_HEADER) exe_file.write(PE.packDictionary(PE.IMAGE_NT_HEADERS, nt_headers)) file_offset += PE.structSize(PE.IMAGE_NT_HEADERS) exe_file.write(PE.packDictionary(PE.IMAGE_FILE_HEADER, file_header)) file_offset += PE.structSize(PE.IMAGE_FILE_HEADER) exe_file.write(PE.packDictionary(PE.IMAGE_OPTIONAL_HEADER, optional_header)) file_offset += PE.structSize(PE.IMAGE_OPTIONAL_HEADER) for data_directory in data_directories: exe_file.write(PE.packDictionary(PE.IMAGE_DATA_DIRECTORY, data_directory)) file_offset += PE.structSize(PE.IMAGE_DATA_DIRECTORY) exe_file.write(PE.packDictionary(PE.IMAGE_SECTION_HEADER, section_code)) file_offset += PE.structSize(PE.IMAGE_SECTION_HEADER) exe_file.write(PE.packDictionary(PE.IMAGE_SECTION_HEADER, section_iat)) file_offset += PE.structSize(PE.IMAGE_SECTION_HEADER)