单位内训

Windbg 调试VC程序

2017-12-12  本文已影响8人  星夜兼程工作笔记

windbg中的调试指令有三种:  http://www.360doc.com/content/16/1110/14/30953065_605412205.shtml

1. 基本命令: 调试器自带,提供最基本的调试功能,不区分大小写。 例如 bp ,g  ,dt ,dv ,k,s等

2. 元命令:调试器自带,以“.”开头. 提供基本命令没有提供的功能。例如 .reload  .sympath等

3. 扩展命令:外部加入的命令,以“!”开头。用于扩展某一方面的调试功能,其实现在动态加载的模块中。例如:!analyze

使用;分隔符,可以在一行输入多个命令。使用 ctrl + break 可以终止一个命令。当输入框显示为busy时,即使输入框可以输入命令,输入的命令也不会立刻执行。

一. windbg 启动调试的办法

分为两种:

1. 命令行方式启动:(又分为打开和附加两种方式)

windbg  - i        // 将windbg设置为默认调试器

windbg “notepad”  arguments   //使用windbg 启动notepad调试,设置启动参数

windbg -p  4200    //使用windbg 附加到一个正在运行的PID = 4200的进程

windbg -pn "notepad"  //使用windbg附加到一个正在运行的名字为"notepad"的进程

2. 图形界面方式:直接运行windbg.exe

二. 常用的元命令

1.   .restart      //重启并调试

2   .kill             //强制结束当前调试

3.  .help          //打印出所有元命令

4.   .hh            //打开windbg  chm帮助文档

三. 常用基本命令

1.  搜索命令

       s -a 0012ff40 L0x20 "Hello"     //搜索ansi字符串“hello”, 从0012ff40地址开始, 长度是 0x20的范围。即搜索范围是 0012ff40~ 0012ff60.

 2.  断点命令

      bp 0040108c             //直接在地址下断

      bp test1!Max  ; bp  Max          //直接在函数名上下断

      bp  'test1.cpp:30'                         //在test1.cpp第30行下断

      bp  CObject::CObject           //在CObject构造函数上下断

     bp   kernel32!CreateFileA      //在kernel32.dll模块CreateFileA函数头位置下断

     bp  TestCommand!CObject::add   //在TestCommand.dll模块的CObject类函数add头部下断。

     bp `ConsoleTest.cpp:40` ".if (poi(pVar)>5) {};{g}"

      // ".if (Condition) {Optional Commands}; {g}"    条件断点 pVar指针指向的值>5,执行空语句(;),断住  否则继续执行

      bu  test1!Max  ;bu  Max          //在函数的开头下断

      bm add_*                     // 匹配add_开头的函数,并在这些函数起始处都打上断点

     ba w4 0x0483dfe0// 当对0483dfe0地址写操作时停下,前面要带上0x,否则会报错。

          //ba [r|w|e] [Size] Addr      [r=read/write, w=write, e=execute], Size=[1|2|4 bytes]

           //这个指令比较强大,可以下内存访问,写入以及执行断点。  内存大小Size :单字节, 双字节,4字节,8字节。

 3. 断点管理

bl       // 列出所有断点     breakpoint  list

bc *     // 清除所有断点    breakpoint  clear

bc 1     // 清除1号断点

bc 1 2 5      // 清除1号、2号、5号断点

be *       // 启用所有断点   breakpoint   enable

be 1      // 启用1号断点

be 1 2 5     // 启用1号、2号、5号断点

bd *      // 禁用所有断点   breakpoint  disable

bd 1     // 禁用1号断点

bd 1 2 5      // 禁用1号、2号、5号断点

4. 断点执行

g       // Go(F5)

gu     // 执行到当前函数完成时停下【Go Up】

p      // 单步执行(F10)  【Step】

 pc     // 执行到下一个函数调用处停下【Step to  Next Call】

 pa 7c801b0b      // 执行到7c801b0b地址处停下  【Step to Adress】

 t        // Step into(F11) 【Trace】

tc       // 执行到下一个进入点处停下 【Trace to Next Call】

ta 7c801b12       // 执行到7c801b12地址处停下 【Trace to Adress】

5.  进程相关

|         // 列出调试进程

|*        // 列出调试进程

6.  线程相关

~       // 列出线程

~*       // 所有线程

~* k     // 所有线程堆栈信息

~* r    // 所有线程寄存器信息

~.       // 查看当前线程

~0s      // 查看主线程

~#      // 查看导致当前事件或异常的线程

7.  模块相关

lm     //列出进程加载模块 

