From: David Collett Subject: [PATCH] kernel32: Adjust data directories in UpdateResource API. Message-Id: <1511413375-18914-1-git-send-email-david.collett@gmail.com> Date: Thu, 23 Nov 2017 16:02:55 +1100 When adding resources to a PE file using the UpdateResource API and the resource section is not the last section (i.e. we had to move existing sections), ensure any data directory entries pointing into moved sections is adjusted. Fixes issue where binaries commonly have relocations section after the resource section. If the resources section is extended, the base relocations data directory entry will no longer be valid and the binary will fail to be loaded (assuming relocation is required). Signed-off-by: David Collett --- dlls/kernel32/resource.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dlls/kernel32/resource.c b/dlls/kernel32/resource.c index c88c921..d526b39 100644 --- a/dlls/kernel32/resource.c +++ b/dlls/kernel32/resource.c @@ -1615,15 +1615,29 @@ static BOOL write_raw_resources( QUEUEDUPDATES *updates ) sec->SizeOfRawData = section_size; sec->Misc.VirtualSize = virtual_section_size; if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + DWORD i; nt64->OptionalHeader.SizeOfImage += rva_delta; nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = sec->VirtualAddress; nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = res_size.total_size; nt64->OptionalHeader.SizeOfInitializedData = get_init_data_size( write_map->base, mapping_size ); + + for (i=0; iOptionalHeader.NumberOfRvaAndSizes; i++) { + if (nt64->OptionalHeader.DataDirectory[i].VirtualAddress > sec->VirtualAddress) { + nt64->OptionalHeader.DataDirectory[i].VirtualAddress += rva_delta; + } + } } else { + DWORD i; nt->OptionalHeader.SizeOfImage += rva_delta; nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = sec->VirtualAddress; nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = res_size.total_size; nt->OptionalHeader.SizeOfInitializedData = get_init_data_size( write_map->base, mapping_size ); + + for (i=0; iOptionalHeader.NumberOfRvaAndSizes; i++) { + if (nt->OptionalHeader.DataDirectory[i].VirtualAddress > sec->VirtualAddress) { + nt->OptionalHeader.DataDirectory[i].VirtualAddress += rva_delta; + } + } } } -- 2.7.4