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()
print 'New entropy:', round(entropy(h, l), 2) ######################################################################## # Make the IAT ######################################################################## iat = IatTable(base_offset_iat) iat.add_function('kernel32.dll', 'TerminateProcess') iat.add_function('user32.dll', 'MessageBoxA') iat_table = iat.pack() ######################################################################## # Make the sections ######################################################################## section_code = PE.structDictionary(PE.IMAGE_SECTION_HEADER) section_code['Name'] = '.text' section_code['Misc_VirtualSize'] = len(code) section_code['VirtualAddress'] = base_offset_code section_code['SizeOfRawData'] = PE.align_value(len(code), 0x200) section_code['PointerToRawData'] = PE.align_value( PE.structSize(PE.IMAGE_DOS_HEADER) + PE.structSize(PE.IMAGE_NT_HEADERS) + PE.structSize(PE.IMAGE_FILE_HEADER) + PE.structSize(PE.IMAGE_OPTIONAL_HEADER) + PE.structSize(PE.IMAGE_DATA_DIRECTORY) * PE.IMAGE_NUMBEROF_DIRECTORY_ENTRIES + PE.structSize(PE.IMAGE_SECTION_HEADER) * nb_sections, 0x200) section_code[ 'Characteristics'] = PE.IMAGE_SCN_CNT_CODE | PE.IMAGE_SCN_MEM_EXECUTE | PE.IMAGE_SCN_MEM_READ section_iat = PE.structDictionary(PE.IMAGE_SECTION_HEADER)