8. 查看变量

dt     i_c        //查看变量地址, 类型, 值

dt ntdll!*      // 显示ntdll里的所有类型信息

dt  *!*IMAGE_DOS*     // 显示所有模块中含有IMAGE_DOS字符的类型信息

dt myApp!g_app             // 表示显示myApp进程里全局变量g_app的内存布局

dt WindbgTest!CTest       // 查看模块WindbgTest的CTest的内存布局

dt WindbgTest!CTest 0x0041f8d4          // 将0x0041f8d4地址处内容按照模块WindbgTest的CTest的内存布局来解析

 dt this                   // 查看this指针的类型及成员变量

dt  -v   _PEB @$PEB           // 使用详细模式查看PEB(process's environment block)内存结构

dt   tagMSG 0x0336e54c              // 类型要使用tagMSG,不能使用typedef产生出的MSG

typedef  struct   tagMSG{

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG, *PMSG;

dv               // 显示当前函数内所有局部变量,函数参数的值   

dv  nCount    // 查看局部变量nCount的值

x              //显示当前函数内所有局部变量 ,函数参数的值, 包括变量地址、

x   nCount   // 查看局部变量nCount的值 和地址


9.  查看堆栈

k          // 显示当前调用堆栈

kn        // 带栈编号显示当前调用堆栈

kb         // 打印出前3个函数参数的当前调用堆栈

kb 5        // 只显示最上的5层调用堆栈

kv             // 在kb的基础上增加了函数调用约定等信息

kp         // 显示每一层函数调用的完整参数,包括参数类型、名字、取值(必须是完整符号的情况下,private symbols);注意:若程序被优化,这些值不一定对

kd         // 打印堆栈的地址

dds        //显示栈帧

10. 显示反汇编

u      //显示当前eip位置往后的8条指令

uf CTest::add    // 反汇编CTest类的add函数

uf /c main         // 反汇编main函数,通过/c可以查看main函数中的函数调用(call)都有哪些

ub 000c135d L20          // 查看地址为000c135d指令前的20条指令内容


11.  显示寄存器

r                // 显示所有寄存器信息及发生core所在的指令

r eax, edx     // 显示eax,edx寄存器信息

r eax=5, edx=6       // 对寄存器eax赋值为5,edx赋值为6


12. 显示内存

!address       // 查看进程的所有内存页属性

!address 7ffd8000       // 查看7ffd8000地址处内存页属性

dd /c 5 7c801e02      // 从7c801e02内存处开始以dword为单位显示内存(宽度为:5)

dd /c 5 7c801e02 L8    // 从7c801e02内存处开始以dword为单位显示内存(宽度为:5)【显示8个dword】

da /c 100 7c80ff03     // 从7c80ff03内存处开始显示Ascii字符串(宽度为:100)

du /c 100 7c8022f5     // 从7c8022f5内存处开始显示Unicode字符串(宽度为:100)

s -w 522e0000 L0x100  0x1212 0x2212 0x1234    // 表示在起始地址522e0000之后的0x100个单位内搜索0x1212 0x2212 0x1234系列的起始地址

s -u 522e0000 527d1000 "web"    //表示在522e0000 和527d1000之间搜索Unicode 字符串”web”

ea 0x445634 "abc"    // 表示在0x445634地址写入Ascii字符串abc, 不包含结束符0

eza 0x445634 "abc"    // 表示在0x445634地址写入Ascii字符串abc, 包含结束符0

eu 0x445634 "abc"   // 表示在0x445634地址写入Unicode字符串abc, 不包含结束符0

ezu 0x445634 "abc"    // 表示在0x445634地址写入Unicode字符串abc, 包含结束符0

ed nCounter 80      // 将变量nCounter的值修改为80(注:80为10进制还是16进制,还是其他,取决于当前进制)

.writemem D:\Test\0041a5e4.bin 0041a5e4 L0x1000   // 将内存地址处0x0041a5e4后面0x1000长度的内容拷贝存储到D:\Test\0041a5e4.bin中

13 查看堆

!heap -s     // 显示进程堆的个数(每一项是一个堆,也就是_HEAP结构指针,对应的API是HeapCreate)

dt _HEAP 00140000   // 选取一个堆的地址,打印该堆的内存结构

!heap -a 00140000   // 选取一个堆的地址,打印该堆的信息,比上面打印内存命令更详细直观

14. 虚拟内存

!vadump   // 查看虚拟内存布局

15. 查看句柄

!handle   // 查看所有句柄的ID

上一篇下一篇

猜你喜欢

热点阅读