[VERIFIER] Add skeleton provider.
[reactos.git] / dll / win32 / verifier / verifier.c
1 /*
2 * PROJECT: Application verifier
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Main entrypoint
5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include <ndk/rtlfuncs.h>
9 #include <reactos/verifier.h>
10
11 #if 0
12 #define PROVIDER_PREFIX "AVRF"
13 #else
14 #define PROVIDER_PREFIX "RVRF"
15 #endif
16
17
18 VOID NTAPI AVrfpDllLoadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
19 VOID NTAPI AVrfpDllUnloadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
20 VOID NTAPI AVrfpNtdllHeapFreeCallback(PVOID AllocationBase, SIZE_T AllocationSize);
21
22 // DPFLTR_VERIFIER_ID
23
24
25 NTSTATUS NTAPI AVrfpLdrGetProcedureAddress(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress);
26
27 static RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpNtdllThunks[] =
28 {
29 { "LdrGetProcedureAddress", NULL, AVrfpLdrGetProcedureAddress },
30 { NULL }
31 };
32
33 FARPROC WINAPI AVrfpGetProcAddress(IN HMODULE hModule, IN LPCSTR lpProcName);
34
35 static RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpKernel32Thunks[] =
36 {
37 { "GetProcAddress", NULL, AVrfpGetProcAddress },
38 { NULL }
39 };
40
41 static RTL_VERIFIER_DLL_DESCRIPTOR AVrfpDllDescriptors[] =
42 {
43 { L"ntdll.dll", 0, NULL, AVrfpNtdllThunks },
44 { L"kernel32.dll", 0, NULL, AVrfpKernel32Thunks },
45 { NULL }
46 };
47
48 RTL_VERIFIER_PROVIDER_DESCRIPTOR AVrfpProvider =
49 {
50 /*.Length =*/ sizeof(AVrfpProvider),
51 /*.ProviderDlls =*/ AVrfpDllDescriptors,
52 /*.ProviderDllLoadCallback =*/ AVrfpDllLoadCallback,
53 /*.ProviderDllUnloadCallback =*/ AVrfpDllUnloadCallback,
54 /*.VerifierImage =*/ NULL,
55 /*.VerifierFlags =*/ 0,
56 /*.VerifierDebug =*/ 0,
57 /*.RtlpGetStackTraceAddress =*/ NULL,
58 /*.RtlpDebugPageHeapCreate =*/ NULL,
59 /*.RtlpDebugPageHeapDestroy =*/ NULL,
60 /*.ProviderNtdllHeapFreeCallback =*/ AVrfpNtdllHeapFreeCallback
61 };
62
63
64
65 BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
66 {
67 switch (dwReason)
68 {
69 case DLL_PROCESS_ATTACH:
70 case DLL_PROCESS_DETACH:
71 case DLL_THREAD_ATTACH:
72 case DLL_THREAD_DETACH:
73 break;
74 case DLL_PROCESS_VERIFIER:
75 *(PRTL_VERIFIER_PROVIDER_DESCRIPTOR*)lpReserved = &AVrfpProvider;
76 break;
77 }
78 return TRUE;
79 }
80
81 VOID NTAPI AVrfpDllLoadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
82 {
83 PLDR_DATA_TABLE_ENTRY LdrEntry = (PLDR_DATA_TABLE_ENTRY)Reserved;
84 DbgPrint(PROVIDER_PREFIX ": %ws @ %p: ep: %p\n", DllName, DllBase, LdrEntry->EntryPoint);
85 /* TODO: Hook entrypoint */
86 }
87
88
89 VOID NTAPI AVrfpDllUnloadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
90 {
91 DbgPrint(PROVIDER_PREFIX ": unloading %ws\n", DllName);
92 }
93
94 VOID NTAPI AVrfpNtdllHeapFreeCallback(PVOID AllocationBase, SIZE_T AllocationSize)
95 {
96 DbgPrint(PROVIDER_PREFIX ": Heap free 0x%x @ %p\n", AllocationSize, AllocationBase);
97 /* TODO: Sanity checks */
98 }
99
100 PVOID AVrfpFindReplacementThunk(PVOID Proc)
101 {
102 PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
103 PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
104
105 for (DllDescriptor = AVrfpDllDescriptors; DllDescriptor->DllName; ++DllDescriptor)
106 {
107 for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor->ThunkName; ++ThunkDescriptor)
108 {
109 if (ThunkDescriptor->ThunkOldAddress == Proc)
110 {
111 return ThunkDescriptor->ThunkNewAddress;
112 }
113 }
114 }
115 return Proc;
116 }
117
118
119 NTSTATUS NTAPI AVrfpLdrGetProcedureAddress(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress)
120 {
121 NTSTATUS (NTAPI *oLdrGetProcedureAddress)(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress);
122 NTSTATUS Status;
123 PVOID Replacement;
124
125 oLdrGetProcedureAddress = AVrfpNtdllThunks[0].ThunkOldAddress;
126
127 Status = oLdrGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress);
128 if (!NT_SUCCESS(Status))
129 return Status;
130
131 Replacement = AVrfpFindReplacementThunk(*ProcedureAddress);
132 if (Replacement != *ProcedureAddress)
133 {
134 *ProcedureAddress = Replacement;
135 if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_SHOWDYNTHUNKS)
136 DbgPrint(PROVIDER_PREFIX ": AVrfpLdrGetProcedureAddress (%p, %Z) -> thunk address %p\n", BaseAddress, Name, *ProcedureAddress);
137 }
138
139 return Status;
140 }
141
142 FARPROC WINAPI AVrfpGetProcAddress(IN HMODULE hModule, IN LPCSTR lpProcName)
143 {
144 FARPROC (WINAPI* oGetProcAddress)(IN HMODULE hModule, IN LPCSTR lpProcName);
145 FARPROC Proc, Replacement;
146
147 if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_LOGCALLS)
148 DbgPrint(PROVIDER_PREFIX ": AVrfpGetProcAddress (%p, %s)\n", hModule, lpProcName);
149
150 oGetProcAddress = AVrfpKernel32Thunks[0].ThunkOldAddress;
151 Proc = oGetProcAddress(hModule, lpProcName);
152 if (!Proc)
153 return Proc;
154
155 Replacement = AVrfpFindReplacementThunk(Proc);
156 if (Replacement != Proc)
157 {
158 Proc = Replacement;
159 if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_SHOWDYNTHUNKS)
160 DbgPrint(PROVIDER_PREFIX ": AVrfpGetProcAddress (%p, %s) -> thunk address %p\n", hModule, lpProcName, Proc);
161 }
162
163 return Proc;
164 }
165