思路
简单粗暴,直接注册一个模块监听,然后当目标驱动加载时hook它的驱动加载函数,直接返回成功,对付一下比较简单的驱动保护效果屡试不爽
获取DriverEntry
PVOID GetDriverEntryByImageBase(PVOID ImageBase)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS64 pNTHeader;
PVOID pEntryPoint;
pDOSHeader = (PIMAGE_DOS_HEADER)ImageBase;
pNTHeader = (PIMAGE_NT_HEADERS64)((ULONG64)ImageBase + pDOSHeader->e_lfanew);
pEntryPoint = (PVOID)((ULONG64)ImageBase + pNTHeader->OptionalHeader.AddressOfEntryPoint);
return pEntryPoint;
}
监视模块加载 ProcessId 为0则是加载驱动,否者是dll
VOID UnicodeToChar(PUNICODE_STRING dst, char* src)
{
ANSI_STRING string;
if (!src || !dst || !dst->Buffer) return;
if (RtlUnicodeStringToAnsiString(&string, dst, TRUE) == STATUS_SUCCESS) {
strcpy(src, string.Buffer);
RtlFreeAnsiString(&string);
}
}
VOID LoadImageNotifyRoutine
(
__in_opt PUNICODE_STRING FullImageName,
__in HANDLE ProcessId,
__in PIMAGE_INFO ImageInfo
)
{
PVOID pDrvEntry;
char szFullImageName[260] = { 0 };
if (FullImageName != NULL && MmIsAddressValid(FullImageName))
{
if (ProcessId == 0)
{
pDrvEntry = GetDriverEntryByImageBase(ImageInfo->ImageBase);
UnicodeToChar(FullImageName, szFullImageName);
if (strstr(_strlwr(szFullImageName), "目标驱动或者dll名称,不带后缀名"))
{
Log("拦截驱动 [%s]", szFullImageName);
DenyLoadDriver(pDrvEntry);
return;
}
}
}
}
注册回调
PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine);
HOOK
KIRQL 关闭写保护()
{
KIRQL irql = KeRaiseIrqlToDpcLevel();
ULONG_PTR cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
_disable();
__writecr0(cr0);
return irql;
}
VOID 开启写保护(KIRQL irql)
{
ULONG_PTR cr0 = __readcr0();
cr0 |= 0x10000;
__writecr0(cr0);
_enable();
KeLowerIrql(irql);
}
NTSTATUS FakeDriverEntry(IN PDRIVER_OBJECT MyDriver, IN PUNICODE_STRING RegistryPath)
{
//MyDriver->DriverUnload = FakeDriverUnLoad;
return STATUS_SUCCESS;
}
void DenyLoadDriver(PVOID DriverEntry)
{
KIRQL irql = 关闭写保护();
RtlCopyMemory(DriverEntry, (PCHAR)FakeDriverEntry, 32);
开启写保护(irql);
}