首页
社区
课程
招聘
[分享]windbg常用指令
发表于: 2020-3-14 01:07 15950

[分享]windbg常用指令

2020-3-14 01:07
15950


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编辑 ,原因: 添加内容
收藏
免费 4
支持
分享
最新回复 (13)
雪    币: 4094
活跃值: (4039)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
记录在看雪主要是为了以后方便查看,也欢迎大家来补充
2020-3-14 11:05
0
雪    币: 83
活跃值: (1082)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3

感谢总结 但是看完后 发现其中一些问题 还请帮忙回复一下 :

我的windbg版本是windbg:6.12.0002.633 AMd64 双机调试的操作系统版本是win7x64 6.1.7601 Service Pack 1内部版本7601

1 dt nt!_P* 显示nt模块中所有以_P为开头的结构体的名称 x nt!zw* 显示nt模块内的所有zw开头的函数 那问题来啦 如何显示win32k内 nt开头的函数呢 hal.dll内某些结构呢? 我试了一下 不行啊

2 标注一二三四五六七八 地方 我看不懂 你知道是啥意思吗
!process EPROCESS地址 7 查看进程详细信息 部分显示如下
  THREAD fffffa8032424060  Cid 0004.0364  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffffa80323fce58  SynchronizationEvent  一哪个命令查看谁占用这个事件对象呢?
        Not impersonating  二这个是啥意思
        DeviceMap                 fffff8a000008bc0
        Owning Process            fffffa8030ed5040       Image:         System
        Attached Process          N/A            Image:         N/A   三什么是N/A?
        Wait Start TickCount      3611 四是啥意思           Ticks: 493562 (0:02:08:19.616) 五啥意思?
        Context Switch Count      1             
        UserTime                  00:00:00.000 六 是啥意思
        KernelTime                00:00:00.000
        Win32 Start Address nt!EtwpLogger (0xfffff800041f1064)
        Stack Init fffff880026fcc70 Current fffff880026fc6b0
        Base fffff880026fd000 Limit fffff880026f7000 Call 0
        Priority 15 BasePriority 15 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5 七 UnusualBoost ForegroundBoost IoPriority PagePriority 八这四个分别啥意思?
        Child-SP          RetAddr           : Args to Child                                                           : Call Site
        fffff880`026fc6f0 fffff800`03eda992 : fffff880`04b660b8 fffffa80`32424060 fffffa80`00000000 00000000`00000000 : nt!KiSwapContext+0x7a
        fffff880`026fc830 fffff800`03ed9eaa : fffffa80`312bc2c0 fffffa80`315bf102 00000000`00000000 fffff880`04b66390 : nt!KiCommitThreadWait+0x1d2
        fffff880`026fc8c0 fffff800`041f1156 : 00000000`00000001 fffff880`026fcbc0 fffffa80`00000001 fffffa80`00000000 : nt!KeWaitForMultipleObjects+0x272
        fffff880`026fcb80 fffff800`04172cce : 00000000`812576a0 fffffa80`32424060 00000000`00000080 fffffa80`30ed5040 : nt!EtwpLogger+0xf2
        fffff880`026fcc00 fffff800`03ec6fe6 : fffff800`04047e80 fffffa80`32424060 fffff800`04055cc0 fffff880`0126f384 : nt!PspSystemThreadStartup+0x5a
        fffff880`026fcc40 00000000`00000000 : fffff880`026fd000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KxStartSystemThread+0x16

3 lmf并没有显示模块路径 如下所示
0: kd> lmf 
start             end                 module name
fffff800`03e55000 fffff800`0443f000   nt       ntkrnlmp.exe

Unloaded modules:
fffff880`15a31000 fffff880`191d6000   34364088.sys
fffff880`0374f000 fffff880`037c0000   spsys.sys
fffff880`01880000 fffff880`0188e000   crashdmp.sys
fffff880`0188e000 fffff880`01898000   dump_storport.sys
fffff880`01898000 fffff880`018b5000   dump_LSI_SAS.sys
fffff880`01bcc000 fffff880`01bdf000   dump_dumpfve.sys
fffff880`05408000 fffff880`0540a000   USBD.SYS
fffff880`05400000 fffff880`05408000   USBPcap.sys
fffff880`055c5000 fffff880`055c7000   USBD.SYS
fffff880`055bd000 fffff880`055c5000   USBPcap.sys

4.lmvm *nt* 显示名字中包含nt的模块的详细信息(注意exe、dll等都不要带后缀名)貌似只能查看内核模块 你这个exe dll是啥意思?

5 !dml_proc和.call 你忘记注释它的用法了  我这里发出来吧: 显示进程列表 第一个是一个进程eproess地址 是个链接 可以点进去详细查看更多信息 第二个是进程id 第三个是进程名字  .call 是调用某个函数  类似于od的远程线程调用call测试一样  

6 !gflag +ksl 这一块 你说此时断下来后 进程还没创建呢  内存空间没初始化 所以全是???? 也无法下cc断点 你说需要 ida查看入口 完后去下断点 其实太麻烦了 直接kvn查看堆栈 最后一个用户层的返回地址 下硬断就行了 完后恢复运行 windbg执行完内核函数回到用户层的时候  在syscall后面的ret地址处断下来 此时已经进城创建完毕 内存空间可以查看了

7 .load wow64exts 
    !sw
    这和.effmach x86啥区别?

8 下面这些异常中断分别啥意思啊
.sx
显示所有支持的异常中断
  eh - C++ EH exception - second-chance break - not handled
 clr - CLR exception - second-chance break - not handled
clrn - CLR notification exception - second-chance break - handled
 cce - Control-Break exception - break
  cc - Control-Break exception continue - handled
 cce - Control-C exception - break
  cc - Control-C exception continue - handled

9 下面这些指令( !address  !gle  !gle -all   !uniqstack |  |#   ~ 等相关命令 )都不能用啊  不管是用户模式还是内核模式 我都尝试过 我也看过微软官方windbg文档 都试过 提示这些乱七八糟的错误
1: kd> !address fffff800`03ecd490
unable to resolve nt!MiSessionViewStart
0: kd:x86> !gle 
Unable to read thread 0's TEB
0: kd:x86> !gle -all
Last error for thread 0:
Unable to read thread 0's TEB
0: kd:x86> !uniqstack
No export uniqstack found
32.0: kd:x86> |.
               ^ Extra character error in '|.'
