Alexandre Julliard : ntdll: Load the COR header directly from the file handle.

Alexandre Julliard julliard at winehq.org
Mon Jan 25 16:42:05 CST 2021


Module: wine
Branch: master
Commit: 7203ad0ecd06b451116fcfe3b08e4d620e853bd5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=7203ad0ecd06b451116fcfe3b08e4d620e853bd5

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jan 21 12:31:34 2021 +0100

ntdll: Load the COR header directly from the file handle.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/loader.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 10 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3f43062f9f8..fa757fefa90 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2016,11 +2016,49 @@ static BOOL convert_to_pe64( HMODULE module, const SECTION_IMAGE_INFORMATION *in
     NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, old_prot, &old_prot );
     return TRUE;
 }
+
+/* check COM header for ILONLY flag, ignoring runtime version */
+static BOOL get_cor_header( HANDLE file, const SECTION_IMAGE_INFORMATION *info, IMAGE_COR20_HEADER *cor )
+{
+    IMAGE_DOS_HEADER mz;
+    IMAGE_NT_HEADERS32 nt;
+    IO_STATUS_BLOCK io;
+    LARGE_INTEGER offset;
+    IMAGE_SECTION_HEADER sec[96];
+    unsigned int i, count;
+    DWORD va, size;
+
+    offset.QuadPart = 0;
+    if (NtReadFile( file, 0, NULL, NULL, &io, &mz, sizeof(mz), &offset, NULL )) return FALSE;
+    if (io.Information != sizeof(mz)) return FALSE;
+    if (mz.e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
+    offset.QuadPart = mz.e_lfanew;
+    if (NtReadFile( file, 0, NULL, NULL, &io, &nt, sizeof(nt), &offset, NULL )) return FALSE;
+    if (io.Information != sizeof(nt)) return FALSE;
+    if (nt.Signature != IMAGE_NT_SIGNATURE) return FALSE;
+    if (nt.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return FALSE;
+    va = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
+    size = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
+    if (!va || size < sizeof(*cor)) return FALSE;
+    offset.QuadPart = offsetof( IMAGE_NT_HEADERS32, OptionalHeader ) + nt.FileHeader.SizeOfOptionalHeader;
+    count = min( 96, nt.FileHeader.NumberOfSections );
+    if (NtReadFile( file, 0, NULL, NULL, &io, &sec, count * sizeof(*sec), &offset, NULL )) return FALSE;
+    if (io.Information != count * sizeof(*sec)) return FALSE;
+    for (i = 0; i < count; i++)
+    {
+        if (va < sec[i].VirtualAddress) continue;
+        if (sec[i].Misc.VirtualSize && va - sec[i].VirtualAddress >= sec[i].Misc.VirtualSize) continue;
+        offset.QuadPart = sec->PointerToRawData + va - sec[i].VirtualAddress;
+        if (NtReadFile( file, 0, NULL, NULL, &io, cor, sizeof(*cor), &offset, NULL )) return FALSE;
+        return (io.Information == sizeof(*cor));
+    }
+    return FALSE;
+}
 #endif
 
 /* On WoW64 setups, an image mapping can also be created for the other 32/64 CPU */
 /* but it cannot necessarily be loaded as a dll, so we need some additional checks */
-static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *info )
+static BOOL is_valid_binary( HANDLE file, const SECTION_IMAGE_INFORMATION *info )
 {
 #ifdef __i386__
     return info->Machine == IMAGE_FILE_MACHINE_I386;
@@ -2037,13 +2075,11 @@ static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *in
     if (!info->ImageContainsCode) return TRUE;
     if (!(info->u.ImageFlags & IMAGE_FLAGS_ComPlusNativeReady))
     {
-        /* check COM header directly, ignoring runtime version */
-        DWORD size;
-        const IMAGE_COR20_HEADER *cor_header = RtlImageDirectoryEntryToData( module, TRUE,
-                                                          IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &size );
-        if (!cor_header || !(cor_header->Flags & COMIMAGE_FLAGS_ILONLY)) return FALSE;
+        IMAGE_COR20_HEADER cor_header;
+        if (!get_cor_header( file, info, &cor_header )) return FALSE;
+        if (!(cor_header.Flags & COMIMAGE_FLAGS_ILONLY)) return FALSE;
     }
-    return convert_to_pe64( module, info );
+    return TRUE;
 #else
     return FALSE;  /* no wow64 support on other platforms */
 #endif
@@ -2267,8 +2303,6 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
                               SECTION_MAP_READ | SECTION_MAP_EXECUTE,
                               NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
-    NtClose( handle );
-
     if (!status)
     {
         if (*module)
@@ -2282,13 +2316,22 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
         if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
         NtClose( mapping );
     }
-    if (!status && !is_valid_binary( *module, image_info ))
+    if (!status && !is_valid_binary( handle, image_info ))
     {
         TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine );
         NtUnmapViewOfSection( NtCurrentProcess(), *module );
         *module = NULL;
         status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
     }
+#ifdef _WIN64
+    if (!status &&
+        image_info->Machine != IMAGE_FILE_MACHINE_AMD64 &&
+        image_info->Machine != IMAGE_FILE_MACHINE_ARM64)
+    {
+        if (!convert_to_pe64( *module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
+    }
+#endif
+    NtClose( handle );
     return status;
 }
 




More information about the wine-cvs mailing list