#include <ntddk.h>
#include <stdio.h>
NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject);
int IsNeedProtect(DEVICE_OBJECT *DeviceObject, PIRP Irp);
ULONG GetFunctionAddr(IN PCWSTR FunctionName);
VOID InlineHook();
NTKERNELAPI UCHAR *PsGetProcessImageFileName(__in PEPROCESS Process);
typedef NTSTATUS(FASTCALL *pIofCallDriver)(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp);
pIofCallDriver OldAddress;
NTSTATUS FASTCALL MyIofCallDriver(IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp)
{
NTSTATUS stat;
//先保存所有寄存器的原来状态,到时好恢复现场环境,跟加壳软件开始的指令也是一样
__asm
{
pushad
pushfd
}
if (IsNeedProtect(DeviceObject, Irp))
{
//返回删除失败的提示
__asm
{
popfd
popad
mov eax, 0xC000000D
mov stat, eax
}
return stat;
}
//先恢复现场环境,跳转回原地址
__asm
{
popfd
popad
mov ecx, DeviceObject
mov edx, Irp
call OldAddress;
mov stat, eax
}
return stat;
}
int IsNeedProtect(DEVICE_OBJECT *DeviceObject, PIRP Irp)
{
NTSTATUS status;
int nResult = FALSE;
DRIVER_OBJECT *DriverObject = DeviceObject->DriverObject;
WCHAR *pwsz = NULL;
IO_STACK_LOCATION *sp;
FILE_OBJECT *FileObject = NULL;
status = STATUS_INVALID_PARAMETER;
sp = IoGetNextIrpStackLocation(Irp);;
switch (sp->MajorFunction)
{
case IRP_MJ_SET_INFORMATION:
case IRP_MJ_WRITE:
case IRP_MJ_CREATE:
case IRP_MJ_READ:
goto Continue11;
default:
goto Exit00;
}
Continue11:
FileObject = sp->FileObject;
_try
{
pwsz = wcsrchr(DriverObject->DriverName.Buffer, L'\\');
pwsz++;
//判断Irp是不是发往ntfs和fastfat驱动的,不是则跳出
if (_wcsnicmp(pwsz, L"ntfs", 4) && _wcsnicmp(pwsz, L"fastfat", 7))
{
goto Exit00;
}
//DbgPrint("IofCallDriver:Delete File:%ws\n", FileObject->FileName.Buffer);
pwsz = wcsrchr(FileObject->FileName.Buffer, L'\\');
if (pwsz != NULL)
{
pwsz++;
}
if (!_wcsnicmp(pwsz, L"456789.sys", 20)) //保护的文件名xxxxx
{
do
{
UCHAR * szProcessName = PsGetProcessImageFileName(PsGetCurrentProcess());
if (szProcessName)
{
if (_stricmp(szProcessName, "explorer.exe") == 0)
{
KdPrint(("桌面进程过滤掉\n"));
break;
}
if (_stricmp(szProcessName, "notepad.exe") == 0)
{
KdPrint(("notepad进程过滤掉\n"));
break;
}
KdPrint(("当前进程%s 访问文件\n", szProcessName));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
nResult = TRUE;
goto Exit00;
}
} while (FALSE);
}
}
except(1)
{
goto Exit00;
}
Exit00:
return nResult;
}
ULONG GetFunctionAddr(IN PCWSTR FunctionName)
{
UNICODE_STRING HookFunctionName;
RtlInitUnicodeString(&HookFunctionName, FunctionName);
return (ULONG)MmGetSystemRoutineAddress(&HookFunctionName);
}
//inlineHook IofCallDriver函数
VOID InlineHook()
{
KIRQL oldIrql;
ULONG Address;
Address = (ULONG)GetFunctionAddr(L"IofCallDriver");
__asm
{
mov eax, Address
mov esi, [eax + 2]
mov eax, [esi]
mov OldAddress, eax
}
//提升中断层次
oldIrql = KeRaiseIrqlToDpcLevel();
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
//进行地址替换
_asm
{
mov eax, Address
mov esi, [eax + 2]
mov dword ptr[esi], offset MyIofCallDriver
}
_asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
//恢复中断层次
KeLowerIrql(oldIrql);
return;
}
VOID UninlineHook()
{
KIRQL oldIrql;
ULONG Address;
Address = (ULONG)GetFunctionAddr(L"IofCallDriver");
//提升中断层次
oldIrql = KeRaiseIrqlToDpcLevel();
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
//进行地址替换
_asm
{
mov eax, Address
mov esi, [eax + 2]
mov eax, OldAddress
mov dword ptr[esi], eax
}
_asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
//恢复中断层次
KeLowerIrql(oldIrql);
return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
IN PUNICODE_STRING theRegistryPath)
{
DbgPrint("Hook Called!\n");
//DbgBreakPoint();
theDriverObject->DriverUnload = DriverUnload;
InlineHook();
return STATUS_SUCCESS;
}
NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("OnUnload called!\n");
UninlineHook();
return status;
}