Windows.用户态程序高效排错.2007.电子工业出版社(熊力)__笔记(杂)

ZC: 下面记录的页码编号(P.??)都是指 书的 页码,而非 PDF的页码 (书P.21 <--> Pdf.P.41)

1、P.32:SRV*D:\Symbols_Web*http://msdl.microsoft.com/download/symbols;C:\Symbols

    ZC: 各个 应该是使用 分号(";")隔开

    ZC: VC6编译的Release,默认设置下,未发现 pdb文件

    ZC: 应该把本地的目录写在前面:D:\XiongLi(被调试程序对应的symbol文件目录);C:\Symbols(本地系统symbol所在目录);SRV*D:\Symbols_Web*http://msdl.microsoft.com/download/symbols

      D:\XiongLi;C:\Symbols;SRV*D:\Symbols_Web*http://msdl.microsoft.com/download/symbols

  1.1、P.25: 命令g:让程序继续运行

  1.2、P.26: 让程序暂停接受检查:快捷键(Ctrl+Break)、菜单栏(Debug-->Break)

  1.3、ZC: 在 WinDBG--> File --> Symbol File Path ... 的对话框中,填入信息之后,"√"选 复选框"Reload",即可加载新设置的symbol 。(或者命令".reload"

  1.4、P.26: x命令 查找 函数二进制入口  (P.38)

    x exe名称不带后缀!函数名称

    ZC: 注意上面是 感叹号("!"),而非竖线("|") ! ! 且 感叹号 前面不能有空格,后面可以有空格

  1.5、P.26: 设置断点:bp 16进制地址(不带0x)

  1.6、P.27: 命令k:检查当前的callstack  (P.37)

  1.7、P.28: WinDBG--> Open --> Open Source File ...  (源代码级别的调试)

    ZC: 貌似 这里打开的源文件 不是 原来编译的工程里面的源代码文件 也是可以的(也就是说把 原来编译的工程里面的源代码文件 copy到另一个地方,再用WinDBG打开复制的源代码文件,WinDBG照样能够做好对应)

  1.8、P.29: 命令"bc 1":清除 第二个断点

    ZC: 显示所有断点的命令是什么?显示出来的断点的顺序就是设置的顺序吗?

  1.9、P.29: 命令dc:看目标内存(eax)上的数据是什么

    "dc eax"  ZC: 就是看 eax指向的内存地址的内容

  1.10、P.30: "!address" :"!address eax"  检查对应内存页的属性(P.35:显示内存页信息)

  1.11、P.31: VS中检查局部变量的值

 

2、P.32: WinDBG --> File --> Open Executable

    WinDBG --> File --> Attach to a Process

    Alt+1 (ZC: 这里是 数字"1",应该是 切换到 第一个命令窗口的意思)

  2.1、P.32: vertarget命令:显示当前进程的大致信息

    0:019> vertarget

    "0:019>"是命令提示符,019表示 当前线程ID。后面介绍切换线程的命令,到时候可以看到提示符的变化。

  2.2、P.33: "!peb":显示 Process Environment Block

  2.3、P.33: "lmvm 模块名":检查模块的加载信息("lmvm iexplore")(ZC: 第一个字符是 小写字母"l",还有一个命令"lm" 也是小写字母"l"。)

    ZC: 此时,是attach到ieplore进程上的,执行"lmvm explorer" 没有信息显示出来。个人感觉,应该只能显示 本进程中的有的模块的信息。

    显示出来的信息的第二行中的“(deferred)” 表示 目前并没有加载iexplore的模块信息

  2.4、P.33: "!sym"命令 让调试器在自动寻找symbol的时候给出详细的信息,比如搜索和下载的路径  (!sym noisy

  2.5、P.33: ".reload /f 模块名.后缀" :让调试器加载指定模块的 symbol (".reload /f iexplore.exe"

    执行".reload /f user32" 和".reload /f iexplore"时,遇到如下情况:(ZC: 貌似教程里面就是带 后缀的...没看仔细啊...)

0:019> .reload /f iexplore

"iexplore" was not found in the image list.
Debugger will attempt to load "iexplore" at given base 00000000.

Please provide the full image name, including the extension (i.e. kernel32.dll)
for more reliable results.Base address and size overrides can be given as
.reload <image.ext>=<base>,<size>.
Unable to add module at 00000000

    ZC: 根据WinDBG的说明,尝试了加上后缀的方式(".reload /f user32.dll"、".reload /f iexplore.exe") 就OK了

    ZC: 我也尝试了“.reload <image.ext>=<base>,<size>”的方式,“<base>”和“<size>”都是使用 lmvm 显示的信息("start"和"ImageSize"),貌似没有成功...

  2.6、P.34: "lmf" 列出当前进程中加载的所有模块

  2.7、P.34: r,d,e --> 寄存器,内存的 检查和修改

    r:显示和修改寄存器上的值

    d:显示内存地址上的值

    e:修改内存地址上的值

    2.7.1、"r":显示所有寄存器的值

      "r eax":显示寄存器eax的值

      "r eax=0":把 寄存器eax的值 修改为 0

    2.7.2、"d":ZC: 貌似是显示 eip所指向的内存,默认为 byte 格式(好像也不对,貌似不一定会显示哪里的内存...)

      "d esp":显示寄存器esp指向额内存,默认为 byte 格式

      "dd 03c0ffcc":直接指定 显示地址0x03c0ffcc处的内存。第二个d 表示用DWORD格式,还有 db(byte)、du(Unicode)、dc(char)等等。详细信息参考帮主文档中d命令的说明。(ZC: 有像CMD中一样 打个"?"就能显示参数说明明的功能吗?)

      P.35: "dd 03c0ffcc L4","L4"参数指定内存取件的长度,这里长度为4个DWORD。这样输出就只会有1行,而不是默认的8行。(ZC: 这个字母"L",大小写 都行)

    2.7.3、P.35: "ed 03c0ffcc 11112222":把 地址0x03c0ffcc上的值修改为 0x11112222

  2.8、P.36: "S": 搜索内存 (ZC: 貌似大小写一样)

    “s -u 0012ff40 L?80000000 "www.msdn.com"

      ZC: 为什么是从 0x0012ff40 开始查找?

      ZC: “L?80000000”里面的 问号("?")是什么意思?(貌似必须有这个问号,没有的话 会报错...)

  2.9、P.36: "!runaway":检查线程的CPU消耗

    显示每一个线程所耗费 usermode CPU 时间的统计信息

    P.36: "!runaway f":可以显示"User Mode Time"(用户态的 繁忙时间)、"Kernel Mode Time"(内核态的 繁忙时间)、"Elapsed Time"

      ZC: Elapsed:(时间)消逝,过去。"Elapsed Time" 可能是指 线程从创建到 命令"!runaway f"执行时 总共的时间

    ZC: 这应该是显示的是 正在调试的进程的所有线程的信息吧?不是系统中所有线程的信息吧?

  2.10、P.37: "~":切换线程。可以显示线程信息和在不同线程之间切换。

    "0:001>~0s":把当前线程掐换到0号线程,也就是主线程。切换后 命令提示符会变为"0:000"(原来是 "0:001")。

  2.11、P.37: k,kb,kp,kv,kn  检查 call stack

    k:显示当前线程的 call stack。

    k后面可以跟很多后缀(跟d命令一样),如 kb、kp、kn、kv、kL等。这些后缀控制了显示的格式和信息量。具体信息参考帮主文档和动手实践。

   结合 ~ 和 k 命令,来显示所有线程的 call stack。也可以直接使用 命令"~*k" 有同样的效果。

  2.12、P.38: "u":反汇编。把指定地址上的代码翻译成汇编输出。

    "u 7739d023"

    如果符号文件加载正确,可以用 命令uf 直接反汇编整个函数,比如 "uf user32!NtUserWaitMessage" 。

  2.13、P.38: "x":查找符号的二进制地址。

    有了符号文件,调试器就能查找源代码和该符号所处的二进制地址之间的映射。如果要找一个符号文件保存在什么二进制地址上,可以使用 x命令。

    "x msvcrt!printf"  --> 找函数入口地址

    0:019> x msvcrt!printf
    77c1186a msvcrt!printf = <no type information>

     上面的命令找到了 printf函数 的入口地址在 0x77c1186a

    "x ntdll!GlobalCounter" --> 找变量所在地址

      注意:符号对应的是 变量和变量所在的地址,并不是变量的值。

    0:019> x ntdll!globalCounter
    7c99e73c ntdll!GlobalCounter = <no type information>
    0:019> x ntdll!globalcounter
    7c99e73c ntdll!GlobalCounter = <no type information>
    0:019> x ntdll!GlobalCounter
    7c99e73c ntdll!GlobalCounter = <no type information>

    ZC: 即 0x7c99e73c 是 变量GlobalCounter的地址(应该可以理解成 &GlobalCounter)

    ZC: 看现象,这里查找变量 是 大小写不敏感的。(这里能找到的变量 应该是全局变量)(我们自己写的全局变量,如果有两个 是一样的名字 只是大小写不同,这里能够找到它们吗?能够区分它们吗?经测试,WinDBG会将它们全部列举打印出来)

    x命令 还支持通配符,如 "x ntdll!*" 列出ntdll模块中所有的符号,以及对应的二进制地址。

  2.14、P.38: "dds" 对应二进制地址的符号

    打印内存地址上的二进制值,同时自动搜索二进制对应的符号。

    "dds ebp":检查ebp指向的内存 --> 看看当前 stack中保存了哪些函数地址

    P.39: COM Interface 和 C++ Vtable 里面的成员函数都是顺序排列的,所以 dds命令 可以方便的找到虚函数表中的具体的函数地址。比如用下面的米宁可以找到OpaqueDataInfo类型中序函数对应的实际函数地址。

      (1)、首先用 x命令 找到 OpaqueDataInfo 虚函数表地址

        "x ole32! OpaqueDataInfo::`vftable'"  ZC: 注意"vftable"前面的那个符号 不是单引号(英文的/中文的都不是),是"~"下面的那个符号(主键盘区"!"/"1"的左侧)

        0:019> x ole32! OpaqueDataInfo::`vftable'
        769a697c ole32!OpaqueDataInfo::`vftable' = <no type information>
        769a69a0 ole32!OpaqueDataInfo::`vftable' = <no type information>

      (2)、dds命令 打印出虚函数表中的函数名字

        "dds 769a697c"

        "dds 769a69a0"

  2.15、P.40: 检查程序资料的小例子

3、

4、

5、

6、

 

posted @ 2017-12-25 13:47  DebugSkill  阅读(281)  评论(0编辑  收藏  举报