首页
社区
课程
招聘
[原创]让Windbg在驱动入口前断下来
发表于: 2018-6-17 17:30 10576

[原创]让Windbg在驱动入口前断下来

2018-6-17 17:30
10576

实验环境:Win7 64位

1.使用符号

  • 优点:使用方便,不用每次都设置断点
  • 缺点:对于没带有符号的驱动会失败

用到windbg命令:

  • bu 对某个符号下断点.在有模块加载时,windbg会自动判断符号是否符合.
  • bm 也是对某个符号下断点,但是它支持匹配表达式.比如对MyDriver的所有函数下断点bm MyDriver!*,不过使用通配符的时候,它需要符号存在.

bu 驱动名称!DriverEntry

 

示例:MyDriver

kd> bu MyDriver!DriverEntry
kd> bl
     0 e Disable Clear u                      0001 (0001) (MyDriver!DriverEntry)

加载MyDriver,成功的断了下来

 

 

对MyDriver所有函数下断点:

kd> bm MyDriver!*
  2: fffff880`03409050 @!"MyDriver!_guard_dispatch_icall_nop"
  3: fffff880`0340e000 @!"MyDriver!GsDriverEntry"
  4: fffff880`03409000 @!"MyDriver!Unload"
  5: fffff880`03409030 @!"MyDriver!_guard_check_icall_nop"
  6: fffff880`0340e02c @!"MyDriver!__security_init_cookie"
breakpoint 0 redefined
  0: fffff880`03409010 @!"MyDriver!DriverEntry"
kd> bl
     0 e Disable Clear  fffff880`03409010  [e:\studio\vs2017\mydriver\mydriver\driver.cpp @ 10]     0001 (0001) MyDriver!DriverEntry
     2 e Disable Clear  fffff880`03409050  [minkernel\crts\crtw32\misc\amd64\guard_dispatch.asm @ 57]     0001 (0001) MyDriver!_guard_dispatch_icall_nop
     3 e Disable Clear  fffff880`0340e000  [minkernel\tools\gs_support\kmode\gs_support.c @ 113]     0001 (0001) MyDriver!GsDriverEntry
     4 e Disable Clear  fffff880`03409000  [e:\studio\vs2017\mydriver\mydriver\driver.cpp @ 4]     0001 (0001) MyDriver!Unload
     5 e Disable Clear  fffff880`03409030  [minkernel\crts\crtw32\misc\guard_support.c @ 81]     0001 (0001) MyDriver!_guard_check_icall_nop
     6 e Disable Clear  fffff880`0340e02c  [minkernel\tools\gs_support\kmode\gs_support.c @ 57]     0001 (0001) MyDriver!__security_init_cookie

 

其实使用bm MyDriver!DriverEntry,也可以断下来,不需要符号存在.但当使用了通配符就需要符号存在.我把MyDriver卸载,会提示找不到符号.

kd> bm MyDriver!*
No matching code symbols found, no breakpoints set.

2.通过分析PE文件的入口点来下断

  • 优点: 无需符号的支持,理论上对所有的驱动都适用
  • 缺点: 没有使用符号方便,每次都需要确定入口点.

用到windbg命令

  • bp 在某个地址下断点, 可以 bp 0x80007780也可以 bp MyDriver!FunctionName,但是bp 要求符号存在.
  • ln 查找地址附近的符号

下断: bp MyDriver+0x6000 (可以使用bp,bu,bm,使用bp只是为了说明它无需符号的支持,避免造成混淆)

kd> bc *
kd> bp MyDriver+0x6000
Bp expression 'MyDriver+0x6000' could not be resolved, adding deferred bp
*** Bp expression 'MyDriver+0x6000' contains symbols not qualified with module name.
kd> bl
     0 e Disable Clear u                      0001 (0001) (MyDriver+0x6000)

加载MyDriver

MyDriver!GsDriverEntry:
fffff880`03416000 48895c2408      mov     qword ptr [rsp+8],rbx

我们看到并不是DriverEntry,让我们看一下这个函数的完整信息,可以看到有调用DriverEntry的地方.

MyDriver!GsDriverEntry:
fffff880`03416000 48895c2408      mov     qword ptr [rsp+8],rbx
kd>  uf MyDriver!GsDriverEntry
MyDriver!GsDriverEntry [minkernel\tools\gs_support\kmode\gs_support.c @ 113]:
  113 fffff880`03416000 48895c2408      mov     qword ptr [rsp+8],rbx
  113 fffff880`03416005 57              push    rdi
  113 fffff880`03416006 4883ec20        sub     rsp,20h
  113 fffff880`0341600a 488bda          mov     rbx,rdx
  113 fffff880`0341600d 488bf9          mov     rdi,rcx
  115 fffff880`03416010 e817000000      call    MyDriver!__security_init_cookie (fffff880`0341602c)
  116 fffff880`03416015 488bd3          mov     rdx,rbx
  116 fffff880`03416018 488bcf          mov     rcx,rdi
  ;这里调用了MyDriver!DriverEntry
  ;-------------------------------------------------------------------
  116 fffff880`0341601b e8f0afffff      call    MyDriver!DriverEntry ;(fffff880`03411010)
  ;------------------------------------------------------------------
  117 fffff880`03416020 488b5c2430      mov     rbx,qword ptr [rsp+30h]
  117 fffff880`03416025 4883c420        add     rsp,20h
  117 fffff880`03416029 5f              pop     rdi
  117 fffff880`0341602a c3              ret
  • 提示:可能并不是每一个驱动都有GsDriverEntry.

扩展:通过系统调用DriverEntry或GsDriverEntry时断下来.

我们查看一下ESP指向地址的值

kd> dq esp
fffff880`0456f858  fffff800`042cc467 fffffa80`32eee060
fffff880`0456f868  fffffa80`32eee060 00000000`00000000
fffff880`0456f878  00000000`000007ff fffff880`0456f9b8
fffff880`0456f888  00000000`00000000 00000000`00000000
fffff880`0456f898  00000000`00000000 fffff880`0456f978
fffff880`0456f8a8  fffff880`04e8fa80 00000000`000a0000
fffff880`0456f8b8  fffffa80`004a0048 fffff8a0`02ee3680
fffff880`0456f8c8  fffff800`001a0018 fffff8a0`02e3fa50

fffff800`042cc467 就是其返回地址,我们用ln命令查看一下该地址

kd> bp MyDriver!opq
Couldn't resolve error at 'MyDriver!opq'
kd> ln fffff800`042cc467
Browse module
Set bu breakpoint

(fffff800`042cba60)   nt!IopLoadDriver+0xa07   |  (fffff800`042cc810)   nt!IopLoadUnloadDriver

是IopLoadDriver+0xa07 处的位置.我们看一下他的上一条指令

fffff800`042cc45e 488bd6          mov     rdx,rsi
fffff800`042cc461 488bcb          mov     rcx,rbx
;------------------------------------------------------------------
fffff800`042cc464 ff5358          call    qword ptr [rbx+58h]
fffff800`042cc467 4c8b15da3bdaff  mov     r10,qword ptr [nt!PnpEtwHandle 
(fffff800`04070048)]  ;nt!IopLoadDriver+0xa07
;---------------------------------------------------------------------

