windbg文档网页:
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/
windbg官网:
http://windbg.org/
windbg preview官方文档:
CSDNl下载: https://download.csdn.net/download/qq_33522888/12263017
百度网盘链接:https://pan.baidu.com/s/1wJ1RYnjMnTEqO5yZJeL7XQ
提取码:oens
参考网站:
https://www.stl-tec.de/tutorials/WinReverseEng/setup/
三类命令:
1.基本命令
2.元命令: 总是以"."开头
3.扩展命令: 外部扩展模块加入的命令,总是以"!"开头
.cls
清屏(最重要的指令)
?
列举所有基本命令
.help [/D]
列举所有原命令
!模块名.help
列举指定扩展模块的所有扩展命令
.chain [/D]
给出扩展命令集的链表。前两行显示扩展模块的搜索路径,后面列出自带的扩展模块。
!模块名.help
列出该模块的扩展命令列表(绝大多数模块可以)
.load/.unload
动态加载/卸载第三方扩展调试模块
.prefer_dml 1
开始DML
.prefer_dml 0
关闭DML
反汇编:
u [地址] 进行反汇编
ub [地址] 倒着反汇编
uf [函数地址]:对nt模块的函数进行反汇编
uf [模块名!函数地址]:反汇编函数
uf /i [函数地址/模块名!函数地址]:反汇编并显示共有多少条指令
例如:
u IofCallDriver L5:显示五行的IofCallDriver的反汇编代码
uf /i nt!PspProcessOpen
ln 地址
搜索距离指定地址最近的符号
.dml_flow 地址A 地址B
从地址A到地址B进行反汇编,能画出流程图
!dml_proc [进程号|进程地址]
内核模式下用于查看指定进程信息,用户模式下只能查看被调试进程信息
version
查看软件版本、启动参数、软件设置命令
vertarget
列出当前调试系统的版本系统
.time
查看系统时间,以及系统正常运行持续时间,用户模式下还会显示当前进程的持续时间
n [8|10|16]
查看当前数字进制/修改数字显示为8/10/16进制
.effmach [x86/amd64/ia64/ebc]
查看当前处理器模式/修改处理器模式为x86/amd64/ia64/ebc
在Processes and Threads工作窗口下可以查看系统序号、进程序号、线程序号
切换当前调试系统:
||<system_index> s
切换当前调试进程:
|<process_index> s
切换当前调试线程:
~<thread_index> s
x64切换到x86模式下:
.load wow64exts
!sw
再切换回x64模式下:
!ws
.formats 整数
将一个整数以各种格式显示,包括:16进制、10进制、8进制、二进制、字符串、日期、
浮点数等
将windbg调试器附加到进程上:
.attach PID
windbg -p PID
windbg -pn 进程名
用windbg调试器启动进程调试:
.create 程序启动命令行
windbg 程序启动命令行
.dump 文件名
保存到dump文件
.dump /ma "d:\mydmpfile.dmp"
将当前调试进程输出到dump文件
.opendump 文件名
打开dump文件
.detach
结束当前调试会话,解挂后,被调试进程能够独立运行
qd
结束当前调试会话,解挂后,被调试进程能够独立运行
q|qq
结束调试,windbg和被调试进程一起关闭
.crash
内核调试时引发一个系统蓝屏,并生成dump文件
.reboot
内核调试时使系统重启,不产生dump文件
查看当前堆栈:
1.kv
提示FPO信息,ChildEBP、retaddr、前三个参数
2.kb
ChildEBP、retaddr、前三个参数
3.kp
全参数(需要所有符号)
e命令修改内存:
eb/ed/eq [地址] 数值
ea [地址] 数值 ASCII字符串
eu [地址] 数值 UNICODE字符串
lm/lmD:
lm [选项] [a Address] [m Pattern | M Pattern]
lmD [选项] [a Address] [m Pattern | M Pattern]
(1)/v选项能列出模块的详细信息
(2)参数[a Address]只有指定地址所在的模块能够被列出
(3)参数[m Pattern | M Pattern]通过模块名称通配符列出模块
例子:
lm m *o* 将显示所有名称中包含字母o的模块
lmva 00400000 显示地址00400000所在模块的详细信息
lmvm *nt* 显示名字中包含nt的模块的详细信息(注意exe、dll等都不要带后缀名)
lmf 显示所有模块的信息(包含模块的文件路径)
!lmi uxtheme 想要了解uxtheme.dll的详细调试文件(PDB)信息
lmv 列出所有模块(加载和未加载)对应的符号信息
!dlls [选项] [LoaderEntryAddress]
选项:
-i/-l/-m: 排序方式,分别按照初始化顺序、加载顺序、内存起始地址顺序排列
-a: 列出镜像文件PE结构的文件头、Section头等详细信息
-c LoaderEntryAddress: 指定函数所在的模块
.reload /l
列出模块
!imgreloc
列出模块列表并显示模块是否处于preferred地址范围内
!lmi 地址
获取地址所在的模块对调试器有用的信息
!dh 模块地址
显示模块的PE头信息
!dh -a 模块地址
显示模块的PE结构详细信息,包括导入导出表内的函数
.sympath
显示当前符号路径
.sympath [路径]
设置符号路径
.sympath+ [路径]
添加新的符号路径
注: 使用.sympath改变符号路径之后,需要用.reload更新已加载的符号文件
例子:
.sympath+ SRV*D:\symbols\currentsymbols*http://msdl.microsoft.com/download/symbols
.symopt
查看当前符号选项
.symopt +/- Flags
开启/关闭符号选项
ld 模块名 [/f 符号文件名]
调试器默认采用延迟模式加载符号,ld使得延迟模式被打破,让指定模块的符号文件立刻加载到调试器中。/f表示即使符号不匹配也要强制加载。
此指令可为模块的符号文件设置自定义的匹配名称。
例子:
ld 123 /f abc
强制将abc.pdb作为123.exe的符号文件
ld *
强制加载所有模块的符号文件
ld kernel32
强制加载kernel32模块的符号文件
.reload 为所有已加载模块载入符号信息
.reload命令的作用是删除指定或所有已加载的符号文件,默认情况下,调试器不会立刻根据符号路径重新搜索并加载新的符号文件,而是推迟到调试器下一次使用到此文件时
.reload [参数] [模块名]
参数:
/u: 卸载符号
/f: 迫使调试器立刻搜索并重新加载新的符号文件
/v: 将搜索过程中的详细信息都显示出来
/i: 不检查pdb文件的版本信息
/l: 只显示模块信息
/n: 仅重载内核符号,不重载用户符号
/o: 强制覆盖符号库中的符号文件,即使版本相同
/d: 用户层模式下使用Windbg时的默认选项,重载调试器模块列表中的所有模块;
/s: 内核模式下使用Windbg时的默认选项,重载系统模块列表中的所有模块,另外,如果调试器在用户模式下运行,要加载内核模块,也必须使用/s选项,否则调试器将只会在调试器模块列表中搜索而导致找不到内核模块
/u: 卸载指定模块。如发现当前符号版本不对,使用/u开关先卸载之再重新加载
例子:
.reload /f 用户/内核模式下强制重新加载符号文件
.reload /f /user 内核模式下强制重新加载用户层程序的符号文件
.reload /u 卸载所有符号
.reload /i 重新加载不匹配符号的模块(dmp文件没有对应的pdb时使用)
.reload /i TGame.exe 重新加载不匹配符号的TGame.exe
.reload /f @"c:\windows\System32\verifier.dll" 为指定模块加载符号信息
.reload /f TGame.exe 为TGame.exe加载符号信息
!chksym <模块名> [符号名]
验证一个模块的符号文件
符号全局搜索:
x [选项] 模块名!符号名
选项:
/D: 以DML格式显示
/f: 将只显示函数符号,并且会显示函数的详细定义
/d: 显示更多的变量类型相关信息
/t: 显示符号的数据类型
/v: 显示符号的类型和大小
控制显示结果的排列顺序: /a和/A分别按地址的升序和降序,/n和/N分别按名称的升序和降序,/z和/Z分别按符号大小的升序和降序
模块名和符号名都可以包含通配符,*代表0或任意多个字符,?代表任一单一字符,#代表前面的一个字符可以出现任意次,如果中间允许多个字符重复,用方括号
例子:
x kernel32!a*
x /D *!*NtCreateFile*
x MyModule!GlobalVariableName 查看模块MyModule中名为GlobalVariableName的全局变量
x *! 列出所有模块对应的符号信息
x ConsoleTest!* 列出ConsoleTest模块中的所有符号
x ConsoleTest!add* 列出ConsoleTest模块中的所有add开头的符号
x /t /v ConsoleTest!* 带数据类型、符号类型和大小信息,列出ConsoleTest模块中的所有符号
x kernel32!*LoadLib* 列出kernel32模块中所有含LoadLib字样的符号
.srcpath
显示当前源码路径
.srcpath <路径信息>
设置源码路径
.srcpath+/- <路径信息>
添加/删除源码路径
.srcnoisy [1|0]
显示/开启/关闭“嘈杂的源码”(在调试时会显示很多信息)
代码行选项:
l+[选项] 打开
l-[选项] 关闭
例子:
l+t 源码模式
l-t 汇编模式
l+* 打开所有行选项(效果会很不错)
查看进程简略信息:
.tlist [选项] [进程名]
显示当前系统中的进程列表/显示指定进程名的进程信息,内核模式和用户模式都可使用
.tlist -v
显示进程详细信息
.tlist -c
只显示当前进程信息
内核模式下查看进程详细信息:
!process 显示进程信息
!process PID 获取进程号为PID的进程信息
!process -1 0 获取当前进程的简略信息
!process 0 0 SoftMgr.exe 获取进程名为SoftMgr.exe的信息
!process 0 0 查看所有进程信息,包括EPROCESS地址和DirBase
!process 0 7 查看所有进程的详细信息
!process EPROCESS地址 查看进程信息
!process EPROCESS地址 0 获取进程简略信息
!process EPROCESS地址 7 查看进程详细信息
查看进程环境块:
!peb
用户模式下显示当前进程的PEB信息
!peb [PEB地址] / dt nt!_peb [PEB地址]
内核模式下显示环境块详细信息(内核模式下可通过!process命令获取PEB地址)
内核模式下进程切换:
.process
显示当前进程EPROCESS地址
.process [EPROCESS地址]
切换进程
.context
显示当前页目录地址
.context [页目录地址]
切换页目录地址,页目录地址就是!process命令中显示的DirBase值
内核模式下线程切换
.thread [ETHREAD地址]
~
列出当前被调试进程的所有线程
~2
查看2号线程信息
~2s
切换到2号线程
~~[11a0]s
切换到线程ID为11a0的线程
~2f
将2号线程冻住(freeze)
~2u
将2号线程解冻(unfress)
~2n
增加2号线程的挂起计数(suspend)
~2m
减少2号线程的挂起计数(resume)
!teb [TEB地址]
查看线程环境块信息
~k
显示当前线程的线程栈信息
~2k
显示2号线程的线程栈信息
~*k
显示所有线程栈信息
~r
显示当前线程的寄存器信息
~2r
显示2号线程的寄存器信息
~*r
显示所有线程的寄存器信息
~*e 命令
对每个线程执行指定命令
例子:
~*e k;r
对每个线程中,分别执行k指令(栈指令)和r指令(寄存器指令)
显示线程运行时间:
.ttime
显示当前线程的创建日期、用户模式时间、内核模式时间
!runaway 7
显示所有线程的用户模式时间、内核模式时间、总运行时间
调试事件设置:
sx
列出针对当前调试目标的异常或非异常事件的处理
sxr
恢复到对调试事件的默认设置
.lastevent
显示最近发生的一次调试事件
sx{e|d|n|i} [-c "Cmd1"] [-c2 "Cm2"] [-h] {Exception|Event|*}
(1)
如果没有-h开关,就是设置中断状态,
其中e|d|n|i分别对应着Enabled|Disabled|Output|Ignore
Enabled:第一轮和第二轮都中断给用户
Disabled:第一轮不中断,第二轮中断
Output:输出信息通知用户,不中断
Ignore:忽略事件,不中断
如果有-h开关,就是设置处理状态,sxe命令设置的处理状态是Handled,其他sxd|sxn|sxi都是设置为Not Handled
(2)
-c和-c2分别用来定义第一轮处理和第二轮处理的关联命令
(3)
Exception|Event|*用来指定命令所针对的是异常或者事件
例子:
加载内核模块时下断
sxe ld:MyDriver 驱动MyDriver加载前下断
sxn ld:MyDriver 驱动MyDriver加载时不会中断,但会显示一条相关信息
sxi ld:MyDriver 取消对MyDriver加载时的设置
卸载驱动时下断
sxe ud:MyDriver 驱动MyDriver卸载前下断
sxn ud:MyDriver 驱动MyDriver卸载时不会中断,但会显示一条相关信息
sxi ud:MyDriver 取消对MyDriver卸载时的设置
当调试器因异常而中断时,可以返回与设置不同的状态:
gh
异常已经处理(Handled)
gn
异常没有处理(Not Handled)
.bugcheck
内核模式下显示当前bug check的详细信息
!analyze -v
显示最近异常事件的详细信息
!analyze -hang
分析死锁。另一个分析死锁的命令是!locks
内核模式下,分析内核锁和DPC栈
用户模式下,分析线程的调用栈
!analyze -show bug-check-代码 [参数]
内核模式下显示指定bug check的详细信息
!error
查看错误码
获取错误码为2的Win32错误信息,可用: !error 2
获取错误码为2的NTSTATUS错误信息,可用: !error 2 1
!gle
针对当前线程调用Win32接口函数GetLastError()取得线程的错误值,并打印分析结果
!gle -all
用户模式下针对所有线程,内核模式下针对所有用户线程,执行GetLastError()
源码调试下获取局部变量:
x和dv都可以直接列出当前局部变量的简略信息
dv [选项] [局部变量名]
选项:
/v 显示虚拟地址
/i 显示变量详细信息
/t 显示变量类型,如int、char等
/f 指定进行分析的函数
bp /p EPROCESS地址 地址
内核模式下对EPROCESS进程的用户空间的地址下断
bp /t ETHREAD地址 地址
内核模式下对ETHREAD线程的用户空间的地址下断
bm /a ntdll!NtCreate*File
批量设置代码断点
ba Access Size Address
下硬件断点
Access可以是r/w/e/i
Size在x86系统可选值为1/2/4,x64系统可选值为1/2/4/8
Address值必须是Size的整数倍
bl 列出断点
bd 禁止断点
be 恢复断点
bc 清除断点
d[类型] [地址范围]
基本类型:
dw 双字节WORD
dd 4字节DWORD
dq 8字节
df 4字节单精度浮点数
dD 8字节双精度浮点数
dp 指针大小格式,32位下4字节,64位下8字节
字符串:
da ASCII字符串
du UNICODE字符串
db 字节+ASCII字符串
dW 双字节WORD+ASCII字符串
dc 4字节DWORD+ASCII字符串
ds ANSI_STRING格式
dS UNICODE_STRING格式
数组:
dd*/dq*/dp* 4字节/8字节/指针长度的数组
dda、ddp、 ddu、dds、dqa、dqp、dqu、dqs、dpa、dpp、dpu、dps
链表(LIST_ENTRY/SINGLE_LIST_ENTRY):
dl 开始地址 从头到尾遍历链表
dl b 尾地址 从尾到头遍历链表
其他:
/p 内核模式下此选项用来显示物理内存信息,不使用此选项将显示虚拟内存信息
!address
显示进程或系统的内存状态与信息
用户模式下列出0x0-0x80000000的全部地址空间信息
内核模式下列出址0x80000000-0xFFFFFFFF的全部地址空间信息
!address [地址]
显示此地址所在内存块的信息
!address -summary
显示内存信息概览
!address -f:MEM_COMMIT -c:"s -a %1 %2 \"
asdfasdfasdf
\";s -u %1 %2 \"
asdfasdfasdf
\""
在所有MEM_COMMIT的内存中搜索字符串"
asdfasdfasdf
",包括宽字符串和多字节字符串
!address -?
显示指令帮助
!vprot [地址]
用户模式显示指定内存块信息,侧重于内存保护信息
!vadump [-v]
用户模式显示整个内存空间信息,使用-v选项将显示详细信息
内核模式下内存统计信息:
!memusage
从物理内存角度显示内存统计信息
!vm
从虚拟内存角度显示内存统计信息,不仅能从全局角度显示虚拟内存的使用情况,还能以进程为单位显示内存使用情况
!filecache
内核模式下显示文件缓存和页表状态
!heap -a
用户模式下查看堆信息,显示每个堆的地址范围以及被申请提交的大小
!heap -p -a 00530B98
查看地址00530B98在哪个堆分配空间中
!heap -a 00530000
查看堆分配空间00530000的堆块信息
将windbg中命令的输出保存到文本文件中:
1. .logopen d:/dump.txt 将显示结果放到文件中
2. 运行你想要输出到文本中的命令
3. .logclose d:/dump.txt 关闭文件
4. .logfile 查看是否还有打开的日志记录
在查看ssdt表和shadowssdt表之前一定要加载好符号
查看ssdt和shadowssdt:
1.x nt!kes*des*table*:得到ssdt和shadowssdt的地址
2.dd 地址:查看表数据
3.dds 地址:查看符号表
蓝屏分析:
1.打开虚拟机的dump功能:
右键“我的电脑”->属性->高级系统设置->启动和故障恢复 设置->写入调试信息 核心内存转储->确定->确定->退出
2.这时,如果电脑蓝屏,会转储核心内存为C:\Windows\MEMORY.DMP文件,在蓝屏的最后一行显示转储进度(Dumping physical memory to disk: 80),并在重启后可以发现该文件。
如果sys文件在系统开机时启动,为防止蓝屏,可以开机时,按f8,进入安全模式,然后查看C:\Windows\MEMORY.DMP文件
3.将dmp文件拷贝到实机
4.打开Windbg,菜单栏File->Open Crash Dump...,选择dmp文件
5.设置Windbg的符号链接
6.在windbg命令行中输入!analyze -v,即可分析出问题的原因
7.在windbg命令行中输入.open -a 自己的引发错误的模块名!引发错误的函数+偏移,即可定位到引起错误的源代码位置
例如:.open -a MyModel!OperUnicodeStr+0x2a .open -a DriverToDump!DriverEntry+2b
8.kv/kp/kb
R0与R3联调:
1.!process 0 0获取用户空间进程块地址或者!process 0 0 SoftMgr.exe就可以直接得到进程SoftMgr.exe的信息
2.输入.process /p + EProcesss地址 切换到应用程序的地址空间
3.如果是x64的系统上调试x86的程序,则输入.effmach x86切换到x86模式,也可以.effmach amd64切换回x64模式,直接输入.effmach可以查看当前模式
4.在符号链接中添加user程序的PDB文件,但不要点击重新加载选择框,然后在命令行输入.reload /f /user
就算没有符号表,也要输入.reload来加载和同步当前用户层内容
5.在windbg中打开应用层源文件
6.下应用层断点,打开R3程序的源代码,按F9下断点
单步步入t指令
tc 继续运行直到call指令停止
tt 继续运行直到ret指令停止
tct 继续运行直到call或者ret指令停止
th 继续运行直到跳转指令停止,跳转指令包括call ret 有条件无条件跳转等
ta [地址] 继续运行程序直到指定地址到达为止
t 单步步入
单步步过p指令
pc 继续运行直到call指令停止
pt 继续运行直到ret指令停止
pct 继续运行直到call或者ret指令停止
ph 继续运行直到跳转指令停止,跳转指令包括call ret 有条件无条件跳转等
pa [地址] 继续运行程序直到指定地址到达为止
p 单步步过
执行/跟踪到指定地址:
1.
ta [r] [= StartAddress] StopAddress
从StartAddress开始执行,到StopAddress为止执行过的指令就像单步按t一样显示出来,如果是tar则不显示寄存器值
例如:
ta 0x401890
从当前地址开始执行,执行到0x401890之前的所有指令都打印出来,并显示寄存器值
tr =0x00401124 0x401890
立刻从地址0x00401124开始执行,到0x401890地址期间执行过的所有指令都会打印出来,并且不显示寄存器值
2.
pa [r] [= StartAddress] StopAddress ["Command"]
从StartAddress开始执行,到StopAddress为止执行过的指令就像单步按p一样显示出来,如果是par则不显示寄存器值
例如:
pa 0x401890
从当前地址开始执行,执行到0x401890之前的所有指令都打印出来
par =0x00401124 0x401890
立刻从地址0x00401124开始执行,到0x401890地址期间执行过的所有指令都会打印出来,并且不显示寄存器值
最好的使用方法就是:
在StartAddress和StopAddress处都下断点,StartAddress处断下时,执行par StopAddress,执行完后,StopAddress处断下
无符号驱动模块360FsFlt的入口点中断:
1.sxe ld:360FsFlt
在加载360FsFlt模块的时候会在DebugService函数里中断下来
2.lm m 360FsFlt
查看360FsFlt的起始地址
3.!dh -a 360FsFlt的起始地址
解析360FsFlt的PE文件,在address of entry point处会显示入口点地址偏移(该入口点并不是DriverEntry,是导出的start)
如果分析失败,则通过ida调整基地址后获取需要下断点的地址并直接用bp下断即可
4.bp 360FsFlt的起始地址+入口点地址偏移
在360FsFlt的入口点处下断点
给进程SoftManagerProxy.exe或者进程模块leakrepair.dll在载入内存时下断点
1.先设置一个异常
!gflag +ksl
sxe ld:SoftManagerProxy.exe
sxe ld:leakrepair.dll
2.接着输入g继续执行,直到进程启动时断下,再输入lm查看想要调试的模块的起始地址
3.断下之后由于peb还没建立,所以这段内存无法访问,但是通过ida找到代码入口点地址然后用bp下断
4.继续执行就会在代码入口点处断下
查找字符串:
s -[type] range pattern
(1)type可以是b w d a u,默认为b
(2)range表示范围,有两种方式表示,一是起始地址+空格+终止地址,二是起始地址+空格+L+长度,如果搜索长度超过256MB,则用起始地址+空格+L?+长度
(3)pattern用于指定要搜索的内容,可以用空格分隔要搜索的数值
1.s-sa
s-sa 00000000`01360000 L00000000`0007b000 显示00000000`01360000开始的长度为00000000`0007b000的内存范围内所有的ASCII字符串
s-sa 00000000`01360000 00000000`013db000 显示00000000`01360000为起点00000000`0007b000为终点的内存范围内所有的ASCII字符串
2.s-su
s-su 00000000`01360000 L00000000`0007b000 显示00000000`01360000开始的长度为00000000`0007b000的内存范围内所有的UNICODE字符串
s-su 00000000`01360000 00000000`013db000 显示00000000`01360000为起点00000000`0007b000为终点的内存范围内所有的UNICODE字符串
3.s -a
s -a 00000000`01360000 L00000000`0007b000 "Windows" 在00000000`01360000开始的长度为00000000`0007b000的内存范围内搜索ASCII字符串"Windows"的地址
s -a 00000000`01360000 00000000`013db000 "Windows" 显示00000000`01360000为起点00000000`0007b000为终点的内存范围内搜索ASCII字符串"Windows"的地址
4.s -u
s -u 00000000`01360000 L00000000`0007b000 "Windows" 在00000000`01360000开始的长度为00000000`0007b000的内存范围内搜索UNICODE字符串"Windows"的地址
s -u 00000000`01360000 00000000`013db000 "Windows" 显示00000000`01360000为起点00000000`0007b000为终点的内存范围内搜索UNICODE字符串"Windows"的地址
5.以下三个是同一个意思
s 0012ff40 L20 'H' 'e' 'l' 'l' 'o'
s 0012ff40 L20 48 65 6c 6c 6f
s -a 0012ff40 L20 "Hello"
6.
s -a 0x0 L?0x7fffffff mytest 在目标空间为2G的user mode内存空间中搜索ASCII字符串"mytest"
内存读/写文件:
.readmem [文件路径] [地址范围]
将文件内容拷贝到被调试目标内存
.writemem [文件路径] [地址范围]
从被调试目标内存拷贝到文件
例:
0:000> .writemem 1234.bin 00000000`76eb0000 l0x20000
Writing 20000 bytes................................................................
显示指定进程块fffffa8003cdeb00的安全描述符信息
(1)dt _OBJECT_HEADER SecurityDescriptor fffffa8003cdeb00
显示安全描述符地址0xfffff8a00000463b
(2)!sd 0xfffff8a000004630
显示安全描述符详细信息
显示进程访问令牌
(1)!process 0 1 进程名
显示出Token的地址
(2)!token Token地址
显示Token详细信息
!exchain
显示当前的异常处理程序链
从指定地址开始输入汇编代码:
a 地址
之后会出现Input>的符号,就可以输入汇编代码了,直接输入回车则退出
!cs 列出CriticalSection的详细信息
!idt 查看中断向量表内容
查看句柄
!handle 查看所有句柄的ID
!handle 000007f8 1 查看ID为000007f8的句柄的类型
!handle 000007f8 4 查看ID为000007f8的句柄的名称
!handle 0 5 查看所有句柄的类型和名称
显示栈帧
.frame 显示当前栈帧
.frame n 设置编号n的栈帧为当前栈帧
.frame /r n 设置编号n的栈帧为当前栈帧 并显示寄存器变量
!uniqstack 显示所有线程的调用堆栈
查看对象信息:
1.获取\driver\acpi驱动对象的信息
kd> !object \driver\acpi
Object: 863dcc08 Type: (86409838) Driver
ObjectHeader: 863dcbf0 (new version)
HandleCount: 0 PointerCount: 137
Directory Object: 8d04e4a0 Name: ACPI
对象体在863dcc08,也就是DRIVER_OBJECT的地址
对象头在863dcbf0,也就是OBJECT_HEADER的地址
类型对象Driver的在86409838,也就是OBJECT_TYPE的地址
2.查看对象头
OBJECT_HEADER
信息
kd> dt nt!_OBJECT_HEADER 0x863dcbf0
+0x000 PointerCount : 0n137
+0x004 HandleCount : 0n0
+0x004 NextToFree : (null)
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : 0x1a ''
+0x00d TraceFlags : 0 ''
+0x00e InfoMask : 0x2 ''
+0x00f Flags : 0x12 ''
+0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x00000001 Void
+0x014 SecurityDescriptor : 0x8d065ec4 Void
+0x018 Body : _QUAD
可以看到_OBJECT_HEADER的大小是0x18+0x4,但是由于最后一个成员Body本身就是对象体结构体的一部分,所以对象体地址=对象头地址+0x18
3.查看对象名
kd> dt nt!_object_header_name_info 0x863dcbf0-0x10
+0x000 Directory : 0x8d04e4a0 _OBJECT_DIRECTORY
+0x004 Name : _UNICODE_STRING "ACPI"
+0x00c ReferenceCount : 0n0
4.查看对象体信息
kd> dt nt!_DRIVER_OBJECT 0x863dcbf0+0x18
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : 0x8643b198 _DEVICE_OBJECT
+0x008 Flags : 0x12
+0x00c DriverStart : 0x8c0ba000 Void
+0x010 DriverSize : 0x48000
+0x014 DriverSection : 0x863447b8 Void
+0x018 DriverExtension : 0x863dccb0 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\ACPI"
+0x024 HardwareDatabase : 0x84178250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : 0x8c0e2de0 _FAST_IO_DISPATCH
+0x02c DriverInit : 0x8c0f88a0 long ACPI!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0x8c0c331c void ACPI!ACPIUnload+0
+0x038 MajorFunction : [28] 0x8c0c34cc long ACPI!ACPIDispatchIrp+0
5.直接查看驱动对象的信息
1: kd> !drvobj 0x863dcbf0+0x18
Driver object (863dcc08) is for:
\Driver\ACPI
Driver Extension List: (id , addr)
Device Object list:
8643b198 8643b8d8 865de558 8680c2c0
87287f08 866a54a8 866a55d0 86992030
......
6.查看Driver类型对象信息
kd> dt nt!_OBJECT_TYPE 0x86409838
+0x000 TypeList : _LIST_ENTRY [ 0x86409838 - 0x86409838 ]
+0x008 Name : _UNICODE_STRING "Driver"
+0x010 DefaultObject : 0x83f4fbe0 Void
+0x014 Index : 0x1a ''
+0x018 TotalNumberOfObjects : 0x76
+0x01c TotalNumberOfHandles : 0
+0x020 HighWaterNumberOfObjects : 0x77
+0x024 HighWaterNumberOfHandles : 1
+0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x078 TypeLock : _EX_PUSH_LOCK
+0x07c Key : 0x76697244
+0x080 CallbackList : _LIST_ENTRY [ 0x864098b8 - 0x864098b8 ]
页堆(Page Heap)
1.开启页堆
开启该机制后,堆溢出时就立即触发异常
!gflag +hpa
!gflag -i app.exe +hpa
2.关闭页堆
!gflag -hpa
!gflag -i app.exe -hpa
3.查看是否gflag开启了哪些调试选项f
!gflag
开启子进程调试
.childdbg 1
关闭子进程调试
.childdbg 0
查看是否调试子进程
.childdbg
设置windows虚拟机的调试端口
1.设置虚拟机的调试端口为\\.\pipe\com_1
2.管理员权限打开windows虚拟机的cmd
3.在cmd中输入命令
bcdedit /debug on
bcdedit /dbgsettings serial debugport:1 baudrate:115200
4.重启计算机
调试模式下运行虚拟机时让windbg不再显示无用信息:
每次调试模式打开虚拟机时,在第一个断点处输入
ed nt!Kd_SXS_Mask 0
ed nt!Kd_FUSION_Mask 0 #这条可有可无
x86调用约定:
__stdcall:参数从右到左压入堆栈,被调用函数自身修改堆栈
__cdecl:参数从右到左压入堆栈,调用函数自身修改堆栈,所以可以支持变参函数
fastcall:第一个参数和第二个参数通过ecx和edx传递,剩余参数从右到左压入堆栈,被调用者还原堆栈
thiscall:如果参数个数确定,C++类成员函数缺省调用约定,参数从右到左压入堆栈,this指针通过ecx传递,被调用者清理堆栈;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈,调用者清理堆栈。
x64调用约定:
前四个参数存放到rcx、rdx、r8、r9上,但在栈上也会预留4个参数空间。
参数入栈会对齐到8个字节。
调用者负责平衡堆栈。
无中断:
PASSIVE_LEVEL->常规线程执行
软中断:
APC_LEVEL->异步过程调用执行
DISPATCH_LEVEL->线程调度
硬中断:
DIRQL->设备中断
PROFILE_LEVEL
CLOCK2_LEVEL
SYNCH_LEVEL
IPI_LEVEL
POWER_LEVEL
DriverEntry、DriverUnload-->Passive级
各种分发函数-->Passive级
完成函数-->Dispatch级
各种NDIS回调函数-->Dispatch级
部分常用机器码:
eb->short jump e9->near jump ea->far jump
je/jz->74 jne/jnz->75
nop->90
int 3->cc
ret->c3
[课程]Linux pwn 探索篇!
最后于 2020-6-29 11:02
被TechForBad编辑
,原因: 添加内容