第一章:Windows调试支持
gushaow@mails.gscas.ac.cn
符号文件
安装Windows 2000 Customer Support-Diagnostic Tools光盘。如果是free build,运行/symbols/i386/retail/symbolsx.exe,如果是checked build,运行/symbols/i386/debug/symbolsx.exe。默认在%systemroot%/symbols目录下添加环境变量_NT_SYMBOL_PATH。DDK的核心驱动文档说,Symbols子目录必须被包括。但在平台SDK文档中,关于dbghelp.dll的符号路径有不同说法:库使用符号搜寻路径为.dll,.exe和.sys文件定位调试符号(.dbg文件),分别添加/symbols,/dll和/exe,/sys到路径。比如一般.dll文件的符号文件位于c:/mysymbols/symblos/dll。如果你设置了_NT_SYMBOL_PATH环境变量。搜寻路径如下:
1程序的当前工作目录
2_NT_SYMBOL_PATH环境变量
3_NT_ALT_SYMBOL_PATH环境变量
4 SYSTEMROOT环境变量
听起来_NT_SYMBOL_PATH应该设置成d:/winnt,而不是d:/winnt/symbols。事实上,两者都是可以的。
如果要用i386kd来检查crash dump文件,需要-z参数,比如快捷方式的目标为 /bin/i386kd.exe –z c:/winnt/memory.dmp
kd的扩展dll:kdextx86 userkdx dbghelp。可以在扩展命令前面加模块的名字。
最有用的十大调试参数:
u:反汇编机器码.
格式: u <from> 反汇编八条机器指令;u <from> <to>不包括<to>所指的机器指令;u 从上一次u命令停止的地方开始反汇编。u命令最令人感兴趣的地方在于它能够解析没有被目标模块导出的内部符号。
db,dw,dd:显示内存
参数和u命令一样,只不过<to>所指内容也被包括,如果没有参数,将显示128-byte。
x:检查符号
它能够创建已安装符号文件得到的符号列表。
1 x *!* 显示所有模块的符号列表。启动之后,只有ntoskrnl.exe的符号默认可用。
2 x <module>!<filter>显示<module>的符号文件中用<filter>过滤得到的符号列表。比如x nt!*,列出所有ntoskrnl.dbg中的符号。x win32k!*列出win32k.dbg中的符号。
3 x <filter>显示所有可用符号匹配<filter>表达式的部分。符号名和关联的虚拟地址都会显示。对于函数名,那是函数的入口地址。对于变量,那是指向基地址的指针。最重要的是,它的输出包括许多内部符号,不仅仅是可执行文件的输出表。
ln:列出最近的符号.
如果你需要许多符号的一个地址列表,ln命令可以用符号的名字或者地址察看单个符号。
l ln <address>显示给定地址附近的符号。
l ln<symbol>把给定的符号名字解析成虚拟地址,并且象ln <address>一样处理.
请注意,u,db,dw,dd可以接受符号(解析成地址)。
!processfields:列出EPROCESS成员(kdextx86.dll中的命令)
这个命令列出进程结构的所有偏移和成员
!threadfields:列出ETHREAD成员
!drivers:列出所有已经加载的驱动
在新版的debugging tools中已经不再支持,而是lm代替
!sel检查选择子的值。
如果没有参数,显示16个内存选择子。在新版debugging tools中,被内部命令dg代替。dg <from> <to>
调试接口
psapi.dll,imagehlp.dll,dbghelp.dll
psapi提供了14个查询系统信息的函数,包括驱动程序,进程,内存使用,进程模块,工作集,内存映射文件。
imagehlp和dbghelp,包括不同范围的任务。它们导出相似的函数集,imagehlp提供更多的函数,而dbghelp是可以重发布的组件。它们都包括很丰富的分析和操作PE文件的函数。它们的主要区别在于从符号文件中解析符号的能力.表1-1列出了两个dll所导出的函数。p51-53。
psapi.dll和imagehlp.dll可以完成如下任务
l 枚举所有的内核组件和驱动
EnumDeviceDrivers,GetDeviceDriverFileName
l 枚举系统当前管理的所有进程
EnumProcesses,OpenProcess
l 枚举加载到一个进程虚拟地址空间的所有模块
EnumProcessModules
l 枚举给定组件的所有符号,如果符号可用。
因为psapi.dll和imagehlp.dll函数不是标准Win32 API的一部分,所以在VC++工程中,它们的头文件和导入库不会自动包含。如果使用它们,需要如下四行语句:
#include<imagehlp.h>
#image<psapi.h>
#pragma comment(linker,"/defaultlib:imagehlp.lib")
#pragma comment(linker,"/defaultlib:psapi.lib")
w2k_sym.exe和w2k_dbg.dll使用了这两个dll。
在2k下HMODULE就是模块的基地址,在sdk头文件中,它被定义为HINSTANCE的别名,而后者是HANDLE类型.尽管如此,在严格意义上来说HMODULE不是句柄.句柄通常是系统维护的表格的索引,对象的属性从那里查找,每一个系统返回的句柄增加对象的句柄计数。对象实例在所有句柄被返回给系统之前无法从内存中移走。函数CloseHandle就是用于这个目的的。对应的本机函数是Ntciose ( ) 。关于HMODULES的要点在于它不需要关闭。SDK文档中GetModuleHandle ( )的评论部分指出多线程应用程序必须小心。因为一个线程可能卸载模块,使得另一个线程使用的HMODULE无效。
两种情况下HMODULE可以保持有效
1. 通过LoadLibrary ( ) or LoadLibraryEx ( )返回的HMODULE在进程调用FreeLibrary ( )之前有效 ,因为这些函数与模块参考计数有关,因此阻止了其它线程不可预料的卸载。
2. 一个从不同进程来的HMODULE有效,如果引用一个永久加载的模块。比如,所有的Windows 2000内核模块(不包括核心驱动程序)总是映射到不同进程固定的相同地址,在进程的生命周期中都有效。
不幸的是从psapi.dll函数EnumProcessModules返回的模块句柄不符合上面两种情形。所以只在调用的当时有效。这个和EnumDeviceDrivers,EnumProcesses返回的数组都是同样的问题。
EnumProcessModules函数比前几个好,因为它指示了还有多少字节missing,请注意list1-7中并没有包含增长缓存的循环。基本上,它调用,NtQueryinf ormationProcess ( ) 得到目标进程的PEB,然后从PEB获得模块信息表的指针。因为这些数据都在另一个进程中,所以需要调用ReadProcessMemory 去获得数据
调整进程特权
打开低ID进程需要更高权限。通过把自己声明为调试器可以获得更多权限。
调整权限的步骤:
1 调用advapi32.OpenProcessToken,打开进程令牌。
2 准备一个包含需要权限的TOKEN_PRIVILEGES结构。通常用advapi32.LookupPrivilegeValue。特权用名字说明,在winnt.h中定义了27个特权的名字和符号。比如,调试特权是SE_DEBUG_NAME,等价于字符串"SetDebugPrivilege"
3 调用advapi32.AdjustTokenPrivileges()
GetCurrentProcess返回一个伪句柄-1, GetCurrentThread也返回一个伪句柄-2。
微软符号信息通常包含前缀或者后缀。C语言产生的代码常常有下划线或@开头。@表示_fastcall函数,而下划线表示_stdcall和_cdecl函数。因为fastcall和stdcall预定把清除参数堆栈的任务留给了被调用函数,符号信息也包含了调用者放入堆栈的参数字节数。这个信息通过@分隔的十进制数方式附加于后面。全局变量和_cdecl函数一样对待。
symbol Undecorated symbol (might have been declared in an ASM module)
_symbol cdecl function or global variable
_symbol@N stdcall function with N argument bytes
@symbol@N fastcall function with N argument bytes
_imp_symbol import thunk of a cdecl function or variable
_imp_symbol@N import thunk of a stdcall function with N argument bytes_
_imp_@symbol@N import thunk of a fastcall function with N argument bytes
?symbol C++ symbol with embedded argument type information
__@@_PchSym_symbol PCH symbol
原书接下来还有很大部分是对微软调试文件格式的分析,没有耐心看下去了。