mirror of
https://github.com/reactos/reactos.git
synced 2025-06-24 17:59:54 +00:00
[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). svn path=/trunk/; revision=52618
This commit is contained in:
parent
d730393e07
commit
c93b41ab3f
3 changed files with 123 additions and 17 deletions
|
@ -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)
|
||||
|
|
|
@ -244,6 +244,11 @@ C_ASSERT(HEAP_CREATE_VALID_MASK == 0x0007F0FF);
|
|||
//
|
||||
#define RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE 4
|
||||
|
||||
//
|
||||
// RtlImageNtHeaderEx Flags
|
||||
//
|
||||
#define RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK 0x00000001
|
||||
|
||||
//
|
||||
// Codepages
|
||||
//
|
||||
|
|
|
@ -120,36 +120,137 @@ LdrVerifyMappedImageMatchesChecksum(
|
|||
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue