xref: /reactos/dll/win32/verifier/verifier.c (revision cce399e7)
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
26 NTAPI
27 AVrfpLdrGetProcedureAddress(
28     _In_ PVOID BaseAddress,
29     _In_opt_ _When_(Ordinal == 0, _Notnull_) PANSI_STRING Name,
30     _In_opt_ _When_(Name == NULL, _In_range_(>, 0)) ULONG Ordinal,
31     _Out_ PVOID *ProcedureAddress);
32 
33 static RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpNtdllThunks[] =
34 {
35     { "LdrGetProcedureAddress", NULL, AVrfpLdrGetProcedureAddress },
36     { NULL }
37 };
38 
39 FARPROC WINAPI AVrfpGetProcAddress(IN HMODULE hModule, IN LPCSTR lpProcName);
40 
41 static RTL_VERIFIER_THUNK_DESCRIPTOR AVrfpKernel32Thunks[] =
42 {
43     { "GetProcAddress", NULL, AVrfpGetProcAddress },
44     { NULL }
45 };
46 
47 static RTL_VERIFIER_DLL_DESCRIPTOR AVrfpDllDescriptors[] =
48 {
49     { L"ntdll.dll", 0, NULL, AVrfpNtdllThunks },
50     { L"kernel32.dll", 0, NULL, AVrfpKernel32Thunks },
51     { NULL }
52 };
53 
54 RTL_VERIFIER_PROVIDER_DESCRIPTOR AVrfpProvider =
55 {
56     /*.Length =*/ sizeof(AVrfpProvider),
57     /*.ProviderDlls =*/ AVrfpDllDescriptors,
58     /*.ProviderDllLoadCallback =*/ AVrfpDllLoadCallback,
59     /*.ProviderDllUnloadCallback =*/ AVrfpDllUnloadCallback,
60     /*.VerifierImage =*/ NULL,
61     /*.VerifierFlags =*/ 0,
62     /*.VerifierDebug =*/ 0,
63     /*.RtlpGetStackTraceAddress =*/ NULL,
64     /*.RtlpDebugPageHeapCreate =*/ NULL,
65     /*.RtlpDebugPageHeapDestroy =*/ NULL,
66     /*.ProviderNtdllHeapFreeCallback =*/ AVrfpNtdllHeapFreeCallback
67 };
68 
69 
70 
71 BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
72 {
73     switch (dwReason)
74     {
75     case DLL_PROCESS_ATTACH:
76     case DLL_PROCESS_DETACH:
77     case DLL_THREAD_ATTACH:
78     case DLL_THREAD_DETACH:
79         break;
80     case DLL_PROCESS_VERIFIER:
81         *(PRTL_VERIFIER_PROVIDER_DESCRIPTOR*)lpReserved = &AVrfpProvider;
82         break;
83     }
84     return TRUE;
85 }
86 
87 VOID NTAPI AVrfpDllLoadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
88 {
89     PLDR_DATA_TABLE_ENTRY LdrEntry = (PLDR_DATA_TABLE_ENTRY)Reserved;
90     DbgPrint(PROVIDER_PREFIX ": %ws @ %p: ep: %p\n", DllName, DllBase, LdrEntry->EntryPoint);
91     /* TODO: Hook entrypoint */
92 }
93 
94 
95 VOID NTAPI AVrfpDllUnloadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
96 {
97     DbgPrint(PROVIDER_PREFIX ": unloading %ws\n", DllName);
98 }
99 
100 VOID NTAPI AVrfpNtdllHeapFreeCallback(PVOID AllocationBase, SIZE_T AllocationSize)
101 {
102     DbgPrint(PROVIDER_PREFIX ": Heap free 0x%x @ %p\n", AllocationSize, AllocationBase);
103     /* TODO: Sanity checks */
104 }
105 
106 PVOID AVrfpFindReplacementThunk(PVOID Proc)
107 {
108     PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
109     PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
110 
111     for (DllDescriptor = AVrfpDllDescriptors; DllDescriptor->DllName; ++DllDescriptor)
112     {
113         for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor->ThunkName; ++ThunkDescriptor)
114         {
115             if (ThunkDescriptor->ThunkOldAddress == Proc)
116             {
117                 return ThunkDescriptor->ThunkNewAddress;
118             }
119         }
120     }
121     return Proc;
122 }
123 
124 
125 NTSTATUS NTAPI
126 AVrfpLdrGetProcedureAddress(
127     _In_ PVOID BaseAddress,
128     _In_opt_ _When_(Ordinal == 0, _Notnull_) PANSI_STRING Name,
129     _In_opt_ _When_(Name == NULL, _In_range_(>, 0)) ULONG Ordinal,
130     _Out_ PVOID *ProcedureAddress)
131 {
132     NTSTATUS(NTAPI *oLdrGetProcedureAddress)(
133         _In_ PVOID BaseAddress,
134         _In_opt_ _When_(Ordinal == 0, _Notnull_) PANSI_STRING Name,
135         _In_opt_ _When_(Name == NULL, _In_range_(>, 0)) ULONG Ordinal,
136         _Out_ PVOID *ProcedureAddress);
137     NTSTATUS Status;
138     PVOID Replacement;
139 
140     oLdrGetProcedureAddress = AVrfpNtdllThunks[0].ThunkOldAddress;
141 
142     Status = oLdrGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress);
143     if (!NT_SUCCESS(Status))
144         return Status;
145 
146     Replacement = AVrfpFindReplacementThunk(*ProcedureAddress);
147     if (Replacement != *ProcedureAddress)
148     {
149         *ProcedureAddress = Replacement;
150         if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_SHOWDYNTHUNKS)
151             DbgPrint(PROVIDER_PREFIX ": AVrfpLdrGetProcedureAddress (%p, %Z) -> thunk address %p\n", BaseAddress, Name, *ProcedureAddress);
152     }
153 
154     return Status;
155 }
156 
157 FARPROC WINAPI AVrfpGetProcAddress(IN HMODULE hModule, IN LPCSTR lpProcName)
158 {
159     FARPROC (WINAPI* oGetProcAddress)(IN HMODULE hModule, IN LPCSTR lpProcName);
160     FARPROC Proc, Replacement;
161 
162     if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_LOGCALLS)
163         DbgPrint(PROVIDER_PREFIX ": AVrfpGetProcAddress (%p, %s)\n", hModule, lpProcName);
164 
165     oGetProcAddress = AVrfpKernel32Thunks[0].ThunkOldAddress;
166     Proc = oGetProcAddress(hModule, lpProcName);
167     if (!Proc)
168         return Proc;
169 
170     Replacement = AVrfpFindReplacementThunk(Proc);
171     if (Replacement != Proc)
172     {
173         Proc = Replacement;
174         if (AVrfpProvider.VerifierDebug & RTL_VRF_DBG_VERIFIER_SHOWDYNTHUNKS)
175             DbgPrint(PROVIDER_PREFIX ": AVrfpGetProcAddress (%p, %s) -> thunk address %p\n", hModule, lpProcName, Proc);
176     }
177 
178     return Proc;
179 }
180 
181