windebug 指令详解

1. 线程相关
线程命令是以~开始,后面跟线程id(不是tid,是windbg从0开始的一个编号),或者.,#,*等
~. 表示当前线程
~# 表示异常或者产生调试事件的线程
~* 表示所有线程
~1 表示一号线程
~2 s 表示选择2号线程作为当前线程
~3 f 冻结三号线程
~3 u 解冻三号线程
~2 n 挂起二号线程
~2 m 恢复二线程
线程指令还可以与其他指令混合使用,如查看某一个线程的栈:
~1 k 查看一号线程的栈
~* k 查看所有线程的栈
如只想让某个线程激活断点,可以使用
~ 1 bp CPeListCtrl::ShowExportFuncs 对一号线程下断点
 

2. 查看栈指令: k
k指令单独使用时,之显示栈地址、返回地址、函数名信息。如果需要其他信息需要使用参数。常见的有
b 显示函数调用时的前三个参数
c 只显示函数名
p 显示函数的所有参数,包括参数的名字、类型、值。
v 显示帧指针遗漏(FPO)信息。在基于x86处理器,显示器还包括调用约定信息
n 显示调用栈的每帧编号
f 显示调用栈的每帧占用字节数
默认情况下使用k显示当前线程栈,如果加上线程命令前缀,可以查看某个线程栈,如~* k查看所有线程栈
 

3. 显示局部变量: dv。显示本层局部变量信息
常用的参数:
/i 显示变量是局部的、全局的、参数、还是函数等信息
/v 显示变量所在地址
/t 显示变量的类型
 

4. 切换栈帧:.frame 切换栈帧
与dv命令一起可以查看每帧的局部变量
 

5. 查看类型指令: dt
默认显示所有类型信息。加参数-b显示子类型信息
 

6. 断点
bp 常用执行断点
bm 设置执行符号断点,可以同时对多个符号下断
bu 设置一个延时断点,可以对一个还未加载的模块执行代码下断。当模块加载时,此断点自动激活
ba 设置内存访问断点
以上断点都可以针对某个线程下断。如 ~1 bp 在一号线程上下执行断点
bl 查看断点列表
bd 1 禁用一号断点
be 2 启用二号断点
bc * 清除所有断点
 

7. 执行命令:g
g是执行命令,可以指定从某处执行,也可以在执行到某处时断下,如:
g =00423aef 00423af3
修改当前eip为00423aef,执行到00423af3处中断
当然也可以让某个线程继续执行,而其他的线程处在冻结状态。如:
~1 g 一号线程继续执行
 

8. 其他执行命令:
p 单步步过
t 单步步入
gu 执行到返回
gc 从断点处继续执行,用在条件断点内
gn 忽略异常继续执行。允许应用程序的异常处理程序来处理异常。
gh 异常被处理,继续执行

9. 显示汇编指令: u 
u 向下反汇编
ub向上反汇编
uf反汇编整个函数
 

10. 写入汇编指令: a
此命令可以直接修改代码段中的指令

11. 显示符号指令: x
不光可以显示全局符号,也可以显示局部符号
其中符号包括:函数、全局对象、静态对象、参数、局部对象等

12. 显示最近的符号: ln
此命令在不知道某处地址是属于哪个函数时,此命令很有用。它可以告诉你此地址附近的函数是什么

13. C++表达式的用法
当我们查看某个变量或者下条件断点时,可能会获取一个对象中的成员值。那应该怎么获取呢?
13.1. c++表达式求值运算:??
0:000> ?? this->m_nFlags //显示C++变量
unsigned int 0 //默认为unsigned int类型
0:000> ?? this->m_nFlags=0x78458789 //修改C++变量值
unsigned int 0x78458789
0:000> ?? (this->m_nFlags) 
unsigned int 0x78458789
0:000> ?? int(this->m_nFlags) //按int类型显示
int 0n2017822601
0:000> ?? (unsigned short)(this->m_nFlags) //按unsigned short类型显示
unsigned short 0x8789
0:000> ?? (short)(this->m_nFlags) //按short类型显示
short 0n-30839
0:000> ?? (unsigned char)(this->m_nFlags) //按unsigned char类型显示
unsigned char 0x89 ''
0:000> ?? (char)(this->m_nFlags) //按char类型显示
char 0n-119 ''
 