32.0: kd:x86> |
32.0: kd:x86> |#
               ^ Extra character error in '|#'
32.0: kd:x86> |
32.0: kd:x86> ~ 
              ^ Syntax error in '~'


10: DebugInfo 和 LockSemaphore 啥意思
 kd> !cs
-----------------------------------------
DebugInfo          = 0x00000000770f7088 啥意思
Critical section   = 0x00000000770f7060 (ntdll!RtlCriticalSectionLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0 啥意思
SpinCount          = 0x0000000002000000

11 你文章中说道:花指令:无用指令或者干扰指令 你windbg是怎么处理的?

12 我想跟踪进程某段区间内 所有api的调用(包含syscall的调用) 有没有好的脚本 命令 或者啥其他建议?


2020-3-17 09:59
1
雪    币: 4094
活跃值: (4039)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
killpy 感谢总结 但是看完后 发现其中一些问题 还请帮忙回复一下 :我的windbg版本是windbg:6.12.0002.633 AMd64 双机调试的操作系统版本是win7x64&nbsp;6 ...
老哥NB,我把以前的一些东西发上去,是防止哪天丢了或者忘了,你指出的这些问题我回家后会一个一个看的,这个笔记我会更新的
2020-3-17 11:11
0
雪    币: 883
活跃值: (884)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我的CPU也是AMD,对windbg只会简单使用,学习了。
2020-3-17 12:02
0
雪    币: 16
活跃值: (527)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
老哥,问一下,现在微软的符号服务器已经不给用了,你是怎么加载符号的
2020-3-19 09:34
0
雪    币: 83
活跃值: (1082)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
7
昵称好麻烦 老哥NB,我把以前的一些东西发上去,是防止哪天丢了或者忘了,你指出的这些问题我回家后会一个一个看的,这个笔记我会更新的[em_41]
经过再次调试 发现微软官方windbg说 有些命令只能在用户模式执行 不能在内核模式执行 而且用户模式 貌似指的是本地windbg调试 不是双机windbg 断在进程用户空间 也算是内核调试 比如我上面回复的那些不能用的指令 在本地windbg调试的时候 都能用了 双机无论在用户层还是内核层断下来 命令都不行 如果命令支持内核模式 那么双机就可以
2020-3-19 10:07
0
雪    币: 0
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
mark下
2020-3-19 10:18
0
雪    币: 4094
活跃值: (4039)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
沉醉星渊 老哥,问一下,现在微软的符号服务器已经不给用了,你是怎么加载符号的
被q了,需要梯子才能下载到
2020-3-22 18:23
0
雪    币: 4094
活跃值: (4039)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
killpy 经过再次调试 发现微软官方windbg说 有些命令只能在用户模式执行 不能在内核模式执行 而且用户模式 貌似指的是本地windbg调试 不是双机windbg 断在进程用户空间 也算是内核调试 比如我上 ...
嗯,除了这些,还有些问题可能的原因是符号表没下载到,比如!address无法使用,至于其他的问题,我以后再慢慢改吧
2020-3-22 18:25
0
雪    币: 38
活跃值: (185)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
11
mark 收藏
2020-4-16 18:39
0
雪    币: 13904
活跃值: (17017)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
12
mark,楼主辛苦了
2020-4-16 20:50
0
雪    币: 190
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
问个问题,符号表如果通过微软服务器下载,是下载一次就不需要再次联网下了么?
2020-5-28 21:27
0
雪    币: 259
活跃值: (283)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
666
2020-5-28 21:44
0
游客
登录 | 注册 方可回帖
返回
//