def __adjust_resource_table(self, header_offset, raw_offset_for_directory_header): resource_table_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_RESOURCE_TABLE_RVA) original_raw_offset_for_resource_table = Win32BinaryUtils.convert_rva_to_raw(self.binary_data, header_offset, resource_table_rva) raw_offset_for_current_directory = None # Function being called for the first time if raw_offset_for_directory_header != 0: raw_offset_for_current_directory = raw_offset_for_directory_header else: raw_offset_for_current_directory = original_raw_offset_for_resource_table raw_offset_for_current_directory_entry = raw_offset_for_current_directory + Win32BinaryOffsetsAndSizes.OFFSET_TO_FIRST_DIRECTORY_ENTRY_WITHIN_RESOURCE_DIRECTORY_HEADER number_of_named_entries = MultiByteHandler.get_word_given_offset(self.binary_data, raw_offset_for_current_directory + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_NAMED_ENTRIES_WITHIN_RESOURCE_DIRECTORY_HEADER) number_of_id_entries = MultiByteHandler.get_word_given_offset(self.binary_data, raw_offset_for_current_directory + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_ID_ENTRIES_WITHIN_RESOURCE_DIRECTORY_HEADER) for entry_index in range(0, number_of_named_entries + number_of_id_entries): offset_to_directory_or_data_entry = MultiByteHandler.get_dword_given_offset(self.binary_data, raw_offset_for_current_directory_entry + 0x4) # print("Offset to directory or data entry:" + hex(offset_to_directory_or_data_entry)) if offset_to_directory_or_data_entry & 0x80000000 == 0x80000000: # It is a directory so we call this function again self.__adjust_resource_table(header_offset, original_raw_offset_for_resource_table + offset_to_directory_or_data_entry & 0x7FFFFFFF) else: resource_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, original_raw_offset_for_resource_table + offset_to_directory_or_data_entry) MultiByteHandler.set_dword_given_offset(self.binary_data, original_raw_offset_for_resource_table + offset_to_directory_or_data_entry, resource_rva + self.rva_delta) raw_offset_for_current_directory_entry += 0x8
def get_raw_offset_for_header_of_section_containing_given_rva( binary, header_offset, rva): number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset( binary, number_of_sections_offset) current_header_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BEGINNING_OF_SECTION_HEADERS for section_index in range(0, number_of_sections): virtual_section_size_offset = current_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_VIRTUAL_SIZE_WITHIN_SECTION_HEADER virtual_section_size = MultiByteHandler.get_dword_given_offset( binary, virtual_section_size_offset) virtual_section_rva_offset = current_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER virtual_section_rva = MultiByteHandler.get_dword_given_offset( binary, virtual_section_rva_offset) virtual_end_of_section_rva = virtual_section_rva + virtual_section_size if (rva >= virtual_section_rva) and (rva < virtual_end_of_section_rva): return (section_index, current_header_offset) current_header_offset += Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER return (None, None)
def compute_checksum(binary_data, header_offset): # Clear checksum image_checksum_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_CHECKSUM # checksum = MultiByteHandler.get_dword_given_offset(self.binary, image_checksum_offset) MultiByteHandler.set_dword_given_offset(binary_data, image_checksum_offset, 0x0) checksum = 0x0 word_index = 0x0 has_odd_byte = True if len( binary_data ) % Win32BinaryOffsetsAndSizes.CHECKSUM_COMPUTATION_UNIT == 1 else False while word_index < len(binary_data): if word_index == image_checksum_offset: word_index += Win32BinaryOffsetsAndSizes.CHECKSUM_SIZE else: checksum += MultiByteHandler.get_word_given_offset( binary_data, word_index) checksum & GenericConstants.DWORD_MASK # checksum += (checksum >> Win32BinaryOffsetsAndSizes.CHECKSUM_COMPUTATION_UNIT) word_index += Win32BinaryOffsetsAndSizes.CHECKSUM_COMPUTATION_UNIT if has_odd_byte: checksum += binary_data[-1] checksum = ( checksum >> Win32BinaryOffsetsAndSizes.CHECKSUM_COMPUTATION_UNIT * GenericConstants.BITS_PER_BYTE) + (checksum & 0xFFFF) checksum += ( checksum >> Win32BinaryOffsetsAndSizes.CHECKSUM_COMPUTATION_UNIT * GenericConstants.BITS_PER_BYTE) checksum = (checksum & 0xFFFF) checksum += len(binary_data) return checksum
def __adjust_base_relocation_table(self, header_offset): offset_to_base_relocation_table_rva_within_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_RELOCATION_TABLE_RVA base_relocation_table_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, offset_to_base_relocation_table_rva_within_header) if base_relocation_table_rva == 0x0: return offset_to_base_relocation_table_size = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_RELOCATION_TABLE_SIZE base_relocation_table_size = MultiByteHandler.get_dword_given_offset(self.binary_data, offset_to_base_relocation_table_size) base_relocation_table_raw = Win32BinaryUtils.convert_rva_to_raw(self.binary_data, header_offset, base_relocation_table_rva) current_base_relocation_table_raw = base_relocation_table_raw while current_base_relocation_table_raw < base_relocation_table_raw + base_relocation_table_size: rva_of_block = MultiByteHandler.get_dword_given_offset(self.binary_data, current_base_relocation_table_raw) size_of_block = MultiByteHandler.get_dword_given_offset(self.binary_data, current_base_relocation_table_raw + 0x4) if not Win32BinaryUtils.rva_is_after_entrypoint_and_requires_change(self.binary_data, header_offset, rva_of_block): current_base_relocation_table_raw += size_of_block continue type_rva_offset = current_base_relocation_table_raw + 0x8 #Type RVA entries start two dwords after the beginning of the block number_of_type_rva_entries = (int)((size_of_block - 0x8)/0x2) for type_rva_index in range(0, number_of_type_rva_entries): type_rva = MultiByteHandler.get_word_given_offset(self.binary_data, type_rva_offset) if type_rva != 0x0: MultiByteHandler.set_word_given_offset(self.binary_data, type_rva_offset, type_rva + self.rva_delta) type_rva_offset += 0x2 MultiByteHandler.set_dword_given_offset(self.binary_data, current_base_relocation_table_raw, rva_of_block + self.rva_delta) current_base_relocation_table_raw += size_of_block # Adjusting RVA on Data Directories header. MultiByteHandler.set_dword_given_offset(self.binary_data, offset_to_base_relocation_table_rva_within_header, base_relocation_table_rva + self.rva_delta)
def __adjust_section_headers(self, header_offset): number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset( self.binary_data, number_of_sections_offset) # Moving to the next section header current_section_header_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BEGINNING_OF_SECTION_HEADERS for section_index in range(0, number_of_sections): if self.rva_delta != 0: virtual_section_rva_offset = current_section_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER virtual_section_rva = MultiByteHandler.get_dword_given_offset( self.binary_data, current_section_header_offset + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER) virtual_section_rva = ( virtual_section_rva + self.rva_delta) if virtual_section_rva != 0 else 0 MultiByteHandler.set_dword_given_offset( self.binary_data, virtual_section_rva_offset, virtual_section_rva) raw_section_offset_offset = current_section_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RAW_OFFSET_WITHIN_SECTION_HEADER raw_section_offset = MultiByteHandler.get_dword_given_offset( self.binary_data, raw_section_offset_offset) raw_section_offset = ( raw_section_offset + Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER + self.header_padding) if raw_section_offset != 0 else 0 MultiByteHandler.set_dword_given_offset(self.binary_data, raw_section_offset_offset, raw_section_offset) current_section_header_offset += Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER
def get_raw_offset_for_last_section_header(binary_data, header_offset): number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset( binary_data, number_of_sections_offset) # Jumping to last header beginning_of_last_section_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BEGINNING_OF_SECTION_HEADERS beginning_of_last_section_header += Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER * ( number_of_sections - 1) return beginning_of_last_section_header
def get_raw_offset_and_size_for_last_section(binary_data, header_offset): raw_offset_for_last_section_header = Win32BinaryUtils.get_raw_offset_for_last_section_header( binary_data, header_offset) raw_offset_for_last_section = MultiByteHandler.get_word_given_offset( binary_data, raw_offset_for_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RAW_OFFSET_WITHIN_SECTION_HEADER) raw_size_for_last_section = MultiByteHandler.get_dword_given_offset( binary_data, raw_offset_for_last_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RAW_SIZE_WITHIN_SECTION_HEADER) return (raw_offset_for_last_section, raw_size_for_last_section)
def __adjust_standard_coff_fields_and_coff_header(self, header_offset, size_of_new_section): # Set size of code size_of_code_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SIZE_OF_CODE current_size_of_code = MultiByteHandler.get_dword_given_offset( self.binary_data, size_of_code_offset) MultiByteHandler.set_dword_given_offset( self.binary_data, size_of_code_offset, current_size_of_code + size_of_new_section) # Adjust number of sections number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset( self.binary_data, number_of_sections_offset) number_of_sections += 1 MultiByteHandler.set_word_given_offset(self.binary_data, number_of_sections_offset, number_of_sections) if self.rva_delta != 0: # Adjust address of entrypoint address_of_entrypoint = MultiByteHandler.get_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_ENTRYPOINT_RVA) address_of_entrypoint += self.rva_delta MultiByteHandler.set_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_ENTRYPOINT_RVA, address_of_entrypoint) # Adjust BaseOfCode base_of_code_rva = MultiByteHandler.get_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_OF_CODE_RVA) base_of_code_rva += self.rva_delta MultiByteHandler.set_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_OF_CODE_RVA, base_of_code_rva) # Adjust BaseOfData base_of_data_rva = MultiByteHandler.get_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_OF_DATA_RVA) base_of_data_rva += self.rva_delta MultiByteHandler.set_dword_given_offset( self.binary_data, header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BASE_OF_DATA_RVA, base_of_data_rva)
def get_rva_and_virtual_size_for_last_section(binary, header_offset): number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset( binary, number_of_sections_offset) #Jumping to last header beginning_of_section_header = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_BEGINNING_OF_SECTION_HEADERS beginning_of_section_header += Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER * ( number_of_sections - 1) rva_for_last_section = MultiByteHandler.get_dword_given_offset( binary, beginning_of_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER) virtual_size_of_last_section = MultiByteHandler.get_dword_given_offset( binary, beginning_of_section_header + Win32BinaryOffsetsAndSizes. OFFSET_TO_SECTION_VIRTUAL_SIZE_WITHIN_SECTION_HEADER) return (rva_for_last_section, virtual_size_of_last_section)
def __adjust_section_headers(self, header_offset): 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) section_header_index_and_offset = Win32BinaryUtils.get_raw_offset_for_header_of_section_containing_given_rva(self.binary_data, header_offset, entrypoint_rva) offset_of_header_of_section_containing_entrypoint = section_header_index_and_offset [1] # Set raw section size for shellcoded section raw_section_size_offset = offset_of_header_of_section_containing_entrypoint + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RAW_SIZE_WITHIN_SECTION_HEADER raw_section_size = MultiByteHandler.get_dword_given_offset(self.binary_data, raw_section_size_offset) raw_section_size += len(self.shell_code) MultiByteHandler.set_dword_given_offset(self.binary_data, raw_section_size_offset, raw_section_size) # Set virtual section size for shellcoded section virtual_section_size_offset = offset_of_header_of_section_containing_entrypoint + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_VIRTUAL_SIZE_WITHIN_SECTION_HEADER virtual_section_size = MultiByteHandler.get_dword_given_offset(self.binary_data, virtual_section_size_offset) virtual_section_size += len(self.shell_code) MultiByteHandler.set_dword_given_offset(self.binary_data, virtual_section_size_offset, virtual_section_size) number_of_sections_offset = header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_NUMBER_OF_SECTIONS number_of_sections = MultiByteHandler.get_word_given_offset(self.binary_data, number_of_sections_offset) remaining_sections_after_shell_code_section = number_of_sections - (section_header_index_and_offset[0] + 1) # Moving to the next section header current_section_header_offset = offset_of_header_of_section_containing_entrypoint + Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER for section_index in range(0, remaining_sections_after_shell_code_section): if self.rva_delta != 0: virtual_section_rva_offset = current_section_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER virtual_section_rva = MultiByteHandler.get_dword_given_offset(self.binary_data, current_section_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RVA_WITHIN_SECTION_HEADER) virtual_section_rva = (virtual_section_rva + self.rva_delta) if virtual_section_rva != 0 else 0 MultiByteHandler.set_dword_given_offset(self.binary_data, virtual_section_rva_offset, virtual_section_rva) raw_section_offset_offset = current_section_header_offset + Win32BinaryOffsetsAndSizes.OFFSET_TO_SECTION_RAW_OFFSET_WITHIN_SECTION_HEADER raw_section_offset = MultiByteHandler.get_dword_given_offset(self.binary_data, raw_section_offset_offset) raw_section_offset = (raw_section_offset + len(self.shell_code)) if raw_section_offset !=0 else 0 MultiByteHandler.set_dword_given_offset(self.binary_data, raw_section_offset_offset, raw_section_offset) current_section_header_offset += Win32BinaryOffsetsAndSizes.SIZE_OF_SECTION_HEADER