Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3297 lines
86 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. verifier.c
  5. Abstract:
  6. This module implements the core support for application verifier.
  7. Author:
  8. Silviu Calinoiu (SilviuC) 2-Feb-2001
  9. Revision History:
  10. --*/
  11. #include "ldrp.h"
  12. #include "ntos.h"
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <heap.h>
  17. #define AVRF_FLG_EXPORT_DLL_LOADED 0x0001
  18. ULONG AVrfpDebug = 0x0000;
  19. #define AVRF_DBG_SHOW_SNAPS 0x0001
  20. #define AVRF_DBG_SHOW_VERIFIED_EXPORTS 0x0002
  21. #define AVRF_DBG_SHOW_DLLS_WITH_EXPORTS 0x0004
  22. #define AVRF_DBG_SHOW_PROVIDER_LOADS 0x0008
  23. #define AVRF_DBG_SHOW_CHAIN_ACTIVITY 0x0010
  24. #define AVRF_DBG_SHOW_CHAIN_DETAILS 0x0020
  25. #define AVRF_DBG_SHOW_PAGE_HEAP_DETAILS 0x0040
  26. BOOLEAN AVrfpEnabled;
  27. //
  28. // Default system-wide settings
  29. //
  30. #define RTL_VRF_FLG_SYSTEM_WIDE_SETTINGS \
  31. (0 \
  32. | RTL_VRF_FLG_FAST_FILL_HEAP \
  33. | RTL_VRF_FLG_LOCK_CHECKS \
  34. | RTL_VRF_FLG_HANDLE_CHECKS \
  35. )
  36. //
  37. // Local vars
  38. //
  39. ULONG AVrfpVerifierFlags;
  40. LOGICAL AVrfpEnabledSystemWide;
  41. WCHAR AVrfpVerifierDllsString [512];
  42. LIST_ENTRY AVrfpVerifierProvidersList;
  43. RTL_CRITICAL_SECTION AVrfpVerifierLock;
  44. #define VERIFIER_LOCK() RtlEnterCriticalSection(&AVrfpVerifierLock)
  45. #define VERIFIER_UNLOCK() RtlLeaveCriticalSection(&AVrfpVerifierLock)
  46. ULONG AVrfpVirtualProtectFailures;
  47. //
  48. // Local types
  49. //
  50. typedef struct _AVRF_VERIFIER_DESCRIPTOR {
  51. LIST_ENTRY List;
  52. UNICODE_STRING VerifierName;
  53. PVOID VerifierHandle;
  54. PVOID VerifierEntryPoint;
  55. PRTL_VERIFIER_DLL_DESCRIPTOR VerifierDlls;
  56. RTL_VERIFIER_DLL_LOAD_CALLBACK VerifierLoadHandler;
  57. RTL_VERIFIER_DLL_UNLOAD_CALLBACK VerifierUnloadHandler;
  58. RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK VerifierNtdllHeapFreeHandler;
  59. } AVRF_VERIFIER_DESCRIPTOR, *PAVRF_VERIFIER_DESCRIPTOR;
  60. //
  61. // Local functions
  62. //
  63. NTSTATUS
  64. AVrfpSnapDllImports (
  65. PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
  66. );
  67. BOOLEAN
  68. AVrfpDetectVerifiedExports (
  69. PRTL_VERIFIER_DLL_DESCRIPTOR Dll,
  70. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks
  71. );
  72. BOOLEAN
  73. AVrfpParseVerifierDllsString (
  74. PWSTR Dlls
  75. );
  76. VOID
  77. AVrfpSnapAlreadyLoadedDlls (
  78. );
  79. VOID
  80. AVrfpMoveProviderToEndOfInitializationList (
  81. PWSTR ProviderName
  82. );
  83. BOOLEAN
  84. AVrfpLoadAndInitializeProvider (
  85. PAVRF_VERIFIER_DESCRIPTOR Provider
  86. );
  87. BOOLEAN
  88. AVrfpIsVerifierProviderDll (
  89. PVOID Handle
  90. );
  91. VOID
  92. AVrfpDumpProviderList (
  93. );
  94. PVOID
  95. AVrfpFindClosestThunkDuplicate (
  96. PAVRF_VERIFIER_DESCRIPTOR Verifier,
  97. PWCHAR DllName,
  98. PCHAR ThunkName
  99. );
  100. VOID
  101. AVrfpChainDuplicateVerificationLayers (
  102. );
  103. NTSTATUS
  104. AVrfpDllLoadNotificationInternal (
  105. PLDR_DATA_TABLE_ENTRY LoadedDllData
  106. );
  107. PWSTR
  108. AVrfpGetProcessName (
  109. );
  110. BOOLEAN
  111. AVrfpEnableVerifierOptions (
  112. );
  113. LOGICAL
  114. AVrfpIsDebuggerPresent (
  115. VOID
  116. );
  117. NTSTATUS
  118. AVrfpVerifierStopInitialize (
  119. VOID
  120. );
  121. VOID
  122. RtlpPageHeapStop (
  123. ULONG_PTR Code,
  124. PCHAR Message,
  125. ULONG_PTR Param1, PCHAR Description1,
  126. ULONG_PTR Param2, PCHAR Description2,
  127. ULONG_PTR Param3, PCHAR Description3,
  128. ULONG_PTR Param4, PCHAR Description4
  129. );
  130. int __cdecl _snwprintf (wchar_t *, size_t, const wchar_t *, ...);
  131. int __cdecl swprintf (wchar_t *, const wchar_t *, ...);
  132. int __cdecl _vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
  133. int __cdecl _vsnprintf(char *, size_t, const char *, va_list);
  134. /////////////////////////////////////////////////////////////////////
  135. /////////////////////////////////////////////////////////////////////
  136. /////////////////////////////////////////////////////////////////////
  137. // ISSUE: SilviuC: should change this to return status and fail process init
  138. VOID
  139. AVrfInitializeVerifier (
  140. BOOLEAN EnabledSystemWide,
  141. PCUNICODE_STRING ImageName,
  142. ULONG Phase
  143. )
  144. /*++
  145. Routine description:
  146. This routine initializes the verifier package. Reads options
  147. from registry, loads verifier dlls, etc.
  148. Parameters:
  149. EnabledSystemWide - true if all processes are supposed to run with
  150. application verifier enabled. If this is the case we will scale
  151. down our memory-demanding checks so that we can boot.
  152. ImageName - unicode name of the current process
  153. Phase - initialization happens in several stages.
  154. 0 - we read registry settings under image file execution options.
  155. in this phase the other two parameters have a meaning.
  156. 1 - we parse the verifier dlls and load them.
  157. Return value:
  158. None.
  159. --*/
  160. {
  161. BOOLEAN Result;
  162. PLIST_ENTRY Entry;
  163. PAVRF_VERIFIER_DESCRIPTOR Provider;
  164. BOOLEAN LoadSuccess;
  165. NTSTATUS Status;
  166. ULONG RegistryFlags = 0;
  167. switch (Phase) {
  168. case 0: // Phase 0
  169. AVrfpVerifierFlags = RTL_VRF_FLG_SYSTEM_WIDE_SETTINGS;
  170. AVrfpVerifierDllsString[0] = L'\0';
  171. //
  172. // Attempt to read verifier registry settings even if verifier
  173. // is enabled system wide. In the worst case no values are there
  174. // and nothing will be read. If we have some options per process
  175. // this will override system wide settings.
  176. //
  177. LdrQueryImageFileExecutionOptions (ImageName,
  178. L"VerifierFlags",
  179. REG_DWORD,
  180. &RegistryFlags,
  181. sizeof(AVrfpVerifierFlags),
  182. NULL);
  183. if (RegistryFlags == 0) {
  184. //
  185. // Store if verifier enabled system wide. We will need it during
  186. // phase 1 initialization but in that case the EnabledsystemWide
  187. // parameter will not have an accurate value. We do it only if
  188. // we do not find a setting or the setting is zero.
  189. //
  190. if (EnabledSystemWide) {
  191. AVrfpEnabledSystemWide = TRUE;
  192. }
  193. }
  194. else {
  195. AVrfpVerifierFlags = RegistryFlags;
  196. }
  197. LdrQueryImageFileExecutionOptions (ImageName,
  198. L"VerifierDebug",
  199. REG_DWORD,
  200. &AVrfpDebug,
  201. sizeof(AVrfpDebug),
  202. NULL);
  203. LdrQueryImageFileExecutionOptions (ImageName,
  204. L"VerifierDlls",
  205. REG_SZ,
  206. AVrfpVerifierDllsString,
  207. 512,
  208. NULL);
  209. AVrfpEnableVerifierOptions ();
  210. break;
  211. case 1: // Phase 1
  212. InitializeListHead (&AVrfpVerifierProvidersList);
  213. Status = RtlInitializeCriticalSection (&AVrfpVerifierLock);
  214. if (! NT_SUCCESS(Status)) {
  215. goto Done;
  216. }
  217. DbgPrint ("AVRF: %ws: pid 0x%X: flags 0x%X: application verifier enabled\n",
  218. AVrfpGetProcessName(),
  219. RtlGetCurrentProcessId(),
  220. AVrfpVerifierFlags);
  221. Result = AVrfpParseVerifierDllsString (AVrfpVerifierDllsString);
  222. if (Result == FALSE) {
  223. DbgPrint ("AVRF: %ws: pid 0x%X: application verifier will be disabled due to an initialization error.\n",
  224. AVrfpGetProcessName(),
  225. RtlGetCurrentProcessId());
  226. NtCurrentPeb()->NtGlobalFlag &= ~FLG_APPLICATION_VERIFIER;
  227. }
  228. Entry = AVrfpVerifierProvidersList.Flink;
  229. while (Entry != &AVrfpVerifierProvidersList) {
  230. Provider = CONTAINING_RECORD (Entry,
  231. AVRF_VERIFIER_DESCRIPTOR,
  232. List);
  233. //
  234. // Load provider, probe it to make sure it is really a
  235. // provider, call initialize routine with PROCESS_VERIFIER, etc.
  236. //
  237. LoadSuccess = AVrfpLoadAndInitializeProvider (Provider);
  238. //
  239. // Move to next provider
  240. //
  241. Entry = Provider->List.Flink;
  242. //
  243. // Get this provider out of the providers list if we
  244. // encountered an error while loading
  245. //
  246. if (! LoadSuccess) {
  247. RemoveEntryList (&Provider->List);
  248. RtlFreeHeap (RtlProcessHeap(), 0, Provider);
  249. }
  250. }
  251. //
  252. // Chain duplicate verification functions.
  253. //
  254. AVrfpChainDuplicateVerificationLayers ();
  255. //
  256. // Enable verifier. Resnap already loaded dlls.
  257. // Now we will start processing dll load
  258. // notifications coming from loader.
  259. //
  260. AVrfpEnabled = TRUE;
  261. AVrfpSnapAlreadyLoadedDlls ();
  262. if ((AVrfpDebug & AVRF_DBG_SHOW_PROVIDER_LOADS)) {
  263. DbgPrint ("AVRF: -*- final list of providers -*- \n");
  264. AVrfpDumpProviderList ();
  265. }
  266. //
  267. // Enable verifier stops logic. This involves discovering the
  268. // entry point for VerifierStopMessage from verifier.dll ...
  269. //
  270. AVrfpVerifierStopInitialize ();
  271. break;
  272. default:
  273. break;
  274. }
  275. Done:
  276. NOTHING;
  277. }
  278. extern const WCHAR VerifierDllWCharArray[] = L"verifier.dll";
  279. extern const UNICODE_STRING VerifierDllString =
  280. {
  281. sizeof(VerifierDllWCharArray) - sizeof(VerifierDllWCharArray[0]),
  282. sizeof(VerifierDllWCharArray),
  283. (PWSTR)VerifierDllWCharArray
  284. };
  285. BOOLEAN
  286. AVrfpParseVerifierDllsString (
  287. PWSTR Dlls
  288. )
  289. {
  290. PWSTR Current;
  291. PWSTR Start;
  292. WCHAR Save;
  293. PAVRF_VERIFIER_DESCRIPTOR Entry;
  294. HANDLE Heap;
  295. //
  296. // Create by default an entry for the standard provider "verifier.dll"
  297. //
  298. Entry = RtlAllocateHeap (Heap = RtlProcessHeap (), 0, sizeof *Entry);
  299. if (Entry == NULL) {
  300. return FALSE;
  301. }
  302. RtlZeroMemory (Entry, sizeof *Entry);
  303. Entry->VerifierName = VerifierDllString;
  304. InsertTailList (&AVrfpVerifierProvidersList, &Entry->List);
  305. //
  306. // Parse the string
  307. //
  308. Current = Dlls;
  309. while (*Current != L'\0') {
  310. while (*Current == L' ' || *Current == L'\t') {
  311. Current += 1;
  312. }
  313. Start = Current;
  314. while (*Current && *Current != L' ' && *Current != L'\t') {
  315. Current += 1;
  316. }
  317. if (Start == Current) {
  318. break;
  319. }
  320. Save = *Current;
  321. *Current = L'\0';
  322. //
  323. // Check if standard provider was specified explicitely.
  324. // In this case we ignore it because we already have it
  325. // in the list.
  326. //
  327. if (_wcsicmp (Start, VerifierDllWCharArray) != 0) {
  328. Entry = RtlAllocateHeap (Heap, 0, sizeof *Entry);
  329. if (Entry == NULL) {
  330. return FALSE;
  331. }
  332. RtlZeroMemory (Entry, sizeof *Entry);
  333. RtlInitUnicodeString (&Entry->VerifierName, Start);
  334. InsertTailList (&AVrfpVerifierProvidersList, &Entry->List);
  335. }
  336. // *Current = Save;
  337. Current += 1;
  338. }
  339. return TRUE;
  340. }
  341. VOID
  342. AVrfpSnapAlreadyLoadedDlls (
  343. )
  344. {
  345. PPEB_LDR_DATA Ldr;
  346. PLIST_ENTRY Head;
  347. PLIST_ENTRY Next;
  348. PLDR_DATA_TABLE_ENTRY Entry;
  349. Ldr = &PebLdr;
  350. Head = &Ldr->InLoadOrderModuleList;
  351. Next = Head->Flink;
  352. while (Next != Head) {
  353. Entry = CONTAINING_RECORD (Next,
  354. LDR_DATA_TABLE_ENTRY,
  355. InLoadOrderLinks);
  356. Next = Next->Flink;
  357. if (! AVrfpIsVerifierProviderDll (Entry->DllBase)) {
  358. if ((AVrfpDebug & AVRF_DBG_SHOW_SNAPS)) {
  359. DbgPrint ("AVRF: resnapping %ws ... \n",
  360. Entry->BaseDllName.Buffer);
  361. }
  362. AVrfpDllLoadNotificationInternal (Entry);
  363. }
  364. else {
  365. if ((AVrfpDebug & AVRF_DBG_SHOW_SNAPS)) {
  366. DbgPrint ("AVRF: skipped resnapping provider %ws ... \n",
  367. Entry->BaseDllName.Buffer);
  368. }
  369. }
  370. }
  371. }
  372. VOID
  373. AVrfpMoveProviderToEndOfInitializationList (
  374. PWSTR ProviderName
  375. )
  376. {
  377. PPEB_LDR_DATA Ldr;
  378. PLIST_ENTRY Head;
  379. PLIST_ENTRY Next;
  380. PLDR_DATA_TABLE_ENTRY Entry;
  381. BOOLEAN Done = FALSE;
  382. Ldr = &PebLdr;
  383. Head = &Ldr->InInitializationOrderModuleList;
  384. Next = Head->Flink;
  385. while (Next != Head) {
  386. Entry = CONTAINING_RECORD (Next,
  387. LDR_DATA_TABLE_ENTRY,
  388. InInitializationOrderLinks);
  389. if (_wcsicmp (Entry->BaseDllName.Buffer, ProviderName) == 0) {
  390. RemoveEntryList (Next);
  391. InsertTailList (Head, Next);
  392. Done = TRUE;
  393. break;
  394. }
  395. Next = Next->Flink;
  396. }
  397. if (! Done) {
  398. DbgPrint ("AVRF: provider %ws was not found in the initialization list \n",
  399. ProviderName);
  400. DbgBreakPoint ();
  401. }
  402. }
  403. //
  404. // Disable warnings for conversions from function pointers to data pointers.
  405. // We do this when we pass ntdll private entry points to verifier providers.
  406. //
  407. #pragma warning(disable:4054)
  408. BOOLEAN
  409. AVrfpLoadAndInitializeProvider (
  410. PAVRF_VERIFIER_DESCRIPTOR Provider
  411. )
  412. {
  413. PIMAGE_NT_HEADERS NtHeaders;
  414. BOOLEAN LoadError = FALSE;
  415. NTSTATUS Status;
  416. PVOID Descriptor;
  417. PRTL_VERIFIER_PROVIDER_DESCRIPTOR Dscr;
  418. BOOLEAN InitStatus;
  419. static WCHAR SystemDllPathBuffer[DOS_MAX_PATH_LENGTH];
  420. UNICODE_STRING SystemDllPath;
  421. if ((AVrfpDebug & AVRF_DBG_SHOW_SNAPS)) {
  422. DbgPrint ("AVRF: verifier dll `%ws' \n",
  423. Provider->VerifierName.Buffer);
  424. }
  425. //
  426. // Prepare the system search path (%windir%\system32).
  427. // Verifier providers can be loaded only from this directory.
  428. //
  429. SystemDllPath.Buffer = SystemDllPathBuffer;
  430. SystemDllPath.Length = 0;
  431. SystemDllPath.MaximumLength = sizeof(SystemDllPathBuffer);
  432. RtlAppendUnicodeToString (&SystemDllPath, USER_SHARED_DATA->NtSystemRoot);
  433. RtlAppendUnicodeStringToString (&SystemDllPath, &SlashSystem32SlashString);
  434. //
  435. // Load provider dll
  436. //
  437. Status = LdrLoadDll (SystemDllPath.Buffer,
  438. NULL,
  439. &Provider->VerifierName,
  440. &Provider->VerifierHandle);
  441. if (! NT_SUCCESS(Status)) {
  442. DbgPrint ("AVRF: %ws: failed to load provider `%ws' (status %08X) from %ws\n",
  443. AVrfpGetProcessName(),
  444. Provider->VerifierName.Buffer,
  445. Status,
  446. SystemDllPath.Buffer);
  447. LoadError = TRUE;
  448. goto Error;
  449. }
  450. //
  451. // Make sure we have a dll.
  452. //
  453. try {
  454. NtHeaders = RtlImageNtHeader (Provider->VerifierHandle);
  455. if (! NtHeaders) {
  456. LoadError = TRUE;
  457. goto Error;
  458. }
  459. if ((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
  460. DbgPrint ("AVRF: provider %ws is not a DLL image \n",
  461. Provider->VerifierName.Buffer);
  462. LoadError = TRUE;
  463. goto Error;
  464. }
  465. }
  466. except (EXCEPTION_EXECUTE_HANDLER) {
  467. DbgPrint ("AVRF: exception raised while probing provider %ws \n",
  468. Provider->VerifierName.Buffer);
  469. LoadError = TRUE;
  470. goto Error;
  471. }
  472. //
  473. // We loaded the provider successfully. We will move it to the end
  474. // of the initialization list so that code from other system dlls
  475. // on which the provider relies gets initialized first. For normal
  476. // DLLs this is not an issue but a verifier provider gets loaded
  477. // before any normal DLL no matter what dependencies has.
  478. //
  479. AVrfpMoveProviderToEndOfInitializationList (Provider->VerifierName.Buffer);
  480. //
  481. // Now call the initialization routine with the special
  482. // PROCESS_VERIFIER reason.
  483. //
  484. Provider->VerifierEntryPoint = LdrpFetchAddressOfEntryPoint(Provider->VerifierHandle);
  485. if (Provider->VerifierEntryPoint == NULL) {
  486. DbgPrint ("AVRF: cannot find an entry point for provider %ws \n",
  487. Provider->VerifierName.Buffer);
  488. LoadError = TRUE;
  489. goto Error;
  490. }
  491. try {
  492. //
  493. // We are passing a pointer to the verifier dll and expect it to
  494. // fill out its verifier descriptor address in it.
  495. //
  496. Descriptor = NULL;
  497. InitStatus = LdrpCallInitRoutine ((PDLL_INIT_ROUTINE)(ULONG_PTR)(Provider->VerifierEntryPoint),
  498. Provider->VerifierHandle,
  499. DLL_PROCESS_VERIFIER,
  500. (PCONTEXT)(&Descriptor));
  501. if (InitStatus && Descriptor != NULL) {
  502. Dscr = (PRTL_VERIFIER_PROVIDER_DESCRIPTOR)Descriptor;
  503. //
  504. // Check if this is really a provider descriptor.
  505. //
  506. if (Dscr->Length != sizeof (*Dscr)) {
  507. LoadError = TRUE;
  508. DbgPrint ("AVRF: provider %ws passed an invalid descriptor @ %p \n",
  509. Provider->VerifierName.Buffer,
  510. Descriptor);
  511. }
  512. else {
  513. if ((AVrfpDebug & AVRF_DBG_SHOW_PROVIDER_LOADS)) {
  514. DbgPrint ("AVRF: initialized provider %ws (descriptor @ %p) \n",
  515. Provider->VerifierName.Buffer,
  516. Descriptor);
  517. }
  518. Provider->VerifierDlls = Dscr->ProviderDlls;
  519. Provider->VerifierLoadHandler = Dscr->ProviderDllLoadCallback;
  520. Provider->VerifierUnloadHandler = Dscr->ProviderDllUnloadCallback;
  521. Provider->VerifierNtdllHeapFreeHandler = Dscr->ProviderNtdllHeapFreeCallback;
  522. //
  523. // Fill out the provider descriptor structure with goodies.
  524. //
  525. Dscr->VerifierImage = AVrfpGetProcessName();
  526. Dscr->VerifierFlags = AVrfpVerifierFlags;
  527. Dscr->VerifierDebug = AVrfpDebug;
  528. Dscr->RtlpGetStackTraceAddress = (PVOID)RtlpGetStackTraceAddress;
  529. Dscr->RtlpDebugPageHeapCreate = (PVOID)RtlpDebugPageHeapCreate;
  530. Dscr->RtlpDebugPageHeapDestroy = (PVOID)RtlpDebugPageHeapDestroy;
  531. //
  532. // If verifier is enabled system wide we need to flip the bit
  533. // in the VerifierFlags field so that the provider knows about this.
  534. //
  535. if (AVrfpEnabledSystemWide) {
  536. Dscr->VerifierFlags |= RTL_VRF_FLG_ENABLED_SYSTEM_WIDE;
  537. }
  538. //
  539. // Now call again with PROCESS_ATTACH. verifier.dll knowns how to
  540. // deal with multiple PROCESS_ATTACH calls so this is not an issue.
  541. // We need to do this because of a side-effect created by WinSafer.
  542. // WinSafer checks every dll load but in order to do this it loads
  543. // advapi32.dll before anything else. This links statically to a
  544. // bunch of others like kerne32.dll, msvcrt.dll, etc. This creates
  545. // a different load order and init code in kernel32 runs before
  546. // verifier init code managed to run. So this double call here
  547. // fixes that.
  548. //
  549. InitStatus = LdrpCallInitRoutine ((PDLL_INIT_ROUTINE)(ULONG_PTR)(Provider->VerifierEntryPoint),
  550. Provider->VerifierHandle,
  551. DLL_PROCESS_ATTACH,
  552. (PCONTEXT)(&Descriptor));
  553. if (! InitStatus) {
  554. LoadError = TRUE;
  555. DbgPrint ("AVRF: provider %ws did not initialize correctly \n",
  556. Provider->VerifierName.Buffer);
  557. }
  558. }
  559. }
  560. else {
  561. LoadError = TRUE;
  562. DbgPrint ("AVRF: provider %ws did not initialize correctly \n",
  563. Provider->VerifierName.Buffer);
  564. }
  565. }
  566. except (EXCEPTION_EXECUTE_HANDLER) {
  567. DbgPrint ("AVRF: exception raised in provider %ws initialization routine \n",
  568. Provider->VerifierName.Buffer);
  569. LoadError = TRUE;
  570. goto Error;
  571. }
  572. Error:
  573. return !LoadError;
  574. }
  575. BOOLEAN
  576. AVrfpIsVerifierProviderDll (
  577. PVOID Handle
  578. )
  579. {
  580. PLIST_ENTRY Current;
  581. PAVRF_VERIFIER_DESCRIPTOR Entry;;
  582. Current = AVrfpVerifierProvidersList.Flink;
  583. while (Current != &AVrfpVerifierProvidersList) {
  584. Entry = CONTAINING_RECORD (Current,
  585. AVRF_VERIFIER_DESCRIPTOR,
  586. List);
  587. Current = Current->Flink;
  588. if (Entry->VerifierHandle == Handle) {
  589. return TRUE;
  590. }
  591. }
  592. return FALSE;
  593. }
  594. VOID
  595. AVrfpDumpProviderList (
  596. )
  597. {
  598. PLIST_ENTRY Current;
  599. PAVRF_VERIFIER_DESCRIPTOR Entry;
  600. Current = AVrfpVerifierProvidersList.Flink;
  601. while (Current != &AVrfpVerifierProvidersList) {
  602. Entry = CONTAINING_RECORD (Current,
  603. AVRF_VERIFIER_DESCRIPTOR,
  604. List);
  605. Current = Current->Flink;
  606. DbgPrint ("AVRF: provider %ws \n",
  607. Entry->VerifierName.Buffer);
  608. }
  609. }
  610. PVOID
  611. AVrfpFindClosestThunkDuplicate (
  612. PAVRF_VERIFIER_DESCRIPTOR Verifier,
  613. PWCHAR DllName,
  614. PCHAR ThunkName
  615. )
  616. /*++
  617. Routine description:
  618. This function searches the list of providers backwards (reverse load order)
  619. for a function that verifies original export ThunkName from DllName. This
  620. is necessary to implement chaining of verification layers.
  621. Parameters:
  622. Verifier - verifier provider descriptor for which we want to find
  623. duplicates.
  624. DllName - name of a dll containing a verified export
  625. ThunkName - name of the verified export
  626. Return value:
  627. Address of a verification function for the same thunk. Null if none
  628. was found.
  629. --*/
  630. {
  631. PLIST_ENTRY Current;
  632. PAVRF_VERIFIER_DESCRIPTOR Entry;
  633. PRTL_VERIFIER_DLL_DESCRIPTOR Dlls;
  634. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks;
  635. ULONG Di;
  636. ULONG Ti;
  637. Current = Verifier->List.Blink;
  638. while (Current != &AVrfpVerifierProvidersList) {
  639. Entry = CONTAINING_RECORD (Current,
  640. AVRF_VERIFIER_DESCRIPTOR,
  641. List);
  642. Current = Current->Blink;
  643. //
  644. // Search in this provider for the thunk.
  645. //
  646. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_DETAILS)) {
  647. DbgPrint ("AVRF: chain: searching in %ws\n",
  648. Entry->VerifierName.Buffer);
  649. }
  650. Dlls = Entry->VerifierDlls;
  651. for (Di = 0; Dlls[Di].DllName; Di += 1) {
  652. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_DETAILS)) {
  653. DbgPrint ("AVRF: chain: dll: %ws\n",
  654. Dlls[Di].DllName);
  655. }
  656. if (_wcsicmp(Dlls[Di].DllName, DllName) == 0) {
  657. Thunks = Dlls[Di].DllThunks;
  658. for (Ti = 0; Thunks[Ti].ThunkName; Ti += 1) {
  659. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_DETAILS)) {
  660. DbgPrint ("AVRF: chain: thunk: %s == %s ?\n",
  661. Thunks[Ti].ThunkName,
  662. ThunkName);
  663. }
  664. if (_stricmp(Thunks[Ti].ThunkName, ThunkName) == 0) {
  665. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_DETAILS)) {
  666. DbgPrint ("AVRF: Found duplicate for (%ws: %s) in %ws\n",
  667. DllName,
  668. ThunkName,
  669. Dlls[Di].DllName);
  670. }
  671. return Thunks[Ti].ThunkNewAddress;
  672. }
  673. }
  674. }
  675. }
  676. }
  677. return NULL;
  678. }
  679. VOID
  680. AVrfpChainDuplicateVerificationLayers (
  681. )
  682. /*++
  683. Routine description:
  684. This routines is called in the final stage of verifier initialization,
  685. after all provider dlls have been loaded, and makes a final sweep to
  686. detect providers that attempt to verify the same interface. This will be
  687. chained together so that they will be called in reverse load order
  688. (last declared will be first called).
  689. Parameters:
  690. None.
  691. Return value:
  692. None.
  693. --*/
  694. {
  695. PLIST_ENTRY Current;
  696. PAVRF_VERIFIER_DESCRIPTOR Entry;
  697. PRTL_VERIFIER_DLL_DESCRIPTOR Dlls;
  698. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks;
  699. ULONG Di;
  700. ULONG Ti;
  701. PVOID Duplicate;
  702. Current = AVrfpVerifierProvidersList.Flink;
  703. while (Current != &AVrfpVerifierProvidersList) {
  704. Entry = CONTAINING_RECORD (Current,
  705. AVRF_VERIFIER_DESCRIPTOR,
  706. List);
  707. Current = Current->Flink;
  708. //
  709. // Search in this provider for duplicate thunks.
  710. //
  711. Dlls = Entry->VerifierDlls;
  712. for (Di = 0; Dlls[Di].DllName; Di += 1) {
  713. Thunks = Dlls[Di].DllThunks;
  714. for (Ti = 0; Thunks[Ti].ThunkName; Ti += 1) {
  715. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_DETAILS)) {
  716. DbgPrint ("AVRF: Checking %ws for duplicate (%ws: %s) \n",
  717. Entry->VerifierName.Buffer,
  718. Dlls[Di].DllName,
  719. Thunks[Ti].ThunkName);
  720. }
  721. Duplicate = AVrfpFindClosestThunkDuplicate (Entry,
  722. Dlls[Di].DllName,
  723. Thunks[Ti].ThunkName);
  724. if (Duplicate) {
  725. if ((AVrfpDebug & AVRF_DBG_SHOW_CHAIN_ACTIVITY)) {
  726. DbgPrint ("AVRF: Chaining (%ws: %s) to %ws\n",
  727. Dlls[Di].DllName,
  728. Thunks[Ti].ThunkName,
  729. Entry->VerifierName.Buffer);
  730. }
  731. Thunks[Ti].ThunkOldAddress = Duplicate;
  732. }
  733. }
  734. }
  735. }
  736. }
  737. NTSTATUS
  738. AVrfDllLoadNotification (
  739. PLDR_DATA_TABLE_ENTRY LoadedDllData
  740. )
  741. /*++
  742. Routine description:
  743. This routine is the DLL load hook of application verifier. It gets called
  744. whenever a dll got loaded in the process space and after its import
  745. descriptors have been walked.
  746. Parameters:
  747. LoadedDllData - LDR loader structure for the dll.
  748. Return value:
  749. None.
  750. --*/
  751. {
  752. PLIST_ENTRY Current;
  753. PAVRF_VERIFIER_DESCRIPTOR Entry;
  754. NTSTATUS Status;
  755. Status = STATUS_SUCCESS;
  756. //
  757. // Do nothing if application verifier is not enabled. The function
  758. // should not even get called if the flag is not set but we
  759. // double check just in case.
  760. //
  761. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  762. return STATUS_SUCCESS;
  763. }
  764. //
  765. // Get verifier global lock.
  766. //
  767. VERIFIER_LOCK ();
  768. //
  769. // We skip verifier providers. Otherwise we get into infinite loops.
  770. //
  771. if (AVrfpIsVerifierProviderDll (LoadedDllData->DllBase)) {
  772. goto Exit;
  773. }
  774. //
  775. // Call internal function.
  776. //
  777. Status = AVrfpDllLoadNotificationInternal (LoadedDllData);
  778. if (!NT_SUCCESS(Status)) {
  779. goto Exit;
  780. }
  781. //
  782. // Iterate the verifier provider list and notify each one of the
  783. // load event.
  784. Current = AVrfpVerifierProvidersList.Flink;
  785. while (Current != &AVrfpVerifierProvidersList) {
  786. Entry = CONTAINING_RECORD (Current,
  787. AVRF_VERIFIER_DESCRIPTOR,
  788. List);
  789. Current = Current->Flink;
  790. if (Entry->VerifierLoadHandler) {
  791. Entry->VerifierLoadHandler (LoadedDllData->BaseDllName.Buffer,
  792. LoadedDllData->DllBase,
  793. LoadedDllData->SizeOfImage,
  794. LoadedDllData);
  795. }
  796. }
  797. Exit:
  798. VERIFIER_UNLOCK ();
  799. return Status;
  800. }
  801. NTSTATUS
  802. AVrfpDllLoadNotificationInternal (
  803. PLDR_DATA_TABLE_ENTRY LoadedDllData
  804. )
  805. /*++
  806. Routine description:
  807. This routine is the DLL load hook of application verifier. It gets called
  808. whenever a dll got loaded in the process space and after its import
  809. descriptors have been walked. It is also called internally in early stages
  810. of process initialization when we just loaded verifier providers and
  811. we need to resnap dlls already loaded (.exe, ntdll.dll (although on
  812. ntdll this will have zero effect because it does not import anything)).
  813. Parameters:
  814. LoadedDllData - LDR loader structure for the dll.
  815. Return value:
  816. None.
  817. --*/
  818. {
  819. ULONG Index;
  820. PLIST_ENTRY Current;
  821. PAVRF_VERIFIER_DESCRIPTOR Entry;
  822. NTSTATUS Status;
  823. Status = STATUS_SUCCESS;
  824. //
  825. // If verifier is disabled skip.
  826. //
  827. if (AVrfpEnabled == FALSE) {
  828. return Status;
  829. }
  830. //
  831. // Iterate the verifier provider list and for each one determine
  832. // if one of the dlls that has exports to be verified is loaded.
  833. // If this is the case we need to look at its export table in order
  834. // to find out real addresses for functions being redirected.
  835. //
  836. Current = AVrfpVerifierProvidersList.Flink;
  837. while (Current != &AVrfpVerifierProvidersList) {
  838. PRTL_VERIFIER_DLL_DESCRIPTOR Dlls;
  839. Entry = CONTAINING_RECORD (Current,
  840. AVRF_VERIFIER_DESCRIPTOR,
  841. List);
  842. Current = Current->Flink;
  843. Dlls = Entry->VerifierDlls;
  844. for (Index = 0; Dlls[Index].DllName; Index += 1) {
  845. if ((Dlls[Index].DllFlags & AVRF_FLG_EXPORT_DLL_LOADED) == 0) {
  846. int CompareResult;
  847. CompareResult = _wcsicmp (LoadedDllData->BaseDllName.Buffer,
  848. Dlls[Index].DllName);
  849. if (CompareResult == 0) {
  850. if ((AVrfpDebug & AVRF_DBG_SHOW_DLLS_WITH_EXPORTS)) {
  851. DbgPrint ("AVRF: pid 0x%X: found dll descriptor for `%ws' with verified exports \n",
  852. RtlGetCurrentProcessId(),
  853. LoadedDllData->BaseDllName.Buffer);
  854. }
  855. //
  856. // ISSUE: SilviuC: should check failures in detecting
  857. // exports. These can come from fusion land.
  858. //
  859. AVrfpDetectVerifiedExports (&(Dlls[Index]),
  860. Dlls[Index].DllThunks);
  861. }
  862. }
  863. }
  864. }
  865. //
  866. // Note. We do not have to snap other DLLs already loaded because they cannot
  867. // possibly have a dependence on a verifier export just discovered in
  868. // current DLL. If this had been the case, the DLL would have been loaded
  869. // earlier (before the current one).
  870. //
  871. Status = AVrfpSnapDllImports (LoadedDllData);
  872. return Status;
  873. }
  874. VOID
  875. AVrfDllUnloadNotification (
  876. PLDR_DATA_TABLE_ENTRY DllData
  877. )
  878. /*++
  879. Routine description:
  880. This routine is the DLL unload hook of application verifier.
  881. It gets called whenever a dll gets unloaded from the process space.
  882. The hook is called after the DllMain routine of the DLL got called
  883. with PROCESS_DETACH therefore this is the right moment to check for
  884. leaks.
  885. The function will call DllUnload notification routines for all providers
  886. loaded into the process space.
  887. Parameters:
  888. LoadedDllData - LDR loader structure for the dll.
  889. Return value:
  890. None.
  891. --*/
  892. {
  893. PLIST_ENTRY Current;
  894. PAVRF_VERIFIER_DESCRIPTOR Entry;;
  895. //
  896. // Do nothing if application verifier is not enabled. The function
  897. // should not even get called if the flag is not set but we
  898. // double check just in case.
  899. //
  900. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  901. return;
  902. }
  903. //
  904. // If verifier is disabled skip.
  905. //
  906. if (AVrfpEnabled == FALSE) {
  907. return;
  908. }
  909. //
  910. // Get verifier global lock.
  911. //
  912. VERIFIER_LOCK ();
  913. //
  914. // We should never get this call for a verifier provider DLL because
  915. // these are never unloaded.
  916. //
  917. if (AVrfpIsVerifierProviderDll (DllData->DllBase)) {
  918. DbgPrint ("AVRF: AVrfDllUnloadNotification called for a provider (%p) \n",
  919. DllData);
  920. DbgBreakPoint ();
  921. VERIFIER_UNLOCK ();
  922. return;
  923. }
  924. //
  925. // Iterate the verifier provider list and notify each one of the
  926. // unload event.
  927. //
  928. Current = AVrfpVerifierProvidersList.Flink;
  929. while (Current != &AVrfpVerifierProvidersList) {
  930. Entry = CONTAINING_RECORD (Current,
  931. AVRF_VERIFIER_DESCRIPTOR,
  932. List);
  933. Current = Current->Flink;
  934. if (Entry->VerifierUnloadHandler) {
  935. Entry->VerifierUnloadHandler (DllData->BaseDllName.Buffer,
  936. DllData->DllBase,
  937. DllData->SizeOfImage,
  938. DllData);
  939. }
  940. }
  941. VERIFIER_UNLOCK ();
  942. }
  943. VOID
  944. AVrfInternalHeapFreeNotification (
  945. PVOID AllocationBase,
  946. SIZE_T AllocationSize
  947. )
  948. /*++
  949. Routine description:
  950. This routine is the application verifier hook for internal ntdll
  951. HeapFree operations. It gets called by the HeapDestroy page heap
  952. code for each block in the heap being destroyied.
  953. Parameters:
  954. AllocationBase - Heap allocation base address.
  955. AllocationSize - Heap allocation size.
  956. Return value:
  957. None.
  958. --*/
  959. {
  960. PLIST_ENTRY Current;
  961. PAVRF_VERIFIER_DESCRIPTOR Entry;;
  962. //
  963. // Do nothing if application verifier is not enabled. The function
  964. // should not even get called if the flag is not set but we
  965. // double check just in case.
  966. //
  967. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  968. return;
  969. }
  970. //
  971. // If verifier is disabled skip.
  972. //
  973. if (AVrfpEnabled == FALSE) {
  974. return;
  975. }
  976. //
  977. // Get verifier global lock.
  978. //
  979. VERIFIER_LOCK ();
  980. //
  981. // Iterate the verifier provider list and notify each one of the
  982. // unload event.
  983. //
  984. Current = AVrfpVerifierProvidersList.Flink;
  985. while (Current != &AVrfpVerifierProvidersList) {
  986. Entry = CONTAINING_RECORD (Current,
  987. AVRF_VERIFIER_DESCRIPTOR,
  988. List);
  989. Current = Current->Flink;
  990. if (Entry->VerifierNtdllHeapFreeHandler) {
  991. Entry->VerifierNtdllHeapFreeHandler (AllocationBase,
  992. AllocationSize);
  993. }
  994. }
  995. VERIFIER_UNLOCK ();
  996. }
  997. NTSTATUS
  998. AVrfpSnapDllImports (
  999. PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
  1000. )
  1001. /*++
  1002. Routine description:
  1003. This routine walks the already resolved import tables of a loaded
  1004. dll and modifies the addresses of all functions that need to be
  1005. verifier. The dll has just been loaded, imports resolved but dll
  1006. main function has not been called.
  1007. Parameters:
  1008. LdrDataTableEntry - loader descriptor for a loaded dll
  1009. Return value:
  1010. True if we checked all imports of the dll and modified the ones
  1011. that need to be verified. False if an error was encountered along
  1012. the way.
  1013. --*/
  1014. {
  1015. PVOID IATBase;
  1016. SIZE_T BigIATSize;
  1017. ULONG LittleIATSize;
  1018. PVOID *ProcAddresses;
  1019. ULONG NumberOfProcAddresses;
  1020. ULONG OldProtect;
  1021. NTSTATUS st;
  1022. ULONG Pi; // procedure index
  1023. ULONG Di; // dll index
  1024. ULONG Ti; // thunk index
  1025. PLIST_ENTRY Current;
  1026. PAVRF_VERIFIER_DESCRIPTOR Entry;
  1027. PRTL_VERIFIER_DLL_DESCRIPTOR Dlls;
  1028. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks;
  1029. //
  1030. // Determine the location and size of the IAT. If found, scan the
  1031. // IAT address to see if any are pointing to functions that should be
  1032. // verified and replace those thunks.
  1033. //
  1034. IATBase = RtlImageDirectoryEntryToData (LdrDataTableEntry->DllBase,
  1035. TRUE,
  1036. IMAGE_DIRECTORY_ENTRY_IAT,
  1037. &LittleIATSize);
  1038. if (IATBase == NULL) {
  1039. //
  1040. // It is not an error if we do not find an import table in the image.
  1041. // This can be a DLL that simply does not import anything (a resource
  1042. // dll for instance).
  1043. //
  1044. return STATUS_SUCCESS;
  1045. }
  1046. BigIATSize = LittleIATSize;
  1047. //
  1048. // Make table read/write.
  1049. //
  1050. // ISSUE: SilviuC: we can strenghten this a bit if we add some retry scheme
  1051. // to deal with out of mem conditions. This is the typical scenario in
  1052. // which protect can fail.
  1053. //
  1054. st = NtProtectVirtualMemory (NtCurrentProcess(),
  1055. &IATBase,
  1056. &BigIATSize,
  1057. PAGE_READWRITE,
  1058. &OldProtect);
  1059. if (!NT_SUCCESS (st)) {
  1060. InterlockedIncrement ((PLONG)(&AVrfpVirtualProtectFailures));
  1061. if ((AVrfpDebug & AVRF_DBG_SHOW_SNAPS)) {
  1062. DbgPrint ("AVRF: Unable to unprotect IAT to modify thunks (status %08X).\n", st);
  1063. }
  1064. return st;
  1065. }
  1066. ProcAddresses = (PVOID *)IATBase;
  1067. NumberOfProcAddresses = (ULONG)(BigIATSize / sizeof(PVOID));
  1068. for (Pi = 0; Pi < NumberOfProcAddresses; Pi += 1) {
  1069. //
  1070. // If we find a null in the import table we skip over it.
  1071. //
  1072. if (*ProcAddresses == NULL) {
  1073. ProcAddresses += 1;
  1074. continue;
  1075. }
  1076. Current = AVrfpVerifierProvidersList.Flink;
  1077. while (Current != &AVrfpVerifierProvidersList) {
  1078. Entry = CONTAINING_RECORD (Current,
  1079. AVRF_VERIFIER_DESCRIPTOR,
  1080. List);
  1081. Current = Current->Flink;
  1082. Dlls = Entry->VerifierDlls;
  1083. for (Di = 0; Dlls[Di].DllName; Di += 1) {
  1084. Thunks = Dlls[Di].DllThunks;
  1085. for (Ti = 0; Thunks[Ti].ThunkName; Ti += 1) {
  1086. if (*ProcAddresses == Thunks[Ti].ThunkOldAddress) {
  1087. if (Thunks[Ti].ThunkNewAddress) {
  1088. *ProcAddresses = Thunks[Ti].ThunkNewAddress;
  1089. }
  1090. else {
  1091. DbgPrint ("AVRF: internal error: New thunk for %s is null. \n",
  1092. Thunks[Ti].ThunkName);
  1093. DbgBreakPoint ();
  1094. }
  1095. if ((AVrfpDebug & AVRF_DBG_SHOW_SNAPS)) {
  1096. DbgPrint ("AVRF: Snapped (%ws: %s) with (%ws: %p). \n",
  1097. LdrDataTableEntry->BaseDllName.Buffer,
  1098. Thunks[Ti].ThunkName,
  1099. Entry->VerifierName.Buffer,
  1100. Thunks[Ti].ThunkNewAddress);
  1101. }
  1102. }
  1103. }
  1104. }
  1105. }
  1106. ProcAddresses += 1;
  1107. }
  1108. //
  1109. // Restore old protection for the table. We do not fail the entire
  1110. // function if this protect fails because not managing to switch back
  1111. // from RW to RO is something we can live with.
  1112. //
  1113. NtProtectVirtualMemory (NtCurrentProcess(),
  1114. &IATBase,
  1115. &BigIATSize,
  1116. OldProtect,
  1117. &OldProtect);
  1118. return st;
  1119. }
  1120. BOOLEAN
  1121. AVrfpDetectVerifiedExports (
  1122. PRTL_VERIFIER_DLL_DESCRIPTOR Dll,
  1123. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks
  1124. )
  1125. /*++
  1126. Routine description:
  1127. This routine checks if `DllString' is the name of a dll that has
  1128. exports that need to be verifier. If it does then we detect the
  1129. addresses of all those exports. We need the addresses to detect
  1130. what imports need to be modified by application verifier.
  1131. Parameters:
  1132. DlString - name of a dll exporting verified interfaces.
  1133. Thunks - array of thunk descriptors for our dll
  1134. Return value:
  1135. True if verified exports have been detected. False if an error has been
  1136. encountered.
  1137. --*/
  1138. {
  1139. UNICODE_STRING DllName;
  1140. PLDR_DATA_TABLE_ENTRY DllData;
  1141. BOOLEAN Result = FALSE;
  1142. NTSTATUS Status;
  1143. WCHAR StaticRedirectionBuffer[DOS_MAX_PATH_LENGTH];
  1144. UNICODE_STRING StaticRedirectionString;
  1145. UNICODE_STRING DynamicRedirectionString;
  1146. PUNICODE_STRING DllNameToUse;
  1147. BOOLEAN Redirected = FALSE;
  1148. ULONG Ti;
  1149. DllData = NULL;
  1150. //
  1151. // "Fusion-ize" the dll name.
  1152. //
  1153. RtlInitUnicodeString (&DllName,
  1154. Dll->DllName);
  1155. DynamicRedirectionString.Buffer = NULL;
  1156. DynamicRedirectionString.Length = 0;
  1157. DynamicRedirectionString.MaximumLength = 0;
  1158. StaticRedirectionString.Length = 0;
  1159. StaticRedirectionString.MaximumLength = sizeof(StaticRedirectionBuffer);
  1160. StaticRedirectionString.Buffer = StaticRedirectionBuffer;
  1161. DllNameToUse = &DllName;
  1162. Status = RtlDosApplyFileIsolationRedirection_Ustr(
  1163. RTL_DOS_APPLY_FILE_REDIRECTION_USTR_FLAG_RESPECT_DOT_LOCAL,
  1164. &DllName,
  1165. &DefaultExtension,
  1166. &StaticRedirectionString,
  1167. &DynamicRedirectionString,
  1168. &DllNameToUse,
  1169. NULL,
  1170. NULL,
  1171. NULL);
  1172. if (NT_SUCCESS(Status)) {
  1173. Redirected = TRUE;
  1174. } else if (Status == STATUS_SXS_KEY_NOT_FOUND) {
  1175. Status = STATUS_SUCCESS;
  1176. }
  1177. //
  1178. // Get the loader descriptor for this dll.
  1179. //
  1180. // ISSUE: SilviuC: This search and fusion code above are totally redundant
  1181. // because this function is always called when the dll in which we look for
  1182. // exports is loaded (just loaded actually) and the function above that
  1183. // calls this one has actually a pointer to the LDR entry therefore we do
  1184. // not need to search here again.
  1185. //
  1186. if (NT_SUCCESS(Status)) {
  1187. Result = LdrpCheckForLoadedDll (NULL,
  1188. DllNameToUse,
  1189. TRUE,
  1190. Redirected,
  1191. &DllData);
  1192. if (DynamicRedirectionString.Buffer != NULL) {
  1193. RtlFreeUnicodeString(&DynamicRedirectionString);
  1194. }
  1195. }
  1196. if (Result == FALSE) {
  1197. //
  1198. // We exit of we failed to fusionize name or did not find
  1199. // the dll among the loaded ones.
  1200. //
  1201. return FALSE;
  1202. }
  1203. //
  1204. // Search for exports from this dll that need to be verified.
  1205. // We need their original addresses.
  1206. //
  1207. for (Ti = 0; Thunks[Ti].ThunkName; Ti += 1) {
  1208. PVOID OriginalAddress;
  1209. ANSI_STRING FunctionName;
  1210. //
  1211. // If old thunk already filled (can happen due to chaining)
  1212. // then skip search for the original address.
  1213. //
  1214. if (Thunks[Ti].ThunkOldAddress) {
  1215. continue;
  1216. }
  1217. RtlInitAnsiString (&FunctionName, Thunks[Ti].ThunkName);
  1218. //
  1219. // It is crucial that the last parameter is FALSE so that
  1220. // LdrpGetProcedureAddress() does not call init routines.
  1221. //
  1222. Status = LdrpGetProcedureAddress (DllData->DllBase,
  1223. &FunctionName,
  1224. 0,
  1225. &OriginalAddress,
  1226. FALSE);
  1227. if (! NT_SUCCESS(Status)) {
  1228. DbgPrint ("AVRF: warning: did not find `%s' export in %ws . \n",
  1229. Thunks[Ti].ThunkName,
  1230. DllData->BaseDllName.Buffer);
  1231. continue;
  1232. }
  1233. Thunks[Ti].ThunkOldAddress = OriginalAddress;
  1234. if ((AVrfpDebug & AVRF_DBG_SHOW_VERIFIED_EXPORTS)) {
  1235. DbgPrint ("AVRF: (%ws) %s export found. \n",
  1236. DllData->BaseDllName.Buffer,
  1237. Thunks[Ti].ThunkName);
  1238. }
  1239. }
  1240. return TRUE;
  1241. }
  1242. PWSTR
  1243. AVrfpGetProcessName (
  1244. VOID
  1245. )
  1246. {
  1247. PPEB_LDR_DATA Ldr;
  1248. PLIST_ENTRY Head;
  1249. PLIST_ENTRY Next;
  1250. PLDR_DATA_TABLE_ENTRY Entry;
  1251. Ldr = &PebLdr;
  1252. Head = &Ldr->InLoadOrderModuleList;
  1253. Next = Head->Flink;
  1254. Entry = CONTAINING_RECORD (Next,
  1255. LDR_DATA_TABLE_ENTRY,
  1256. InLoadOrderLinks);
  1257. return Entry->BaseDllName.Buffer;
  1258. }
  1259. /////////////////////////////////////////////////////////////////////
  1260. ///////////////////////////////////// Verifier options initialization
  1261. /////////////////////////////////////////////////////////////////////
  1262. BOOLEAN
  1263. AVrfpEnableHandleVerifier (
  1264. VOID
  1265. )
  1266. {
  1267. PROCESS_HANDLE_TRACING_ENABLE HandleCheckEnable;
  1268. NTSTATUS Status;
  1269. RtlZeroMemory (&HandleCheckEnable, sizeof HandleCheckEnable);
  1270. Status = NtSetInformationProcess (NtCurrentProcess(),
  1271. ProcessHandleTracing,
  1272. &HandleCheckEnable,
  1273. sizeof HandleCheckEnable);
  1274. if (!NT_SUCCESS (Status)) {
  1275. DbgPrint ("AVRF: failed to enable handle checking (status %X) \n",
  1276. Status);
  1277. return FALSE;
  1278. }
  1279. return TRUE;
  1280. }
  1281. BOOLEAN
  1282. AVrfpEnableStackVerifier (
  1283. VOID
  1284. )
  1285. {
  1286. //
  1287. // We enable potential stack overflow checking only if we have some debugger
  1288. // attached and logging was not requested. Since stack overflows are very
  1289. // difficult to catch without a debugger attached we consider it is better
  1290. // disabling it than confusing people.
  1291. //
  1292. if (AVrfpIsDebuggerPresent() &&
  1293. (AVrfpVerifierFlags & RTL_VRF_FLG_ENABLE_LOGGING) == 0) {
  1294. NtCurrentPeb()->NtGlobalFlag |= FLG_DISABLE_STACK_EXTENSION;
  1295. }
  1296. return TRUE;
  1297. }
  1298. BOOLEAN
  1299. AVrfpEnableLockVerifier (
  1300. VOID
  1301. )
  1302. {
  1303. RtlpCriticalSectionVerifier = TRUE;
  1304. return TRUE;
  1305. }
  1306. BOOLEAN
  1307. AVrfpEnableHeapVerifier (
  1308. VOID
  1309. )
  1310. {
  1311. extern ULONG RtlpDphGlobalFlags;
  1312. if (AVrfpVerifierFlags & RTL_VRF_FLG_FULL_PAGE_HEAP) {
  1313. NtCurrentPeb()->NtGlobalFlag |= FLG_HEAP_PAGE_ALLOCS;
  1314. RtlpDphGlobalFlags |= PAGE_HEAP_ENABLE_PAGE_HEAP;
  1315. }
  1316. else if (AVrfpVerifierFlags & RTL_VRF_FLG_FAST_FILL_HEAP) {
  1317. NtCurrentPeb()->NtGlobalFlag |= FLG_HEAP_PAGE_ALLOCS;
  1318. }
  1319. else {
  1320. //
  1321. // Nothing.
  1322. //
  1323. }
  1324. return TRUE;
  1325. }
  1326. BOOLEAN
  1327. AVrfpEnableVerifierOptions (
  1328. VOID
  1329. )
  1330. {
  1331. BOOLEAN Result;
  1332. BOOLEAN Failures = FALSE;
  1333. //
  1334. // Heap verifier in some form is enabled always.
  1335. //
  1336. Result = AVrfpEnableHeapVerifier ();
  1337. if (Result == FALSE) {
  1338. Failures = TRUE;
  1339. }
  1340. //
  1341. // Handle checks
  1342. //
  1343. if (AVrfpVerifierFlags & RTL_VRF_FLG_HANDLE_CHECKS) {
  1344. Result = AVrfpEnableHandleVerifier ();
  1345. if (Result == FALSE) {
  1346. Failures = TRUE;
  1347. }
  1348. }
  1349. //
  1350. // Stack overflow checks
  1351. //
  1352. if (AVrfpVerifierFlags & RTL_VRF_FLG_STACK_CHECKS) {
  1353. Result = AVrfpEnableStackVerifier ();
  1354. if (Result == FALSE) {
  1355. Failures = TRUE;
  1356. }
  1357. }
  1358. //
  1359. // Lock checks
  1360. //
  1361. if (AVrfpVerifierFlags & RTL_VRF_FLG_LOCK_CHECKS) {
  1362. Result = AVrfpEnableLockVerifier ();
  1363. if (Result == FALSE) {
  1364. Failures = TRUE;
  1365. }
  1366. }
  1367. return !Failures;
  1368. }
  1369. /////////////////////////////////////////////////////////////////////
  1370. ////////////////////////////////////////// Application verifier stops
  1371. /////////////////////////////////////////////////////////////////////
  1372. //
  1373. // VerifierStopMessage entry point from verifier.dll.
  1374. //
  1375. #pragma warning(disable:4055)
  1376. typedef VOID
  1377. (* STOP_MESSAGE_FUNCTION_TYPE) (
  1378. ULONG_PTR Code,
  1379. PCHAR Message,
  1380. ULONG_PTR Param1, PCHAR Description1,
  1381. ULONG_PTR Param2, PCHAR Description2,
  1382. ULONG_PTR Param3, PCHAR Description3,
  1383. ULONG_PTR Param4, PCHAR Description4
  1384. );
  1385. STOP_MESSAGE_FUNCTION_TYPE AVrfpVerifierStopMessageFunction;
  1386. LOGICAL
  1387. AVrfpIsDebuggerPresent (
  1388. VOID
  1389. )
  1390. /*++
  1391. Routine description:
  1392. This routine checks out if we have any kind of debuggers active.
  1393. Note that we cannot do this check only once during process
  1394. initialization because debuggers can be attached and detached
  1395. from a process while the process is running.
  1396. Parameters:
  1397. None.
  1398. Return value:
  1399. TRUE if a user mode debugger is attached to the current process or
  1400. kernel mode debugger is enabled.
  1401. --*/
  1402. {
  1403. if (NtCurrentPeb()->BeingDebugged) {
  1404. return TRUE;
  1405. }
  1406. if (USER_SHARED_DATA->KdDebuggerEnabled) {
  1407. return TRUE;
  1408. }
  1409. return FALSE;
  1410. }
  1411. NTSTATUS
  1412. AVrfpVerifierStopInitialize (
  1413. VOID
  1414. )
  1415. {
  1416. NTSTATUS Status;
  1417. PVOID VerifierDllAddress = NULL;
  1418. ANSI_STRING FunctionName;
  1419. PVOID FunctionAddress;
  1420. PLIST_ENTRY Entry;
  1421. PAVRF_VERIFIER_DESCRIPTOR Provider;
  1422. //
  1423. // Find load address for verifier.dll.
  1424. //
  1425. Entry = AVrfpVerifierProvidersList.Flink;
  1426. while (Entry != &AVrfpVerifierProvidersList) {
  1427. Provider = CONTAINING_RECORD (Entry,
  1428. AVRF_VERIFIER_DESCRIPTOR,
  1429. List);
  1430. if (_wcsicmp(Provider->VerifierName.Buffer, L"verifier.dll") == 0) {
  1431. VerifierDllAddress = Provider->VerifierHandle;
  1432. break;
  1433. }
  1434. Entry = Provider->List.Flink;
  1435. }
  1436. ASSERT (VerifierDllAddress != NULL);
  1437. if (VerifierDllAddress == NULL) {
  1438. DbgPrint ("AVRF: Failed to find verifier.dll among loaded providers! \n");
  1439. return STATUS_UNSUCCESSFUL;
  1440. }
  1441. //
  1442. // It is crucial that the last parameter is FALSE so that
  1443. // LdrpGetProcedureAddress() does not call init routines.
  1444. //
  1445. RtlInitAnsiString (&FunctionName, "VerifierStopMessage");
  1446. Status = LdrpGetProcedureAddress (VerifierDllAddress,
  1447. &FunctionName,
  1448. 0,
  1449. &FunctionAddress,
  1450. FALSE);
  1451. if (! NT_SUCCESS(Status)) {
  1452. DbgPrint ("AVRF: Failed to find `VerifierStopMessage()' export in verifier.dll! \n");
  1453. return Status;
  1454. }
  1455. AVrfpVerifierStopMessageFunction = (STOP_MESSAGE_FUNCTION_TYPE)FunctionAddress;
  1456. return Status;
  1457. }
  1458. VOID
  1459. RtlApplicationVerifierStop (
  1460. ULONG_PTR Code,
  1461. PCHAR Message,
  1462. ULONG_PTR Param1, PCHAR Description1,
  1463. ULONG_PTR Param2, PCHAR Description2,
  1464. ULONG_PTR Param3, PCHAR Description3,
  1465. ULONG_PTR Param4, PCHAR Description4
  1466. )
  1467. /*++
  1468. Routine description:
  1469. This routine will call the real implementation from
  1470. verifier.dll VerifierStopMessage().
  1471. Parameters:
  1472. Code: Verifier stop code. The two flags described above can be OR'd into the code
  1473. to change the behavior of the API. The verifier stop codes are defined in
  1474. \base\published\nturtl.w and described in \base\win32\verifier\verifier_stop.doc.
  1475. Message: Ascii string describing the failure. It is considered bad style to use several
  1476. different messages with the same `Code'. Every different issue should have its own
  1477. unique (Code, Message) pair.
  1478. Param1, Description1: First arbitrary pointer to information and ascii description.
  1479. Param2, Description2: Second arbitrary pointer to information and ascii description.
  1480. Param3, Description3: Third arbitrary pointer to information and ascii description.
  1481. Param4, Description4: Fourth arbitrary pointer to information and ascii description.
  1482. Return value:
  1483. None.
  1484. --*/
  1485. {
  1486. ULONG GlobalFlags;
  1487. GlobalFlags = NtCurrentPeb()->NtGlobalFlag;
  1488. if ((GlobalFlags & FLG_APPLICATION_VERIFIER) == 0 &&
  1489. (GlobalFlags & FLG_HEAP_PAGE_ALLOCS) != 0) {
  1490. //
  1491. // If page heap is enabled separately then go to a simplified function.
  1492. //
  1493. RtlpPageHeapStop (Code, Message,
  1494. Param1, Description1,
  1495. Param2, Description2,
  1496. Param3, Description3,
  1497. Param4, Description4);
  1498. return;
  1499. }
  1500. else if (AVrfpVerifierStopMessageFunction) {
  1501. //
  1502. // If application verifier is enabled and we have discovered
  1503. // the entry point for VerifierStopMessage() then call it.
  1504. //
  1505. AVrfpVerifierStopMessageFunction (Code, Message,
  1506. Param1, Description1,
  1507. Param2, Description2,
  1508. Param3, Description3,
  1509. Param4, Description4);
  1510. }
  1511. else {
  1512. //
  1513. // Nothing. We can get here if someone calls this interface w/o
  1514. // enabling application verifier.
  1515. //
  1516. }
  1517. }
  1518. ULONG_PTR AVrfpPageHeapPreviousStopData[5];
  1519. ULONG_PTR AVrfpPageHeapStopData[5];
  1520. VOID
  1521. RtlpPageHeapStop (
  1522. ULONG_PTR Code,
  1523. PCHAR Message,
  1524. ULONG_PTR Param1, PCHAR Description1,
  1525. ULONG_PTR Param2, PCHAR Description2,
  1526. ULONG_PTR Param3, PCHAR Description3,
  1527. ULONG_PTR Param4, PCHAR Description4
  1528. )
  1529. {
  1530. //
  1531. // Make it easy for a debugger to pick up the failure info.
  1532. //
  1533. RtlCopyMemory (AVrfpPageHeapPreviousStopData,
  1534. AVrfpPageHeapStopData,
  1535. sizeof AVrfpPageHeapStopData);
  1536. AVrfpPageHeapStopData[0] = Code;
  1537. AVrfpPageHeapStopData[1] = Param1;
  1538. AVrfpPageHeapStopData[2] = Param2;
  1539. AVrfpPageHeapStopData[3] = Param3;
  1540. AVrfpPageHeapStopData[4] = Param4;
  1541. DbgPrint ("\n\n"
  1542. "===========================================================\n"
  1543. "VERIFIER STOP %p: pid 0x%X: %s \n"
  1544. "\n\t%p : %s\n\t%p : %s\n\t%p : %s\n\t%p : %s\n"
  1545. "===========================================================\n\n",
  1546. Code, RtlGetCurrentProcessId(), Message,
  1547. Param1, Description1,
  1548. Param2, Description2,
  1549. Param3, Description3,
  1550. Param4, Description4);
  1551. DbgBreakPoint ();
  1552. }
  1553. /////////////////////////////////////////////////////////////////////
  1554. ////////////////////////////////////////// Page heap target dll logic
  1555. /////////////////////////////////////////////////////////////////////
  1556. //
  1557. // ISSUE: SilviuC: pageheap per dll code should move into verifier.dll
  1558. //
  1559. BOOLEAN AVrfpDphKernel32Snapped;
  1560. BOOLEAN AVrfpDphMsvcrtSnapped;
  1561. #define SNAP_ROUTINE_GLOBALALLOC 0
  1562. #define SNAP_ROUTINE_GLOBALREALLOC 1
  1563. #define SNAP_ROUTINE_GLOBALFREE 2
  1564. #define SNAP_ROUTINE_LOCALALLOC 3
  1565. #define SNAP_ROUTINE_LOCALREALLOC 4
  1566. #define SNAP_ROUTINE_LOCALFREE 5
  1567. #define SNAP_ROUTINE_HEAPALLOC 6
  1568. #define SNAP_ROUTINE_HEAPREALLOC 7
  1569. #define SNAP_ROUTINE_HEAPFREE 8
  1570. #define SNAP_ROUTINE_HEAPCREATE 9
  1571. #define SNAP_ROUTINE_MALLOC 10
  1572. #define SNAP_ROUTINE_CALLOC 11
  1573. #define SNAP_ROUTINE_REALLOC 12
  1574. #define SNAP_ROUTINE_FREE 13
  1575. #define SNAP_ROUTINE_NEW 14
  1576. #define SNAP_ROUTINE_DELETE 15
  1577. #define SNAP_ROUTINE_NEW_ARRAY 16
  1578. #define SNAP_ROUTINE_DELETE_ARRAY 17
  1579. #define SNAP_ROUTINE_MAX_INDEX 18
  1580. PVOID AVrfpDphSnapRoutines [SNAP_ROUTINE_MAX_INDEX];
  1581. typedef struct _DPH_SNAP_NAME {
  1582. PSTR Name;
  1583. ULONG Index;
  1584. } DPH_SNAP_NAME, * PDPH_SNAP_NAME;
  1585. DPH_SNAP_NAME
  1586. AVrfpDphSnapNamesForKernel32 [] = {
  1587. { "GlobalAlloc", 0 },
  1588. { "GlobalReAlloc", 1 },
  1589. { "GlobalFree", 2 },
  1590. { "LocalAlloc", 3 },
  1591. { "LocalReAlloc", 4 },
  1592. { "LocalFree", 5 },
  1593. { "HeapAlloc", 6 },
  1594. { "HeapReAlloc", 7 },
  1595. { "HeapFree", 8 },
  1596. { "HeapCreate", 9 },
  1597. { NULL, 0 }
  1598. };
  1599. DPH_SNAP_NAME
  1600. AVrfpDphSnapNamesForMsvcrt [] = {
  1601. { "malloc", 10},
  1602. { "calloc", 11},
  1603. { "realloc", 12},
  1604. { "free", 13},
  1605. #if defined(_X86_) // compilers for various architectures decorate slightly different
  1606. {"??2@YAPAXI@Z", 14},
  1607. {"??3@YAXPAX@Z", 15},
  1608. {"??_U@YAPAXI@Z", 16},
  1609. {"??_V@YAXPAX@Z", 17},
  1610. #elif defined(_IA64_)
  1611. {"??2@YAPEAX_K@Z", 14},
  1612. {"??3@YAXPEAX@Z", 15},
  1613. {"??_U@YAPEAX_K@Z",16},
  1614. {"??_V@YAXPEAX@Z", 17},
  1615. #elif defined(_AMD64_)
  1616. {"??2@YAPAX_K@Z", 14},
  1617. {"??3@YAXPAX@Z", 15},
  1618. {"??_U@YAPAX_K@Z", 16},
  1619. {"??_V@YAXPAX@Z", 17},
  1620. #else
  1621. #error Unknown architecture
  1622. #endif
  1623. { NULL, 0 }
  1624. };
  1625. //
  1626. // Declarations for replacement functions
  1627. //
  1628. PVOID
  1629. AVrfpDphDllHeapAlloc (
  1630. IN PVOID HeapHandle,
  1631. IN ULONG Flags,
  1632. IN SIZE_T Size
  1633. );
  1634. PVOID
  1635. AVrfpDphDllHeapReAlloc (
  1636. IN PVOID HeapHandle,
  1637. IN ULONG Flags,
  1638. IN PVOID Address,
  1639. IN SIZE_T Size
  1640. );
  1641. BOOLEAN
  1642. AVrfpDphDllHeapFree(
  1643. IN PVOID HeapHandle,
  1644. IN ULONG Flags,
  1645. IN PVOID Address
  1646. );
  1647. PVOID
  1648. AVrfpDphDllLocalAlloc (
  1649. IN ULONG Flags,
  1650. IN SIZE_T Size
  1651. );
  1652. PVOID
  1653. AVrfpDphDllLocalReAlloc (
  1654. IN PVOID Address,
  1655. IN SIZE_T Size,
  1656. IN ULONG Flags
  1657. );
  1658. PVOID
  1659. AVrfpDphDllLocalFree(
  1660. IN PVOID Address
  1661. );
  1662. PVOID
  1663. AVrfpDphDllGlobalAlloc (
  1664. IN ULONG Flags,
  1665. IN SIZE_T Size
  1666. );
  1667. PVOID
  1668. AVrfpDphDllGlobalReAlloc (
  1669. IN PVOID Address,
  1670. IN SIZE_T Size,
  1671. IN ULONG Flags
  1672. );
  1673. PVOID
  1674. AVrfpDphDllGlobalFree(
  1675. IN PVOID Address
  1676. );
  1677. PVOID __cdecl
  1678. AVrfpDphDllmalloc (
  1679. IN SIZE_T Size
  1680. );
  1681. PVOID __cdecl
  1682. AVrfpDphDllcalloc (
  1683. IN SIZE_T Number,
  1684. IN SIZE_T Size
  1685. );
  1686. PVOID __cdecl
  1687. AVrfpDphDllrealloc (
  1688. IN PVOID Address,
  1689. IN SIZE_T Size
  1690. );
  1691. VOID __cdecl
  1692. AVrfpDphDllfree (
  1693. IN PVOID Address
  1694. );
  1695. PVOID __cdecl
  1696. AVrfpDphDllNew (
  1697. IN SIZE_T Size
  1698. );
  1699. VOID __cdecl
  1700. AVrfpDphDllDelete (
  1701. IN PVOID Address
  1702. );
  1703. PVOID __cdecl
  1704. AVrfpDphDllNewArray (
  1705. IN SIZE_T Size
  1706. );
  1707. VOID __cdecl
  1708. AVrfpDphDllDeleteArray (
  1709. IN PVOID Address
  1710. );
  1711. //
  1712. // Replacement function for msvcrt HeapCreate used to intercept
  1713. // the CRT heap creation.
  1714. //
  1715. PVOID
  1716. AVrfpDphDllHeapCreate (
  1717. ULONG Options,
  1718. SIZE_T InitialSize,
  1719. SIZE_T MaximumSize
  1720. );
  1721. //
  1722. // Address of heap created by msvcrt. This is needed
  1723. // by the replacements of malloc/free etc.
  1724. //
  1725. PVOID AVrfpDphMsvcrtHeap;
  1726. //
  1727. // Snap implementation
  1728. //
  1729. BOOLEAN
  1730. AVrfpDphDetectSnapRoutines (
  1731. PWSTR DllString,
  1732. PDPH_SNAP_NAME SnapNames
  1733. )
  1734. {
  1735. PLDR_DATA_TABLE_ENTRY DllData;
  1736. PIMAGE_EXPORT_DIRECTORY Directory;
  1737. ULONG Size;
  1738. PCHAR NameAddress;
  1739. PCHAR FunctionAddress;
  1740. PCHAR Base;
  1741. PCHAR IndexAddress;
  1742. ULONG Index;
  1743. ULONG RealIndex;
  1744. BOOLEAN Result = FALSE;
  1745. UNICODE_STRING DllName;
  1746. PDPH_SNAP_NAME CurrentSnapName;
  1747. NTSTATUS Status;
  1748. WCHAR StaticRedirectionBuffer[DOS_MAX_PATH_LENGTH];
  1749. UNICODE_STRING StaticRedirectionString;
  1750. UNICODE_STRING DynamicRedirectionString;
  1751. PUNICODE_STRING DllNameToUse;
  1752. BOOLEAN Redirected = FALSE;
  1753. DllData = NULL;
  1754. RtlInitUnicodeString (
  1755. &DllName,
  1756. DllString);
  1757. DynamicRedirectionString.Buffer = NULL;
  1758. DynamicRedirectionString.Length = 0;
  1759. DynamicRedirectionString.MaximumLength = 0;
  1760. StaticRedirectionString.Length = 0;
  1761. StaticRedirectionString.MaximumLength = sizeof(StaticRedirectionBuffer);
  1762. StaticRedirectionString.Buffer = StaticRedirectionBuffer;
  1763. DllNameToUse = &DllName;
  1764. Status = RtlDosApplyFileIsolationRedirection_Ustr(
  1765. RTL_DOS_APPLY_FILE_REDIRECTION_USTR_FLAG_RESPECT_DOT_LOCAL,
  1766. &DllName,
  1767. &DefaultExtension,
  1768. &StaticRedirectionString,
  1769. &DynamicRedirectionString,
  1770. &DllNameToUse,
  1771. NULL,
  1772. NULL,
  1773. NULL);
  1774. if (NT_SUCCESS(Status)) {
  1775. Redirected = TRUE;
  1776. } else if (Status == STATUS_SXS_KEY_NOT_FOUND) {
  1777. Status = STATUS_SUCCESS;
  1778. }
  1779. if (NT_SUCCESS(Status)) {
  1780. Result = LdrpCheckForLoadedDll (
  1781. NULL,
  1782. DllNameToUse,
  1783. TRUE,
  1784. Redirected,
  1785. &DllData);
  1786. if (DynamicRedirectionString.Buffer != NULL)
  1787. RtlFreeUnicodeString(&DynamicRedirectionString);
  1788. }
  1789. if (Result == FALSE) {
  1790. return FALSE;
  1791. }
  1792. Base = DllData->DllBase;
  1793. Directory = RtlImageDirectoryEntryToData (
  1794. DllData->DllBase,
  1795. TRUE,
  1796. IMAGE_DIRECTORY_ENTRY_EXPORT,
  1797. &Size
  1798. );
  1799. if (Directory == NULL) {
  1800. return FALSE;
  1801. }
  1802. for (CurrentSnapName = SnapNames; CurrentSnapName->Name; CurrentSnapName += 1) {
  1803. for (Index = 0; Index < Directory->NumberOfFunctions; Index += 1) {
  1804. NameAddress = Base + Directory->AddressOfNames;
  1805. NameAddress = Base + ((ULONG *)NameAddress)[Index];
  1806. IndexAddress = Base + Directory->AddressOfNameOrdinals;
  1807. RealIndex = (ULONG)(((USHORT *)IndexAddress)[Index]);
  1808. if (_stricmp (NameAddress, CurrentSnapName->Name) == 0) {
  1809. FunctionAddress = Base + Directory->AddressOfFunctions;
  1810. FunctionAddress = Base + ((ULONG *)FunctionAddress)[RealIndex];
  1811. AVrfpDphSnapRoutines[CurrentSnapName->Index] = FunctionAddress;
  1812. if ((AVrfpDebug & AVRF_DBG_SHOW_PAGE_HEAP_DETAILS)) {
  1813. DbgPrint ("Page heap: found %s @ address %p \n",
  1814. NameAddress,
  1815. FunctionAddress);
  1816. }
  1817. }
  1818. }
  1819. }
  1820. return TRUE;
  1821. }
  1822. NTSTATUS
  1823. AVrfpDphSnapImports (
  1824. PLDR_DATA_TABLE_ENTRY LdrDataTableEntry,
  1825. BOOLEAN CallToDetectCrtHeap
  1826. )
  1827. {
  1828. PVOID IATBase;
  1829. SIZE_T BigIATSize;
  1830. ULONG LittleIATSize;
  1831. PVOID *ProcAddresses;
  1832. ULONG NumberOfProcAddresses;
  1833. ULONG OldProtect;
  1834. NTSTATUS st;
  1835. st = STATUS_SUCCESS;
  1836. //
  1837. // Determine the location and size of the IAT. If found, scan the
  1838. // IAT address to see if any are pointing to alloc/free functions
  1839. // and replace those thunks.
  1840. //
  1841. IATBase = RtlImageDirectoryEntryToData(
  1842. LdrDataTableEntry->DllBase,
  1843. TRUE,
  1844. IMAGE_DIRECTORY_ENTRY_IAT,
  1845. &LittleIATSize);
  1846. if (IATBase != NULL) {
  1847. BigIATSize = LittleIATSize;
  1848. st = NtProtectVirtualMemory (NtCurrentProcess(),
  1849. &IATBase,
  1850. &BigIATSize,
  1851. PAGE_READWRITE,
  1852. &OldProtect);
  1853. if (!NT_SUCCESS(st)) {
  1854. InterlockedIncrement ((PLONG)(&AVrfpVirtualProtectFailures));
  1855. if ((AVrfpDebug & AVRF_DBG_SHOW_PAGE_HEAP_DETAILS)) {
  1856. DbgPrint ("Page heap: Unable to unprotect IAT to enable per DLL page heap.\n" );
  1857. }
  1858. return st;
  1859. }
  1860. else {
  1861. ProcAddresses = (PVOID *)IATBase;
  1862. NumberOfProcAddresses = (ULONG)(BigIATSize / sizeof(PVOID));
  1863. while (NumberOfProcAddresses--) {
  1864. //
  1865. // If we find a null in the import table we skip over it.
  1866. // Otherwise we will erroneously think it is a malloc() routine
  1867. // to be replaced. This can happen if msvcrt was not loaded yet
  1868. // and therefore the address of malloc() is also null.
  1869. //
  1870. if (*ProcAddresses == NULL) {
  1871. ProcAddresses += 1;
  1872. continue;
  1873. }
  1874. if (CallToDetectCrtHeap) {
  1875. if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_HEAPCREATE]) {
  1876. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapCreate;
  1877. if ((AVrfpDebug & AVRF_DBG_SHOW_PAGE_HEAP_DETAILS)) {
  1878. DbgPrint ("Page heap: Snapped (%ws) HeapCreate ... \n",
  1879. LdrDataTableEntry->BaseDllName.Buffer);
  1880. }
  1881. }
  1882. } else {
  1883. //
  1884. // ntdll imports
  1885. //
  1886. if (*ProcAddresses == RtlAllocateHeap) {
  1887. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapAlloc;
  1888. } else if (*ProcAddresses == RtlReAllocateHeap) {
  1889. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapReAlloc;
  1890. } else if (*ProcAddresses == RtlFreeHeap) {
  1891. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapFree;
  1892. }
  1893. //
  1894. // kernel32 imports
  1895. //
  1896. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_HEAPALLOC]) {
  1897. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapAlloc;
  1898. } else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_HEAPREALLOC]) {
  1899. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapReAlloc;
  1900. } else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_HEAPFREE]) {
  1901. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllHeapFree;
  1902. }
  1903. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALALLOC]) {
  1904. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllLocalAlloc;
  1905. }
  1906. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALREALLOC]) {
  1907. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllLocalReAlloc;
  1908. }
  1909. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALFREE]) {
  1910. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllLocalFree;
  1911. }
  1912. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALALLOC]) {
  1913. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllGlobalAlloc;
  1914. }
  1915. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALREALLOC]) {
  1916. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllGlobalReAlloc;
  1917. }
  1918. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALFREE]) {
  1919. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllGlobalFree;
  1920. }
  1921. //
  1922. // msvcrt imports
  1923. //
  1924. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_MALLOC]) {
  1925. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllmalloc;
  1926. }
  1927. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_REALLOC]) {
  1928. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllrealloc;
  1929. }
  1930. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_CALLOC]) {
  1931. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllcalloc;
  1932. }
  1933. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_FREE]) {
  1934. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllfree;
  1935. }
  1936. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_NEW]) {
  1937. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllNew;
  1938. }
  1939. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_DELETE]) {
  1940. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllDelete;
  1941. }
  1942. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_NEW_ARRAY]) {
  1943. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllNewArray;
  1944. }
  1945. else if (*ProcAddresses == AVrfpDphSnapRoutines[SNAP_ROUTINE_DELETE_ARRAY]) {
  1946. *ProcAddresses = (PVOID) (ULONG_PTR) AVrfpDphDllDeleteArray;
  1947. }
  1948. }
  1949. ProcAddresses += 1;
  1950. }
  1951. //
  1952. // We do not complain for protecting the import table back because
  1953. // we can live with that.
  1954. //
  1955. NtProtectVirtualMemory (NtCurrentProcess(),
  1956. &IATBase,
  1957. &BigIATSize,
  1958. OldProtect,
  1959. &OldProtect);
  1960. }
  1961. }
  1962. return st;
  1963. }
  1964. NTSTATUS
  1965. AVrfPageHeapDllNotification (
  1966. PLDR_DATA_TABLE_ENTRY LoadedDllData
  1967. )
  1968. /*++
  1969. Routine description:
  1970. This routine is the DLL load hook for page heap per dll. It gets called
  1971. whenever a dll got loaded in the process space and after its import
  1972. descriptors have been walked.
  1973. Parameters:
  1974. LoadedDllData - LDR loader structure for the dll.
  1975. Return value:
  1976. None.
  1977. --*/
  1978. {
  1979. BOOLEAN Kernel32JustSnapped = FALSE;
  1980. BOOLEAN MsvcrtJustSnapped = FALSE;
  1981. NTSTATUS Status = STATUS_SUCCESS;
  1982. //
  1983. // If we do not have per dll page heap feature enabled
  1984. // we return immediately.
  1985. //
  1986. if (! (RtlpDphGlobalFlags & PAGE_HEAP_USE_DLL_NAMES)) {
  1987. return Status;
  1988. }
  1989. if (! AVrfpDphKernel32Snapped) {
  1990. Kernel32JustSnapped = AVrfpDphDetectSnapRoutines (
  1991. Kernel32String.Buffer,
  1992. AVrfpDphSnapNamesForKernel32);
  1993. AVrfpDphKernel32Snapped = Kernel32JustSnapped;
  1994. }
  1995. if (! AVrfpDphMsvcrtSnapped) {
  1996. MsvcrtJustSnapped = AVrfpDphDetectSnapRoutines (
  1997. L"msvcrt.dll",
  1998. AVrfpDphSnapNamesForMsvcrt);
  1999. AVrfpDphMsvcrtSnapped = MsvcrtJustSnapped;
  2000. }
  2001. //
  2002. // Snap everything already loaded if we just managed
  2003. // to detect snap routines.
  2004. //
  2005. if (Kernel32JustSnapped || MsvcrtJustSnapped) {
  2006. //
  2007. // ISSUE: SilviuC: I need to think if this code path is needed. If a dll
  2008. // imports something from the exports of interest that dll will get loaded
  2009. // (and exports detected) first. So in case of kernel32/msvcrt we will
  2010. // take this code path and snap their imports and then redundantly
  2011. // snap them again in the end of the function (that is the general case).
  2012. //
  2013. PWSTR Current;
  2014. PWSTR End;
  2015. WCHAR SavedChar;
  2016. PLDR_DATA_TABLE_ENTRY DllData;
  2017. BOOLEAN Result;
  2018. UNICODE_STRING DllName;
  2019. WCHAR StaticRedirectionBuffer[DOS_MAX_PATH_LENGTH];
  2020. UNICODE_STRING StaticRedirectionString;
  2021. UNICODE_STRING DynamicRedirectionString;
  2022. PUNICODE_STRING DllNameToUse;
  2023. BOOLEAN Redirected = FALSE;
  2024. DynamicRedirectionString.Buffer = NULL;
  2025. DynamicRedirectionString.Length = 0;
  2026. DynamicRedirectionString.MaximumLength = 0;
  2027. StaticRedirectionString.Length = 0;
  2028. StaticRedirectionString.MaximumLength = sizeof(StaticRedirectionBuffer);
  2029. StaticRedirectionString.Buffer = StaticRedirectionBuffer;
  2030. Current = RtlpDphTargetDlls;
  2031. while (*Current) {
  2032. while (*Current == L' ') {
  2033. Current += 1;
  2034. }
  2035. End = Current;
  2036. while (*End && *End != L' ') {
  2037. End += 1;
  2038. }
  2039. if (*Current == L'\0') {
  2040. break;
  2041. }
  2042. SavedChar = *End;
  2043. *End = L'\0';
  2044. RtlInitUnicodeString (
  2045. &DllName,
  2046. Current);
  2047. Result = FALSE;
  2048. DllData = NULL;
  2049. DllNameToUse = &DllName;
  2050. Status = RtlDosApplyFileIsolationRedirection_Ustr(
  2051. RTL_DOS_APPLY_FILE_REDIRECTION_USTR_FLAG_RESPECT_DOT_LOCAL,
  2052. &DllName,
  2053. &DefaultExtension,
  2054. &StaticRedirectionString,
  2055. &DynamicRedirectionString,
  2056. &DllNameToUse,
  2057. NULL,
  2058. NULL,
  2059. NULL);
  2060. if (NT_SUCCESS(Status)) {
  2061. Redirected = TRUE;
  2062. } else if (Status == STATUS_SXS_KEY_NOT_FOUND) {
  2063. Status = STATUS_SUCCESS;
  2064. }
  2065. if (NT_SUCCESS(Status)) {
  2066. Result = LdrpCheckForLoadedDll (
  2067. NULL,
  2068. DllNameToUse,
  2069. TRUE,
  2070. Redirected,
  2071. &DllData);
  2072. if (DynamicRedirectionString.Buffer != NULL)
  2073. RtlFreeUnicodeString(&DynamicRedirectionString);
  2074. }
  2075. if (Result) {
  2076. if (DllData->DllBase == LoadedDllData->DllBase) {
  2077. if ((AVrfpDebug & AVRF_DBG_SHOW_PAGE_HEAP_DETAILS)) {
  2078. DbgPrint ("Page heap: oversnapping %ws \n",
  2079. DllData->BaseDllName);
  2080. }
  2081. }
  2082. Status = AVrfpDphSnapImports (DllData, FALSE);
  2083. if (!NT_SUCCESS(Status)) {
  2084. return Status;
  2085. }
  2086. }
  2087. *End = SavedChar;
  2088. Current = End;
  2089. }
  2090. }
  2091. //
  2092. // If we just loaded msvcrt.dll we need to redirect HeapCreate call
  2093. // in order to detect when the CRT heap gets created.
  2094. //
  2095. if (_wcsicmp (LoadedDllData->BaseDllName.Buffer, L"msvcrt.dll") == 0) {
  2096. Status = AVrfpDphSnapImports (LoadedDllData, TRUE);
  2097. if (!NT_SUCCESS(Status)) {
  2098. return Status;
  2099. }
  2100. }
  2101. //
  2102. // Call back into page heap manager to figure out if the
  2103. // currently loaded dll is a target for page heap.
  2104. //
  2105. if (RtlpDphIsDllTargeted (LoadedDllData->BaseDllName.Buffer)) {
  2106. Status = AVrfpDphSnapImports (LoadedDllData, FALSE);
  2107. if (!NT_SUCCESS(Status)) {
  2108. return Status;
  2109. }
  2110. }
  2111. return Status;
  2112. }
  2113. /////////////////////////////////////////////////////////////////////
  2114. /////////////////////////////////////////////////////// Snap routines
  2115. /////////////////////////////////////////////////////////////////////
  2116. //
  2117. // A biased heap pointer signals to the page heap manager that
  2118. // this allocation needs to get into page heap (not normal heap).
  2119. // This needs to happen only for allocation function (not free, delete).
  2120. //
  2121. #define BIAS_POINTER(p) ((PVOID)((ULONG_PTR)(p) | 0x01))
  2122. PVOID
  2123. AVrfpDphDllHeapAlloc (
  2124. IN PVOID HeapHandle,
  2125. IN ULONG Flags,
  2126. IN SIZE_T Size
  2127. )
  2128. {
  2129. return RtlpDebugPageHeapAllocate (
  2130. BIAS_POINTER(HeapHandle),
  2131. Flags,
  2132. Size);
  2133. }
  2134. PVOID
  2135. AVrfpDphDllHeapReAlloc (
  2136. IN PVOID HeapHandle,
  2137. IN ULONG Flags,
  2138. IN PVOID Address,
  2139. IN SIZE_T Size
  2140. )
  2141. {
  2142. return RtlpDebugPageHeapReAllocate (
  2143. BIAS_POINTER(HeapHandle),
  2144. Flags,
  2145. Address,
  2146. Size);
  2147. }
  2148. BOOLEAN
  2149. AVrfpDphDllHeapFree(
  2150. IN PVOID HeapHandle,
  2151. IN ULONG Flags,
  2152. IN PVOID Address
  2153. )
  2154. {
  2155. return RtlpDebugPageHeapFree (
  2156. HeapHandle,
  2157. Flags,
  2158. Address);
  2159. }
  2160. //
  2161. // LocalAlloc, LocalReAlloc, LocalFree
  2162. // GlobalAlloc, GlobalReAlloc, GlobalFree
  2163. //
  2164. // The following macros are copied from sdk\inc\winbase.h
  2165. // There is very low probability that anybody will ever change
  2166. // these values for application compatibility reasons.
  2167. //
  2168. #define LMEM_MOVEABLE 0x0002
  2169. #define LMEM_ZEROINIT 0x0040
  2170. #if defined(_AMD64_) || defined(_IA64_)
  2171. #define BASE_HANDLE_MARK_BIT 0x08
  2172. #else
  2173. #define BASE_HANDLE_MARK_BIT 0x04
  2174. #endif
  2175. typedef PVOID
  2176. (* FUN_LOCAL_ALLOC) (
  2177. IN ULONG Flags,
  2178. IN SIZE_T Size
  2179. );
  2180. typedef PVOID
  2181. (* FUN_LOCAL_REALLOC) (
  2182. IN PVOID Address,
  2183. IN SIZE_T Size,
  2184. IN ULONG Flags
  2185. );
  2186. typedef PVOID
  2187. (* FUN_LOCAL_FREE)(
  2188. IN PVOID Address
  2189. );
  2190. typedef PVOID
  2191. (* FUN_GLOBAL_ALLOC) (
  2192. IN ULONG Flags,
  2193. IN SIZE_T Size
  2194. );
  2195. typedef PVOID
  2196. (* FUN_GLOBAL_REALLOC) (
  2197. IN PVOID Address,
  2198. IN SIZE_T Size,
  2199. IN ULONG Flags
  2200. );
  2201. typedef PVOID
  2202. (* FUN_GLOBAL_FREE)(
  2203. IN PVOID Address
  2204. );
  2205. PVOID
  2206. AVrfpDphDllLocalAlloc (
  2207. IN ULONG Flags,
  2208. IN SIZE_T Size
  2209. )
  2210. {
  2211. PVOID Block;
  2212. FUN_LOCAL_ALLOC Original;
  2213. if (!(Flags & LMEM_MOVEABLE)) {
  2214. Block = RtlpDebugPageHeapAllocate (
  2215. BIAS_POINTER(RtlProcessHeap()),
  2216. 0,
  2217. Size);
  2218. if (Block && (Flags & LMEM_ZEROINIT)) {
  2219. RtlZeroMemory (Block, Size);
  2220. }
  2221. return Block;
  2222. }
  2223. else {
  2224. Original = (FUN_LOCAL_ALLOC)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALALLOC]);
  2225. return (* Original) (Flags, Size);
  2226. }
  2227. }
  2228. PVOID
  2229. AVrfpDphDllLocalReAlloc (
  2230. IN PVOID Address,
  2231. IN SIZE_T Size,
  2232. IN ULONG Flags
  2233. )
  2234. {
  2235. PVOID Block;
  2236. FUN_LOCAL_REALLOC Original;
  2237. if (!(Flags & LMEM_MOVEABLE)) {
  2238. Block = RtlpDebugPageHeapReAllocate (
  2239. BIAS_POINTER(RtlProcessHeap()),
  2240. 0,
  2241. Address,
  2242. Size);
  2243. return Block;
  2244. }
  2245. else {
  2246. Original = (FUN_LOCAL_REALLOC)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALREALLOC]);
  2247. return (* Original) (Address, Size, Flags);
  2248. }
  2249. }
  2250. PVOID
  2251. AVrfpDphDllLocalFree(
  2252. IN PVOID Address
  2253. )
  2254. {
  2255. BOOLEAN Result;
  2256. FUN_LOCAL_FREE Original;
  2257. if ((ULONG_PTR)Address & BASE_HANDLE_MARK_BIT) {
  2258. Original = (FUN_LOCAL_FREE)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_LOCALFREE]);
  2259. return (* Original) (Address);
  2260. }
  2261. else {
  2262. Result = RtlpDebugPageHeapFree (
  2263. RtlProcessHeap(),
  2264. 0,
  2265. Address);
  2266. if (Result) {
  2267. return NULL;
  2268. }
  2269. else {
  2270. return Address;
  2271. }
  2272. }
  2273. }
  2274. PVOID
  2275. AVrfpDphDllGlobalAlloc (
  2276. IN ULONG Flags,
  2277. IN SIZE_T Size
  2278. )
  2279. {
  2280. PVOID Block;
  2281. FUN_GLOBAL_ALLOC Original;
  2282. if (!(Flags & LMEM_MOVEABLE)) {
  2283. Block = RtlpDebugPageHeapAllocate (
  2284. BIAS_POINTER(RtlProcessHeap()),
  2285. 0,
  2286. Size);
  2287. if (Block && (Flags & LMEM_ZEROINIT)) {
  2288. RtlZeroMemory (Block, Size);
  2289. }
  2290. return Block;
  2291. }
  2292. else {
  2293. Original = (FUN_GLOBAL_ALLOC)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALALLOC]);
  2294. return (* Original) (Flags, Size);
  2295. }
  2296. }
  2297. PVOID
  2298. AVrfpDphDllGlobalReAlloc (
  2299. IN PVOID Address,
  2300. IN SIZE_T Size,
  2301. IN ULONG Flags
  2302. )
  2303. {
  2304. PVOID Block;
  2305. FUN_GLOBAL_REALLOC Original;
  2306. if (!(Flags & LMEM_MOVEABLE)) {
  2307. Block = RtlpDebugPageHeapReAllocate (
  2308. BIAS_POINTER(RtlProcessHeap()),
  2309. 0,
  2310. Address,
  2311. Size);
  2312. return Block;
  2313. }
  2314. else {
  2315. Original = (FUN_GLOBAL_REALLOC)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALREALLOC]);
  2316. return (* Original) (Address, Size, Flags);
  2317. }
  2318. }
  2319. PVOID
  2320. AVrfpDphDllGlobalFree(
  2321. IN PVOID Address
  2322. )
  2323. {
  2324. BOOLEAN Result;
  2325. FUN_GLOBAL_FREE Original;
  2326. if ((ULONG_PTR)Address & BASE_HANDLE_MARK_BIT) {
  2327. Original = (FUN_GLOBAL_FREE)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_GLOBALFREE]);
  2328. return (* Original) (Address);
  2329. }
  2330. else {
  2331. Result = RtlpDebugPageHeapFree (
  2332. RtlProcessHeap(),
  2333. 0,
  2334. Address);
  2335. if (Result) {
  2336. return NULL;
  2337. }
  2338. else {
  2339. return Address;
  2340. }
  2341. }
  2342. }
  2343. //
  2344. // malloc, calloc, realloc, free
  2345. //
  2346. PVOID __cdecl
  2347. AVrfpDphDllmalloc (
  2348. IN SIZE_T Size
  2349. )
  2350. {
  2351. PVOID Block;
  2352. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2353. Block = RtlpDebugPageHeapAllocate (
  2354. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2355. 0,
  2356. Size);
  2357. return Block;
  2358. }
  2359. PVOID __cdecl
  2360. AVrfpDphDllcalloc (
  2361. IN SIZE_T Number,
  2362. IN SIZE_T Size
  2363. )
  2364. {
  2365. PVOID Block;
  2366. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2367. Block = RtlpDebugPageHeapAllocate (
  2368. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2369. 0,
  2370. Size * Number);
  2371. if (Block) {
  2372. RtlZeroMemory (Block, Size * Number);
  2373. }
  2374. return Block;
  2375. }
  2376. PVOID __cdecl
  2377. AVrfpDphDllrealloc (
  2378. IN PVOID Address,
  2379. IN SIZE_T Size
  2380. )
  2381. {
  2382. PVOID Block;
  2383. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2384. if (Address == NULL) {
  2385. Block = RtlpDebugPageHeapAllocate (
  2386. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2387. 0,
  2388. Size);
  2389. }
  2390. else {
  2391. Block = RtlpDebugPageHeapReAllocate (
  2392. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2393. 0,
  2394. Address,
  2395. Size);
  2396. }
  2397. return Block;
  2398. }
  2399. VOID __cdecl
  2400. AVrfpDphDllfree (
  2401. IN PVOID Address
  2402. )
  2403. {
  2404. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2405. RtlpDebugPageHeapFree (
  2406. AVrfpDphMsvcrtHeap,
  2407. 0,
  2408. Address);
  2409. }
  2410. //
  2411. // operator new, delete
  2412. // operator new[], delete[]
  2413. //
  2414. PVOID __cdecl
  2415. AVrfpDphDllNew (
  2416. IN SIZE_T Size
  2417. )
  2418. {
  2419. PVOID Block;
  2420. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2421. Block = RtlpDebugPageHeapAllocate (
  2422. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2423. 0,
  2424. Size);
  2425. return Block;
  2426. }
  2427. VOID __cdecl
  2428. AVrfpDphDllDelete (
  2429. IN PVOID Address
  2430. )
  2431. {
  2432. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2433. RtlpDebugPageHeapFree (
  2434. AVrfpDphMsvcrtHeap,
  2435. 0,
  2436. Address);
  2437. }
  2438. PVOID __cdecl
  2439. AVrfpDphDllNewArray (
  2440. IN SIZE_T Size
  2441. )
  2442. {
  2443. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2444. return RtlpDebugPageHeapAllocate (
  2445. BIAS_POINTER(AVrfpDphMsvcrtHeap),
  2446. 0,
  2447. Size);
  2448. }
  2449. VOID __cdecl
  2450. AVrfpDphDllDeleteArray (
  2451. IN PVOID Address
  2452. )
  2453. {
  2454. ASSERT(AVrfpDphMsvcrtHeap != NULL);
  2455. RtlpDebugPageHeapFree (
  2456. AVrfpDphMsvcrtHeap,
  2457. 0,
  2458. Address);
  2459. }
  2460. //
  2461. // HeapCreate
  2462. //
  2463. typedef PVOID
  2464. (* FUN_HEAP_CREATE) (
  2465. ULONG Options,
  2466. SIZE_T InitialSize,
  2467. SIZE_T MaximumSize
  2468. );
  2469. PVOID
  2470. AVrfpDphDllHeapCreate (
  2471. ULONG Options,
  2472. SIZE_T InitialSize,
  2473. SIZE_T MaximumSize
  2474. )
  2475. {
  2476. PVOID Heap;
  2477. FUN_HEAP_CREATE Original;
  2478. Original = (FUN_HEAP_CREATE)(ULONG_PTR)(AVrfpDphSnapRoutines[SNAP_ROUTINE_HEAPCREATE]);
  2479. Heap = (* Original) (Options, InitialSize, MaximumSize);
  2480. AVrfpDphMsvcrtHeap = Heap;
  2481. if ((AVrfpDebug & AVRF_DBG_SHOW_PAGE_HEAP_DETAILS)) {
  2482. DbgPrint ("Page heap: detected CRT heap @ %p \n",
  2483. AVrfpDphMsvcrtHeap);
  2484. }
  2485. return Heap;
  2486. }