两种不使用过滤驱动从驱动获取数据的方法
2010-09-03 20:56
741 查看
1、 Hook Dispatch例程。
首先通过ObReferenceObjectByName等函数拿到被Hook设备的DriverObject。有了这个之后,我们就可以用指向自己例程的指针改写MajorFunction数组里面的指针。
NTSTATUS ntStatus = STATUS_SUCCESS;
UNICODE_STRING wszDriverName;
PDRIVER_OBJECT pDriverObject = NULL;
PDRIVER_DISPATCH pOrgDispatch = NULL;
RtlInitUnicodeString( &wszDriverName, DRIVER_NAME);
ntStatus = ObReferenceObjectByName( &wszDriverName,
0,
NULL,
0,
*IoDriverObjectType,
//NULL,
KernelMode,
NULL,
(PVOID*)&pDriverObject);
if( !NT_SUCCESS(ntStatus))
{
DbgPrint( "ObReferenceObjectByName Fail.\r\n");
return FALSE;
}
pOrgDispatch = (PDRIVER_DISPATCH) InterlockedExchange( ( PLONG)&pDriverObject->MajorFunction[IRP_MJ_READ], (LONG)&DispatchMyRead);
……
卸载的时候同样这样修改回去即可。
这种方法比较方便,由于只需要改写一个函数指针,避免了inline hook的很多不稳定因素。另外,在调用原来的Dispatch例程的时候也只需要直接call它就行了。
但是,如果有些IRP不能立即完成的,例如键盘鼠标驱动的IRP,用这种方法就拿不到完成时候的数据了。因此我们还需要第二种方式J
2、 Hook Completion Routine。
在Hook掉的Dispatch里面,我们已经拿到了发到下层驱动的IRP。想在完成时再获得控制权,很简单,只需要再Hook掉Completion Routine。
NTSTATUS DispatchMyRead ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp);
//需要保存一下旧的完成例程信息
g_RecentIrpInfo.ComplettionRoutine = irpSp->CompletionRoutine;
g_RecentIrpInfo.Context = irpSp->Context;
g_RecentIrpInfo.Control = irpSp->Control;
g_RecentIrpInfo.irpSp = irpSp;
//安装自己的完成例程
irpSp->CompletionRoutine = MyIoCompletion;
irpSp->Context = NULL;
irpSp->Control = SL_INVOKE_ON_SUCCESS;
//OK,call下去。
ntStatus = g_ pOrgDispatch ( pDeviceObject, Irp);
return ntStatus;
}
在MyIoCompletion当然就是同样的标准hook操作咯,处理数据,call原来的IoCompletion。需要注意的是很多Irp并没有安装完成例程。
首先通过ObReferenceObjectByName等函数拿到被Hook设备的DriverObject。有了这个之后,我们就可以用指向自己例程的指针改写MajorFunction数组里面的指针。
NTSTATUS ntStatus = STATUS_SUCCESS;
UNICODE_STRING wszDriverName;
PDRIVER_OBJECT pDriverObject = NULL;
PDRIVER_DISPATCH pOrgDispatch = NULL;
RtlInitUnicodeString( &wszDriverName, DRIVER_NAME);
ntStatus = ObReferenceObjectByName( &wszDriverName,
0,
NULL,
0,
*IoDriverObjectType,
//NULL,
KernelMode,
NULL,
(PVOID*)&pDriverObject);
if( !NT_SUCCESS(ntStatus))
{
DbgPrint( "ObReferenceObjectByName Fail.\r\n");
return FALSE;
}
pOrgDispatch = (PDRIVER_DISPATCH) InterlockedExchange( ( PLONG)&pDriverObject->MajorFunction[IRP_MJ_READ], (LONG)&DispatchMyRead);
……
卸载的时候同样这样修改回去即可。
这种方法比较方便,由于只需要改写一个函数指针,避免了inline hook的很多不稳定因素。另外,在调用原来的Dispatch例程的时候也只需要直接call它就行了。
但是,如果有些IRP不能立即完成的,例如键盘鼠标驱动的IRP,用这种方法就拿不到完成时候的数据了。因此我们还需要第二种方式J
2、 Hook Completion Routine。
在Hook掉的Dispatch里面,我们已经拿到了发到下层驱动的IRP。想在完成时再获得控制权,很简单,只需要再Hook掉Completion Routine。
NTSTATUS DispatchMyRead ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp);
//需要保存一下旧的完成例程信息
g_RecentIrpInfo.ComplettionRoutine = irpSp->CompletionRoutine;
g_RecentIrpInfo.Context = irpSp->Context;
g_RecentIrpInfo.Control = irpSp->Control;
g_RecentIrpInfo.irpSp = irpSp;
//安装自己的完成例程
irpSp->CompletionRoutine = MyIoCompletion;
irpSp->Context = NULL;
irpSp->Control = SL_INVOKE_ON_SUCCESS;
//OK,call下去。
ntStatus = g_ pOrgDispatch ( pDeviceObject, Irp);
return ntStatus;
}
在MyIoCompletion当然就是同样的标准hook操作咯,处理数据,call原来的IoCompletion。需要注意的是很多Irp并没有安装完成例程。
相关文章推荐
- DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
- PHP使用ajax跨域获取json数据的两种方法
- ListView动态加载数据分页(使用Handler+线程和AsyncTask两种方法)
- Ext.data.JsonStore使用HttpProxy加载数据时传递参数的两种方法
- ListView动态加载数据分页(使用Handler+线程和AsyncTask两种方法)
- VC中ADO使用SQLOLEDB数据驱动时,无法获取存储过程RAISERROR返回的字符串描述
- 树形数据的反选有两种方法以及处理后台返回拼装htmL的异步获取不到现象(但是页面F12可以看到)
- Struts2的模型驱动封装方法获取页面提交的表单数据(接收表单数据的最常用的方法)
- 获取网上数据的两种方法HttpURLConnection和HttpClient
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- Android使用命令获取sha1证书指纹数据的方法
- HttpURLConnection和okHttp两种获取网络数据的实现方法
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- 详解vue 中使用 AJAX获取数据的方法
- php使用CURL模拟GET与POST向微信接口提交及获取数据的方法
- 使用jQuery的data方法来为页面中的某个元素存储数据,(获取焦点,清除默认值)
- jQuery使用JSONP实现跨域获取数据的三种方法详解
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- C#使用SqlDataAdapter对象获取数据的方法
- swift:使用NSJSONSerialization和SwiftyJSON两种方法解析网络返回的json格式数据