实验环境: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直播授课