IoCallDriver是一个非常重要的内核例程,利用它可以过滤所有的系统请求,在IoCallDriver中调用IofCallDriver例程,几乎所有的内核驱动都调用了IofCallDriver。IoCallDriver的原型如下:
NTSTATUS
IoCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
它的作用是向指定的设备对象发送一个IRP。
在微软发布的内核的源码的\WRK-V1.2\base\ntos\io\iomgr\iosubs.c(2244)找到了IofCallDriver的实现
NTSTATUS FASTCALL IofCallDriver( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { if (pIofCallDriver != NULL) {
// // This routine will either jump immediately to IovCallDriver or // IoPerfCallDriver. // return pIofCallDriver(DeviceObject, Irp, _ReturnAddress()); }
return IopfCallDriver(DeviceObject, Irp); } |
几乎所有的系统调用都是如此,进入之后,就会出现一个jmp,跳到真实的调用处,这就形成了一个系统调用跳转表,只要修改这个地址,就能构成一个hook,当然现在安全软件能够很容易的检测到它。
来看实现hook的代码
// 首先定义一个函数指针类型
typdef NTSTATUS FASTCALL ( *PMY_IOFCALLDRIVER_FP) (IN PDEVICE_OBJECT, IN OUT PIRP);
// 以下函数用函数newIofCallDriver去代替现有的IofCallDriver
// 同时返回旧的IofCallDriver所跳转的实际地址,如果失败,则返回空
PMY_IOFCALLDRIVER_FP MyHookIofCallDriverXP (
IN PMY_IOFCALLDRIVER_FP newIofCallDriver,
IN BOOLEAN hookOrUnhook)
{
UNICODE_STRING functionName;
PBYTE address;
Static PMY_IOFCALLDRIVER_FP oldIofCallDriverBody = NULL;
RtlInitUnicodeString ( &functionName, L”IofCallDriver”);
// 得到IofCallDriver的入口地址
Address = MmGetSysemRoutineAddress (&functionName);
If(hookOrUnhook)
{
// 获得入口地址后,加2字节的地址就是旧的
// IofCallDriver 的执行体的地址
oldIofCallDriverBody = ( PMY_IOFCALLDRIVER_FP )( *(PLONG)(address + 2);
InterlockedExchange((PLONG) (address +2), newIoCallDriver);
return oldIofCallDriverBody;
}
Else
{
// 复原
if(oldIofCallDriverBody == NULL)
{
InterlockedExchange ((PLONG)(address + 2),
oldIofCallDriverBody);
return oldIofCallDriverBody;
}
}