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.

1087 lines
34 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. verifier.c
  5. Abstract:
  6. This module implements the main entry points for
  7. the base application verifier provider (verifier.dll).
  8. Author:
  9. Silviu Calinoiu (SilviuC) 2-Feb-2001
  10. Revision History:
  11. --*/
  12. //
  13. // IMPORTANT NOTE.
  14. //
  15. // This dll cannot contain non-ntdll dependencies. This way we can run
  16. // verifier systemwide for any process (including smss and csrss).
  17. //
  18. #include "pch.h"
  19. #include "verifier.h"
  20. #include "support.h"
  21. #include "settings.h"
  22. #include "critsect.h"
  23. #include "faults.h"
  24. #include "deadlock.h"
  25. #include "vspace.h"
  26. #include "logging.h"
  27. //
  28. // ntdll.dll thunks
  29. //
  30. RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpNtdllThunks [] =
  31. {
  32. {"NtAllocateVirtualMemory", NULL, AVrfpNtAllocateVirtualMemory},
  33. {"NtFreeVirtualMemory", NULL, AVrfpNtFreeVirtualMemory},
  34. {"NtMapViewOfSection", NULL, AVrfpNtMapViewOfSection},
  35. {"NtUnmapViewOfSection", NULL, AVrfpNtUnmapViewOfSection},
  36. {"NtCreateSection", NULL, AVrfpNtCreateSection},
  37. {"NtOpenSection", NULL, AVrfpNtOpenSection},
  38. {"NtCreateFile", NULL, AVrfpNtCreateFile},
  39. {"NtOpenFile", NULL, AVrfpNtOpenFile},
  40. {"NtCreateKey", NULL, AVrfpNtCreateKey},
  41. {"NtOpenKey", NULL, AVrfpNtOpenKey},
  42. {"LdrGetProcedureAddress", NULL, AVrfpLdrGetProcedureAddress},
  43. {"RtlTryEnterCriticalSection", NULL, AVrfpRtlTryEnterCriticalSection},
  44. {"RtlEnterCriticalSection", NULL, AVrfpRtlEnterCriticalSection},
  45. {"RtlLeaveCriticalSection", NULL, AVrfpRtlLeaveCriticalSection},
  46. {"RtlInitializeCriticalSection", NULL, AVrfpRtlInitializeCriticalSection},
  47. {"RtlInitializeCriticalSectionAndSpinCount", NULL, AVrfpRtlInitializeCriticalSectionAndSpinCount},
  48. {"RtlDeleteCriticalSection", NULL, AVrfpRtlDeleteCriticalSection},
  49. {"RtlInitializeResource", NULL, AVrfpRtlInitializeResource},
  50. {"RtlDeleteResource", NULL, AVrfpRtlDeleteResource},
  51. {"RtlAcquireResourceShared", NULL, AVrfpRtlAcquireResourceShared},
  52. {"RtlAcquireResourceExclusive", NULL, AVrfpRtlAcquireResourceExclusive},
  53. {"RtlReleaseResource", NULL, AVrfpRtlReleaseResource},
  54. {"RtlConvertSharedToExclusive", NULL, AVrfpRtlConvertSharedToExclusive},
  55. {"RtlConvertExclusiveToShared", NULL, AVrfpRtlConvertExclusiveToShared},
  56. {"NtCreateEvent", NULL, AVrfpNtCreateEvent },
  57. {"NtClose", NULL, AVrfpNtClose},
  58. {"RtlAllocateHeap", NULL, AVrfpRtlAllocateHeap },
  59. {"RtlReAllocateHeap", NULL, AVrfpRtlReAllocateHeap },
  60. {"RtlFreeHeap", NULL, AVrfpRtlFreeHeap },
  61. {"NtReadFile", NULL, AVrfpNtReadFile},
  62. {"NtReadFileScatter", NULL, AVrfpNtReadFileScatter},
  63. {"NtWriteFile", NULL, AVrfpNtWriteFile},
  64. {"NtWriteFileGather", NULL, AVrfpNtWriteFileGather},
  65. {"NtWaitForSingleObject", NULL, AVrfpNtWaitForSingleObject},
  66. {"NtWaitForMultipleObjects", NULL, AVrfpNtWaitForMultipleObjects},
  67. {"RtlSetThreadPoolStartFunc", NULL, AVrfpRtlSetThreadPoolStartFunc},
  68. {NULL, NULL, NULL}
  69. };
  70. //
  71. // kernel32.dll thunks
  72. //
  73. RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpKernel32Thunks [] =
  74. {
  75. {"HeapCreate", NULL, AVrfpHeapCreate},
  76. {"HeapDestroy", NULL, AVrfpHeapDestroy},
  77. {"CloseHandle", NULL, AVrfpCloseHandle},
  78. {"ExitThread", NULL, AVrfpExitThread},
  79. {"TerminateThread", NULL, AVrfpTerminateThread},
  80. {"SuspendThread", NULL, AVrfpSuspendThread},
  81. {"TlsAlloc", NULL, AVrfpTlsAlloc},
  82. {"TlsFree", NULL, AVrfpTlsFree},
  83. {"TlsGetValue", NULL, AVrfpTlsGetValue},
  84. {"TlsSetValue", NULL, AVrfpTlsSetValue},
  85. {"CreateThread", NULL, AVrfpCreateThread},
  86. {"GetProcAddress", NULL, AVrfpGetProcAddress},
  87. {"WaitForSingleObject", NULL, AVrfpWaitForSingleObject},
  88. {"WaitForMultipleObjects", NULL, AVrfpWaitForMultipleObjects},
  89. {"WaitForSingleObjectEx", NULL, AVrfpWaitForSingleObjectEx},
  90. {"WaitForMultipleObjectsEx", NULL, AVrfpWaitForMultipleObjectsEx},
  91. {"GlobalAlloc", NULL, AVrfpGlobalAlloc},
  92. {"GlobalReAlloc", NULL, AVrfpGlobalReAlloc},
  93. {"LocalAlloc", NULL, AVrfpLocalAlloc},
  94. {"LocalReAlloc", NULL, AVrfpLocalReAlloc},
  95. {"CreateFileA", NULL, AVrfpCreateFileA},
  96. {"CreateFileW", NULL, AVrfpCreateFileW},
  97. {"FreeLibraryAndExitThread", NULL, AVrfpFreeLibraryAndExitThread},
  98. {"GetTickCount", NULL, AVrfpGetTickCount},
  99. {"IsBadReadPtr", NULL, AVrfpIsBadReadPtr},
  100. {"IsBadHugeReadPtr", NULL, AVrfpIsBadHugeReadPtr},
  101. {"IsBadWritePtr", NULL, AVrfpIsBadWritePtr},
  102. {"IsBadHugeWritePtr", NULL, AVrfpIsBadHugeWritePtr},
  103. {"IsBadCodePtr", NULL, AVrfpIsBadCodePtr},
  104. {"IsBadStringPtrA", NULL, AVrfpIsBadStringPtrA},
  105. {"IsBadStringPtrW", NULL, AVrfpIsBadStringPtrW},
  106. {"ExitProcess", NULL, AVrfpExitProcess},
  107. {"VirtualFree", NULL, AVrfpVirtualFree},
  108. {"VirtualFreeEx", NULL, AVrfpVirtualFreeEx},
  109. {NULL, NULL, NULL}
  110. };
  111. //
  112. // advapi32.dll thunks
  113. //
  114. RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpAdvapi32Thunks [] =
  115. {
  116. {"RegCreateKeyA", NULL, AVrfpRegCreateKeyA},
  117. {"RegCreateKeyW", NULL, AVrfpRegCreateKeyW},
  118. {"RegCreateKeyExA", NULL, AVrfpRegCreateKeyExA},
  119. {"RegCreateKeyExW", NULL, AVrfpRegCreateKeyExW},
  120. {"RegOpenKeyA", NULL, AVrfpRegOpenKeyA},
  121. {"RegOpenKeyW", NULL, AVrfpRegOpenKeyW},
  122. {"RegOpenKeyExA", NULL, AVrfpRegOpenKeyExA},
  123. {"RegOpenKeyExW", NULL, AVrfpRegOpenKeyExW},
  124. {NULL, NULL, NULL}
  125. };
  126. //
  127. // msvcrt.dll thunks
  128. //
  129. RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpMsvcrtThunks [] =
  130. {
  131. {"malloc", NULL, AVrfp_malloc},
  132. {"calloc", NULL, AVrfp_calloc},
  133. {"realloc", NULL, AVrfp_realloc},
  134. {"free", NULL, AVrfp_free},
  135. #if defined(_X86_) // compilers for various architectures decorate slightly different
  136. {"??2@YAPAXI@Z", NULL, AVrfp_new},
  137. {"??3@YAXPAX@Z", NULL, AVrfp_delete},
  138. {"??_U@YAPAXI@Z", NULL, AVrfp_newarray},
  139. {"??_V@YAXPAX@Z", NULL, AVrfp_deletearray},
  140. #elif defined(_IA64_)
  141. {"??2@YAPEAX_K@Z", NULL, AVrfp_new},
  142. {"??3@YAXPEAX@Z", NULL, AVrfp_delete},
  143. {"??_U@YAPEAX_K@Z", NULL, AVrfp_newarray},
  144. {"??_V@YAXPEAX@Z", NULL, AVrfp_deletearray},
  145. #elif defined(_AMD64_)
  146. {"??2@YAPAX_K@Z", NULL, AVrfp_new},
  147. {"??3@YAXPAX@Z", NULL, AVrfp_delete},
  148. {"??_U@YAPAX_K@Z", NULL, AVrfp_newarray},
  149. {"??_V@YAXPAX@Z", NULL, AVrfp_deletearray},
  150. #else
  151. #error Unknown architecture
  152. #endif
  153. {NULL, NULL, NULL}
  154. };
  155. //
  156. // oleaut32.dll thunks
  157. //
  158. RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpOleaut32Thunks [] =
  159. {
  160. {"SysAllocString", NULL, AVrfpSysAllocString},
  161. {"SysReAllocString", NULL, AVrfpSysReAllocString},
  162. {"SysAllocStringLen", NULL, AVrfpSysAllocStringLen},
  163. {"SysReAllocStringLen", NULL, AVrfpSysReAllocStringLen},
  164. {"SysAllocStringByteLen", NULL, AVrfpSysAllocStringByteLen},
  165. {NULL, NULL, NULL}
  166. };
  167. //
  168. // dll's providing thunks verified.
  169. //
  170. RTL_VERIFIER_DLL_DESCRIPTOR AVrfpExportDlls [] =
  171. {
  172. {L"ntdll.dll", 0, NULL, AVrfpNtdllThunks},
  173. {L"kernel32.dll", 0, NULL, AVrfpKernel32Thunks},
  174. {L"advapi32.dll", 0, NULL, AVrfpAdvapi32Thunks},
  175. {L"msvcrt.dll", 0, NULL, AVrfpMsvcrtThunks},
  176. //
  177. // Special care in what new dlls are added here. It is important
  178. // when running in back compat mode. For instance oleaut32.dll
  179. // cannot be hooked in WinXP due to a bug in ntdll\verifier.c
  180. // that has been fixed. Unfortunately when we put the latest verifier
  181. // on WinXP we need to workaround this.
  182. //
  183. {L"oleaut32.dll", 0, NULL, AVrfpOleaut32Thunks},
  184. {NULL, 0, NULL, NULL}
  185. };
  186. RTL_VERIFIER_PROVIDER_DESCRIPTOR AVrfpProvider =
  187. {
  188. sizeof (RTL_VERIFIER_PROVIDER_DESCRIPTOR),
  189. AVrfpExportDlls,
  190. AVrfpDllLoadCallback, // callback for DLL load events
  191. AVrfpDllUnloadCallback, // callback for DLL unload events
  192. NULL, // image name (filled by verifier engine)
  193. 0, // verifier flags (filled by verifier engine)
  194. 0, // debug flags (filled by verifier engine)
  195. NULL, // RtlpGetStackTraceAddress
  196. NULL, // RtlpDebugPageHeapCreate
  197. NULL, // RtlpDebugPageHeapDestroy
  198. AVrfpNtdllHeapFreeCallback // callback for HeapFree events inside the ntdll code (e.g. HeapDestroy);
  199. // the HeapFree calls from the other DLLs are already hooked using AVrfpRtlFreeHeap.
  200. };
  201. //
  202. // Mark if we have been called with PROCESS_ATTACH once.
  203. // In some cases the fusion code loads dynamically kernel32.dll and enforces
  204. // the run of all initialization routines and causes us to get called
  205. // twice.
  206. //
  207. BOOL AVrfpProcessAttachCalled;
  208. BOOL AVrfpProcessAttachResult = TRUE;
  209. //
  210. // Global data.
  211. //
  212. const WCHAR AVrfpThreadName[] = L"Thread";
  213. UNICODE_STRING AVrfpThreadObjectName;
  214. //
  215. // Provider descriptor from WinXP timeframe.
  216. // Used to make verifier backwards compatible.
  217. //
  218. typedef struct _RTL_VERIFIER_PROVIDER_DESCRIPTOR_WINXP {
  219. ULONG Length;
  220. PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls;
  221. RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
  222. RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
  223. PWSTR VerifierImage;
  224. ULONG VerifierFlags;
  225. ULONG VerifierDebug;
  226. //PVOID RtlpGetStackTraceAddress;
  227. //PVOID RtlpDebugPageHeapCreate;
  228. //PVOID RtlpDebugPageHeapDestroy;
  229. } RTL_VERIFIER_PROVIDER_DESCRIPTOR_WINXP, *PRTL_VERIFIER_PROVIDER_DESCRIPTOR_WINXP;
  230. #define WINXP_BUILD_NUMBER 2600
  231. ULONG AVrfpBuildNumber;
  232. PVOID
  233. AVrfpWinXPFakeGetStackTraceAddress (
  234. USHORT Index
  235. )
  236. {
  237. UNREFERENCED_PARAMETER(Index);
  238. return NULL;
  239. }
  240. //
  241. // DllMain
  242. //
  243. BOOL
  244. DllMainWithoutVerifierEnabled (
  245. DWORD Reason
  246. );
  247. NTSTATUS
  248. AVrfpRedirectNtdllStopFunction (
  249. VOID
  250. );
  251. BOOL
  252. WINAPI
  253. DllMain(
  254. HINSTANCE hInstDll, // handle to the DLL module
  255. DWORD fdwReason, // reason for calling function
  256. LPVOID lpvReserved // reserved
  257. )
  258. {
  259. NTSTATUS Status;
  260. UNREFERENCED_PARAMETER (hInstDll);
  261. //
  262. // This function will call a light version of DllMain that enables only
  263. // the stop logic and logging logic for the cases where verifier.dll
  264. // is dynamically loaded by verifier shims just for that functionality.
  265. // For such cases the verifier flag will not be set.
  266. //
  267. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  268. return DllMainWithoutVerifierEnabled (fdwReason);
  269. }
  270. //
  271. // DllMain code when verifier flag is set.
  272. //
  273. switch (fdwReason) {
  274. case DLL_PROCESS_VERIFIER:
  275. //
  276. // DllMain gets called with this special reason by the verifier engine.
  277. // Minimal code should execute here (e.g. passing back the provider
  278. // descriptor). The rest should be postponed to PROCESS_ATTACH moment.
  279. //
  280. AVrfpBuildNumber = NtCurrentPeb()->OSBuildNumber;
  281. if (lpvReserved) {
  282. //
  283. // If we are running on WinXP the latest verifier.dll then we change
  284. // the length to the old one and we disable hooks for oleaut32. A bug
  285. // in ntdll\verifier.c prevents this from being hooked correctly. The
  286. // bug was fixed but we still need to workaround it when running in
  287. // backcompat mode.
  288. //
  289. if (AVrfpBuildNumber == WINXP_BUILD_NUMBER) {
  290. PRTL_VERIFIER_DLL_DESCRIPTOR Descriptor;
  291. AVrfpProvider.Length = sizeof (RTL_VERIFIER_PROVIDER_DESCRIPTOR_WINXP);
  292. Descriptor = &AVrfpExportDlls[0];
  293. while (Descriptor->DllName != NULL) {
  294. if (_wcsicmp (Descriptor->DllName, L"oleaut32.dll") == 0) {
  295. RtlZeroMemory (Descriptor, sizeof *Descriptor);
  296. break;
  297. }
  298. Descriptor += 1;
  299. }
  300. }
  301. *((PRTL_VERIFIER_PROVIDER_DESCRIPTOR *)lpvReserved) = &AVrfpProvider;
  302. Status = AVrfpDllInitialize ();
  303. if (! NT_SUCCESS (Status)) {
  304. return FALSE;
  305. }
  306. //
  307. // Create private verifier heap. We need to do it here because in
  308. // PROCESS_ATTACH it is too late. Verifier will receive a dll load
  309. // notification for kernel32 before verifier DllMain is called
  310. // with PROCESS_ATTACH.
  311. //
  312. AVrfpHeap = RtlCreateHeap (HEAP_CLASS_1 | HEAP_GROWABLE,
  313. NULL,
  314. 0,
  315. 0,
  316. NULL,
  317. NULL);
  318. if (AVrfpHeap == NULL) {
  319. DbgPrint ("AVRF: failed to create verifier heap. \n");
  320. return FALSE;
  321. }
  322. //
  323. // Initialize verifier stops and logging.
  324. //
  325. Status = AVrfpInitializeVerifierStops();
  326. if (!NT_SUCCESS(Status)) {
  327. DbgPrint ("AVRF: failed to initialize verifier stop logic (%X). \n", Status);
  328. return FALSE;
  329. }
  330. //
  331. // Create call trackers.
  332. //
  333. Status = AVrfCreateTrackers ();
  334. if (!NT_SUCCESS(Status)) {
  335. DbgPrint ("AVRF: failed to initialize call trackers (%X). \n", Status);
  336. return FALSE;
  337. }
  338. }
  339. break;
  340. case DLL_PROCESS_ATTACH:
  341. //
  342. // Execute only minimal code here and avoid too many DLL dependencies.
  343. //
  344. if (! AVrfpProcessAttachCalled) {
  345. AVrfpProcessAttachCalled = TRUE;
  346. //
  347. // Pickup private ntdll entrypoints required by verifier.
  348. //
  349. if (AVrfpBuildNumber == WINXP_BUILD_NUMBER) {
  350. AVrfpGetStackTraceAddress = AVrfpWinXPFakeGetStackTraceAddress;
  351. AVrfpRtlpDebugPageHeapCreate = NULL;
  352. AVrfpRtlpDebugPageHeapDestroy = NULL;
  353. }
  354. else {
  355. AVrfpGetStackTraceAddress = (PFN_RTLP_GET_STACK_TRACE_ADDRESS)(AVrfpProvider.RtlpGetStackTraceAddress);
  356. AVrfpRtlpDebugPageHeapCreate = (PFN_RTLP_DEBUG_PAGE_HEAP_CREATE)(AVrfpProvider.RtlpDebugPageHeapCreate);
  357. AVrfpRtlpDebugPageHeapDestroy = (PFN_RTLP_DEBUG_PAGE_HEAP_DESTROY)(AVrfpProvider.RtlpDebugPageHeapDestroy);
  358. }
  359. //
  360. // Cache some basic system information for later use.
  361. //
  362. Status = NtQuerySystemInformation (SystemBasicInformation,
  363. &AVrfpSysBasicInfo,
  364. sizeof (AVrfpSysBasicInfo),
  365. NULL);
  366. if (! NT_SUCCESS (Status)) {
  367. if ((AVrfpProvider.VerifierDebug & VRFP_DEBUG_GENERIC) != 0) {
  368. DbgPrint ("AVRF: NtQuerySystemInformation (SystemBasicInformation) failed, status %#x\n",
  369. Status);
  370. }
  371. AVrfpProcessAttachResult = FALSE;
  372. return AVrfpProcessAttachResult;
  373. }
  374. //
  375. // For XP client only try to patch old stop function from ntdll
  376. // so that it jumps unconditionally into the better stop function
  377. // from verifier.dll.
  378. //
  379. if (AVrfpBuildNumber == WINXP_BUILD_NUMBER) {
  380. Status = AVrfpRedirectNtdllStopFunction ();
  381. if (! NT_SUCCESS (Status)) {
  382. DbgPrint ("AVRF: failed to patch old stop function (%X). \n", Status);
  383. AVrfpProcessAttachResult = FALSE;
  384. return AVrfpProcessAttachResult;
  385. }
  386. }
  387. RtlInitUnicodeString(&AVrfpThreadObjectName,
  388. AVrfpThreadName);
  389. //
  390. // Initialize various sub-modules.
  391. //
  392. if (AVrfpProvider.VerifierImage) {
  393. try {
  394. //
  395. // Initialize exception checking support (logging etc.).
  396. //
  397. AVrfpInitializeExceptionChecking ();
  398. //
  399. // Reserve a TLS slot for verifier.
  400. //
  401. Status = AVrfpAllocateVerifierTlsSlot ();
  402. if (! NT_SUCCESS (Status)) {
  403. AVrfpProcessAttachResult = FALSE;
  404. return AVrfpProcessAttachResult;
  405. }
  406. //
  407. // Initialize the thread hash table.
  408. //
  409. Status = AVrfpThreadTableInitialize();
  410. if (! NT_SUCCESS (Status)) {
  411. AVrfpProcessAttachResult = FALSE;
  412. return AVrfpProcessAttachResult;
  413. }
  414. //
  415. // Initialize the fault injection support.
  416. //
  417. Status = AVrfpInitializeFaultInjectionSupport ();
  418. if (! NT_SUCCESS (Status)) {
  419. AVrfpProcessAttachResult = FALSE;
  420. return AVrfpProcessAttachResult;
  421. }
  422. //
  423. // Initialize the lock verifier package.
  424. //
  425. Status = CritSectInitialize ();
  426. if (! NT_SUCCESS (Status)) {
  427. AVrfpProcessAttachResult = FALSE;
  428. return AVrfpProcessAttachResult;
  429. }
  430. //
  431. // Initialize deadlock verifier. If anything goes
  432. // wrong during initialization we clean up and
  433. // verifier will march forward. Just deadlock verifier
  434. // will be disabled.
  435. //
  436. if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_DEADLOCK_CHECKS) != 0) {
  437. AVrfDeadlockDetectionInitialize ();
  438. }
  439. //
  440. // Initialize the virtual space tracker.
  441. //
  442. if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_VIRTUAL_SPACE_TRACKING) != 0) {
  443. Status = AVrfpVsTrackInitialize ();
  444. if (! NT_SUCCESS (Status)) {
  445. AVrfpProcessAttachResult = FALSE;
  446. return AVrfpProcessAttachResult;
  447. }
  448. }
  449. //
  450. // Enable logging logic. We do this here separate from the
  451. // initialization done in PROCESS_VERIFIER for verifier
  452. // stops because we need to check the verifier flags and
  453. // verifier image name and these are passed from ntdll.dll to
  454. // verifier.dll only during PROCESS_ATTACH.
  455. //
  456. // Note. If verifier is enabled system wide we do not enable
  457. // logging. This is a special case for internal users where
  458. // it is assumed you have a kernel debugger attached and you
  459. // are ready to deal with failures this way.
  460. //
  461. if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_ENABLED_SYSTEM_WIDE) == 0) {
  462. Status = AVrfpInitializeVerifierLogging();
  463. if (!NT_SUCCESS(Status)) {
  464. //
  465. // Failure to initialize logging is not fatal. This can happen
  466. // in out of memory conditions or for early processes like smss.exe.
  467. //
  468. DbgPrint ("AVRF: failed to initialize verifier logging (%X). \n", Status);
  469. }
  470. }
  471. }
  472. except (EXCEPTION_EXECUTE_HANDLER) {
  473. AVrfpProcessAttachResult = FALSE;
  474. return AVrfpProcessAttachResult;
  475. }
  476. //
  477. // Print a successful message.
  478. //
  479. DbgPrint ("AVRF: verifier.dll provider initialized for %ws with flags 0x%X\n",
  480. AVrfpProvider.VerifierImage,
  481. AVrfpProvider.VerifierFlags);
  482. }
  483. }
  484. else {
  485. //
  486. // This is the second time our DllMain (DLL_PROCESS_ATTACH) gets called.
  487. // Return the same result as last time.
  488. //
  489. return AVrfpProcessAttachResult;
  490. }
  491. break;
  492. case DLL_PROCESS_DETACH:
  493. //
  494. // Cleanup exception checking support.
  495. //
  496. AVrfpCleanupExceptionChecking ();
  497. //
  498. // Uninitialize the locks checking packages.
  499. //
  500. CritSectUninitialize ();
  501. break;
  502. case DLL_THREAD_ATTACH:
  503. AvrfpThreadAttach ();
  504. break;
  505. case DLL_THREAD_DETACH:
  506. AvrfpThreadDetach ();
  507. break;
  508. default:
  509. break;
  510. }
  511. return TRUE;
  512. }
  513. BOOL
  514. DllMainWithoutVerifierEnabled (
  515. DWORD Reason
  516. )
  517. {
  518. NTSTATUS Status;
  519. switch (Reason) {
  520. case DLL_PROCESS_ATTACH:
  521. //
  522. // Create private verifier heap. Since we run in a mode where verifier.dll
  523. // is used only for verifier stops and logging it is ok to create the
  524. // verifier private heap so late. The heap is used by verifier stops
  525. // to keep a list of stops that should be skipped.
  526. //
  527. AVrfpHeap = RtlCreateHeap (HEAP_CLASS_1 | HEAP_GROWABLE,
  528. NULL,
  529. 0,
  530. 0,
  531. NULL,
  532. NULL);
  533. if (AVrfpHeap == NULL) {
  534. DbgPrint ("AVRF: failed to create verifier heap. \n");
  535. return FALSE;
  536. }
  537. //
  538. // Initialize verifier stops and logging.
  539. //
  540. Status = AVrfpInitializeVerifierStops();
  541. if (!NT_SUCCESS(Status)) {
  542. DbgPrint ("AVRF: failed to initialize verifier stop logic (%X). \n", Status);
  543. return FALSE;
  544. }
  545. Status = AVrfpInitializeVerifierLogging();
  546. if (! NT_SUCCESS(Status)) {
  547. DbgPrint ("AVRF: failed to initialize verifier logging (%X). \n", Status);
  548. return FALSE;
  549. }
  550. break;
  551. default:
  552. return FALSE;
  553. }
  554. return TRUE;
  555. }
  556. PRTL_VERIFIER_THUNK_DESCRIPTOR
  557. AVrfpGetThunkDescriptor (
  558. PRTL_VERIFIER_THUNK_DESCRIPTOR DllThunks,
  559. ULONG Index)
  560. {
  561. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunk = NULL;
  562. Thunk = &(DllThunks[Index]);
  563. if (Thunk->ThunkNewAddress == NULL) {
  564. DbgPrint ("AVRF: internal error: we do not have a replace for %s !!! \n",
  565. Thunk->ThunkName);
  566. DbgBreakPoint ();
  567. }
  568. return Thunk;
  569. }
  570. //WINBASEAPI
  571. BOOL
  572. WINAPI
  573. AVrfpCloseHandle(
  574. IN OUT HANDLE hObject
  575. )
  576. {
  577. typedef BOOL (WINAPI * FUNCTION_TYPE) (HANDLE);
  578. FUNCTION_TYPE Function;
  579. Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks,
  580. AVRF_INDEX_KERNEL32_CLOSEHANDLE);
  581. if (hObject == NULL) {
  582. BUMP_COUNTER(CNT_CLOSE_NULL_HANDLE_CALLS);
  583. CHECK_BREAK(BRK_CLOSE_NULL_HANDLE);
  584. }
  585. else if (hObject == NtCurrentProcess() ||
  586. hObject == NtCurrentThread()) {
  587. BUMP_COUNTER(CNT_CLOSE_PSEUDO_HANDLE_CALLS);
  588. CHECK_BREAK(BRK_CLOSE_PSEUDO_HANDLE);
  589. }
  590. return (* Function)(hObject);
  591. }
  592. //WINBASEAPI
  593. FARPROC
  594. WINAPI
  595. AVrfpGetProcAddress(
  596. IN HMODULE hModule,
  597. IN LPCSTR lpProcName
  598. )
  599. {
  600. typedef FARPROC (WINAPI * FUNCTION_TYPE) (HMODULE, LPCSTR);
  601. FUNCTION_TYPE Function;
  602. ULONG DllIndex;
  603. ULONG ThunkIndex;
  604. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks;
  605. FARPROC ProcAddress;
  606. if ((AVrfpProvider.VerifierDebug & VRFP_DEBUG_LOADLIBRARY_CALLS) != 0) {
  607. DbgPrint ("AVRF: AVrfpGetProcAddress (%p, %s)\n",
  608. hModule,
  609. lpProcName);
  610. }
  611. //
  612. // Call the original GetProcAddress from kernel32.
  613. //
  614. Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks,
  615. AVRF_INDEX_KERNEL32_GETPROCADDRESS);
  616. ProcAddress = (* Function)(hModule, lpProcName);
  617. //
  618. // Check if we want to thunk this export on the fly.
  619. //
  620. if (ProcAddress != NULL) {
  621. //
  622. // Parse all thunked DLLs.
  623. //
  624. // N.B.
  625. //
  626. // We cannot look only for thunked functions inside
  627. // the hModule DLL because that can be forwarded to another thunked DLL.
  628. // (e.g. kernel32!TryEnterCriticalSection is forwarded
  629. // to ntdll!RtlTryEnterCriticalSection).
  630. //
  631. for (DllIndex = 0; AVrfpExportDlls[DllIndex].DllName != NULL; DllIndex += 1) {
  632. //
  633. // Parse all thunks for this DLL.
  634. //
  635. Thunks = AVrfpExportDlls[ DllIndex ].DllThunks;
  636. for (ThunkIndex = 0; Thunks[ ThunkIndex ].ThunkName != NULL; ThunkIndex += 1) {
  637. if (Thunks[ ThunkIndex ].ThunkOldAddress == ProcAddress) {
  638. ProcAddress = Thunks[ ThunkIndex ].ThunkNewAddress;
  639. if ((AVrfpProvider.VerifierDebug & VRFP_DEBUG_LOADLIBRARY_THUNKED) != 0) {
  640. DbgPrint ("AVRF: AVrfpGetProcAddress (%p, %s) -> thunk address %p\n",
  641. hModule,
  642. lpProcName,
  643. ProcAddress);
  644. }
  645. goto Done;
  646. }
  647. }
  648. }
  649. }
  650. Done:
  651. return ProcAddress;
  652. }
  653. NTSTATUS
  654. NTAPI
  655. AVrfpLdrGetProcedureAddress(
  656. IN PVOID DllHandle,
  657. IN CONST ANSI_STRING* ProcedureName OPTIONAL,
  658. IN ULONG ProcedureNumber OPTIONAL,
  659. OUT PVOID *ProcedureAddress
  660. )
  661. /*++
  662. Routine description:
  663. This routine is used to chain APIs hooked by other hook engines.
  664. If the routine searched is one already hooked by verifier
  665. then the verifier replacement is returned instead of the
  666. original export.
  667. --*/
  668. {
  669. NTSTATUS Status;
  670. ULONG DllIndex;
  671. ULONG ThunkIndex;
  672. PRTL_VERIFIER_THUNK_DESCRIPTOR Thunks;
  673. Status = LdrGetProcedureAddress (DllHandle,
  674. ProcedureName,
  675. ProcedureNumber,
  676. ProcedureAddress);
  677. if (! NT_SUCCESS(Status)) {
  678. return Status;
  679. }
  680. //
  681. // Parse all thunks with hooks for this DLL.
  682. //
  683. for (DllIndex = 0; AVrfpExportDlls[DllIndex].DllName != NULL; DllIndex += 1) {
  684. Thunks = AVrfpExportDlls[DllIndex].DllThunks;
  685. for (ThunkIndex = 0; Thunks[ThunkIndex].ThunkName != NULL; ThunkIndex += 1) {
  686. if (Thunks[ThunkIndex].ThunkOldAddress == *ProcedureAddress) {
  687. *ProcedureAddress = Thunks[ThunkIndex].ThunkNewAddress;
  688. if ((AVrfpProvider.VerifierDebug & VRFP_DEBUG_LOADLIBRARY_THUNKED) != 0) {
  689. DbgPrint ("AVRF: AVrfpLdrGetProcedureAddress (%p, %s) -> new address %p\n",
  690. DllHandle,
  691. Thunks[ThunkIndex].ThunkName,
  692. *ProcedureAddress);
  693. }
  694. goto Exit;
  695. }
  696. }
  697. }
  698. Exit:
  699. return Status;
  700. }
  701. #define READ_POINTER(Address, Bias) (*((PLONG_PTR)((PBYTE)(LONG_PTR)(Address) + (Bias))))
  702. NTSTATUS
  703. AVrfpRedirectNtdllStopFunction (
  704. VOID
  705. )
  706. /*++
  707. Routine description:
  708. This function is called only on XP client to patch RtlApplicationVerifierStop
  709. so that it jumps unconditionally to the better VerifierStopMessage. For .NET
  710. server and later this is not an issue but for XP client there is code in ntdll
  711. (namely page heap) that calls this old function that is not flexible enough.
  712. The main drawback is that it breaks into debugger no questions asked. The
  713. newer function is more sophisticated (it logs, skips known stops, etc.).
  714. Since verifier.dll can be refreshed on an XP client system through the
  715. verifier package but ntdll.dll remains the one shipped with XP client
  716. we need this patching solution.
  717. The patching works by writing an unconditional jump at the start of
  718. RtlApplicationVerifieStop to the better function VerifierStopMessage.
  719. Parameters:
  720. None.
  721. Return value:
  722. STATUS_SUCCESS or various failure codes.
  723. --*/
  724. {
  725. #if defined(_X86_)
  726. PVOID TargetAddress;
  727. PVOID ThunkAddress;
  728. PVOID SourceAddress;
  729. PVOID ProtectAddress;
  730. BYTE JumpCode[5];
  731. LONG_PTR JumpAddress;
  732. NTSTATUS Status;
  733. ULONG OldProtection;
  734. SIZE_T PageSize;
  735. SIZE_T ProtectSize;
  736. //
  737. // Sanity check. The function should be called only for XP client.
  738. //
  739. if (AVrfpBuildNumber != WINXP_BUILD_NUMBER) {
  740. ASSERT (AVrfpBuildNumber == WINXP_BUILD_NUMBER);
  741. return STATUS_UNSUCCESSFUL;
  742. }
  743. //
  744. // Prepare the code to be patched. The code layout is explained below.
  745. //
  746. // RtlApplicationVerifierStop points to 0xFF 0x25 THUNKADDRESS
  747. // THUNKADDRESS points NTDLL_ADDRESS
  748. //
  749. ThunkAddress = (PVOID)READ_POINTER(RtlApplicationVerifierStop, 2); // FF 25 ADDRESS
  750. SourceAddress = (PVOID)READ_POINTER(ThunkAddress, 0); // ADDRESS
  751. TargetAddress = VerifierStopMessage;
  752. JumpAddress = (LONG_PTR)TargetAddress - (LONG_PTR)SourceAddress - sizeof JumpCode;
  753. JumpCode[0] = 0xE9; // unconditional jump X86 opcode
  754. *((LONG_PTR *)(JumpCode + 1)) = JumpAddress;
  755. PageSize = (SIZE_T)(AVrfpSysBasicInfo.PageSize);
  756. if (PageSize == 0) {
  757. ASSERT (PageSize != 0 && "AVrfpSysBasicInfo not initialized");
  758. PageSize = 0x1000;
  759. }
  760. //
  761. // Make R/W the start of the ntdll function to be patched.
  762. //
  763. ProtectAddress = SourceAddress;
  764. ProtectSize = PageSize;
  765. Status = NtProtectVirtualMemory (NtCurrentProcess(),
  766. &ProtectAddress,
  767. &ProtectSize,
  768. PAGE_READWRITE,
  769. &OldProtection);
  770. if (! NT_SUCCESS(Status)) {
  771. DbgPrint ("AVRF: failed to make R/W old verifier stop function @ %p (%X) \n",
  772. SourceAddress,
  773. Status);
  774. return Status;
  775. }
  776. //
  777. // Write patch code over old function.
  778. //
  779. RtlCopyMemory (SourceAddress, JumpCode, sizeof JumpCode);
  780. //
  781. // Change the protection back.
  782. //
  783. Status = NtProtectVirtualMemory (NtCurrentProcess(),
  784. &ProtectAddress,
  785. &ProtectSize,
  786. OldProtection,
  787. &OldProtection);
  788. if (! NT_SUCCESS(Status)) {
  789. DbgPrint ("AVRF: failed to revert protection of old verifier stop function @ %p (%X) \n",
  790. SourceAddress,
  791. Status);
  792. //
  793. // At this point we managed to patch the code so we will not fail the function
  794. // since this will actually fail process startup.
  795. //
  796. Status = STATUS_SUCCESS;
  797. }
  798. return Status;
  799. #else
  800. //
  801. // Just x86 for now. For other architectures the operation will be considered
  802. // successful. The side-effect of not patching is that some verification code
  803. // from ntdll will cause debugger breaks. So basically the verified process
  804. // needs to be run under debugger for meaningful results.
  805. //
  806. // The only other architecture shipped for XP client is IA64 so eventually we
  807. // will need to write code for that too.
  808. //
  809. return STATUS_SUCCESS;
  810. #endif // #if defined(_X86_)
  811. }