selph
selph
发布于 2021-12-01 / 427 阅读
0
0

Windows 内核编程 ch5--调试

本章介绍了windbg对用户层和内核层的常用调试命令,以及介绍了给DriverEntry下断点的方法

5.1 Debugging Tools for Windows

Download Debugging Tools for Windows - WinDbg - Windows drivers | Microsoft Docs

该软件包有好多种调试器,就 windbg 是有界面的调试器

这些调试器都是基于调试器引擎: DbgEng.dll,该调试器引擎有文档,可以用来写新的调试器

5.2 Windbg 用户调试

Windbg 支持三种命令:

  • 内部命令:内建在调试器之中,用于操作被调试的目标
  • 元命令:以 . 开头,操作调试进程自身,不直接操作被调试的目标
  • 扩展命令:以 ! 开头,扩展 DLL 为调试器提供了很多功能

用户模式调试,调试进程有两种方法:使用调试器打开进程,使用调试器附加进程

线程进程内部所有线程信息:

0:004> ~
   0  Id: 2688.6c88 Suspend: 1 Teb: 00000085`0ba9d000 Unfrozen
   1  Id: 2688.5274 Suspend: 1 Teb: 00000085`0ba9f000 Unfrozen
   2  Id: 2688.6a78 Suspend: 1 Teb: 00000085`0baa1000 Unfrozen
   3  Id: 2688.1908 Suspend: 1 Teb: 00000085`0baa3000 Unfrozen
.  4  Id: 2688.68d4 Suspend: 1 Teb: 00000085`0baa5000 Unfrozen	// 前面有点的是当前线程

快速设置符号:

.symfix Path

查看已有符号信息:

lm

符号信息常见的有这几种类型:

  • deferred:在当前调试会话中未用到,在需要时会被装入
  • pdb symbol:正确符号已经被装入,后面会显示本地地址
  • export symbol:这个 DLL 只有导出符号可用
  • no symbol:没有符号

强制重新加载符号:

.reload /f modulename.dll

显示当前线程的栈追踪信息:

0:004> k
 # Child-SP          RetAddr               Call Site
00 00000085`0c0ff7e8 00007ff8`7ba1c98e     ntdll!DbgBreakPoint
01 00000085`0c0ff7f0 00007ff8`7aad7034     ntdll!DbgUiRemoteBreakin+0x4e
02 00000085`0c0ff820 00007ff8`7b9a2651     KERNEL32!BaseThreadInitThunk+0x14
03 00000085`0c0ff850 00000000`00000000     ntdll!RtlUserThreadStart+0x21

切换到其他线程:~ns 这里的 n 是线程索引号

0:004> ~2s
ntdll!NtWaitForWorkViaWorkerFactory+0x14:
00007ff8`7b9f07c4 c3              ret

0:002> ~
   0  Id: 2688.6c88 Suspend: 1 Teb: 00000085`0ba9d000 Unfrozen
   1  Id: 2688.5274 Suspend: 1 Teb: 00000085`0ba9f000 Unfrozen
.  2  Id: 2688.6a78 Suspend: 1 Teb: 00000085`0baa1000 Unfrozen	// 当前线程
   3  Id: 2688.1908 Suspend: 1 Teb: 00000085`0baa3000 Unfrozen
#  4  Id: 2688.68d4 Suspend: 1 Teb: 00000085`0baa5000 Unfrozen	// 引起最后一个断点的线程

线程信息内容含义:

0  Id: 2688.6c88 Suspend: 1 Teb: 00000085`0ba9d000 Unfrozen
0			调试器线程索引
Id: 2688.6c88		进程ID.线程ID
Suspend: 1		挂起计数
Teb: 00000085`0ba9d000	TEB
Unfrozen		是否冻结(未冻结)

查看十进制和反查十六进制:

0:002> ? 0x400
Evaluate expression: 1024 = 00000000`00000400

0:002> ? 0n1024	// 十进制以0n开头
Evaluate expression: 1024 = 00000000`00000400

