489 lines
12 KiB
C
489 lines
12 KiB
C
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
verifier.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the standard application verifier provider.
|
|
|
|
Author:
|
|
|
|
Silviu Calinoiu (SilviuC) 2-Feb-2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// IMPORTANT NOTE.
|
|
//
|
|
// This dll cannot contain non-ntdll dependencies. This way it allows
|
|
// verifier to be run system wide including for processes like smss and csrss.
|
|
//
|
|
// SilviuC: we might decide in the future that it is not worth enforcing this
|
|
// restriction and we loose smss/csrss verification but we can do more stuff
|
|
// in the verifier dll.
|
|
//
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "verifier.h"
|
|
#include "support.h"
|
|
#include "settings.h"
|
|
|
|
//
|
|
// ntdll.dll thunks
|
|
//
|
|
|
|
RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpNtdllThunks [] =
|
|
{
|
|
{"NtAllocateVirtualMemory", NULL, AVrfpNtAllocateVirtualMemory},
|
|
{"NtFreeVirtualMemory", NULL, AVrfpNtFreeVirtualMemory},
|
|
{"NtMapViewOfSection", NULL, AVrfpNtMapViewOfSection},
|
|
{"NtUnmapViewOfSection", NULL, AVrfpNtUnmapViewOfSection},
|
|
{"NtCreateSection", NULL, AVrfpNtCreateSection},
|
|
{"NtOpenSection", NULL, AVrfpNtOpenSection},
|
|
{"NtCreateFile", NULL, AVrfpNtCreateFile},
|
|
{"NtOpenFile", NULL, AVrfpNtOpenFile},
|
|
|
|
{"RtlTryEnterCriticalSection", NULL, AVrfpRtlTryEnterCriticalSection},
|
|
{"RtlEnterCriticalSection", NULL, AVrfpRtlEnterCriticalSection},
|
|
{"RtlLeaveCriticalSection", NULL, AVrfpRtlLeaveCriticalSection},
|
|
{"RtlInitializeCriticalSection", NULL, AVrfpRtlInitializeCriticalSection},
|
|
{"RtlInitializeCriticalSectionAndSpinCount", NULL, AVrfpRtlInitializeCriticalSectionAndSpinCount},
|
|
{"RtlDeleteCriticalSection", NULL, AVrfpRtlDeleteCriticalSection},
|
|
|
|
{"NtCreateEvent", NULL, AVrfpNtCreateEvent },
|
|
{"NtClose", NULL, AVrfpNtClose},
|
|
|
|
{"RtlAllocateHeap", NULL, AVrfpRtlAllocateHeap },
|
|
{"RtlReAllocateHeap", NULL, AVrfpRtlReAllocateHeap },
|
|
{"RtlFreeHeap", NULL, AVrfpRtlFreeHeap },
|
|
|
|
// {"RtlQueueWorkItem", NULL, AVrfpRtlQueueWorkItem },
|
|
|
|
// ISSUE: silviuc: these two are tricky (callback can be called several times)
|
|
// {"RtlRegisterWait", NULL, AVrfpRtlRegisterWait },
|
|
// {"RtlCreateTimer", NULL, AVrfpRtlCreateTimer },
|
|
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
//
|
|
// kernel32.dll thunks
|
|
//
|
|
|
|
RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpKernel32Thunks [] =
|
|
{
|
|
{"HeapCreate", NULL, AVrfpHeapCreate},
|
|
{"HeapDestroy", NULL, AVrfpHeapDestroy},
|
|
{"CloseHandle", NULL, AVrfpCloseHandle},
|
|
{"ExitThread", NULL, AVrfpExitThread},
|
|
{"TerminateThread", NULL, AVrfpTerminateThread},
|
|
{"SuspendThread", NULL, AVrfpSuspendThread},
|
|
{"TlsAlloc", NULL, AVrfpTlsAlloc},
|
|
{"TlsFree", NULL, AVrfpTlsFree},
|
|
{"TlsGetValue", NULL, AVrfpTlsGetValue},
|
|
{"TlsSetValue", NULL, AVrfpTlsSetValue},
|
|
#if 0
|
|
{"CreateThread", NULL, AVrfpCreateThread},
|
|
#endif
|
|
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
//
|
|
// advapi32.dll thunks
|
|
//
|
|
|
|
RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpAdvapi32Thunks [] =
|
|
{
|
|
{"RegCreateKeyExW", NULL, AVrfpRegCreateKeyExW},
|
|
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
//
|
|
// msvcrt.dll thunks
|
|
//
|
|
|
|
RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpMsvcrtThunks [] =
|
|
{
|
|
{"malloc", NULL, AVrfp_malloc},
|
|
{"calloc", NULL, AVrfp_calloc},
|
|
{"realloc", NULL, AVrfp_realloc},
|
|
{"free", NULL, AVrfp_free},
|
|
{"??2@YAPAXI@Z", NULL, AVrfp_new},
|
|
{"??3@YAXPAX@Z", NULL, AVrfp_delete},
|
|
{"??_U@YAPAXI@Z", NULL, AVrfp_newarray},
|
|
{"??_V@YAXPAX@Z", NULL, AVrfp_deletearray},
|
|
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
//
|
|
// dll's providing thunks verified.
|
|
//
|
|
|
|
RTL_VERIFIER_DLL_DESCRIPTOR AVrfpExportDlls [] =
|
|
{
|
|
{L"ntdll.dll", 0, NULL, AVrfpNtdllThunks},
|
|
{L"kernel32.dll", 0, NULL, AVrfpKernel32Thunks},
|
|
{L"advapi32.dll", 0, NULL, AVrfpAdvapi32Thunks},
|
|
{L"msvcrt.dll", 0, NULL, AVrfpMsvcrtThunks},
|
|
|
|
{NULL, 0, NULL, NULL}
|
|
};
|
|
|
|
|
|
RTL_VERIFIER_PROVIDER_DESCRIPTOR AVrfpProvider =
|
|
{
|
|
sizeof (RTL_VERIFIER_PROVIDER_DESCRIPTOR),
|
|
AVrfpExportDlls,
|
|
NULL, // not interested in Dll load notifications
|
|
NULL, // not interested in Dll unload notifications
|
|
NULL, // image name (filled by verifier engine)
|
|
0, // verifier flags (filled by verifier engine)
|
|
0, // debug flags (filled by verifier engine)
|
|
};
|
|
|
|
//
|
|
// Mark if we have been called with PROCESS_ATTACH once.
|
|
// In some cases the fusion code loads dynamically kernel32.dll and enforces
|
|
// the run of all initialization routines and causes us to get called
|
|
// twice.
|
|
//
|
|
|
|
BOOL AVrfpProcessAttachCalled;
|
|
|
|
BOOL
|
|
WINAPI
|
|
DllMain(
|
|
HINSTANCE hinstDLL, // handle to the DLL module
|
|
DWORD fdwReason, // reason for calling function
|
|
LPVOID lpvReserved // reserved
|
|
)
|
|
{
|
|
switch (fdwReason) {
|
|
|
|
case DLL_PROCESS_VERIFIER:
|
|
|
|
//
|
|
// DllMain gets called with this special reason by the verifier engine.
|
|
// No code should execute here except passing back the provider
|
|
// descriptor.
|
|
//
|
|
|
|
if (lpvReserved) {
|
|
*((PRTL_VERIFIER_PROVIDER_DESCRIPTOR *)lpvReserved) = &AVrfpProvider;
|
|
}
|
|
|
|
break;
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
//
|
|
// Execute only minimal code here and avoid too many DLL dependencies.
|
|
//
|
|
|
|
if (! AVrfpProcessAttachCalled) {
|
|
|
|
AVrfpProcessAttachCalled = TRUE;
|
|
|
|
if (AVrfpProvider.VerifierImage) {
|
|
|
|
try {
|
|
HandleInitialize();
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
return FALSE;
|
|
}
|
|
|
|
DbgPrint ("AVRF: verifier.dll provider initialized for %ws with flags 0x%X \n",
|
|
AVrfpProvider.VerifierImage,
|
|
AVrfpProvider.VerifierFlags);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PRTL_VERIFIER_THUNK_DESCRIPTOR
|
|
AVrfpGetThunkDescriptor (
|
|
PRTL_VERIFIER_THUNK_DESCRIPTOR DllThunks,
|
|
ULONG Index)
|
|
{
|
|
PRTL_VERIFIER_THUNK_DESCRIPTOR Thunk = NULL;
|
|
|
|
Thunk = &(DllThunks[Index]);
|
|
|
|
if (Thunk->ThunkNewAddress == NULL) {
|
|
|
|
// silviuc: delete
|
|
DbgPrint ("AVRF: we do not have a replace for %s !!! \n",
|
|
Thunk->ThunkName);
|
|
DbgBreakPoint ();
|
|
}
|
|
|
|
return Thunk;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////// msvcrt.dll verified exports
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
LONG AVrfpKernel32Count[8];
|
|
|
|
//WINBASEAPI
|
|
HANDLE
|
|
WINAPI
|
|
AVrfpHeapCreate(
|
|
IN DWORD flOptions,
|
|
IN SIZE_T dwInitialSize,
|
|
IN SIZE_T dwMaximumSize
|
|
)
|
|
{
|
|
typedef HANDLE (WINAPI * FUNCTION_TYPE) (DWORD, SIZE_T, SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks,
|
|
AVRF_INDEX_KERNEL32_HEAPCREATE);
|
|
|
|
InterlockedIncrement (&(AVrfpKernel32Count[0]));
|
|
|
|
return (* Function)(flOptions, dwInitialSize, dwMaximumSize);
|
|
}
|
|
|
|
//WINBASEAPI
|
|
BOOL
|
|
WINAPI
|
|
AVrfpHeapDestroy(
|
|
IN OUT HANDLE hHeap
|
|
)
|
|
{
|
|
typedef BOOL (WINAPI * FUNCTION_TYPE) (HANDLE);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks,
|
|
AVRF_INDEX_KERNEL32_HEAPDESTROY);
|
|
|
|
InterlockedIncrement (&(AVrfpKernel32Count[1]));
|
|
|
|
return (* Function)(hHeap);
|
|
}
|
|
|
|
//WINBASEAPI
|
|
BOOL
|
|
WINAPI
|
|
AVrfpCloseHandle(
|
|
IN OUT HANDLE hObject
|
|
)
|
|
{
|
|
typedef BOOL (WINAPI * FUNCTION_TYPE) (HANDLE);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks,
|
|
AVRF_INDEX_KERNEL32_CLOSEHANDLE);
|
|
|
|
InterlockedIncrement (&(AVrfpKernel32Count[2]));
|
|
|
|
return (* Function)(hObject);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////// msvcrt.dll verified exports
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
LONG AVrfpAdvapi32Count[8];
|
|
|
|
//WINADVAPI
|
|
LONG
|
|
APIENTRY
|
|
AVrfpRegCreateKeyExW (
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpSubKey,
|
|
IN DWORD Reserved,
|
|
IN LPWSTR lpClass,
|
|
IN DWORD dwOptions,
|
|
IN REGSAM samDesired,
|
|
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
OUT PHKEY phkResult,
|
|
OUT LPDWORD lpdwDisposition
|
|
)
|
|
{
|
|
typedef LONG (APIENTRY * FUNCTION_TYPE)
|
|
(HKEY, LPCWSTR, DWORD, LPWSTR, DWORD,
|
|
REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
|
|
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks,
|
|
AVRF_INDEX_ADVAPI32_REGCREATEKEYEXW);
|
|
|
|
InterlockedIncrement (&(AVrfpAdvapi32Count[0]));
|
|
|
|
return (* Function) (hKey,
|
|
lpSubKey,
|
|
Reserved,
|
|
lpClass,
|
|
dwOptions,
|
|
samDesired,
|
|
lpSecurityAttributes,
|
|
phkResult,
|
|
lpdwDisposition);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////// msvcrt.dll verified exports
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
LONG AVrfpMsvcrtCount[8];
|
|
|
|
PVOID __cdecl
|
|
AVrfp_malloc (
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_MALLOC);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[0]));
|
|
|
|
return (* Function)(Size);
|
|
}
|
|
|
|
PVOID __cdecl
|
|
AVrfp_calloc (
|
|
IN SIZE_T Number,
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T, SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_CALLOC);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[1]));
|
|
|
|
return (* Function)(Number, Size);
|
|
}
|
|
|
|
PVOID __cdecl
|
|
AVrfp_realloc (
|
|
IN PVOID Address,
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
typedef PVOID (__cdecl * FUNCTION_TYPE) (PVOID, SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_REALLOC);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[2]));
|
|
|
|
return (* Function)(Address, Size);
|
|
}
|
|
|
|
VOID __cdecl
|
|
AVrfp_free (
|
|
IN PVOID Address
|
|
)
|
|
{
|
|
typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_FREE);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[3]));
|
|
|
|
(* Function)(Address);
|
|
}
|
|
|
|
PVOID __cdecl
|
|
AVrfp_new (
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_NEW);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[4]));
|
|
|
|
return (* Function)(Size);
|
|
}
|
|
|
|
VOID __cdecl
|
|
AVrfp_delete (
|
|
IN PVOID Address
|
|
)
|
|
{
|
|
typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_DELETE);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[5]));
|
|
|
|
(* Function)(Address);
|
|
}
|
|
|
|
PVOID __cdecl
|
|
AVrfp_newarray (
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
typedef PVOID (__cdecl * FUNCTION_TYPE) (SIZE_T);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_NEWARRAY);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[6]));
|
|
|
|
return (* Function)(Size);
|
|
}
|
|
|
|
VOID __cdecl
|
|
AVrfp_deletearray (
|
|
IN PVOID Address
|
|
)
|
|
{
|
|
typedef VOID (__cdecl * FUNCTION_TYPE) (PVOID);
|
|
FUNCTION_TYPE Function;
|
|
|
|
Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpMsvcrtThunks,
|
|
AVRF_INDEX_MSVCRT_DELETEARRAY);
|
|
|
|
InterlockedIncrement (&(AVrfpMsvcrtCount[7]));
|
|
|
|
(* Function)(Address);
|
|
}
|
|
|
|
|