首页
社区
课程
招聘
[原创]一个特别的tdi蓝屏
发表于: 2013-8-25 14:03 14264

[原创]一个特别的tdi蓝屏

2013-8-25 14:03
14264

这篇文章献给那些独自研究技术的同学。
     最近在做一个网页跳转的功能:在浏览器里访问一个网址,然后自动跳转到另外的网址。其实现思路就是修改返回的http应答包。
     为了捕获http应答包,注册了消息TDI_SET_EVENT_HANDLER的响应函数SetEventHandler
;在SetEventHandler里对类型为TDI_EVENT_RECEIVE(ClientEventChainedReceive)和TDI_EVENT_CHAINED_RECEIVE(ClientEventReceive)的回调函数进行了处理。
     这里有一个很有意思的现象,xp下通过tcp接收到数据后是调用ClientEventChainedReceive,而win7、win8则是调用ClientEventReceive(vista没试过,估计也是这样)。就是这个不同,导致我花了半个月才研究出来(当时研究是在xp系统下,测试是在win7系统下)。
      还有就是需要保存每个tcp连接的FileObject。我自己写了一个map模板,专门保存FileObject,里面每个节点都是nonpaged内存。在IRP_MJ_CREATE里保存新创建的FileObject;在TDI_ASSOCIATE_ADDRESS里需要把发送FileObject和接收FileObject关联起来;在TDI_SEND里检测需要过滤的网址;在ClientEventReceive和ClientEventChainedReceive里修改http应答包;最后在IRP_MJ_CLEANUP里清除FileObject。
     驱动写好后,在各个系统下测试:xp 32,没问题; win7 32,蓝屏过一次;win7 64,win8 64,经常蓝屏。
   分析crash dump文件,得到如下结果:
 
    图片1
     没得到半点儿有意义的信息,但是我可以确信是我的驱动导致的蓝屏。那怎么确定呢?在网上找到老外的一篇文章,里面说只需要分析物理堆栈的数据就可以找到证据。在windbg里输入dps esp-3000 esp+3000,然后在打出来的数据里找跟出错堆栈数据相同的地方,如图:
 
    图片2
    在这里几乎就可以确定是哪个驱动导致蓝屏了。但是确定了有毛用,还是不知道是哪里的代码出错了。
  先回到前面,看看Bugcheck Analysis:
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: 0000000000000008, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000000, value 0 = read operation, 1 = write operation
Arg4: fffff88001665257, address which referenced memory
  这个错误码的意思是irql过高时,访问了分页内存。注:irql>= DISPATCH_LEVEL时,就不允许切换线程,而内存倒换需要切换线程,所以irql>= DISPATCH_LEVEL时,就不能访问分页内存,只能访问nonpaged内存。
   而我保存在map里的数据都是nonpaged内存,不应该出现这种错误码。后来又想了下,如果把之前分配的nonpaged内存给delete后,驱动再去访问这个地址,就会出现这种错误码。
    于是把IRP_MJ_CLEANUP里清除FileObject的代码屏蔽掉后,果然没有蓝屏出现了,看来问题就出在这里。但是nonpaged内存是有限的,不可能只new,不delete。原因还是没找到,问题还是没解决。
  为了解决问题,lz想了很多方法:
1、检查代码,结果:看不出任何问题。
2、找人check代码。结果:整个公司只有我一个人写驱动,没人可以求助。
3、上网找。结果:网上没有。
4、分析对手产品的驱动。结果:他们也是用的同样的思路和方法。
5、打算逆tcpip.sys,看看它的实现原理。
  就在准备逆tcpip.sys时,早上突然灵光一闪,既然“在TDI_ASSOCIATE_ADDRESS里需要把发送FileObject和接收FileObject关联起来”,在IRP_MJ_CLEANUP里清除FileObject时,是不是要发送和接收FileObject都关闭了,才都把它们delete掉?
  仔细想想,觉得很有道理,马上按此思路把代码修改了,果然测试通过。

word:
新建 Microsoft Office Word 文档.rar

crash dump:
082013-18860-01.rar

绿网天下的tdi分析文件:
EhomeNet-win7-32.rar


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (8)
雪    币: 193
活跃值: (1220)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
膜拜楼主,完全看不懂
2013-8-25 14:30
0
雪    币: 185
活跃值: (477)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
哈哈 这种东西老外分享的多一些 国内的看到比较少 支持楼主分享
2013-8-25 15:05
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
4
您分析的真好.
2013-8-25 15:18
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
5
看错了,抱歉~

做实验时, 将  dps 写错了~
用您的这招dps, 可以看到大范围的栈调用信息, 谢谢
2013-8-25 15:57
0
雪    币: 405
活跃值: (2285)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
分享经验,不错。
2013-8-26 11:27
0
雪    币: 406
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
guxinyi有大侠风度
2013-8-27 00:54
0
雪    币: 585
活跃值: (573)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
8
更正一个问题,同一个tcp连接的FileObject,会被创建多次。
所以自己要记录下这个FileObject创建次数,并且在IRP_MJ_CLEANUP里清除FileObject时要相应的减掉这个次数。
比如,创建了2次,调用一次IRP_MJ_CLEANUP,就将次数减一,直到次数为0,才完全删除FileObject。

上传的附件:
2013-8-30 00:30
0
雪    币: 121
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
求老外的那篇文章地址,调试方面有待提高。
2013-9-1 21:43
0
游客
登录 | 注册 方可回帖
返回
//