1 /*
2 * PROJECT: ReactOS SDK: Auxiliary Kernel-Mode Library
3 * LICENSE: BSD-2-Clause-Views (https://spdx.org/licenses/BSD-2-Clause-Views)
4 * PURPOSE: Main source file
5 * COPYRIGHT: Copyright 2019-2020 Max Korostil <mrmks04@yandex.ru>
6 * Copyright 2021 Victor Perevertkin <victor.perevertkin@reactos.org>
7 */
8
9 #include <ntifs.h>
10 #include <ntintsafe.h>
11 #include <ndk/ntndk.h>
12 #include <pseh/pseh2.h>
13 #include <aux_klib.h>
14
15 #define TAG_AUXK 'AuxK'
16
17 typedef NTSTATUS (NTAPI *PFN_RTLQUERYMODULEINFORMATION)(PULONG, ULONG, PVOID);
18
19 PFN_RTLQUERYMODULEINFORMATION pfnRtlQueryModuleInformation;
20 LONG gKlibInitialized = 0;
21
22
23 CODE_SEG("PAGE")
24 NTSTATUS
25 NTAPI
AuxKlibInitialize(VOID)26 AuxKlibInitialize(VOID)
27 {
28 RTL_OSVERSIONINFOW osVersion;
29 UNICODE_STRING strRtlQueryModuleInformation = RTL_CONSTANT_STRING(L"RtlQueryModuleInformation");
30
31 PAGED_CODE();
32
33 if (!gKlibInitialized)
34 {
35 RtlGetVersion(&osVersion);
36 if (osVersion.dwMajorVersion >= 5)
37 {
38 pfnRtlQueryModuleInformation = MmGetSystemRoutineAddress(&strRtlQueryModuleInformation);
39 InterlockedExchange(&gKlibInitialized, 1);
40 }
41 else
42 {
43 return STATUS_NOT_SUPPORTED;
44 }
45 }
46
47 return STATUS_SUCCESS;
48 }
49
50 CODE_SEG("PAGE")
51 NTSTATUS
52 NTAPI
AuxKlibQueryModuleInformation(_In_ PULONG InformationLength,_In_ ULONG SizePerModule,_Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo)53 AuxKlibQueryModuleInformation(
54 _In_ PULONG InformationLength,
55 _In_ ULONG SizePerModule,
56 _Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo)
57 {
58 NTSTATUS status;
59
60 PAGED_CODE();
61
62 if (gKlibInitialized != 1)
63 {
64 return STATUS_UNSUCCESSFUL;
65 }
66
67 // if we have the function exported from the kernel, use it
68 if (pfnRtlQueryModuleInformation != NULL)
69 {
70 return pfnRtlQueryModuleInformation(InformationLength, SizePerModule, ModuleInfo);
71 }
72
73 if (SizePerModule != sizeof(AUX_MODULE_BASIC_INFO) &&
74 SizePerModule != sizeof(AUX_MODULE_EXTENDED_INFO))
75 {
76 return STATUS_INVALID_PARAMETER_2;
77 }
78
79 if ((ULONG_PTR)ModuleInfo & (TYPE_ALIGNMENT(AUX_MODULE_EXTENDED_INFO) - 1))
80 {
81 return STATUS_INVALID_PARAMETER_3;
82 }
83
84 // first call the function with a place for only 1 module
85 RTL_PROCESS_MODULES processModulesMinimal;
86 PRTL_PROCESS_MODULES processModules = &processModulesMinimal;
87 ULONG sysInfoLength = sizeof(processModulesMinimal);
88 ULONG resultLength;
89
90 // loop until we have a large-enough buffer for all modules
91 do
92 {
93 status = ZwQuerySystemInformation(SystemModuleInformation,
94 processModules,
95 sysInfoLength,
96 &resultLength);
97
98 if (status == STATUS_INFO_LENGTH_MISMATCH)
99 {
100 // free the old buffer if it's not the first one
101 if (processModules != &processModulesMinimal)
102 {
103 ExFreePoolWithTag(processModules, TAG_AUXK);
104 }
105
106 _SEH2_TRY
107 {
108 // allocate the new one
109 processModules = ExAllocatePoolWithQuotaTag(PagedPool, resultLength, TAG_AUXK);
110 }
111 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
112 {
113 _SEH2_YIELD(return _SEH2_GetExceptionCode());
114 }
115 _SEH2_END;
116
117 if (!processModules)
118 {
119 return STATUS_INSUFFICIENT_RESOURCES;
120 }
121 sysInfoLength = resultLength;
122 }
123
124 } while (status == STATUS_INFO_LENGTH_MISMATCH);
125
126 if (!NT_SUCCESS(status))
127 {
128 goto Cleanup;
129 }
130
131 ULONG modulesSize;
132 status = RtlULongMult(SizePerModule, processModules->NumberOfModules, &modulesSize);
133 if (!NT_SUCCESS(status))
134 {
135 goto Cleanup;
136 }
137
138 if (ModuleInfo == NULL)
139 {
140 ASSERT(status == STATUS_SUCCESS);
141 *InformationLength = modulesSize;
142 goto Cleanup;
143 }
144
145 if (*InformationLength < modulesSize)
146 {
147 status = STATUS_BUFFER_TOO_SMALL;
148 *InformationLength = modulesSize;
149 goto Cleanup;
150 }
151
152 // copy the information to the input array
153 for (UINT32 i = 0; i < processModules->NumberOfModules; i++)
154 {
155 ModuleInfo[i].BasicInfo.ImageBase = processModules->Modules[i].ImageBase;
156
157 if (SizePerModule == sizeof(AUX_MODULE_EXTENDED_INFO))
158 {
159 ModuleInfo[i].ImageSize = processModules->Modules[i].ImageSize;
160 ModuleInfo[i].FileNameOffset = processModules->Modules[i].OffsetToFileName;
161 RtlCopyMemory(&ModuleInfo[i].FullPathName,
162 processModules->Modules[i].FullPathName,
163 sizeof(processModules->Modules[i].FullPathName));
164 }
165 }
166
167 Cleanup:
168 // don't accidentally free the stack buffer
169 if (processModules != NULL && processModules != &processModulesMinimal)
170 {
171 ExFreePoolWithTag(processModules, TAG_AUXK);
172 }
173
174 return status;
175 }
176
177 NTSTATUS
AuxKlibGetBugCheckData(_Inout_ PKBUGCHECK_DATA BugCheckData)178 AuxKlibGetBugCheckData(
179 _Inout_ PKBUGCHECK_DATA BugCheckData)
180 {
181 if (BugCheckData->BugCheckDataSize != sizeof(*BugCheckData))
182 {
183 return STATUS_INFO_LENGTH_MISMATCH;
184 }
185
186 BugCheckData->BugCheckCode = KiBugCheckData[0];
187 BugCheckData->Parameter1 = KiBugCheckData[1];
188 BugCheckData->Parameter2 = KiBugCheckData[2];
189 BugCheckData->Parameter3 = KiBugCheckData[3];
190 BugCheckData->Parameter4 = KiBugCheckData[4];
191
192 return STATUS_SUCCESS;
193 }
194
195 PIMAGE_EXPORT_DIRECTORY
AuxKlibGetImageExportDirectory(_In_ PVOID ImageBase)196 AuxKlibGetImageExportDirectory(
197 _In_ PVOID ImageBase)
198 {
199 ULONG size;
200 return RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
201 }
202
203 _IRQL_requires_max_(PASSIVE_LEVEL)
204 CODE_SEG("PAGE")
205 NTSTATUS
206 NTAPI
AuxKlibEnumerateSystemFirmwareTables(_In_ ULONG FirmwareTableProviderSignature,_Out_writes_bytes_to_opt_ (BufferLength,* ReturnLength)PVOID FirmwareTableBuffer,_In_ ULONG BufferLength,_Out_opt_ PULONG ReturnLength)207 AuxKlibEnumerateSystemFirmwareTables (
208 _In_ ULONG FirmwareTableProviderSignature,
209 _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer,
210 _In_ ULONG BufferLength,
211 _Out_opt_ PULONG ReturnLength)
212 {
213 return STATUS_NOT_IMPLEMENTED;
214 }
215
216 _IRQL_requires_max_(PASSIVE_LEVEL)
217 CODE_SEG("PAGE")
218 NTSTATUS
219 NTAPI
AuxKlibGetSystemFirmwareTable(_In_ ULONG FirmwareTableProviderSignature,_In_ ULONG FirmwareTableID,_Out_writes_bytes_to_opt_ (BufferLength,* ReturnLength)PVOID FirmwareTableBuffer,_In_ ULONG BufferLength,_Out_opt_ PULONG ReturnLength)220 AuxKlibGetSystemFirmwareTable (
221 _In_ ULONG FirmwareTableProviderSignature,
222 _In_ ULONG FirmwareTableID,
223 _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer,
224 _In_ ULONG BufferLength,
225 _Out_opt_ PULONG ReturnLength)
226 {
227 return STATUS_NOT_IMPLEMENTED;
228 }
229