查看 TEB:不带任何地址显示当前线程 TEB(!teb 显示 teb 部分内容,要显示完整内容使用命令:dt ntdll!_TEB

0:002> !teb
TEB at 000000850baa1000
    ExceptionList:        0000000000000000
    StackBase:            000000850bf00000	// 当前线程用户栈基址
    StackLimit:           000000850befd000	// 当前线程用户栈限制
    SubSystemTib:         0000000000000000
    FiberData:            0000000000001e00
    ArbitraryUserPointer: 0000000000000000
    Self:                 000000850baa1000
    EnvironmentPointer:   0000000000000000
    ClientId:             0000000000002688 . 0000000000006a78	// 进程和线程ID
    RpcHandle:            0000000000000000
    Tls Storage:          0000000000000000	// 此线程的TLS数组
    PEB Address:          000000850ba9c000	// PEB
    LastErrorValue:       0			// 上一个Win32错误代码(GetLastError)
    LastStatusValue:      0
    Count Owned Locks:    0
    HardErrorMode:        0

设置断点:

bp kernel32!createfilew

查看断点:

bl

禁用断点:

bd 断点索引
bd *

运行:

g

查看 Unicode 字符串:

du 地址
du @rax

步过执行(F10):

p

步入执行(F11):

t

查看错误值细节:

!error @eax

退出调试器:

q

断开调试器与进程的连接:

.detach

5.3 Windbg 内核调试

此处内容需要配置内核调试才可用,关于配置 Windows 的调试环境见第二章笔记处

显示进程信息:

!process 0 0 csrss.exe	// 显示所有运行csrss.exe的进程信息
// 参数里第一个0:进程EPROCESS地址
// 参数里第二个0:显示信息的详细程度,0表示最小信息

显示作业信息:

!job job地址
dt nt!_EJOB job地址

作业是用来容纳一个或多个进程的对象,可以对其应用各种限制并监视各种统计信息

显式加载用户符号:

.reload /user

显示系统和进程的内存统计信息

!vm

显示系统中正在处理器上运行的线程的信息

!running

5.5 给 DriverEntry 下断点

在虚拟机里运行驱动前,把符号文件 pdb 也复制进去,然后安装驱动,先别启动,这个时候断下来,给未解析的符号处设置断点,然后恢复运行再启动驱动,就会在这里断下来:

1: kd> bu ch4_PriorityBooster!driverentry
1: kd> g
Breakpoint 0 hit
ch4_PriorityBooster!DriverEntry:
fffff805`498b11c0 4889542410      mov     qword ptr [rsp+10h],rdx

可以看到,DriverEntry 是这么被调用的:

2: kd> k
 # Child-SP          RetAddr               Call Site
00 ffffa408`ff2672d8 fffff805`498b5020     ch4_PriorityBooster!DriverEntry [C:\Users\selph\source\Book\WindowsKernelProgramming\ch4_PriorityBooster\ch4_PriorityBooster\entry.cpp @ 82] 
01 ffffa408`ff2672e0 fffff805`41b107c6     ch4_PriorityBooster!GsDriverEntry+0x20 [minkernel\tools\gs_support\kmodefastfail\gs_driverentry.c @ 47] 
02 ffffa408`ff267310 fffff805`41b101fe     nt!IopLoadDriver+0x4c2
03 ffffa408`ff2674f0 fffff805`414bd095     nt!IopLoadUnloadDriver+0x4e
04 ffffa408`ff267530 fffff805`4152a7a5     nt!ExpWorkerThread+0x105
05 ffffa408`ff2675d0 fffff805`415c8b2a     nt!PspSystemThreadStartup+0x55
06 ffffa408`ff267620 00000000`00000000     nt!KiStartSystemThread+0x2a

指定断点在某个进程执行时触发:

bp /p 指定进程EPROCESS地址 断点地址

评论