Author: ion Date: Sun Jul 10 21:55:55 2011 New Revision: 52618
URL: http://svn.reactos.org/svn/reactos?rev=52618&view=rev Log: [NDK]: Add missing RtlImageNtHeaderEx flags. [RTL]: Implement RtlImageNtHeaderEx and make RtlImageNtHeader call it. This will result in much stricter (and correct) PE loading by default, and enable a flag which can do even stricter checks. [NTDLL]: Export RtlImageNtHeaderEx (maybe NTOS should export it too, not sure).
Modified: trunk/reactos/dll/ntdll/def/ntdll.pspec trunk/reactos/include/ndk/rtltypes.h trunk/reactos/lib/rtl/image.c
Modified: trunk/reactos/dll/ntdll/def/ntdll.pspec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.pspec?r... ============================================================================== --- trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] Sun Jul 10 21:55:55 2011 @@ -691,7 +691,7 @@ @ stdcall RtlIdentifierAuthoritySid(ptr) @ stdcall RtlImageDirectoryEntryToData(long long long ptr) @ stdcall RtlImageNtHeader(long) -//@ stdcall RtlImageNtHeaderEx +@ stdcall RtlImageNtHeaderEx(long ptr double ptr) @ stdcall RtlImageRvaToSection(ptr long long) @ stdcall RtlImageRvaToVa(ptr long long ptr) @ stdcall RtlImpersonateSelf(long)
Modified: trunk/reactos/include/ndk/rtltypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtltypes.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] (original) +++ trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] Sun Jul 10 21:55:55 2011 @@ -243,6 +243,11 @@ // RtlFindCharInUnicodeString Flags // #define RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE 4 + +// +// RtlImageNtHeaderEx Flags +// +#define RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK 0x00000001
// // Codepages
Modified: trunk/reactos/lib/rtl/image.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/image.c?rev=52618&a... ============================================================================== --- trunk/reactos/lib/rtl/image.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/image.c [iso-8859-1] Sun Jul 10 21:55:55 2011 @@ -120,6 +120,13 @@
return (BOOLEAN)(CalcSum == HeaderSum); #else + /* + * FIXME: Warning, this violates the PE standard and makes ReactOS drivers + * and other system code when normally on Windows they would not, since + * we do not write the checksum in them. + * Our compilers should be made to write out the checksum and this function + * should be enabled as to reject badly checksummed code. + */ return TRUE; #endif } @@ -127,28 +134,122 @@ /* * @implemented */ +NTSTATUS +NTAPI +RtlImageNtHeaderEx(IN ULONG Flags, + IN PVOID Base, + IN ULONG64 Size, + OUT PIMAGE_NT_HEADERS *OutHeaders) +{ + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_DOS_HEADER DosHeader; + + /* You must want NT Headers, no? */ + if (!OutHeaders) return STATUS_INVALID_PARAMETER; + + /* Assume failure */ + *OutHeaders = NULL; + + /* Validate Flags */ + if (Flags &~ RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK) + { + DPRINT1("Invalid flag combination... check for new API flags?\n"); + return STATUS_INVALID_PARAMETER; + } + + /* Validate base */ + if (!(Base) || (Base == (PVOID)-1)) return STATUS_INVALID_PARAMETER; + + /* Check if the caller wants validation */ + if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK) + { + /* Make sure the image size is at least big enough for the DOS header */ + if (Size < sizeof(IMAGE_DOS_HEADER)) + { + DPRINT1("Size too small\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + } + + /* Check if the DOS Signature matches */ + DosHeader = Base; + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + /* Not a valid COFF */ + DPRINT1("Not an MZ file\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Check if the caller wants validation */ + if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK) + { + /* The offset should fit in the passsed-in size */ + if (DosHeader->e_lfanew >= Size) + { + /* Fail */ + DPRINT1("e_lfanew is larger than PE file\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* It shouldn't be past 4GB either */ + if (DosHeader->e_lfanew >= + (MAXULONG - sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER))) + { + /* Fail */ + DPRINT1("e_lfanew is larger than 4GB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* And the whole file shouldn't overflow past 4GB */ + if ((DosHeader->e_lfanew + + sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER)) >= Size) + { + /* Fail */ + DPRINT1("PE is larger than 4GB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + } + + /* The offset also can't be larger than 256MB, as a hard-coded check */ + if (DosHeader->e_lfanew >= (256 * 1024 * 1024)) + { + /* Fail */ + DPRINT1("PE offset is larger than 256MB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Now it's safe to get the NT Headers */ + NtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)Base + DosHeader->e_lfanew); + + /* Verify the PE Signature */ + if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + /* Fail */ + DPRINT1("PE signature missing\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Now return success and the NT header */ + *OutHeaders = NtHeaders; + return STATUS_SUCCESS; +} + +/* + * @implemented + */ PIMAGE_NT_HEADERS NTAPI -RtlImageNtHeader(IN PVOID BaseAddress) +RtlImageNtHeader(IN PVOID Base) { PIMAGE_NT_HEADERS NtHeader; - PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress; - - if (DosHeader && SWAPW(DosHeader->e_magic) != IMAGE_DOS_SIGNATURE) - { - DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader->e_magic)); - DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew))); - } - else - { - NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew)); - if (SWAPD(NtHeader->Signature) == IMAGE_NT_SIGNATURE) - return NtHeader; - } - - return NULL; -} - + + /* Call the new API */ + RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK, + Base, + 0, + &NtHeader); + return NtHeader; +}
/* * @implemented