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; } }
|