我们只要在call qword ptr [rbx+58h],下断即可.

3.通过事件异常

  • 优点: 使用起来最方便.
  • 缺点: 每次都需要自己手动执行都驱动入口.

用到windbg 命令

  • sx 显示异常列表和所有非异常的事件列表,并且显示调试器遇到每个异常和事件时的行为
  • sxe 当发生该异常时,目标立即中断到调试器中。

用sx 查看事件异常列表

kd> sx
  ct - Create thread - ignore
  et - Exit thread - ignore
 cpr - Create process - ignore
 epr - Exit process - break
  ld - Load module - output
  ud - Unload module - ignore
 ser - System error - ignore
 ibp - Initial breakpoint - ignore
 iml - Initial module load - ignore
 out - Debuggee output - output

可以看到 ld - Load module - output

 

我们在加载模块时中断下来:通过 sxe ld

kd> bc *
kd> sxe ld

加载MyDriver,在nt!DebugService2+0x5中断了下来

kd> u
nt!DebugService2+0x5:
fffff800`03edf4e5 cc              int     3

我们通过Setp Out一层一层的走出函数,来到了我们熟悉的IopLoadDriver,这样子我们就知道怎么到达驱动入口了(不懂请看上面).

nt!DebugService2+0x5:
fffff800`03edf4e5 cc              int     3
kd> gu
nt!DbgLoadImageSymbols+0x4d:
fffff800`03f780ad 4883c440        add     rsp,40h
kd> gu
nt!DbgLoadImageSymbolsUnicode+0x2b:
fffff800`03fd046b 488b4c2428      mov     rcx,qword ptr [rsp+28h]
kd> gu
nt!MiDriverLoadSucceeded+0x2bd:
fffff800`042b1e0d 83f801          cmp     eax,1
kd> gu
nt!MmLoadSystemImage+0x88a:
fffff800`042c985a bf01000000      mov     edi,1
kd> gu
nt!IopLoadDriver+0x44d:
fffff800`042cbead 3bc6            cmp     eax,esi

如果不需要该事件发生了,可以使用 sxn 命令取消:

kd> sxn ld

总结

bu 驱动名称!函数名称
bp 驱动名称+0xXXXX(驱动入口)
sxe -ld ;通过驱动加载事件

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 2
支持
分享
最新回复 (6)
雪    币: 583
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2018-6-19 02:47
0
雪    币: 6977
活跃值: (1780)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
kdBreakPoint
2018-6-19 10:06
0
雪    币: 59
活跃值: (740)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
bu  $iment(模块名)    一直这么用感觉很方便,如果模块名是数字的话,在模块名前加个感叹号就可以了。
2018-6-19 10:51
0
雪    币: 4076
活跃值: (2788)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
5
TopC kdBreakPoint
谢谢提醒,只是为了可以中断任意驱动加载.KdBreakPoint确实也可以中断任意驱动,只需要把相应模块的入口地址代码的一个字节改为0XCC.中断时在还原回去,感觉这个和第2个差不多,而且第2个更加方便一些.当然了调自己代码的时候KdBreakPoint是很方便的.
2018-6-20 06:25
0
雪    币: 4076
活跃值: (2788)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
6
简单未遂 bu $iment(模块名) 一直这么用感觉很方便,如果模块名是数字的话,在模块名前加个感叹号就可以了。
同感
2018-6-20 06:26
0
雪    币: 124
活跃值: (1612)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
7
chpeagle 谢谢提醒,只是为了可以中断任意驱动加载.KdBreakPoint确实也可以中断任意驱动,只需要把相应模块的入口地址代码的一个字节改为0XCC.中断时在还原回去,感觉这个和第2个差不多,而且第2个更加方 ...
大佬,使用KdBreakPoint怎么去中断的
2022-10-11 21:43
0
游客
登录 | 注册 方可回帖
返回
//