You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
4.7 KiB
166 lines
4.7 KiB
#include "RawDriver.hpp"
|
|
#include "ZwSwapCert.hpp"
|
|
|
|
// this function was taken from Kernel-Force-Delete...
|
|
// https://github.com/DragonQuestHero/Kernel-Force-Delete/blob/master/Kernel_Force_Delete/Kernel_Force_Delete.cc#L3
|
|
// (i cleaned it up a little and put it in here)
|
|
NTSTATUS Utils::SwapDriver(PUNICODE_STRING DriverPath, PVOID DriverBuffer, SIZE_T BufferSize)
|
|
{
|
|
HANDLE FileHandle;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IOBlock;
|
|
PDEVICE_OBJECT DeviceObject = nullptr;
|
|
PFILE_OBJECT FileObject = nullptr;
|
|
OBJECT_ATTRIBUTES FileAttributes;
|
|
|
|
RtlZeroMemory(&IOBlock, sizeof IOBlock);
|
|
InitializeObjectAttributes(&FileAttributes,
|
|
DriverPath,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
if ((Status = IoCreateFileSpecifyDeviceObjectHint(
|
|
&FileHandle,
|
|
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA,
|
|
&FileAttributes,
|
|
&IOBlock,
|
|
NULL,
|
|
NULL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
NULL,
|
|
CreateFileTypeNone,
|
|
NULL,
|
|
IO_IGNORE_SHARE_ACCESS_CHECK,
|
|
DeviceObject)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
|
|
if ((Status = ObReferenceObjectByHandle(
|
|
FileHandle, NULL, NULL, NULL, (PVOID*)&FileObject, NULL)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
// Make the driver file object section object null and then try
|
|
// and delete the file on disk...
|
|
FileObject->SectionObjectPointer->ImageSectionObject = 0;
|
|
FileObject->DeleteAccess = 1;
|
|
if ((Status = ZwDeleteFile(&FileAttributes)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
ObDereferenceObject(FileObject);
|
|
if ((Status = ZwClose(FileHandle)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
RtlZeroMemory(&IOBlock, sizeof IOBlock);
|
|
InitializeObjectAttributes(&FileAttributes, DriverPath,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL, NULL);
|
|
|
|
// Create a new file where the driver was on disk
|
|
// instead we are going to write a valid driver to disk...
|
|
// (by valid i mean signed by MS...)
|
|
if ((Status = ZwCreateFile(
|
|
&FileHandle,
|
|
GENERIC_WRITE,
|
|
&FileAttributes,
|
|
&IOBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
NULL
|
|
)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
// Write the driver buffer to disk...
|
|
if ((Status = ZwWriteFile(
|
|
FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IOBlock,
|
|
DriverBuffer,
|
|
BufferSize,
|
|
NULL,
|
|
NULL
|
|
)) != STATUS_SUCCESS)
|
|
return Status;
|
|
|
|
return ZwClose(FileHandle);
|
|
}
|
|
|
|
PVOID Utils::MapDriver(UINT64 ModuleBase, UINT64 DriverBuffer)
|
|
{
|
|
// copy pe header...
|
|
PIMAGE_DOS_HEADER dosHeaders = (IMAGE_DOS_HEADER*)DriverBuffer;
|
|
PIMAGE_NT_HEADERS64 ntHeaders = (PIMAGE_NT_HEADERS64)(DriverBuffer + dosHeaders->e_lfanew);
|
|
|
|
// disable write protect bit in cr0...
|
|
{
|
|
auto cr0 = __readcr0();
|
|
cr0 &= 0xfffffffffffeffff;
|
|
__writecr0(cr0);
|
|
_disable();
|
|
}
|
|
|
|
// PE headers are not writeable (readonly i assume? so we disable WP bit)...
|
|
memcpy((PVOID)ModuleBase, (PVOID)DriverBuffer, ntHeaders->OptionalHeader.SizeOfHeaders);
|
|
|
|
// enable write protect bit in cr0...
|
|
{
|
|
auto cr0 = __readcr0();
|
|
cr0 |= 0x10000;
|
|
_enable();
|
|
__writecr0(cr0);
|
|
}
|
|
|
|
PIMAGE_SECTION_HEADER sections =
|
|
(PIMAGE_SECTION_HEADER)((UINT8*)&ntHeaders->OptionalHeader +
|
|
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
|
|
|
// map sections...
|
|
for (UINT32 i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
|
{
|
|
PIMAGE_SECTION_HEADER section = §ions[i];
|
|
memcpy((PVOID)(ModuleBase + section->VirtualAddress),
|
|
(PVOID)(DriverBuffer + section->PointerToRawData), section->SizeOfRawData);
|
|
}
|
|
|
|
// return entry point...
|
|
return (PVOID)(ModuleBase + ntHeaders->OptionalHeader.AddressOfEntryPoint);
|
|
}
|
|
|
|
NTSTATUS ScDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
UNICODE_STRING DriverPath;
|
|
NTSTATUS Result;
|
|
|
|
// get the path to the current driver on disk...
|
|
if ((Result = IoQueryFullDriverPath(DriverObject, &DriverPath)) != STATUS_SUCCESS)
|
|
return Result;
|
|
|
|
// replace file on disk with the MS driver...
|
|
if ((Result = Utils::SwapDriver(&DriverPath, RawDriver, MS_DRIVER_FILE_SIZE)) != STATUS_SUCCESS)
|
|
return Result;
|
|
|
|
// allocate a temp buffer, copy the MS driver into the buffer
|
|
// and then map the driver from the buffer into the first section
|
|
// of this driver + overwrite this drivers PE headers...
|
|
PVOID DriverTempBuffer =
|
|
ExAllocatePool(NonPagedPool, sizeof RawDriver);
|
|
|
|
memcpy(DriverTempBuffer, RawDriver, sizeof RawDriver);
|
|
PDRIVER_INITIALIZE SignedDriverEntry = (PDRIVER_INITIALIZE)
|
|
Utils::MapDriver((UINT64)DriverObject->DriverStart, (UINT64)DriverTempBuffer);
|
|
|
|
// change driver size and entry point to the mapped MS driver...
|
|
ExFreePool(DriverTempBuffer);
|
|
DriverObject->DriverSize = sizeof RawDriver;
|
|
DriverObject->DriverInit = SignedDriverEntry;
|
|
return DriverEntry(DriverObject, RegistryPath);
|
|
} |