接上面
****************第三步,重点开始过滤数据了************************
过滤设备创建好了,把所有的串口也绑定了,一切准备工作做好了。小样儿,我看你流过串口的所有数据都不跑不掉
了吧,哼哼,所有IRP请求全部都在我的掌握之中,数据都流过我这里,想得到敏感的数据就易如反掌了。请求我在
前面就已经预习到了,不就那几个,我这里只做测试,就只过滤他的写请求吧。过滤的结果只有这么几种,要么不想
要得数据,全部让它过去吧,一律放行,要么是想要的数据,嘿嘿全部记录下来慢慢分析,要么就不给它走,拦截了
我们这里就让它过去吧,不干坏事,读取到信息就OK啦,防止影响他的功能被人发现哦。
这种处理相对简单,直接把当前的栈空间跳过,调用下一层驱动就行了。要想读取这个写请求的数据,得知道这些数
据放在哪啊,记得前面提到过不,不记得了没关系,在WinDbg中一个命令搞定,!strct _IRP
看仔细了,在偏移+04 struct _MDL *MdlAddress内存描述符表指针,+0c void *SystemBuffer--系统缓冲
区,+3c void *UserBuffer--用户地址空间缓冲区。书上49页介绍了这三个空间的效率及使用问题,但是实际上
我们并不知道他使用哪个地方去存放的数据,算了不猜了,三个都读一遍不就完了?这个好,读到数据就不为空,否
则就为空,好办,看例子
PUCHAR buf = NULL;
if(irp->MdlAddress != NULL)
buf = (PUCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
else buf = (PUCHAR)irp->UserBuffer;
if(buf == NULL)
buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
完整的分发函数流程大概这样的,得到当前栈空间IoGetCurrentIrpStackLocation->遍历所有的设备,如果是发送给
本过滤设备的那么就记录->当然是电源IRP请求的话就放他走->如果是写请求那么就记录数据,其他请求一律放过,
代码看看下面的几个需要注意的地方,首先是
电源请求,
if(irpsp->MajorFunction == IRP_MJ_POWER)
{
// 直接发送,然后返回说已经被处理了。
PoStartNextPowerIrp(irp);
IoSkipCurrentIrpStackLocation(irp);
return PoCallDriver(s_nextobj[i],irp);}
如果是写请求,读取缓冲区数据保存一下就OK了,
如果是其他请求,跳过当前栈空间一路call下去,当然书的作者还考虑到了一些不合法的请求。采用下面的处理即可
把IRP设置成无效,并且将它设置成完成就可以了。
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(irp,IO_NO_INCREMENT);
*********************最后一步,卸载不用的驱动,回收资源*******************
偷鸡摸狗的事也干完了,数据也得到了,也保存了,歇息歇息,把绑定的设备给他摘了,创建的设备给他删了,做些
扫尾工作,做到来无影去无踪,让它去找他家的鸡吧。
遍历所有过滤设备,全部给他摘除,然后删除所有设备OK啦,睡大觉了,心想偷了这么多鸡,这下有鸡腿啃了。
for(i=0;i<32;i++)
{
if(过滤设备数组[i] != NULL)
IoDetachDevice(过滤设备数组[i]);//摘除绑定的设备
}
//因为不能保证所有的IRP都完成了,所以 睡眠5秒。等待所有irp处理结束,这里还是假设5秒后都处理完了
interval.QuadPart = (5*1000 * DELAY_ONE_MILLISECOND);
KeDelayExecutionThread(KernelMode,FALSE,&interval);
// 删除这些设备
for(i=0;i<CCP_MAX_COM_ID;i++)
{
if(s_fltobj[i] != NULL)
IoDeleteDevice(s_fltobj[i]);}
本章学习的实例代码在附件中,源码还是很简单的,看看上面的分析步骤,很快就能看懂了。下一张就进入大家最感
兴趣的键盘驱动喽,貌似很重要,期待学习的进步吧,相信前面的基础知识够了。
