Source code of Windows XP (NT5)
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.

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