文章目录
命令系统
注意事项
- 只有暂停时可以输入命令
- 直接回车可以重复上一条命令
- 按上下方向键可以浏览之前输入过的命令
- 当命令提示框为
BUSY时,无法输入命令
标准命令
命令行输入?后,可显示一些基本命令
在输入显示的命令,可以显示命令的具体说明
元命令
命令行输入.help后,可显示一些元命令
扩展命令
用于实现特定调试功能的一些命令,实现与DLL中,一般以!开头。通常是一个单词。
扩展命令存在DLL被称之为扩展模块,使用.chain命令可以列出所有的扩展模块,大部分都有help命令来显示这个模块的基本信息以及所含有的命令。
常用基本命令
| 命令 | 功能 |
|---|---|
| lm | 查看当前模块和符号加载情况 |
| .reload | 刷新符号路径,重新载入符号 |
| ld | 加载某一个符号 |
| .restart | 重新开始调试 |
| .detach | 分离调试 |
| q | 退出调试 |
程序控制相关命令
| 系列 | 命令 | 作用 | 快捷键 |
|---|---|---|---|
| g系列 | g | 恢复执行 | F5 |
| gu | 执行的父函数 | ||
| p系列 | p | 单步步过 | F10 |
| pa | 执行到一个地址 | ||
| pc | 执行到下一个Call | ||
| t系列 | t | 单步步入 | F11 |
| ta | 执行到一个地址 | ||
| tc | 执行到下一个call |
断点控制相关命令
断点命令全是b系列命令
| 命令 | 作用 |
|---|---|
| bp | 设置软件断点 |
| ba w\r\e | 设置硬件断点 |
| bl | 列出所有断点 |
| be\bd\bc | 启用\禁止\删除 断点 |
| bc * | 清除所有断点 |
| bu | 和bp类似,但不是一次性的 |
| bm | 批量设置断点 |
- 示例
bm *!Messag*下断所有Mssage开头的函数
bm Myapp!MyClass::*下断所有MyCalss 类中的函数
堆栈命令
| 命令 | 功能 |
|---|---|
| K | 显示简单的堆栈信息 |
| Kb | 显示每个函数的前三个参数 |
| Kp | 显示每个函数的全部参数 |
| kv | 显示更具体的信息(调用约定) |
| .frame [堆栈序列号] | 切换局部环境上下文 |
- 注意:假如想查看某个线程的堆栈,可以使用
~n k(n代表线程号)
示例:
k:查看堆栈序列.frame [序列号(#列)]:切换序列x:后面跟x命令可以显示局部变量
反汇编命令
| 命令 | 作用 |
|---|---|
| u | 将一个地址之后的内容反汇编显示 |
| ub | 将某一个地址之前的内容反汇编 |
| uf | 显示指定函数地址的反汇编代码(需要符号) |
l+条数显示指定条数的反汇编代码- u | Address | count
- uf命令自动识别函数结尾,将整个函数反汇编出来
模块分析
- 常见的PE文件有
.exe.dll.sys后缀代表的文件 - 内存中每一个可执行文件称之为一个模块。
| 命令 | 作用 |
|---|---|
| lm | 列出所有模块 |
| lm vm 模块名 | 列出某一个模块的详细信息 |
| !dh | 查看某一个模块的PE信息 |
伪寄存器
| 命令 | 作用 |
|---|---|
| $exentry | 程序入口点 |
| $peb | 程序PEB的入口点 |
| $teb | 程序TEB的入口点 |
| $ra | 当前函数的返回地址 |
| $ip | 指针寄存器 |
| $retreg | 当前函数的返回值 |
d系列结构
- d系列命令一般为显示命令
| 命令 | 作用 |
|---|---|
| dt + 结构体 + 地址 | 将地址解析为结构体 |
| dd 地址 | 四字节显示 |
| db 地址 | 单字节显示 |
| dv | 显示当前函数变量信息(包括参数和局部变量) |
搜索内存
| 命令 | 作用 |
|---|---|
| s -[flags]sa\su 范围 | 搜索 Ascall\Unicode数据 |
| s -[flags]type 范围 | 搜索特定的数据类型的数据 |
| flags | 含义 |
|---|---|
| s | 保存搜索结果,供后续搜索筛选 |
| r | 将当前搜索范围限定为上一次搜索中(上次搜索需要使用s) |
| i | 使用在sa\su中,表示搜索的字符长度 |
| w | 只搜索可写入内存 |
| l | 仅显示搜索到的数据地址,在foreach语法中很有用 |
| 类型 | 说明 |
|---|---|
| b | Byte |
| W | WORD |
| d | DWORD |
| q | QWORD |
| a | ASC字符串 |
| u | Unicode字符串 |
示例
- 使用
lm获取模块的地址范围 - 使用
s -[flag]sa\su 起始地址 终止地址搜索数据 - 使用
s -[flag]sa\su 起始地址 l+范围大小搜索指定大小区域数据 - 使用
s -[flag] 范围 "数据"搜索指定类型的数据
4.1s -a 0x400000 0x41f000 "Hello"搜索0x400000 0x41f000范围内Ascall类型的字符Hello
4.2s -b 0x400000 0x41f000 4d 5a搜索0x400000 0x41f000范围内 按字节搜索4d 5a
搜索符号
- 使用
x命令来进行符号搜索 - 使用
x进行模糊搜索,使用*号作为通配符
示例
x *er*!MessageboxA搜索模块名带有er中,MessageboxA函数的地址x KERNEL32!CloseConsoleHandle搜索KERNEL32模块中CloseConsoleHandle函数信息。
搜索调用
# 模块名!函数名# 函数名# 函数名 + 范围
示例
# user32!MessageBoxA搜索对user32模块中MessageboxA函数地址# MessageBoxA搜索所有对MessageBoxA的调用# MessageBoxA 0x400000 0x41f000
分析模块链
- dt 结构体名称 -l 链表节点 地址
将地址以结构体形式解析,并只将链表节点全部解析出来。
搭建双机调试环境
- 安装
Virtual Kd,在其目录下启动对应vmmon.exe程序,点击debugger path,设置windbg调试器路径。 - 将
Virtual Kd,目录下的Target文件夹拷贝至虚拟机中,启动Vminstall.exe并安装,重启虚拟机,以调试模式启动。 - 这时主机的
vmmon.exe程序则可以接受虚拟机的的调试信号。
常见内核结构
SSDT(系统描述服务表)
- 加载
nt模块符号后 命令x nt!KiServiceTable可获得服务表地址,使用dd + 地址可查看所有函数地址,使用u + 地址可查看具体函数反汇编
EPROCESS
dt _EPROCESS
ETHREAD
dt _ETHREAD
内核调试进程
-
!process 0 0
枚举进程 -
.process /i 进程
EPROCESS地址
切入到一个进程的虚拟地址,就可以访问该进程的所有信息
进程之间通过内存分页来隔离
分析DUMP文件
- 设置系统蓝屏时
DUMP核心文件 - 使用
Windbg的!analyze -v分析dump文件
表达式
MASM 表达式
- 使用特点总结
-求值使用?
-默认进制为16进制
-所有的符号均为地址(类似指针)
-poi为取值内容
进制前缀
| 进制 | 前缀 |
|---|---|
| 16进制 | 0x |
| 10进制 | 0n |
| 8进制 | 0t |
| 2进制 | 0y |
MASM常见运算符
| 系列 | 运算符 |
|---|---|
| 算数运算符 | + 、- 、* 、/ 、mod(或者%) |
| 位移运算符 | << 、>> 、>>> |
| 比较运算 | =(或者==)、< 、 > 、 <= 、>= 、!= |
| 位运算 | and(或者&)、xor(或者^)、or(或者丨) |
| 逻辑运算 | not |
=或者==都是比较运算符,赋值通常是通过r命令,r @eax = 1
MASM其他运算符
| 符号 | 作用 |
|---|---|
| hi | 取高16位 ? hi(@eax) |
| low | 取低16位 ? low(@eax) |
| by丨$pby | 取指定地址出的一个字节 ? by(地址) |
| wo丨$pwo | 取指定地址出的两个字节 ? wo(地址) |
| dwo丨$pdwo | 取指定地址出的四个字节 ? dwo(地址) |
| qwo | $pqwo |
| poi丨$ppoi | 取指定地址出的指针大小数据 ? poi(地址) |
$符号后的是解析的物理内存地址
C++ 表达式
-
使用特点总结
-默认使用??求值
-符号根据它自身的类型解析
-变量的数值就是它的实际值,不是地址 -
MASM表达式某一部分被圆括号括住并有两个@符号(@@),该部分会根据C++表达式规则来解析 -
C++表达式某一部分被圆括号括住并有两个@符号(@@),该部分会根据MASM表达式规则来解析 -
也可以通过使用@@c++(…)或者@@masm(…)指定表达式求值
-
MASM不能直接解析结构体的元素,但是C++可以 -
MASM表达式默认是十六进制,C++模式为10进制 -
我们将表达式输入
windbg命令中,求得数据
进制前缀
| 进制 | 前缀 |
|---|---|
| 16进制 | 0x |
| 8进制 | 0 |
不能直接使用二进制
运算符
支持C++大部分运算符
| 系列 | 运算符 |
|---|---|
| 算数运算符 | + - * / -(取负) ++ – |
| 关系运算符 | > >= < <= == != |
| 位运算符 | & 丨 ~ ^ << >> |
| 逻辑运算符 | ! && 丨丨 |
| 赋值运算符 | = += -= *= /= %= |
| 条件运算符 | ? : 作用域符号(::) |
| 逗号运算符 | , 注释(//) |
| 指针运算符 | * & |
| 求字节数运算符 | sizeof |
| 分量运算符 | . -> |
| 下标运算符 | [] |
C++表达式中使用寄存器和伪寄存器必须带有@符号前缀
不能使用赋值运算符修改寄存器或伪寄存器,只能使用r命令修改他们
- 切换默认表达式命令
.expr /s c++/masm
流程控制语句
-
选择结构
- .if
- .else
- .elif
示例
.if (条件) {命令序列} .else {命令序列}
.if (条件) {命令序列} .elif(条件) {命令序列} .else {命令序列}
-
循环结构
- .for
- .while
- .do
示例
.for (初始命令;条件;增量){命令序列}
.while (条件) {命令序列}
.do {命令序列}(条件)
-
continue与break
与C/C++一样的概念
Windbg脚本
- 执行脚本
$$>< 路径 - 注释
$$ 描述
g @$exentry
t
t
t
t
p
p
p
t
r @$t0 = @$ip+0x152 $$根据当前EIP计算下一个call的位置
g @$t0
t
r @$t1 = 0
.while(@$t1 != 4){
p;
.if(by(@$ip) == 0xe8){
r @$t1= @$t1+1
};
}$$循环查找第四个call的位置
t
t
就是一些命令的集合
线程命令
| 符号 | 说明 |
|---|---|
| ~. | 当前线程 |
| ~# | 导致当前异常的线程 |
| ~* | 进程中的所有线程 |
| ~Number | 序号为Number的线程 |
| ~~[tid] | 线程ID为TID的线程 |
| ~{num}s | 切换线程;num为线程序列号 |
寄存器命令
-
寄存器命令主要是r系列
r:直接打印出所有寄存器的值r @eax:直接打印出eax寄存器的值r @eax=表达式:直接修改寄存器的值
-
~1 r查看1号线程的寄存器信息 -
~2 k查看2号线程的堆栈信息
字符串通配语法(类似正则表达式)
| 符号 | 含义 |
|---|---|
| * | 表示零个或多个字符 |
| ? | 表示任意单个字符 |
| [] | 表示该列字符中的任意单个字符,可以使用-表示一个范围 |
| # | 表示匹配零个或多个前字符列表 |
| + | 匹配一个或者多个前字符列表 |
x *!m[a-z]+n搜索任意模块中,m开头,n结尾,中间是[a-z]的函数
条件断点
J命令
-
j表达式 命令1;命令2
如果表达式的值时非0值,则执行命令1,否则执行命令2. -
示例
J @eax>0 r @eax; r @eax=1
断点附加命令
- bp $exentry “r @eax;r @ecx”
当程序如上断下来后,还会执行后面引号中的内容。
伪寄存器
| 伪寄存器 | 含义 |
|---|---|
| $tpid | 当前进程的PID |
| $tid | 当前线程的PID |
| $proc | 当前进程的EPROCESS |
Windbg脚本
- 需要以下内容提供支持
-数据类型(C++/MASM)
-变量定义方式(伪寄存器)
-运算符与表达式(C++/MASM)
-流程控制语句(三大结构)
-库函数功能的命令和语句
伪寄存器
- 自定义伪寄存器
t
0
t0~
t0 t19,可以将其作为事先定义好的20个变量,直接使用。
命令:
r $t0 = 100为伪寄存器赋值
? $t0 + 200寄存器计算
别名
- 固定别名:
$u0 ~ $u9
同样使用r命令修改固定别名所代表的内容。修改的时候需要在u前面加个.
虽然在使用r命令,但是这些别名不是寄存器或伪寄存器,r命令只能修改他们,但不能显示他们的值。 - 自动别名:调试器设置的别名
- 自定义别名:可以由windbg使用者自己设置和命名
- -as(aS) 定义别名
- -ad 删除别名
- -al 列出别名
- 定义别名时的一些参数
| 参数 | 含义 |
| ------------ | ------------ |
| -e | 把环境变量作为别名 |
| -ma | 把一个内存地址中的字符串作为别名 |
| -f | 把文件内容作为别名,只用用在(aS)中 |
伪寄存器相当于变量,而别名更像宏替换
as cmd bp user32!MessageBoxW "j eax=0 '';'gc'"
将bp user32!MessageBoxW "j eax=0 '';'gc'"等效替换为cmd命令。
内存操作指令
| 命令 | 作用 |
|---|---|
| .dvalloc | 申请虚拟内存 |
| .dvfree | 释放虚拟内存 |
| .wirtemem | 写内存到文件 |
| .readmem | 读内存到文件 |
| !address | 内存信息查看 |
| !vprot | 查看内存保护信息 |
修改内存
| 指令 | 作用 |
|---|---|
| e{a丨u丨za丨zu} address “String” | ascll丨unicode丨以零结尾的ascall丨以零结尾的Unicode |
| e{a丨b丨d丨D丨f丨q丨u丨w} address {values} | ascall丨byte丨dword丨double丨float丨8字节丨Unicode丨word |
示例
- eza 0x314342 “pediy”:向地址
0x314342写入字符串pediy - eb 0x314342 70 65 64 69 79:向地址
0x314342写入字符串70 65 64 69 79(字符pediy)
重定向命令输出
. logopen [输出文件路径]
. logclose
Windb脚本
- 解析器
$<FilePath
$><FilePath
$$<FilePath
$$><FilePath
$$>a<FilePath
“<” 表示不会自动将脚本压缩成一行
“><” 会将脚本压缩成一行,并将换行替换为 “;”
“FilePath” 脚本路径
- 数据类型
2进制 0x
8进制 0n
10进制 0t
16进制 0y
- 字符串
"字符串"
使用 " " 括起来
- 变量
;伪寄存器 $t0~$t19
r $t0=0x123
r $t0
- 别名
别名更像宏,解释时直接替换原始操作数
固定别名: u 0 − u0- u0−u9
r $.u0="123"
.echo $u0
自定义别名:as/ad/al
as: as [param1] ${/param2:Name} data
param1:
/ma 参数指定的内存地址当ASCII字符串
/mu 参数指定的内存地址当Unicode字符串
/msa 参数指定的内存地址当做ANSI_STRING字符串
/msu 参数指定的内存地址当做UNICODE_STRING字符串
/f 别名等于参数指定文件的内容
/e 别名等于参数指定的环境变量
param2:
/v 保持别名原样,不翻译,在定义和删除的时候使用
/n 如果别名已定义就翻译为内容,否则不做任何翻译
/f 如果别名已定义就翻译为内容,否则内容为空
/d 如果别名已定义,翻译为1,否则翻译为0,相当于#ifdef
-
表达式
汇编表达式(默认表达式)
C++表达式 :需使用 @@c++() 将表达式括起来 -
语句
.if
.else
.elif
.for
.while
.break
.continue
.do
.printf
.block 语句块,配合{}使用,与其等效
$$ 注释
*内建函数
内核调试
准备工作
- 开启测试模式
bcdedit /set testsigning on - 开启调试模式
bcdedit /debug on - 禁用驱动签名
bcdedit /set loadoptions DDISABLE_INTEGRIITY_CHECKS - 生成秘钥
set /dbgsettings net hostip:x.x.x.x(接受端IP) port:x(50010) key:x.x.x.x(1.2.3.4)
内核调试常用命令
- 获取EPROCESS
!process 0 0 [进程名.exe]
eg:
!process 0 0 notepad.exe
- 切换当前进程环境
.process /p [EPROCESS]
eg:
.process /p 00ffff86、00789564
- 强制加载用户态符号
.reload /f /user
- 附加到当前EPROCESS
侵入式:可下断点
.process /i
- 切换、附加、加载符号
.process /p /i /r
;小P仅仅切换内核态环境,大P切换内核和用户态环境
- 下断点
bp /p EPROCESS kernel32!createfilew
本文详细介绍了Windbg的命令系统,包括注意事项、标准命令、元命令、扩展命令等。重点讲解了程序控制、断点设置、堆栈分析、反汇编、模块分析、内核调试和DUMP文件分析等内容,并提供了丰富的示例和技巧,帮助读者掌握Windbg的使用。
7万+

被折叠的 条评论
为什么被折叠?