13.2. C++前缀:@@()

//设置条件断点。当this->m_nFlags==0x78458789时断下
bp 00423af9 ".if(@@(this->m_nFlags) == 0x78458789){}.else{gc;}"
14. 一般表达式
14.1. 一般表达式求值:?

14.2. 字符串比较
//$scmp 为大小写敏感的字符串比较函数.返回值为-1,0,1之一
0:000> ? $scmp("abc","abc")
Evaluate expression: 0 = 00000000
0:000> ? $scmp("Abc","abc") Evaluate expression: -1 = ffffffff 0:000> ? $scmp("abc","Abc")
Evaluate expression: 1 = 00000001
//$sicmp 为大小写不敏感的字符串比较函数.返回值为-1,0,1之一
0:000> ? $sicmp("abc","Abc")
Evaluate expression: 0 = 00000000
0:000> ? $sicmp("abc","Abcd")
Evaluate expression: -100 = ffffff9c
0:000> ? $sicmp("abcd","abc")
Evaluate expression: 100 = 00000064

//$spat 通配符匹配.返回值为0(false),1(true)之一。支持以下通配符:
// * 表示0-n个任意字符
// ? 表示1个任意字符
// + 表示1-n个前面的字符
// [] 表示任意单个字符的列表。可以使用'-'表示一个范围
// # 表示0-n个前面的字符
//下面为示例用法:

0:000> ? $spat("abcd","abc*")
Evaluate expression: 1 = 00000001
0:000> ? $spat("abcd","abc+")
Evaluate expression: 0 = 00000000
0:000> ? $spat("abcd","abc[abc]")
Evaluate expression: 0 = 00000000
0:000> ? $spat("abcd","abc[abcd]")
Evaluate expression: 1 = 00000001
0:000> ? $spat("abcc","abc+")
Evaluate expression: 1 = 00000001
0:000> ? $spat("abcc","abc")
Evaluate expression: 0 = 00000000
0:000> ? $spat("abc","abc?")
Evaluate expression: 0 = 00000000
0:000> ? $spat("abcd","abc?")
Evaluate expression: 1 = 00000001
0:000> ? $spat("abcde","abc?")
Evaluate expression: 0 = 00000000


14.3. 判断一个地址是否无效:$vvalid
返回0无效,1为有效

0:000> ? $vvalid(0, 100)
Evaluate expression: 0 = 00000000
0:000> ? $vvalid(0x400000, 100)
Evaluate expression: 1 = 00000001


14.4. 格式化数值:.formats 
0:000> .formats 1000
Evaluate expression:
  Hex:     00001000
  Decimal: 4096
  Octal:   00000010000
  Binary:  00000000 00000000 00010000 00000000
  Chars:   ....
  Time:    Thu Jan 01 09:08:16 1970
  Float:   low 5.73972e-042 high 0
  Double:  2.02369e-320
 

15. 返回最近的错误码指令: !gle 
与GetLastError相同
 

16. 查询错误码含义: !error

17. 查看最后一次事件信息: .lastevent
 

18. 查看版本信息: version、vertarget

在调试的过程中我们可能需要修改汇编代码,比如做个跳板改变执行流(在介绍a指令的时候有用到.在第三楼),或者把内存dump到文件中,或者把文件中的数据读入内存中。这就牵涉到怎么分配和释放内存,怎么读写内存等操作。下面我们一起来学习一下内存操作相关指令把。

19. 分配内存指令: .dvalloc 
.dvalloc指令类似与VirtualAlloc函数。可以指定分配的大小、类型(MEM_RESERVE | MEM_COMMIT)(加上参数/r,申请的内存类型为MEM_RESERVE。默认为MEM_COMMIT)、起始地址(加上参数/b)
使用.dvalloc分配的内存都是PAGE_EXECUTE_READWRITE属性


20. 释放内存指令: .dvfree
有分配就有释放.dvfree指令类似VirtualFree 函数。

21. 查看内存属性:!vprot
!vprot指令类似与VirtualQuery 函数。可以获取一个内存块的各种属性。


