[PATCH 0/1] MR10295: Fix ImageGetDigestStream
ImageGetDigestStream is used to hash the "important" parts of PE files. After rigorous experimentation we discovered these changes were sufficient to get identical hashes (and thereby signatures) on Windows and Wine. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10295
From: Trent Waddington <trent.waddington@tensorworks.com.au> --- dlls/imagehlp/integrity.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/dlls/imagehlp/integrity.c b/dlls/imagehlp/integrity.c index ebad7001548..ad31e0a57ae 100644 --- a/dlls/imagehlp/integrity.c +++ b/dlls/imagehlp/integrity.c @@ -830,10 +830,11 @@ BOOL WINAPI ImageGetDigestStream( nt_hdr = (IMAGE_NT_HEADERS *)(map + offset); if( nt_hdr->Signature != IMAGE_NT_SIGNATURE ) goto invalid_parameter; - /* It's clear why the checksum is cleared, but why only these size headers? - */ - nt_hdr->OptionalHeader.SizeOfInitializedData = 0; - nt_hdr->OptionalHeader.SizeOfImage = 0; + + // Set the IMAGE_FILE_SECURITY_DIRECTORY values to zero as Windows does not include them. + nt_hdr->OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY].Size = 0; + nt_hdr->OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY].VirtualAddress = 0; + nt_hdr->OptionalHeader.CheckSum = 0; size = sizeof(nt_hdr->Signature) + sizeof(nt_hdr->FileHeader) + nt_hdr->FileHeader.SizeOfOptionalHeader; @@ -854,19 +855,42 @@ BOOL WINAPI ImageGetDigestStream( section_headers = (IMAGE_SECTION_HEADER *)(map + offset); IMAGEHLP_ReportCodeSections( section_headers, num_sections, map, fileSize, DigestFunction, DigestHandle ); + + IMAGEHLP_ReportSection( section_headers, num_sections, ".rdata", + map, fileSize, DigestFunction, DigestHandle ); + IMAGEHLP_ReportSection( section_headers, num_sections, ".data", map, fileSize, DigestFunction, DigestHandle ); - IMAGEHLP_ReportSection( section_headers, num_sections, ".rdata", + + IMAGEHLP_ReportSection( section_headers, num_sections, ".pdata", + map, fileSize, DigestFunction, DigestHandle ); + + IMAGEHLP_ReportSection( section_headers, num_sections, ".didat", map, fileSize, DigestFunction, DigestHandle ); + IMAGEHLP_ReportImportSection( section_headers, num_sections, map, fileSize, DigestLevel, DigestFunction, DigestHandle ); + + IMAGEHLP_ReportSection( section_headers, num_sections, ".tls", + map, fileSize, DigestFunction, DigestHandle ); + + IMAGEHLP_ReportSection( section_headers, num_sections, ".00cfg", + map, fileSize, DigestFunction, DigestHandle ); + + IMAGEHLP_ReportSection( section_headers, num_sections, "_RDATA", + map, fileSize, DigestFunction, DigestHandle ); + if( DigestLevel & CERT_PE_IMAGE_DIGEST_DEBUG_INFO ) IMAGEHLP_ReportSection( section_headers, num_sections, ".debug", map, fileSize, DigestFunction, DigestHandle ); + if( DigestLevel & CERT_PE_IMAGE_DIGEST_RESOURCES ) IMAGEHLP_ReportSection( section_headers, num_sections, ".rsrc", map, fileSize, DigestFunction, DigestHandle ); + IMAGEHLP_ReportSection( section_headers, num_sections, ".reloc", + map, fileSize, DigestFunction, DigestHandle ); + end: if( map ) UnmapViewOfFile( map ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10295
This needs some tests to cover the changes you make. You could expand the existing tests by adding data for the sections you add in this patch. Also note that this patch causes failures in the existing tests that should be addressed. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10295#note_131796
On Wed Mar 11 09:50:11 2026 +0000, Hans Leidekker wrote:
This needs some tests to cover the changes you make. You could expand the existing tests by adding data for the sections you add in this patch. Also note that this patch causes failures in the existing tests that should be addressed. and to extend Hans' comments:
* it looks very unlikely that digest is computed given a list of sections ordered by name; PE image format doesn't imply anything on the name of the sections ; it's a convention adopted by the toolchain you're using * so it's very likely that's the order you've implemented is the default order generated by toolchain you've used * expanding the tests by changing the order of sections shall demonstrate this * and also follow coding style (eg no c++ comments) side note: * current implementation blinding assumes image has same bitness as the DLL, which is wrong (IIRC native always supports 32 and 64bit images) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10295#note_131800
participants (4)
-
eric pouech (@epo) -
Hans Leidekker (@hans) -
Trent Waddington -
Trent Waddington (@trent.waddington)