1*60a1006dSMark Jansen /* 2*60a1006dSMark Jansen * PROJECT: ReactOS NT User Mode Library 3*60a1006dSMark Jansen * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4*60a1006dSMark Jansen * PURPOSE: Verifier support routines 5*60a1006dSMark Jansen * COPYRIGHT: Copyright 2011 Aleksey Bragin (aleksey@reactos.org) 6*60a1006dSMark Jansen * Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 7*60a1006dSMark Jansen */ 8*60a1006dSMark Jansen 9*60a1006dSMark Jansen 10*60a1006dSMark Jansen #include <ntdll.h> 11*60a1006dSMark Jansen #include <reactos/verifier.h> 12*60a1006dSMark Jansen 13*60a1006dSMark Jansen #define NDEBUG 14*60a1006dSMark Jansen #include <debug.h> 15*60a1006dSMark Jansen 16*60a1006dSMark Jansen extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry; 17*60a1006dSMark Jansen ULONG AVrfpVerifierFlags = 0; 18*60a1006dSMark Jansen WCHAR AVrfpVerifierDllsString[256] = { 0 }; 19*60a1006dSMark Jansen ULONG AVrfpDebug = 0; 20*60a1006dSMark Jansen BOOL AVrfpInitialized = FALSE; 21*60a1006dSMark Jansen RTL_CRITICAL_SECTION AVrfpVerifierLock; 22*60a1006dSMark Jansen LIST_ENTRY AVrfpVerifierProvidersList; 23*60a1006dSMark Jansen 24*60a1006dSMark Jansen #define VERIFIER_DLL_FLAGS_RESOLVED 1 25*60a1006dSMark Jansen 26*60a1006dSMark Jansen 27*60a1006dSMark Jansen typedef struct _VERIFIER_PROVIDER 28*60a1006dSMark Jansen { 29*60a1006dSMark Jansen LIST_ENTRY ListEntry; 30*60a1006dSMark Jansen UNICODE_STRING DllName; 31*60a1006dSMark Jansen PVOID BaseAddress; 32*60a1006dSMark Jansen PVOID EntryPoint; 33*60a1006dSMark Jansen 34*60a1006dSMark Jansen // Provider data 35*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls; 36*60a1006dSMark Jansen RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback; 37*60a1006dSMark Jansen RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback; 38*60a1006dSMark Jansen RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback; 39*60a1006dSMark Jansen } VERIFIER_PROVIDER, *PVERIFIER_PROVIDER; 40*60a1006dSMark Jansen 41*60a1006dSMark Jansen 42*60a1006dSMark Jansen 43*60a1006dSMark Jansen 44*60a1006dSMark Jansen VOID 45*60a1006dSMark Jansen NTAPI 46*60a1006dSMark Jansen AVrfReadIFEO(HANDLE KeyHandle) 47*60a1006dSMark Jansen { 48*60a1006dSMark Jansen NTSTATUS Status; 49*60a1006dSMark Jansen 50*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle, 51*60a1006dSMark Jansen L"VerifierDlls", 52*60a1006dSMark Jansen REG_SZ, 53*60a1006dSMark Jansen AVrfpVerifierDllsString, 54*60a1006dSMark Jansen sizeof(AVrfpVerifierDllsString) - sizeof(WCHAR), 55*60a1006dSMark Jansen NULL); 56*60a1006dSMark Jansen 57*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 58*60a1006dSMark Jansen AVrfpVerifierDllsString[0] = UNICODE_NULL; 59*60a1006dSMark Jansen 60*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle, 61*60a1006dSMark Jansen L"VerifierFlags", 62*60a1006dSMark Jansen REG_DWORD, 63*60a1006dSMark Jansen &AVrfpVerifierFlags, 64*60a1006dSMark Jansen sizeof(AVrfpVerifierFlags), 65*60a1006dSMark Jansen NULL); 66*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 67*60a1006dSMark Jansen AVrfpVerifierFlags = RTL_VRF_FLG_HANDLE_CHECKS | RTL_VRF_FLG_FAST_FILL_HEAP | RTL_VRF_FLG_LOCK_CHECKS; 68*60a1006dSMark Jansen 69*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle, 70*60a1006dSMark Jansen L"VerifierDebug", 71*60a1006dSMark Jansen REG_DWORD, 72*60a1006dSMark Jansen &AVrfpDebug, 73*60a1006dSMark Jansen sizeof(AVrfpDebug), 74*60a1006dSMark Jansen NULL); 75*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 76*60a1006dSMark Jansen AVrfpDebug = 0; 77*60a1006dSMark Jansen } 78*60a1006dSMark Jansen 79*60a1006dSMark Jansen 80*60a1006dSMark Jansen NTSTATUS 81*60a1006dSMark Jansen NTAPI 82*60a1006dSMark Jansen LdrpInitializeApplicationVerifierPackage(HANDLE KeyHandle, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions) 83*60a1006dSMark Jansen { 84*60a1006dSMark Jansen /* If global flags request DPH, perform some additional actions */ 85*60a1006dSMark Jansen if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) 86*60a1006dSMark Jansen { 87*60a1006dSMark Jansen // TODO: Read advanced DPH flags from the registry if requested 88*60a1006dSMark Jansen if (ReadAdvancedOptions) 89*60a1006dSMark Jansen { 90*60a1006dSMark Jansen UNIMPLEMENTED; 91*60a1006dSMark Jansen } 92*60a1006dSMark Jansen 93*60a1006dSMark Jansen /* Enable page heap */ 94*60a1006dSMark Jansen RtlpPageHeapEnabled = TRUE; 95*60a1006dSMark Jansen } 96*60a1006dSMark Jansen 97*60a1006dSMark Jansen AVrfReadIFEO(KeyHandle); 98*60a1006dSMark Jansen 99*60a1006dSMark Jansen return STATUS_SUCCESS; 100*60a1006dSMark Jansen } 101*60a1006dSMark Jansen 102*60a1006dSMark Jansen BOOLEAN 103*60a1006dSMark Jansen AVrfpIsVerifierProviderDll(PVOID BaseAddress) 104*60a1006dSMark Jansen { 105*60a1006dSMark Jansen PLIST_ENTRY Entry; 106*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 107*60a1006dSMark Jansen 108*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 109*60a1006dSMark Jansen { 110*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 111*60a1006dSMark Jansen 112*60a1006dSMark Jansen if (BaseAddress == Provider->BaseAddress) 113*60a1006dSMark Jansen return TRUE; 114*60a1006dSMark Jansen } 115*60a1006dSMark Jansen 116*60a1006dSMark Jansen return FALSE; 117*60a1006dSMark Jansen } 118*60a1006dSMark Jansen 119*60a1006dSMark Jansen SIZE_T 120*60a1006dSMark Jansen AVrfpCountThunks(PIMAGE_THUNK_DATA Thunk) 121*60a1006dSMark Jansen { 122*60a1006dSMark Jansen SIZE_T Count = 0; 123*60a1006dSMark Jansen while (Thunk[Count].u1.Function) 124*60a1006dSMark Jansen Count++; 125*60a1006dSMark Jansen return Count; 126*60a1006dSMark Jansen } 127*60a1006dSMark Jansen 128*60a1006dSMark Jansen VOID 129*60a1006dSMark Jansen AVrfpSnapDllImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 130*60a1006dSMark Jansen { 131*60a1006dSMark Jansen ULONG Size; 132*60a1006dSMark Jansen PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; 133*60a1006dSMark Jansen PBYTE DllBase = LdrEntry->DllBase; 134*60a1006dSMark Jansen 135*60a1006dSMark Jansen ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size); 136*60a1006dSMark Jansen if (!ImportDescriptor) 137*60a1006dSMark Jansen { 138*60a1006dSMark Jansen //SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName); 139*60a1006dSMark Jansen return; 140*60a1006dSMark Jansen } 141*60a1006dSMark Jansen 142*60a1006dSMark Jansen for (; ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk; ImportDescriptor++) 143*60a1006dSMark Jansen { 144*60a1006dSMark Jansen PIMAGE_THUNK_DATA FirstThunk; 145*60a1006dSMark Jansen PVOID UnprotectedPtr = NULL; 146*60a1006dSMark Jansen SIZE_T UnprotectedSize = 0; 147*60a1006dSMark Jansen ULONG OldProtection = 0; 148*60a1006dSMark Jansen FirstThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->FirstThunk); 149*60a1006dSMark Jansen 150*60a1006dSMark Jansen /* Walk all imports */ 151*60a1006dSMark Jansen for (;FirstThunk->u1.Function; FirstThunk++) 152*60a1006dSMark Jansen { 153*60a1006dSMark Jansen PLIST_ENTRY Entry; 154*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 155*60a1006dSMark Jansen 156*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 157*60a1006dSMark Jansen { 158*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor; 159*60a1006dSMark Jansen 160*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 161*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor) 162*60a1006dSMark Jansen { 163*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor; 164*60a1006dSMark Jansen 165*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor) 166*60a1006dSMark Jansen { 167*60a1006dSMark Jansen /* Just compare function addresses, the loader will have handled forwarders and ordinals for us */ 168*60a1006dSMark Jansen if ((PVOID)FirstThunk->u1.Function != ThunkDescriptor->ThunkOldAddress) 169*60a1006dSMark Jansen continue; 170*60a1006dSMark Jansen 171*60a1006dSMark Jansen if (!UnprotectedPtr) 172*60a1006dSMark Jansen { 173*60a1006dSMark Jansen PVOID Ptr = &FirstThunk->u1.Function; 174*60a1006dSMark Jansen SIZE_T Size = sizeof(FirstThunk->u1.Function) * AVrfpCountThunks(FirstThunk); 175*60a1006dSMark Jansen NTSTATUS Status; 176*60a1006dSMark Jansen 177*60a1006dSMark Jansen UnprotectedPtr = Ptr; 178*60a1006dSMark Jansen UnprotectedSize = Size; 179*60a1006dSMark Jansen 180*60a1006dSMark Jansen Status = NtProtectVirtualMemory(NtCurrentProcess(), 181*60a1006dSMark Jansen &Ptr, 182*60a1006dSMark Jansen &Size, 183*60a1006dSMark Jansen PAGE_EXECUTE_READWRITE, 184*60a1006dSMark Jansen &OldProtection); 185*60a1006dSMark Jansen 186*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 187*60a1006dSMark Jansen { 188*60a1006dSMark Jansen DbgPrint("AVRF: Unable to unprotect IAT to modify thunks (status %08X).\n", Status); 189*60a1006dSMark Jansen UnprotectedPtr = NULL; 190*60a1006dSMark Jansen continue; 191*60a1006dSMark Jansen } 192*60a1006dSMark Jansen } 193*60a1006dSMark Jansen 194*60a1006dSMark Jansen if (ThunkDescriptor->ThunkNewAddress == NULL) 195*60a1006dSMark Jansen { 196*60a1006dSMark Jansen DbgPrint("AVRF: internal error: New thunk for %s is null.\n", ThunkDescriptor->ThunkName); 197*60a1006dSMark Jansen continue; 198*60a1006dSMark Jansen } 199*60a1006dSMark Jansen FirstThunk->u1.Function = (SIZE_T)ThunkDescriptor->ThunkNewAddress; 200*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS) 201*60a1006dSMark Jansen DbgPrint("AVRF: Snapped (%wZ: %s) with (%wZ: %p).\n", 202*60a1006dSMark Jansen &LdrEntry->BaseDllName, 203*60a1006dSMark Jansen ThunkDescriptor->ThunkName, 204*60a1006dSMark Jansen &Provider->DllName, 205*60a1006dSMark Jansen ThunkDescriptor->ThunkNewAddress); 206*60a1006dSMark Jansen } 207*60a1006dSMark Jansen } 208*60a1006dSMark Jansen } 209*60a1006dSMark Jansen } 210*60a1006dSMark Jansen 211*60a1006dSMark Jansen if (UnprotectedPtr) 212*60a1006dSMark Jansen { 213*60a1006dSMark Jansen PVOID Ptr = UnprotectedPtr; 214*60a1006dSMark Jansen SIZE_T Size = UnprotectedSize; 215*60a1006dSMark Jansen NTSTATUS Status; 216*60a1006dSMark Jansen 217*60a1006dSMark Jansen UnprotectedPtr = Ptr; 218*60a1006dSMark Jansen UnprotectedSize = Size; 219*60a1006dSMark Jansen 220*60a1006dSMark Jansen Status = NtProtectVirtualMemory(NtCurrentProcess(), 221*60a1006dSMark Jansen &Ptr, 222*60a1006dSMark Jansen &Size, 223*60a1006dSMark Jansen OldProtection, 224*60a1006dSMark Jansen &OldProtection); 225*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 226*60a1006dSMark Jansen { 227*60a1006dSMark Jansen DbgPrint("AVRF: Unable to reprotect IAT to modify thunks (status %08X).\n", Status); 228*60a1006dSMark Jansen } 229*60a1006dSMark Jansen } 230*60a1006dSMark Jansen } 231*60a1006dSMark Jansen } 232*60a1006dSMark Jansen 233*60a1006dSMark Jansen 234*60a1006dSMark Jansen VOID 235*60a1006dSMark Jansen AvrfpResolveThunks(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 236*60a1006dSMark Jansen { 237*60a1006dSMark Jansen PLIST_ENTRY Entry; 238*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 239*60a1006dSMark Jansen 240*60a1006dSMark Jansen if (!AVrfpInitialized) 241*60a1006dSMark Jansen return; 242*60a1006dSMark Jansen 243*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 244*60a1006dSMark Jansen { 245*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor; 246*60a1006dSMark Jansen 247*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 248*60a1006dSMark Jansen 249*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor) 250*60a1006dSMark Jansen { 251*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor; 252*60a1006dSMark Jansen 253*60a1006dSMark Jansen if ((DllDescriptor->DllFlags & VERIFIER_DLL_FLAGS_RESOLVED) || 254*60a1006dSMark Jansen _wcsicmp(DllDescriptor->DllName, LdrEntry->BaseDllName.Buffer)) 255*60a1006dSMark Jansen continue; 256*60a1006dSMark Jansen 257*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWVERIFIEDEXPORTS) 258*60a1006dSMark Jansen DbgPrint("AVRF: pid 0x%X: found dll descriptor for `%wZ' with verified exports\n", 259*60a1006dSMark Jansen NtCurrentTeb()->ClientId.UniqueProcess, 260*60a1006dSMark Jansen &LdrEntry->BaseDllName); 261*60a1006dSMark Jansen 262*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor) 263*60a1006dSMark Jansen { 264*60a1006dSMark Jansen if (!ThunkDescriptor->ThunkOldAddress) 265*60a1006dSMark Jansen { 266*60a1006dSMark Jansen ANSI_STRING ThunkName; 267*60a1006dSMark Jansen 268*60a1006dSMark Jansen RtlInitAnsiString(&ThunkName, ThunkDescriptor->ThunkName); 269*60a1006dSMark Jansen /* We cannot call the public api, because that would run init routines! */ 270*60a1006dSMark Jansen if (NT_SUCCESS(LdrpGetProcedureAddress(LdrEntry->DllBase, &ThunkName, 0, &ThunkDescriptor->ThunkOldAddress, FALSE))) 271*60a1006dSMark Jansen { 272*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWFOUNDEXPORTS) 273*60a1006dSMark Jansen DbgPrint("AVRF: (%wZ) %Z export found.\n", &LdrEntry->BaseDllName, &ThunkName); 274*60a1006dSMark Jansen } 275*60a1006dSMark Jansen else 276*60a1006dSMark Jansen { 277*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWFOUNDEXPORTS) 278*60a1006dSMark Jansen DbgPrint("AVRF: warning: did not find `%Z' export in %wZ.\n", &ThunkName, &LdrEntry->BaseDllName); 279*60a1006dSMark Jansen } 280*60a1006dSMark Jansen } 281*60a1006dSMark Jansen } 282*60a1006dSMark Jansen 283*60a1006dSMark Jansen DllDescriptor->DllFlags |= VERIFIER_DLL_FLAGS_RESOLVED; 284*60a1006dSMark Jansen } 285*60a1006dSMark Jansen } 286*60a1006dSMark Jansen 287*60a1006dSMark Jansen AVrfpSnapDllImports(LdrEntry); 288*60a1006dSMark Jansen } 289*60a1006dSMark Jansen 290*60a1006dSMark Jansen 291*60a1006dSMark Jansen 292*60a1006dSMark Jansen VOID 293*60a1006dSMark Jansen NTAPI 294*60a1006dSMark Jansen AVrfDllLoadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 295*60a1006dSMark Jansen { 296*60a1006dSMark Jansen PLIST_ENTRY Entry; 297*60a1006dSMark Jansen 298*60a1006dSMark Jansen if (!(NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER)) 299*60a1006dSMark Jansen return; 300*60a1006dSMark Jansen 301*60a1006dSMark Jansen RtlEnterCriticalSection(&AVrfpVerifierLock); 302*60a1006dSMark Jansen if (!AVrfpIsVerifierProviderDll(LdrEntry->DllBase)) 303*60a1006dSMark Jansen { 304*60a1006dSMark Jansen AvrfpResolveThunks(LdrEntry); 305*60a1006dSMark Jansen 306*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 307*60a1006dSMark Jansen { 308*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 309*60a1006dSMark Jansen RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback; 310*60a1006dSMark Jansen 311*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 312*60a1006dSMark Jansen 313*60a1006dSMark Jansen ProviderDllLoadCallback = Provider->ProviderDllLoadCallback; 314*60a1006dSMark Jansen if (ProviderDllLoadCallback) 315*60a1006dSMark Jansen { 316*60a1006dSMark Jansen ProviderDllLoadCallback(LdrEntry->BaseDllName.Buffer, 317*60a1006dSMark Jansen LdrEntry->DllBase, 318*60a1006dSMark Jansen LdrEntry->SizeOfImage, 319*60a1006dSMark Jansen LdrEntry); 320*60a1006dSMark Jansen } 321*60a1006dSMark Jansen } 322*60a1006dSMark Jansen } 323*60a1006dSMark Jansen RtlLeaveCriticalSection(&AVrfpVerifierLock); 324*60a1006dSMark Jansen } 325*60a1006dSMark Jansen 326*60a1006dSMark Jansen VOID 327*60a1006dSMark Jansen NTAPI 328*60a1006dSMark Jansen AVrfDllUnloadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 329*60a1006dSMark Jansen { 330*60a1006dSMark Jansen PLIST_ENTRY Entry; 331*60a1006dSMark Jansen 332*60a1006dSMark Jansen if (!(NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER)) 333*60a1006dSMark Jansen return; 334*60a1006dSMark Jansen 335*60a1006dSMark Jansen RtlEnterCriticalSection(&AVrfpVerifierLock); 336*60a1006dSMark Jansen if (!AVrfpIsVerifierProviderDll(LdrEntry->DllBase)) 337*60a1006dSMark Jansen { 338*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 339*60a1006dSMark Jansen { 340*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 341*60a1006dSMark Jansen RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback; 342*60a1006dSMark Jansen 343*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 344*60a1006dSMark Jansen 345*60a1006dSMark Jansen ProviderDllUnloadCallback = Provider->ProviderDllUnloadCallback; 346*60a1006dSMark Jansen if (ProviderDllUnloadCallback) 347*60a1006dSMark Jansen { 348*60a1006dSMark Jansen ProviderDllUnloadCallback(LdrEntry->BaseDllName.Buffer, 349*60a1006dSMark Jansen LdrEntry->DllBase, 350*60a1006dSMark Jansen LdrEntry->SizeOfImage, 351*60a1006dSMark Jansen LdrEntry); 352*60a1006dSMark Jansen } 353*60a1006dSMark Jansen } 354*60a1006dSMark Jansen } 355*60a1006dSMark Jansen RtlLeaveCriticalSection(&AVrfpVerifierLock); 356*60a1006dSMark Jansen } 357*60a1006dSMark Jansen 358*60a1006dSMark Jansen 359*60a1006dSMark Jansen VOID 360*60a1006dSMark Jansen NTAPI 361*60a1006dSMark Jansen AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 362*60a1006dSMark Jansen { 363*60a1006dSMark Jansen /* Check if page heap dll notification is turned on */ 364*60a1006dSMark Jansen if (!(RtlpDphGlobalFlags & DPH_FLAG_DLL_NOTIFY)) 365*60a1006dSMark Jansen return; 366*60a1006dSMark Jansen 367*60a1006dSMark Jansen /* We don't support this flag currently */ 368*60a1006dSMark Jansen UNIMPLEMENTED; 369*60a1006dSMark Jansen } 370*60a1006dSMark Jansen 371*60a1006dSMark Jansen 372*60a1006dSMark Jansen VOID 373*60a1006dSMark Jansen NTAPI 374*60a1006dSMark Jansen AVrfpResnapInitialModules(VOID) 375*60a1006dSMark Jansen { 376*60a1006dSMark Jansen PLIST_ENTRY ListHead, ListEntry; 377*60a1006dSMark Jansen 378*60a1006dSMark Jansen ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 379*60a1006dSMark Jansen for (ListEntry = ListHead->Flink; ListHead != ListEntry; ListEntry = ListEntry->Flink) 380*60a1006dSMark Jansen { 381*60a1006dSMark Jansen PLDR_DATA_TABLE_ENTRY LdrEntry; 382*60a1006dSMark Jansen 383*60a1006dSMark Jansen LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 384*60a1006dSMark Jansen 385*60a1006dSMark Jansen if (AVrfpIsVerifierProviderDll(LdrEntry->DllBase)) 386*60a1006dSMark Jansen { 387*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS) 388*60a1006dSMark Jansen DbgPrint("AVRF: skipped resnapping provider %wZ ...\n", &LdrEntry->BaseDllName); 389*60a1006dSMark Jansen } 390*60a1006dSMark Jansen else 391*60a1006dSMark Jansen { 392*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS) 393*60a1006dSMark Jansen DbgPrint("AVRF: resnapping %wZ ...\n", &LdrEntry->BaseDllName); 394*60a1006dSMark Jansen 395*60a1006dSMark Jansen AvrfpResolveThunks(LdrEntry); 396*60a1006dSMark Jansen } 397*60a1006dSMark Jansen } 398*60a1006dSMark Jansen } 399*60a1006dSMark Jansen 400*60a1006dSMark Jansen PVOID 401*60a1006dSMark Jansen NTAPI 402*60a1006dSMark Jansen AvrfpFindDuplicateThunk(PLIST_ENTRY EndEntry, PWCHAR DllName, PCHAR ThunkName) 403*60a1006dSMark Jansen { 404*60a1006dSMark Jansen PLIST_ENTRY Entry; 405*60a1006dSMark Jansen 406*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != EndEntry; Entry = Entry->Flink) 407*60a1006dSMark Jansen { 408*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 409*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor; 410*60a1006dSMark Jansen 411*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 412*60a1006dSMark Jansen 413*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG) 414*60a1006dSMark Jansen DbgPrint("AVRF: chain: searching in %wZ\n", &Provider->DllName); 415*60a1006dSMark Jansen 416*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor) 417*60a1006dSMark Jansen { 418*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor; 419*60a1006dSMark Jansen 420*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG) 421*60a1006dSMark Jansen DbgPrint("AVRF: chain: dll: %ws\n", DllDescriptor->DllName); 422*60a1006dSMark Jansen 423*60a1006dSMark Jansen if (_wcsicmp(DllDescriptor->DllName, DllName)) 424*60a1006dSMark Jansen continue; 425*60a1006dSMark Jansen 426*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor) 427*60a1006dSMark Jansen { 428*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG) 429*60a1006dSMark Jansen DbgPrint("AVRF: chain: thunk: %s == %s ?\n", ThunkDescriptor->ThunkName, ThunkName); 430*60a1006dSMark Jansen 431*60a1006dSMark Jansen if (!_stricmp(ThunkDescriptor->ThunkName, ThunkName)) 432*60a1006dSMark Jansen { 433*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG) 434*60a1006dSMark Jansen DbgPrint("AVRF: Found duplicate for (%ws: %s) in %wZ\n", 435*60a1006dSMark Jansen DllDescriptor->DllName, ThunkDescriptor->ThunkName, &Provider->DllName); 436*60a1006dSMark Jansen 437*60a1006dSMark Jansen return ThunkDescriptor->ThunkNewAddress; 438*60a1006dSMark Jansen } 439*60a1006dSMark Jansen } 440*60a1006dSMark Jansen } 441*60a1006dSMark Jansen } 442*60a1006dSMark Jansen return NULL; 443*60a1006dSMark Jansen } 444*60a1006dSMark Jansen 445*60a1006dSMark Jansen 446*60a1006dSMark Jansen VOID 447*60a1006dSMark Jansen NTAPI 448*60a1006dSMark Jansen AVrfpChainDuplicateThunks(VOID) 449*60a1006dSMark Jansen { 450*60a1006dSMark Jansen PLIST_ENTRY Entry; 451*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 452*60a1006dSMark Jansen 453*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink) 454*60a1006dSMark Jansen { 455*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor; 456*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor; 457*60a1006dSMark Jansen 458*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 459*60a1006dSMark Jansen 460*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor) 461*60a1006dSMark Jansen { 462*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor) 463*60a1006dSMark Jansen { 464*60a1006dSMark Jansen PVOID Ptr; 465*60a1006dSMark Jansen 466*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG) 467*60a1006dSMark Jansen DbgPrint("AVRF: Checking %wZ for duplicate (%ws: %s)\n", 468*60a1006dSMark Jansen &Provider->DllName, DllDescriptor->DllName, ThunkDescriptor->ThunkName); 469*60a1006dSMark Jansen 470*60a1006dSMark Jansen Ptr = AvrfpFindDuplicateThunk(Entry, DllDescriptor->DllName, ThunkDescriptor->ThunkName); 471*60a1006dSMark Jansen if (Ptr) 472*60a1006dSMark Jansen { 473*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING) 474*60a1006dSMark Jansen DbgPrint("AVRF: Chaining (%ws: %s) to %wZ\n", DllDescriptor->DllName, ThunkDescriptor->ThunkName, &Provider->DllName); 475*60a1006dSMark Jansen 476*60a1006dSMark Jansen ThunkDescriptor->ThunkOldAddress = Ptr; 477*60a1006dSMark Jansen } 478*60a1006dSMark Jansen } 479*60a1006dSMark Jansen } 480*60a1006dSMark Jansen } 481*60a1006dSMark Jansen } 482*60a1006dSMark Jansen 483*60a1006dSMark Jansen NTSTATUS 484*60a1006dSMark Jansen NTAPI 485*60a1006dSMark Jansen AVrfpLoadAndInitializeProvider(PVERIFIER_PROVIDER Provider) 486*60a1006dSMark Jansen { 487*60a1006dSMark Jansen WCHAR StringBuffer[MAX_PATH + 11]; 488*60a1006dSMark Jansen UNICODE_STRING DllPath; 489*60a1006dSMark Jansen PRTL_VERIFIER_PROVIDER_DESCRIPTOR Descriptor; 490*60a1006dSMark Jansen PIMAGE_NT_HEADERS ImageNtHeader; 491*60a1006dSMark Jansen NTSTATUS Status; 492*60a1006dSMark Jansen 493*60a1006dSMark Jansen RtlInitEmptyUnicodeString(&DllPath, StringBuffer, sizeof(StringBuffer)); 494*60a1006dSMark Jansen RtlAppendUnicodeToString(&DllPath, SharedUserData->NtSystemRoot); 495*60a1006dSMark Jansen RtlAppendUnicodeToString(&DllPath, L"\\System32\\"); 496*60a1006dSMark Jansen 497*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS) 498*60a1006dSMark Jansen DbgPrint("AVRF: verifier dll `%wZ'\n", &Provider->DllName); 499*60a1006dSMark Jansen 500*60a1006dSMark Jansen Status = LdrLoadDll(DllPath.Buffer, NULL, &Provider->DllName, &Provider->BaseAddress); 501*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 502*60a1006dSMark Jansen { 503*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: failed to load provider `%wZ' (status %08X) from %wZ\n", 504*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName, 505*60a1006dSMark Jansen &Provider->DllName, 506*60a1006dSMark Jansen Status, 507*60a1006dSMark Jansen &DllPath); 508*60a1006dSMark Jansen return Status; 509*60a1006dSMark Jansen } 510*60a1006dSMark Jansen 511*60a1006dSMark Jansen /* Prevent someone funny from specifying his own application as provider */ 512*60a1006dSMark Jansen ImageNtHeader = RtlImageNtHeader(Provider->BaseAddress); 513*60a1006dSMark Jansen if (!ImageNtHeader || 514*60a1006dSMark Jansen !(ImageNtHeader->FileHeader.Characteristics & IMAGE_FILE_DLL)) 515*60a1006dSMark Jansen { 516*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ is not a DLL image\n", &Provider->DllName); 517*60a1006dSMark Jansen return STATUS_DLL_INIT_FAILED; 518*60a1006dSMark Jansen } 519*60a1006dSMark Jansen 520*60a1006dSMark Jansen Provider->EntryPoint = LdrpFetchAddressOfEntryPoint(Provider->BaseAddress); 521*60a1006dSMark Jansen if (!Provider->EntryPoint) 522*60a1006dSMark Jansen { 523*60a1006dSMark Jansen DbgPrint("AVRF: cannot find an entry point for provider %wZ\n", &Provider->DllName); 524*60a1006dSMark Jansen return STATUS_PROCEDURE_NOT_FOUND; 525*60a1006dSMark Jansen } 526*60a1006dSMark Jansen 527*60a1006dSMark Jansen _SEH2_TRY 528*60a1006dSMark Jansen { 529*60a1006dSMark Jansen if (LdrpCallInitRoutine(Provider->EntryPoint, 530*60a1006dSMark Jansen Provider->BaseAddress, 531*60a1006dSMark Jansen DLL_PROCESS_VERIFIER, 532*60a1006dSMark Jansen &Descriptor)) 533*60a1006dSMark Jansen { 534*60a1006dSMark Jansen if (Descriptor && Descriptor->Length == sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR)) 535*60a1006dSMark Jansen { 536*60a1006dSMark Jansen /* Copy the data */ 537*60a1006dSMark Jansen Provider->ProviderDlls = Descriptor->ProviderDlls; 538*60a1006dSMark Jansen Provider->ProviderDllLoadCallback = Descriptor->ProviderDllLoadCallback; 539*60a1006dSMark Jansen Provider->ProviderDllUnloadCallback = Descriptor->ProviderDllUnloadCallback; 540*60a1006dSMark Jansen Provider->ProviderNtdllHeapFreeCallback = Descriptor->ProviderNtdllHeapFreeCallback; 541*60a1006dSMark Jansen 542*60a1006dSMark Jansen /* Update some info for the provider */ 543*60a1006dSMark Jansen Descriptor->VerifierImage = LdrpImageEntry->BaseDllName.Buffer; 544*60a1006dSMark Jansen Descriptor->VerifierFlags = AVrfpVerifierFlags; 545*60a1006dSMark Jansen Descriptor->VerifierDebug = AVrfpDebug; 546*60a1006dSMark Jansen 547*60a1006dSMark Jansen /* We don't have these yet */ 548*60a1006dSMark Jansen DPRINT1("AVRF: RtlpGetStackTraceAddress MISSING\n"); 549*60a1006dSMark Jansen DPRINT1("AVRF: RtlpDebugPageHeapCreate MISSING\n"); 550*60a1006dSMark Jansen DPRINT1("AVRF: RtlpDebugPageHeapDestroy MISSING\n"); 551*60a1006dSMark Jansen Descriptor->RtlpGetStackTraceAddress = NULL; 552*60a1006dSMark Jansen Descriptor->RtlpDebugPageHeapCreate = NULL; 553*60a1006dSMark Jansen Descriptor->RtlpDebugPageHeapDestroy = NULL; 554*60a1006dSMark Jansen Status = STATUS_SUCCESS; 555*60a1006dSMark Jansen } 556*60a1006dSMark Jansen else 557*60a1006dSMark Jansen { 558*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ passed an invalid descriptor @ %p\n", &Provider->DllName, Descriptor); 559*60a1006dSMark Jansen Status = STATUS_INVALID_PARAMETER_4; 560*60a1006dSMark Jansen } 561*60a1006dSMark Jansen } 562*60a1006dSMark Jansen else 563*60a1006dSMark Jansen { 564*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider->DllName); 565*60a1006dSMark Jansen Status = STATUS_DLL_INIT_FAILED; 566*60a1006dSMark Jansen } 567*60a1006dSMark Jansen } 568*60a1006dSMark Jansen _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 569*60a1006dSMark Jansen { 570*60a1006dSMark Jansen Status = _SEH2_GetExceptionCode(); 571*60a1006dSMark Jansen } 572*60a1006dSMark Jansen _SEH2_END; 573*60a1006dSMark Jansen 574*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 575*60a1006dSMark Jansen return Status; 576*60a1006dSMark Jansen 577*60a1006dSMark Jansen 578*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_LISTPROVIDERS) 579*60a1006dSMark Jansen DbgPrint("AVRF: initialized provider %wZ (descriptor @ %p)\n", &Provider->DllName, Descriptor); 580*60a1006dSMark Jansen 581*60a1006dSMark Jansen /* Done loading providers, allow dll notifications */ 582*60a1006dSMark Jansen AVrfpInitialized = TRUE; 583*60a1006dSMark Jansen 584*60a1006dSMark Jansen AVrfpChainDuplicateThunks(); 585*60a1006dSMark Jansen AVrfpResnapInitialModules(); 586*60a1006dSMark Jansen 587*60a1006dSMark Jansen /* Manually call with DLL_PROCESS_ATTACH, since the process is not done initializing */ 588*60a1006dSMark Jansen _SEH2_TRY 589*60a1006dSMark Jansen { 590*60a1006dSMark Jansen if (!LdrpCallInitRoutine(Provider->EntryPoint, 591*60a1006dSMark Jansen Provider->BaseAddress, 592*60a1006dSMark Jansen DLL_PROCESS_ATTACH, 593*60a1006dSMark Jansen NULL)) 594*60a1006dSMark Jansen { 595*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider->DllName); 596*60a1006dSMark Jansen Status = STATUS_DLL_INIT_FAILED; 597*60a1006dSMark Jansen } 598*60a1006dSMark Jansen 599*60a1006dSMark Jansen } 600*60a1006dSMark Jansen _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 601*60a1006dSMark Jansen { 602*60a1006dSMark Jansen Status = _SEH2_GetExceptionCode(); 603*60a1006dSMark Jansen } 604*60a1006dSMark Jansen _SEH2_END; 605*60a1006dSMark Jansen 606*60a1006dSMark Jansen return Status; 607*60a1006dSMark Jansen } 608*60a1006dSMark Jansen 609*60a1006dSMark Jansen 610*60a1006dSMark Jansen NTSTATUS 611*60a1006dSMark Jansen NTAPI 612*60a1006dSMark Jansen AVrfInitializeVerifier(VOID) 613*60a1006dSMark Jansen { 614*60a1006dSMark Jansen NTSTATUS Status; 615*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider; 616*60a1006dSMark Jansen PLIST_ENTRY Entry; 617*60a1006dSMark Jansen WCHAR* Ptr, *Next; 618*60a1006dSMark Jansen 619*60a1006dSMark Jansen Status = RtlInitializeCriticalSection(&AVrfpVerifierLock); 620*60a1006dSMark Jansen InitializeListHead(&AVrfpVerifierProvidersList); 621*60a1006dSMark Jansen 622*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 623*60a1006dSMark Jansen return Status; 624*60a1006dSMark Jansen 625*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: pid 0x%X: flags 0x%X: application verifier enabled\n", 626*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName, NtCurrentTeb()->ClientId.UniqueProcess, AVrfpVerifierFlags); 627*60a1006dSMark Jansen 628*60a1006dSMark Jansen Provider = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VERIFIER_PROVIDER)); 629*60a1006dSMark Jansen if (!Provider) 630*60a1006dSMark Jansen return STATUS_NO_MEMORY; 631*60a1006dSMark Jansen 632*60a1006dSMark Jansen RtlInitUnicodeString(&Provider->DllName, L"verifier.dll"); 633*60a1006dSMark Jansen InsertTailList(&AVrfpVerifierProvidersList, &Provider->ListEntry); 634*60a1006dSMark Jansen 635*60a1006dSMark Jansen Next = AVrfpVerifierDllsString; 636*60a1006dSMark Jansen 637*60a1006dSMark Jansen do 638*60a1006dSMark Jansen { 639*60a1006dSMark Jansen while (*Next == L' ' || *Next == L'\t') 640*60a1006dSMark Jansen Next++; 641*60a1006dSMark Jansen 642*60a1006dSMark Jansen Ptr = Next; 643*60a1006dSMark Jansen 644*60a1006dSMark Jansen while (*Next != ' ' && *Next != '\t' && *Next) 645*60a1006dSMark Jansen Next++; 646*60a1006dSMark Jansen 647*60a1006dSMark Jansen if (*Next) 648*60a1006dSMark Jansen *(Next++) = '\0'; 649*60a1006dSMark Jansen else 650*60a1006dSMark Jansen Next = NULL; 651*60a1006dSMark Jansen 652*60a1006dSMark Jansen if (*Ptr) 653*60a1006dSMark Jansen { 654*60a1006dSMark Jansen Provider = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VERIFIER_PROVIDER)); 655*60a1006dSMark Jansen if (!Provider) 656*60a1006dSMark Jansen return STATUS_NO_MEMORY; 657*60a1006dSMark Jansen RtlInitUnicodeString(&Provider->DllName, Ptr); 658*60a1006dSMark Jansen InsertTailList(&AVrfpVerifierProvidersList, &Provider->ListEntry); 659*60a1006dSMark Jansen } 660*60a1006dSMark Jansen } while (Next); 661*60a1006dSMark Jansen 662*60a1006dSMark Jansen Entry = AVrfpVerifierProvidersList.Flink; 663*60a1006dSMark Jansen while (Entry != &AVrfpVerifierProvidersList) 664*60a1006dSMark Jansen { 665*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry); 666*60a1006dSMark Jansen Entry = Entry->Flink; 667*60a1006dSMark Jansen 668*60a1006dSMark Jansen Status = AVrfpLoadAndInitializeProvider(Provider); 669*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 670*60a1006dSMark Jansen { 671*60a1006dSMark Jansen RemoveEntryList(&Provider->ListEntry); 672*60a1006dSMark Jansen RtlFreeHeap(RtlGetProcessHeap(), 0, Provider); 673*60a1006dSMark Jansen } 674*60a1006dSMark Jansen } 675*60a1006dSMark Jansen 676*60a1006dSMark Jansen if (!NT_SUCCESS(Status)) 677*60a1006dSMark Jansen { 678*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: pid 0x%X: application verifier will be disabled due to an initialization error.\n", 679*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName, NtCurrentTeb()->ClientId.UniqueProcess); 680*60a1006dSMark Jansen NtCurrentPeb()->NtGlobalFlag &= ~FLG_APPLICATION_VERIFIER; 681*60a1006dSMark Jansen } 682*60a1006dSMark Jansen 683*60a1006dSMark Jansen return Status; 684*60a1006dSMark Jansen } 685*60a1006dSMark Jansen 686