22. 查询内存信息命令: !address
!address命令可以按照性质(image or stack or heap or filemap...)、类型(MEM_IMAGE or MEM_MAPPED or MEM_PRIVATE) 、状态(MEM_COMMIT or MEM_FREE or MEM_RESERVE )、保护属性(PAGE_NOACCESS or PAGE_READONLY ...)等组合查询某一组内存列表。

23. 从文件中读入数据到内存指令: .readmem 
直接使用例子演示。 我在c盘下建立一个hello.txt的文件。
文件中是一句话:hello pediy, I'm ddlx.
下面我把这个文件读入到内存


24. Dump内存指令:.writemem
我们经常会存在如下需求:有一个程序是压缩壳,需要把解压后的代码Dump出来;为了分析某些数据,需要把某个内存块Dump出来。那使用.writemem把。
.writemem与.readmem类似,是他的逆操作。
 

25. 读内存指令:d
读指令是最常用的指令之一。它负责按照指定的格式,格式化输出内存数据。下面介绍一下读各种数据的方法:
 

  1. da 按照ASCII字符串读取
  2. db 按照单字节和ASCII字符串读取
  3. dc 按照4字节和ASCII字符串读取
  4. dd 按照4字节读取
  5. dD 按照双浮点(8字节)格式读取
  6. df 按照单浮点(4字节)格式读取
  7. dp 按照指针(32位系统读取4字节,64位系统读取8字节)格式读取
  8. dq 按照8字节读取
  9. du 按照Unicode字符串读取
  10. dw 按照2字节读取
  11. dW 按照2字节和ASCII字符串读取
  12. dyb 按照单字节和二进制读取
  13. dyd 按照4字节和二进制读取

26. 显示符号表指令: dds、dps、dqs
这个常用在查看虚函数表、导入地址等操作时使用。

27. 查看ascii字符串数组命令: dda、dpa、dqa

28. unicode字符串数组查看: ddu、 dqu、 dpu

29. 内存写入操作命令: e
写指令是负责按照指定的格式,格式化输出内存数据,对命令中已经看到部分写命令的用法。下面介绍一下写各种数据的方法:
 

  1. ea 写入ASCII字符串
  2. eb 写入单字节
  3. ed 写入4字节
  4. eD 写入双浮点(8字节)格式
  5. ef 写入单浮点(4字节)格式
  6. ep 写入指针(32位系统读取4字节,64位系统读取8字节)格式
  7. eq 写入8字节
  8. eu 写入Unicode字符串
  9. ew 写入2字节读取
  10. eza 写入无结束符的ASCII字符串
  11. ezu 写入无结束符的Unicode字符串

30. 内存搜索指令: s
内存搜索指令,在查找某种类型的数据的时候非常有用,我们来看一下内存搜索指令的用法

31. 物理内存读写操作指令
!d 读物理内存
!e 写物理内存

这两个用的很少。不做过多介绍

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WinDBG 是个非常强大的调试器,它设计了极其丰富的功能来支持各种调试任务,包括用户 态调试、 内核态调试、 调试转储文件、 远程调试等等。 WinDBG 具有非常大的灵活性和可扩展性, 用来满足各种各样的调试需求,比如用户可以自由定义调试事件的处理方式,编写调试扩展模块 来定制和补充 WinDBG 的调试功能。 尽管 WinDBG 是个典型的窗口程序, 但是它的大多数调试功能还是以手工输入命令的方式来 工作的。目前版本的 WinDBG 共提供了 20 多条标准命令, 140 多条元命令( Meta-commands), 和难以计数的大量扩展命令。学习和灵活使用这些命令是学习 WinDBG 的关键,也是难点。 上一章我们从设计的角度分析了 WinDBG ,本章将从使用(用户)的角度介绍 WinDBG 。我 们先介绍工作空间的概念和用法(第 1 节),然后介绍命令的分类和不同种类的命令提示符(第 2 节)。 第 3 节介绍不同的调试模式, 也就是如何与不同特征的调试目标建立调试会话。 第 4 节介绍 上下文的概念和在调试时应该如何切换和控制上下文。第 5 节介绍调试事件和如何定制调试事件 的处理方式。 从第 6 节到第 9 节我们将分别介绍如何在 WinDBG 中完成典型的调试操作, 比如控 制调试目标(第 6 节)、设置断点(第 7 节)、观察栈(第 8 节)以及如何观察和修改数据(第 9 节)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值