SUPR3HardenedMainImports-win.cpp revision d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45
/* $Id$ */
/** @file
* VirtualBox Support Library - Hardened Main, Windows Import Trickery.
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/initterm.h>
#include "SUPLibInternal.h"
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
do { static const char s_szWhere[] = a_szWhere; *(char *)(uintptr_t)(a_id) += 1; __debugbreak(); } while (0)
#else
#endif
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
typedef struct SUPHNTIMPFUNC
{
const char *pszName;
typedef SUPHNTIMPFUNC const *PCSUPHNTIMPFUNC;
typedef struct SUPHNTIMPSYSCALL
{
typedef SUPHNTIMPSYSCALL const *PCSUPHNTIMPSYSCALL;
typedef struct SUPHNTIMPDLL
{
/** @name Static data.
* @{ */
const wchar_t *pwszName;
const char *pszName;
/** Array running parallel to paImports if present. */
/** @} */
/** The image base. */
uint8_t const *pbImageBase;
/** The NT headers. */
/** The end of the section headers. */
/** The end of the image. */
/** Offset of the export directory. */
/** Size of the export directory. */
/** Exported functions and data by ordinal (RVAs). */
uint32_t const *paoffExports;
/** The number of exports. */
/** The number of exported names. */
/** Pointer to the array of exported names (RVAs to strings). */
uint32_t const *paoffNamedExports;
/** Array parallel to paoffNamedExports with the corresponding ordinals
* (indexes into paoffExports). */
uint16_t const *pau16NameOrdinals;
} SUPHNTIMPDLL;
typedef SUPHNTIMPDLL *PSUPHNTIMPDLL;
/*
* Declare assembly symbols.
*/
#include "import-template-ntdll.h"
#include "import-template-kernel32.h"
/*
* Import functions.
*/
static const SUPHNTIMPFUNC g_aSupNtImpNtDllFunctions[] =
{
#include "import-template-ntdll.h"
};
static const SUPHNTIMPFUNC g_aSupNtImpKernel32Functions[] =
{
#include "import-template-kernel32.h"
};
/*
* Syscalls in ntdll.
*/
static const SUPHNTIMPSYSCALL g_aSupNtImpNtDllSyscalls[] =
{
#ifdef RT_ARCH_AMD64
# define SUPHARNT_IMPORT_SYSCALL(a_Name, a_cbParamsX86) { &RT_CONCAT(a_Name, _SyscallType1), NULL },
#else
# define SUPHARNT_IMPORT_SYSCALL(a_Name, a_cbParamsX86) { &RT_CONCAT(a_Name,_SyscallType1), &RT_CONCAT(a_Name, _SyscallType2) },
#endif
#include "import-template-ntdll.h"
};
/**
* All the DLLs we import from.
*/
static SUPHNTIMPDLL g_aSupNtImpDlls[] =
{
{ L"ntdll.dll", "ntdll.dll", RT_ELEMENTS(g_aSupNtImpNtDllFunctions), g_aSupNtImpNtDllFunctions, g_aSupNtImpNtDllSyscalls },
{ L"kernel32.dll", "kernel32.dll", RT_ELEMENTS(g_aSupNtImpKernel32Functions), g_aSupNtImpKernel32Functions, NULL },
};
{
{
PLDR_DATA_TABLE_ENTRY pLdrEntry = RT_FROM_MEMBER(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
&& ( pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '\\'
|| pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '/')
&& RTUtf16ICmpAscii(&pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR)],
{
return;
}
cLoops++;
}
else
#else
#endif
}
{
/*
* Locate the PE header, do some basic validations.
*/
{
}
"%ls: Unexpected optional header size: %#x", pDll->pwszName, pNtHdrs->FileHeader.SizeOfOptionalHeader);
"%ls: Unexpected number of RVA and sizes: %#x", pDll->pwszName, pNtHdrs->OptionalHeader.NumberOfRvaAndSizes);
+ sizeof(*pNtHdrs)
/*
* Find the export directory.
*/
"%ls: Missing or invalid export directory: %#lx LB %#x", pDll->pwszName, ExpDir.VirtualAddress, ExpDir.Size);
IMAGE_EXPORT_DIRECTORY const *pExpDir = (IMAGE_EXPORT_DIRECTORY const *)&pDll->pbImageBase[ExpDir.VirtualAddress];
|| pExpDir->AddressOfFunctions + pDll->cExports * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage)
|| pExpDir->AddressOfNames + pExpDir->NumberOfNames * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage)
|| pExpDir->AddressOfNameOrdinals + pExpDir->NumberOfNames * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage)
}
{
/*
* Binary search.
*/
{
if (iDiff > 0) /* pszExpName > pszSymbol: search chunck before i */
else if (iDiff < 0) /* pszExpName < pszSymbol: search chunk after i */
else /* pszExpName == pszSymbol */
{
{
{
{
return NULL;
}
/* Forwarder. */
}
"%ls: The export RVA for '%s' is out of bounds: %#x (SizeOfImage %#x)",
}
"%ls: Name ordinal for '%s' is out of bounds: %#x (max %#x)",
return NULL;
}
}
return NULL;
}
/**
* Resolves imported functions, esp. system calls from NTDLL.
*
* This crap is necessary because there are sandboxing products out there that
* will mess with system calls we make, just like any other wannabe userland
* rootkit. Kudos to microsoft for not providing a generic system call hook API
* in the kernel mode, which I guess is what forcing these kind of products to
* do ugly userland hacks that doesn't really hold water.
*/
DECLHIDDEN(void) supR3HardenedWinInitImports(void)
{
/*
* Find the DLLs we will be needing first (forwarders).
*/
{
}
/*
* Resolve the functions.
*/
{
const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i]);
if (pszForwarder)
{
else if (cchDllName == sizeof("kernelbase") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("kernelbase")) == 0)
else
}
}
}