锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

读书笔记:调试软件 张银奎

时间:2023-06-23 05:07:00 2408连接器

版本     第一版 2021年02月06日 11:53:06 2021年3月9日22:22:25  windbg下载     x64,http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup/WinSDKDebuggingTools_amd64/dbg_amd64.msi     x86,http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup/WinSDKDebuggingTools/dbg_x86.msi  学习windbg时     使用帮助文档     可使用windbg调试windbg   第30章 WindDBG用法详解     30.0 概述         WinDBG支持多种调试服务             用户态调试             内核态调试             转储文件调试             远程调试         灵活性和扩展性都很好     30.1 工作空间         workspace         描述和存储,调试项目的属性、参数、调试设置等         分类             默认工作空间                 基本工作空间(base workspace),调试会话尚未建立                 默认的内核态工作空间(default kernel-mode workspace),开始内核调试,但未连接调试目标                 远程调试工作空间默认(remote default workspace),通过调试服务器(DbgSrv或KdSrv)远程调试                 特定处理器的工作空间(processor-specific workspace),开始内核调试并连接调试目标,了解对方处理器的类型                 默认用户态工作空间(default user-mode workspace),附加到过程中             命名的工作空间(显式工作空间,explicit)         包含的信息             调试会话状态                 断点、开源文件、自定义别名             调试器设置                 可执行图像文件路径的符号文件路径,源文件路径                 设置日志文件,内核调试连接设置                 打开使用文件对话框的设置             WinDBG图形界面信息         保存和打开工作空间             使用注册表保存配置                 路径,HKEY_CURRENT_USER\Software\Microsoft\WinDBG\Workspace                 子键表示类型,User,Kernel,Dump,Explicit             保存到文件         WinDBG,配置以增量的方式应用     30.2 命令概览         30.2.1 标准命令             基本调试功能             实现在WinDBG内部             分类(按相关对象分类)                 调试目标控制                     恢复执行,g系列                     跟踪执行,t系列,trace into                     单步执行,p系列,step over                     追踪监视,wt                 寄存器                     通用寄存器,r                     MSR寄存器,rdmsr,wtmsr                     设置显示掩码,rm                 IO端口                     ib,iw,id                     ob,ow,od                 内存                     查看,d                     编辑,e                     搜索,s                 栈,k系列                 断点                     设置,bp软件断点,ba硬件断点                     列举,bl                     控制,bc、bd、be,参数、禁用、启用                 线程,~,控制和显示                 进程,|,显示                 表达式评估                     ?,汇编                     ?,汇编                     ??,C                   汇编控制                     a,汇编                     u,反汇编                 段选择子,dg,显示                 命令文件,$,执行                 选项设置                     调试事件处理方法,sx                     禁用和启用静默模式,sq                     内核选项,so                     符号后缀,ss                 版本                     version,调试器和调试目标                     vertarget,调试目标所在系统                 符号,x,检查                 源程序,ls,控制和显示                 调试会话结束                     基本,q                     结束远程,qq                     调试会话结束,分离调试目标,qd                 其他                     ld,加载调试符号                     ln,搜索相邻符号                     lm,列举模块                 帮助,?                     B[C|D|E][] - clear/disable/enable breakpoint(s)                     BL - list breakpoints                     BA    - set processor breakpoint                     BP 
- set soft breakpoint D[type][] - dump memory DT [-n|y] [[mod!]name] [[-n|y]fields] [address] [-l list] [-a[]|c|i|o|r[#]|v] - dump using type information DV [] - dump local variables E[type]
[] - enter memory values G[H|N] [=
[
...]] - go K - stacktrace KP - stacktrace with source arguments LM[k|l|u|v] - list modules LN - list nearest symbols P [=] [] - step over Q - quit R [[ [= ]]] - view or set registers S[] - search memory SX [{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2"] [-h] {Exception|Event|*}] - event filter T [=
] [] - trace into U [] - unassemble version - show debuggee and debugger version X [<*|module>!]<*|symbol> - view symbols ?]<*|symbol> - view symbols ? - display expression ?? - display C expression $< - take input from a command file 30.2.2 元命令 meta-command,dot command 常用的调试功能 实现在WinDBG内部 分类(按相关对象分类) 显示和设置调试会话和调试器选项 符号选型,.symopt 符号路径,.sympath和symfix 源文件,.srcpath,.srcnoise,.srcfix 扩展命令模块路径,.extpath 匹配扩展命令,.extmatch 可执行文件,.exepath 反汇编,.asm 表达式评估器,.expr 调试会话和调试目标,控制 创建新进程,.create 附加旧进程,.attach 打开转储文件,.opendump 分离附加目标,.detach 杀掉进程,.kill 重新开始调试会话,.restart 放弃用户态调试目标(进程),.abandon 扩展命令模块,管理 加载,.load 卸载,.unload,.unloadall 显示,.chain 调试器日志文件,管理 新建打开,.logopen 追加打开,.logappend 打开状态,.logfile 关闭,.logclose 远程调试 远程调试客户端,remote.exe 启动,.remote 远程调试服务器,调试引擎服务器 启动服务器,.server 列举服务器,.servers 向服务器发送文件,.send_file 结束服务器,.endsrv 远程进程服务器 结束服务器,.endpsrv 调试器,控制 睡眠,.sleep 唤醒,.wake 启动新调试器,调试当前调试器,.dbgdbg 命令程序,编写 类似于C语言的关键字 .if, .else, .elif .foreach, .do, .while, .continue, .break .catch, .leave, .printf, .block 其他 产生转储文件,.dump 保存内存数据,.writemem 显示调试会话时间,.time 显示线程时间,.ttime 显示任务列表,.tlist 格式化数字,.formats 元命令帮助,.help . commands: .abandon - abandon the current process .allow_exec_cmds [0|1] - control execution commands .allow_image_mapping [0|1] - control on-demand image file mapping .apply_dbp [] - add current data breakpoint state to a register context .asm [] - set disassembly options .asm- [] - clear disassembly options .attach - attach to at next execution .block { } - brackets a set of commands for nested execution .bpsync [0|1] - special breakpoint behavior for multithreaded debuggees .break - break out of the enclosing loop .breakin - break into KD .cache [] - virtual memory cache control .call (, , ...) - run a function in the debuggee .catch { } - catch failures in commands .chain - list current extensions .childdbg <0|1> - turn child process debugging on or off .clients - list currently active clients .closehandle [] [] - close the given handle .continue - continue the enclosing loop .copysym [] - copy current symbol files to a directory .create - create a new process .createdir [] [] - control process creation options .cxr
- dump context record at specified address k* after this gives cxr stack .dbgdbg - attach a debugger to the current debugger .debug_sw_wow [0|1] - allow interaction with software WOW emulation .detach - detach from the current process/dump .dml_file - output DML content from file .dml_flow - show basic block code flow .dml_start [] - navigable overview of debugger activities .do { } () - execute until is zero .drivers - This command was removed -- use 'lm' or .reload -l) .dump [] - create a dump file on the host system .dvalloc [] - VirtualAlloc memory in the debuggee .dvfree [] - VirtualFree memory in the debuggee .echo [""|] - echo string .echotime - output debugger time .echotimestamps [0|1] - toggle timestamp output on events .ecxr - dump context record for current exception .effmach [] - change current machine type .else { } - if/then/else conditional execution .elsif () { } [] - if/then/else conditional execution .enable_long_status [0|1] - dump LONG types in default base .enable_unicode [0|1] - dump USHORT array/pointers and unicode strings .endsrv - disable the given engine server .endpsrv - cause the current session's remote server to exit .enumtag - enumerate available tagged data .event_code - display cached event instructions .eventlog - display log of recent events .events - display and select available events .eventstr - display any event strings registered by debuggee .exepath [[;...]] - set executable search path .exepath+ [[;...]] - append executable search path .expr - control expression evaluator .exptr
- do .exr and .cxr for EXCEPTION_POINTERS .exr
- dump exception record at specified address .extmatch [] - display all extensions matching pattern .extpath [[;...]] - set extension search path .extpath+ [[;...]] - append extension search path .f+ - set current stack frame to caller of current frame .f- - set current stack frame to callee of current frame .fiber
- sets context of fiber at address resets context if no address specified .fiximports - attempts to link imports for images .fnent
- dump function entry for the given code address .fnret [] - display formatted return value .for ( ; ; ) { } - execute and until is zero .force_radix_output [0|1] - dump integer types in default base .force_system_init [] - force pending systems to initialize if possible .force_tb - forcibly allow branch tracing .foreach [opts] ( { } ) { } - execute for each token in the output of .fpo - control override FPO information .frame [] - set current stack frame for locals .formats - displays expression result in many formats .help [] - display this help .holdmem [range] - hold and compare memory data .if () { } [] - if/then/else conditional execution .ignore_missing_pages [0|1] - control kernel summary dump missing page error message .imgscan - scan memory for PE images .jdinfo - interpret AeDebug information .kframes - set default stack trace depth .kill - kill the current process .lastevent - display the last event that occurred .leave - exit the enclosing .catch .lines - toggle line symbol loading .load - add this extension DLL to the extension chain .loadby - add the extension DLL in the module directory to the extension chain .locale [] - set the current locale .logfile - display log status .logopen [] - open new log file .logappend [] - append to log file .logclose - close log file .netsyms [0|1] - allow/disallow net symbol paths .netuse [] - manage net connections .noshell - disable shell commands .noversion - disable extension version checking .ofilter - filter debuggee output against the given pattern .ocommand - treat output with the given prefix as a command .opendump - open a dump file .outmask - set bits in the current output mask .outmask- - clear bits in the current output mask .pcmd [] - control per-prompt command .pop [] - pop state .prefer_dml [0|1] - control DML mode default .printf "", - formatted output .process [
] - sets implicit process resets default if no address specified .process_info - display security related information of current process .prompt_allow [] - control what information can be displayed at the prompt .push [] - push state .quit_lock [] - locks session against unexpected quit .readmem - read raw memory from a file .record_branches [0|1] - controls recording of processor branching .reload [[=
,]] - reload symbols .restart - request a session restart .remote - start remote.exe server .secure [0|1] - disallow operations dangerous for the host .send_file - send files to remote server .server - start engine server .servers - list active remoting servers .setdll - debugger will search for extensions in this DLL first .shell [] - execute shell command .show_read_failures [] - control extra read failure output .show_sym_failures [] - control extra symbol failure output .sleep - debugger sleeps for given duration useful for allowing access to a machine that's broken in on an ntsd -d .srcfix [] - fix source search path .srcfix+ [] - append fixed source search path .srcnoisy [0|1] - control verbose source loading output .srcpath [[;...]] - set source search path .srcpath+ [[;...]] - append source search path .step_filter [] ["[;...]"] - Set symbol patterns to skip when stepping .symfix [] - fix symbol search path .symfix+ [] - append fixed symbol search path .symopt - set symbol options .symopt+ - set symbol options .symopt- - clear symbol options .sympath [[;...]] - set symbol search path .sympath+ [[;...]] - append symbol search path .thread [
] - sets context of thread at address resets default context if no address specified .time - displays session time information .timezone - display timezone information .ttime - displays thread time information .tlist - list running processes .typeopt - set/clear type options .unload - remove this extension DLL from the list of extension DLLs .unloadall - remove all extension DLLs from the list of extensions DLLs .wake - wake up a .sleep'ing debugger .while () { } - execute while is non-zero .writemem - write raw memory to a file Use ".hh " or open debugger.chm in the debuggers directory to get detailed documentation on a command. 30.2.3 扩展命令 extension command 语法,![extension_module].extension_command [parameters] 省略extension_module,则自动搜索 特殊调试功能,针对特殊调试目标 实现在动态链接库(DLL)中 利用WinDBG的SDK,编写扩展模块和扩展命令 WinDBG程序包中,包含了常用的扩展命令模块 NT4CHK目录,调试目标为Windows NT 4.0 Checked版本时的扩展命令模块 NT4FRE目录,调试目标为Windows NT 4.0 Free版本时的扩展命令模块 W2KCHK目录,调试目标为Windows 2000 Checked版本时的扩展命令模块 W2KFRE目录,调试目标为Windows 2000 Free版本时的扩展命令模块 WINXP目录,调试目标为Windows XP或者更高版本时的扩展命令模块 acpikd.dll,用于ACPI调试,追踪调用ASL程序的过程,显示ACPI对象 exts.dll,关于堆(!heap),进程/线程结构(!teb/!peb),安全信息(!token,!sid,!acl),应用程序验证(!avrf)等 kdexts.dll,用于调试内核 fltkd.dll,用于调试过滤驱动程序(FsFilter) minipkd.dll,用于调试AIC78xx小端口(miniport)驱动程序 ndiskd.dll,用于调试网络有关驱动程序 ntsdexts.dll,实现了!handle,!locks,!dp,!dreg rpcexts.dll,用于RPC调试 scsikd.dll,用于调试SCSI有关的驱动程序 traceprt.dll,用于格式化ETW信息 vdmexts.dll,调试运行在VDM中的DOS程序和WOW程序 wow64exts.dll,调试运行在64位Windows中的32位程序 wmitrace.dll,显示WMI追踪有关的数据结构、缓冲区和日志文件 WINEXT目录,适用于所有Windows版本的扩展命令模块 ext.dll,适用于所有调试目标的常用扩展命令 kext.dll,适用于内核态调试的常用扩展命令 uext.dll,适用于用户态调试的常用扩展命令 logexts.dll,用于监视和记录API调用 sos.dll,用于调试托管代码和.Net程序 ks.dll,用于调试内核流(kernel stream) wdfkd.dll,调试使用WDF(Windows Driver Foundation)编写的驱动程序 扩展模块的加载 自动加载 当调试目标被激活时,WinDBG会根据以下条件自动加载命令空间中指定的扩展模块 调试目标的类型 当前的工作空间 完整语法方式 !extension_module.extension_command 自动搜索和加载 手动加载 .load 模块完整路径 .load 模块名称,会在扩展模块搜索路径(EXTPATH)中寻找 .loadby target_module refer_module 在已加载模块(refer_module)所在目录,搜索和加载target_module 列举已经加载的扩展模块 .chain 扩展模块的卸载 .unload .unloadall 查询模块信息 !extension_module.help 30.3 用户界面 30.3.1 窗口概述 框架窗口(Frame Window) 菜单和工具栏 工作窗口 Command,命令输入和显示结果 Watch,观察指定变量 Locals,观察局部变量 Registers,观察寄存器 Memory,观察内存 CallStack,观察调用栈 Disassembly,反汇编 ScratchPad,白板,做调试笔记 ProcessesAndThreads,观察进程和线程 CommandBrowser,执行和浏览命令 状态栏 30.3.2 命令窗口 组成 信息显示区 命令横条 命令提示符,命令编辑框 信息显示区 展示的信息包含 命令执行结果 调试事件 错误信息 调试引擎的提示信息 命令横条 未连接调试目标时 命令提示符,空 命令编辑框,Debuggee not connected 等待命令输入时 命令提示符,调试目标描述> 用户态目标 [||system_index:]process_index:thread_index> 内核态目标或内核态转储文件目标 [||system_index:][processor_index:]kd> 本地内核态调试 [||system_index:][processor_index:]lkd> 其中 system_index 同一Windows中多个用户态目标,同属于一个系统 每个内核目标,独属于一个系统 process_index 线程序号,始于0 processor_index 处理器序号,始于0 线程序号和处理器序号,统一编号 每个内核态目标,被分配一个进程序号 切换 系统 ||system_index s 进程或处理器 |process_or_processor_index s 自动切换系统 线程 ~thread_index s 只能在统一系统内切换 调试目标繁忙 命令提示符,*BUSY* 命令编辑框,Debuggee is running WinDBG执行命令繁忙 命令提示符,*BUSY* 命令编辑框,空 执行.abandon放弃调试目标 命令提示符,NoTarget> 命令编辑框,空 等待用户输入 命令提示符,Input> 命令编辑框,空 30.4 输入和执行命令 30.4.1 要点 命令分隔符,; 重复命令,回车键 历史命令,方向键 终止命令,Ctrl+Break 使用KD或CDB时,使用Ctrl+C 详细输出模式切换,Ctrl+Alt+V 显示WinDBG与内核调试引擎之间的数据通信,Ctrl+Alt+D 帮助,F1或.hh command 30.4.2 表达式 参考 帮助文档,MASM Numbers and Operators 语言 ?宏汇编语法 ??C++表达式 运算符 基本,加减乘除、移位、求余、比较、位操作、正负号 特殊 hi或low,取得32位数的高16位或低16位 by或wo或dwo或qwo,从指定地址读数单字节或单字或双字或四字 poi,从指定地址读数指针长度 类函数运算符 $iment(Address),返回参数代表模块的入口地址 $scmp("String1", "String2"),比较字符串 $sicmp("String1", "String2"),比较字符串,忽略大小写 $spat("String", "Pattern"),判断字符串符合模式 $vvalid(Address, Length),判断有效内存区 $fnsucc(FnAddress, RetVal, Flag),判断函数执行成功 注释 可被记到日志中 *之后皆注释 *中间皆注释; 30.4.3 伪寄存器 参考 帮助文档,Pseudo-Register Syntax WinDGB定义 Pseudo-register Description $ea The effective address of the last instruction that was executed. If this instruction does not have an effective address, the debugger displays "Bad register error". If this instruction has two effective addresses, the debugger displays the first address. $ea2 The second effective address of the last instruction that was executed. If this instruction does not have two effective addresses, the debugger displays "Bad register error". $exp The last expression that was evaluated. $ra The return address that is currently on the stack. This address is especially useful in execution commands. For example, g @$ra continues until the return address is found (although gu (Go Up) is a more precise effective way of "stepping out" of the current function). $ip The instruction pointer register. x86-based processors: The same as eip. Itanium-based processors: Related to iip. (For more information, see the note following this table.) x64-based processors: The same as rip. $eventip The instruction pointer at the time of the current event. This pointer typically matches $ip, unless you switched threads or manually changed the value of the instruction pointer. $previp The instruction pointer at the time of the previous event. (Breaking into the debugger counts as an event.) $relip An instruction pointer that is related to the current event. When you are branch tracing, this pointer is the pointer to the branch source. $scopeip The instruction pointer for the current local context (also known as the scope). $exentry The address of the entry point of the first executable of the current process. $retreg The primary return value register. x86-based processors: The same as eax. Itanium-based processors: The same as ret0. x64-based processors: The same as rax. $retreg64 The primary return value register, in 64-bit format. x86 processor: The same as the edx:eax pair. $csp The current call stack pointer. This pointer is the register that is most representative of call stack depth. x86-based processors: The same as esp. Itanium-based processors: The same as bsp. x64-based processors: The same as rsp. $p The value that the last d* (Display Memory) command printed. $proc The address of the current process (that is, the address of the EPROCESS block). $thread The address of the current thread. In kernel-mode debugging, this address is the address of the ETHREAD block. In user-mode debugging, this address is the address of the thread environment block (TEB). $peb The address of the process environment block (PEB) of the current process. $teb The address of the thread environment block (TEB) of the current thread. $tpid The process ID (PID) for the process that owns the current thread. $tid The thread ID for the current thread. $bpNumber The address of the corresponding breakpoint. For example, $bp3 (or $bp03) refers to the breakpoint whose breakpoint ID is 3. Number is always a decimal number. If no breakpoint has an ID of Number, $bpNumber evaluates to zero. For more information about breakpoints, see Using Breakpoints. $frame The current frame index. This index is the same frame number that the .frame (Set Local Context) command uses. $dbgtime The current time, according to the computer that the debugger is running on. $callret The return value of the last function that .call (Call Function) called or that is used in an .fnret /s command. The data type of $callret is the data type of this return value. $lastclrex Managed debugging only: The address of the last-encountered common language runtime (CLR) exception object. $ptrsize The size of a pointer. In kernel mode, this size is the pointer size on the target computer. $pagesize The number of bytes in one page of memory. In kernel mode, this size is the page size on the target computer. 用户定义 用户定义的伪寄存器(user-defined pseudo-register) 名称,$t0~$t19 初始值为0,可保存任意整数值 30.4.4 别名 分类 用户定义别名(user-named alias) as new_name old_name 固定名称别名(fixed-name alias) 引用,$u<0~9> 修改,r $.u<0~9>=old_name 自动定义别名(automatic alias) Alias name Alias equivalent $ntnsym 内核态下为nt,用户态下为ntdll $ntwsym ntdll32,ntdll $ntsym 与当前调试目标的机器模型匹配的NT模块名称 $CurrentDumpFile 转储文件名称 $CurrentDumpPath 转出文件路径 $CurrentDumpArchiveFile 最近加载的CAB文件名称 $CurrentDumpArchivePath 最近加载的CAB文件路径 查看别名的取值 .echo 别名引用的形式 宽度,适合固定名称别名 空格,适合所有 分隔符,${alias},适合用户定义别名和自动定义别名 30.4.5 循环和分支 z命令 语法,z(condition) 功能,condition不为0和false,则重新执行命令 例子 r ecx=2 r ecx=ecx-1; r ecx; z(ecx), r ecx=ecx+1 !for_each_XXX命令 !for_each_frame !for_each_local dt @#Local 打印每个栈帧中的每个局部变量 j命令 j expression command1; command2 j expression 'commands1'; 'commands2' .if.elif.else .if (expression) {commands1} .elif (expression) {commands2} .else {commands3} 30.4.6 进程和线程限定符 条件 进程 线程 当前 |. ~. 导致当前调试事件 |# ~# 当前系统所有 |* ~* 序号 |Number ~number ID |~ID ~~ID 30.4.7 记录到文件 .logopen,打开日志文件 .logfile,查看日志文件状态 .logclose,关闭日志文件 30.5 建立调试会话 30.5.1 附加到已有进程 菜单方式 File > Attach a Process 设置为JIT调试器 WinDBG.exe -I 当程序崩溃后,在错误对话框中选择Debug,便会启动WinDBG并附加 命令行方式 WinDBG.exe -p PID WinDBG.exe -pn name windbg的命令行选项 帮助文档中搜索,WinDbg Command-Line Options windbg [ -server ServerTransport | -remote ClientTransport ] [-lsrcpath ] [ -premote SmartClientTransport ] [-?] [-ee {masm|c++}] [-clines lines] [-b] [-d] [-aExtension] [-e Event] [-failinc] [-g] [-G] [-hd] [-j] [-n] [-noshell] [-o] [-Q | -QY] [-QS | -QSY] [-robp] [-secure] [-ses] [-sdce] [-sicv] [-sins] [-snc] [-snul] [-sup] [-sflags 0xNumber] [-T Title] [-v] [-log{o|a} LogFile] [-noinh] [-i ImagePath] [-y SymbolPath] [-srcpath SourcePath] [-k [ConnectType] | -kl | -kx ExdiOptions] [-c "command"] [-pb] [-pd] [-pe] [-pr] [-pt Seconds] [-pv] [-W Workspace] [-WF Filename] [-WX] [-zp PageFile] [ -p PID | -pn Name | -psn ServiceName | -z DumpFile | executable ] windbg -I[S] windbg -IU KeyString windbg -IA[S] .attach 需要已经有一个调试会话 常用于同时调试多个目标时 被.abandon抛弃的被调试进程,可以重新附加 WinDBG.exe -pe -p PID 30.5.2 创建进程并调试 菜单方式 File > Open Executable 命令行方式 windbg executable .create 需要已经有一个调试会话 常用于同时调试多个目标时 30.5.3 非侵入式调试 调试用户态进程的一种特殊方式 windbg与目标进程,没有真正建立调试与被调试的关系,不能接收到任何调试事件 不能使用控制调试目标执行的命令,如单步、继续等 只能使用行观目标进程的命令 好处 减少调试器对目标进程的干预,最大程度减少海森伯效应 不影响其他调试器附加到目标进程进行调试 方式 只能用于附加方式 菜单方式 复选Noninvasive 命令行方式 WinDBG.exe -pv PID .attach 加上-v开光 JIT不支持该方式 用途 Windows NT和Windows 2000不支持调试器和调试目标分离(detach) 一旦建立调试关系,结束调试会话将会结束调试进程 若使用非侵入方式附加调试,分析结束时只需执行分离命令,即可恢复 30.5.4 双机内核调试 步骤 1. 选择通信方式 串口方式,兼容性好,可靠性高 1394端口,速度快但不稳定 USB2 2. 启用目标系统的内核调试引擎 Vista之前的系统,修改boot.ini Vista之后的系统,使用BCDEdit工具修改启动选项 3. 启动调试会话 菜单方式 File > Kernel Debug 命令行方式 windbg -k com:port=Com1, baud=115200 4. 后续 windbg显示"Waiting to reconnect..."并进入等待状态 等待目标系统的调试数据 并按照一定时间间隔(10s)发送复位数据包(PACKET_TYPE_KD_RESET) 目标系统在启动早期,初始化内核调试引擎时,会向调试器发送信息 windbg收到信息后,开始与目标系统对话,并建立调试连接 30.5.5 本地内核调试 系统条件 Windows 2000或更早的系统,不支持 Windows XP没有要求 Windows Vista,需要以调试选项启动系统 启动方式 菜单 File > Kernel Debug > Local 命令行 windbg -kl .attach -k 需要已经有一个调试会话 常用于同时调试多个目标时 30.5.6 调试转储文件 菜单 File > Open Crash Dump 命令行 windbg -z .opendump 需要已经有一个调试会话 常用于同时调试多个目标时 30.5.7 远程调试 本质,本地调试+远程通信 实现方式 方式一 服务器 DbgSrv(远程用户态调试) KdSrv(远程内核态调试) 客户端 windbg 方式二(使用) 服务器和客户端,都是windbg 启动服务器 命令行方式 windbg -server 服务器通信字符串 命令方式 建立调试会话 .server 服务器通信字符串 服务器通信字符串 npipe:pipe=pipe_name tcp:port=port_number,password=password 启动客户端 命令行方式 windbg -remote 客户端通信字符串 菜单方式 File > Connect to Remote Session 输入客户端通信字符串或直接浏览 客户端通信字符串 npipe:server=pc_name,pipe=pipe_name tcp:server=pc_name,port=port_number,password=password 30.6 终止调试会话 30.6.1 停止调试 方式 菜单 debug > stop debugging 命令 q 结果 windbg 恢复到赋闲(dormant)状态 调试目标 活动的用户态目标,被终止 活动的内核目标,保持被中断到调试器的状态,可重新与其建立连接 30.6.2 分离调试目标 目的,使调试目标继续运行 方式 菜单 debug > detach debuggee 命令 .detach 结果 windbg 没有其他调试目标时,则恢复到赋闲(dormant)状态 调试目标继续运行 对于进程,系统会修改进程属性,使其脱离被调试状态而成为普通进程 条件 Windows XP或更高版本 依赖于Windows XP才引入的操作系统支持(DebugSetProcessKillOnExit API) 30.6.3 抛弃被调试进程 目的,重新附加调试目标 方式 命令 .abandon 结果 windbg 没有其他调试目标时,则恢复到无调试目标状态 被调试进程 被抛弃后,仍处于挂起状态 调试器中仅执行了注销操作,没有恢复进程状态 重新附加 windbg -pe -p PID 注意 没有-pe,调试器附加失败,并报告DebugPort不为空 有了-pe,调试器不会报错,调试器引擎会产生一个异常,触发调试器进入命令模式,使继续调试 30.6.4 杀死被调试进程 方式 命令 .kill,会调用系统TerminateProcess API来终止进程 结果 windbg 仍可观察调试目标的数据 执行g时,会结束当前调试会话 没有其他调试目标时,则恢复到赋闲(dormant)状态 被调试进程 被终止 30.6.5 调试器终止或僵死 调试器终止 建立的调试会话会被终止 活动的被调试进程,被终止 调试器僵死 可使用-pe -p PID启动windbg,重新附加被调试进程,后终止僵死的调试器 30.6.6 重新开始调试 方式 菜单 debug > restart 命令 .restart 结果 对于调试会话源于"创建进程并调试",关闭被调试进程并重新运行和调试 对于调试会话源于"附加到已有进程",不支持 对于内核态调试 .restart,重启调试器后再建立调试连接 .reboot,目标系统重启 30.7 理解上下文 30.7.0 概述 上下文,操作的执行环境,讨论的背景信息 30.7.1 登录会话上下文(Login Session Context) 含义,登录会话语境,当前操作或陈述的 Windows支持同时多个登录对话,每个对话拥有自身的输入输出设备和桌面 例子 Windows XP系统中,一般只有一个会话,被远程桌面登录后就会有两个 Windows Vista引入对话隔离技术(Session Isolation),所有系统服务运行在会话0以增强系统服务安全性,故至少存在两个会话 目前会话上下文仅在内核调试时有意义,相关扩展命令仅在调试内核目标时有意义 !session !session,显示状态 !session -s index,切换 改变会话后,默认进程会变成新会话中的进程,以前缓存的用户空间数据不再有效 为了避免用户观察到错误的数据,可使用.cache命令在缓存选项中加入forcedecodeuser或forcedecodeptes选项禁止缓存功能,让调试器每次都重新读取内存数据 !spross,列出会话中所有进程 进程的EPROCESS结构的Session字段记录着进程的所属会话 每个会话都包含了Windows子系统服务器进程(CSRSS) 会话管理器不属于任一会话 30.7.2 进程上下文 含义,进程语境,当前操作或陈述的 在Windows操作系统中 所有进程的内核空间是共享的,用户空间是独立的 在32系统中,单个进程共4GB进程空间,低2GB是用户空间,高2GB是内核空间 在内核调试时 观察内核数据,不需要关心当前进程 观察用户空间数据,需要注意当前进程,同一用户态地址对不同进程的含义不同(实际的物理地址不同) 当调试目标中断到调试器中后,WinDBG会根据调试事件设置默认进程 若要观察其他进程的用户空间,需要先切换进程上下文 .process process_EPROCESS_address,根据进程的EPROCESS结构切换进程 .process 0 0,列出所有进程的基本信息 .context 设置和显示页目录基址(base of page directory)(用于翻译用户态地址) 页目录基址是进程的一个重要属性,使用.process设置进程上下文时自动设置 对于x86系统,cr3寄存器存放页目录基址,一个进程只有一个页目录基址 对于安腾系统,一个进程可使用多个页目录基址 .process和.context仅用在内核调试中 调试用户态目标时 所有虚地址都是基于当前进程的,不需要切换进程上下文 在一个调试会话中调试多个用户态目标时,应使用"lNumber s"切换进程 30.7.3 寄存器上下文(register context) 含义,寄存器语境,当前操作或陈述的 在多任务系统中 CPU寄存器保存的是当前正在执行的线程的寄存器值 对于没执行的线程,其寄存器值保存在内存中,当线程恢复执行时,寄存器值从内存加载到寄存器中 在调试器中观察一个线程的寄存器(不含MSR)时,该线程处于挂起状态,观察和修改的寄存器值源于内存 系统会在以下情况中,将寄存器值保存到当前线程的上下文记录(context record)中 线程切换时,该上下文常被称为线程上下文 中断或异常时,该上下文常被称为异常上下文 .thread .thread thread_ETHREAD_address,根据线程的ETHREAD结构切换线程 .thread,查看当前线程 .process process_EPROCESS_address f 列出一个进程的所有线程 .crx或.thread 将线程上下文恢复成以前的情况 .ecrx 在调试用户态转储文件时,可将其中保存的异常上下文设置为寄存器上下文 在不同寄存器上下文中,观察到的寄存器和栈不同 r kv 30.7.4 局部(变量)上下文(local context) 含义,局部变量语境,当前操作或陈述的 一个运行中的函数,对应一个局部上下文 运行中的函数,其局部变量信息存放在调用栈中 使用栈帧号代表局部上下文 .frame .frame,观察当前局部上下文 .frame frame_index(十六进制),切换当前局部上下文到指定栈帧 dv,查看当前局部上下文中的参数和局部变量 例子 源码 void test_windbg(int a) { int b = 2; getchar(); } int main() { test_windbg(1); return 0; } 启动 windbg -g .\Test.exe 线程查看和切换 ~* 查看所有线程 ~0 s 切换到0号线程 ~. 查看当前线程 栈帧查看和切换 k .frame .frame a 查看函数参数和局部变量 dv 30.7.5 上下文的关系 操作或陈述核心,作为操作或陈述的主体 操作或陈述语境,作为操作或陈述的客体 两者是多对多或一对多的关系,两者的组合整体作为新的上一层次的可标识实体(操作或陈述核心) 关系 会话进程 会话上下文 进程 进程上下文 线程(多个) 线程上下文 寄存器上下文 调用栈 局部(变量)上下文(多个) 线程变量 CPU时间片 30.8 调试符号 30.8.1 重要意义 调试符号(debug symbols) 其有无和版本是否准确,严重影响调试器的工作 30.8.2 符号搜索路径 背景 一个调试目标,可能存在多个符号文件,且不在同一位置 需要告诉调试器多个目录并按一定顺序搜索符号文件 符号搜索路径 符号文件搜索路径的列表 多个路径使用分号分隔 简称符号路径(symbol path) 路径种类 文件系统路径 符号服务器 设置方法 符号环境变量 _NT_SYMBOL_PATH _NT_ALT_SYMBOL_PATH 命令行参数,-y .sympath命令,增删显示 .symfix命令,自动设置 菜单,File>Symbol File Path 显示,.sympath命令 30.8.3 符号服务器 背景 一个调试目标,可能存在多个模块,一个模块可能包含多个版本,每个版本对应一个符号文件 这项符号文件查询工作,无聊和繁琐,可以交给程序完成 符号服务器(symbol server),存储符号文件的文件服务器 可以从中获取指定特征(名称和版本)的符号文件 符号服务器架构 示意图 windbg.exe V DbgEng.dll V DbgHelp.dll V 符号服务器Dll(SymSrv.dll) | |------------> 下游符号库 |----(网络)--> 中央符号库(centralized store)(符号服务器) DbgHelp.dll Windows操作系统的调试辅助库模块 windbg通过它,读取和解析调试符号 符号服务器Dll 符号服务器的本地模块 负责从符号服务器查找、下载和管理符号文件 具体dll不固定,只要实现了DbgHelp.dll依赖的符号服务器API windbg开发工具包中DbgHelp帮助文档(sdk\help\dbghelp.chm),描述了符号服务器API 用户可以自己实现符号服务器dll windbg工具包中包含了一个符号服务器(SymSrv.dll) 下游符号库(downstream store) 用于缓存从符号服务器下载的符号文件 工作流程 DbgHelp请求符号服务器Dll,获取指定符号文件 符号服务器Dll先在下游符号库查找,失败后在中央符号库查找 路径表示 完整表示 symsrv*ServerDll*[DownstreamStore*]ServerPath 基于SymSrv.dll的表示 symsrv*SymSrv.dll*[DownstreamStore*]ServerPath 简写为srv*[DownstreamStore*]ServerPath 30.8.4 加载符号文件 设置符号路径 .sympath srv*D:\Symbols*http://msdl.microsoft.com/download/symbols 调试windbg的.reload命令 Child-SP RetAddr Call Site 00000000`0675af58 00007ff9`326b8ba3 ntdll!ZwWaitForSingleObject+0x14 00000000`0675af60 00007ff9`20e34af4 KERNELBASE!WaitForSingleObjectEx+0x93 00000000`0675b000 00007ff9`20e2f737 WININET!InternetFindNextFileW+0xe9d4 00000000`0675b030 00007ff9`20dc69bc WININET!InternetFindNextFileW+0x9617 00000000`0675b060 00007ff9`20d1f069 WININET!UrlCacheServer+0x2cb7c 00000000`0675b1f0 00000000`678b80d2 WININET!InternetReadFile+0xd9 00000000`0675b290 00000000`678b2040 symsrv!EulaDlgProc+0x1742 00000000`0675b2c0 00000000`678b15d1 symsrv!RunDllEntry+0x8d00 00000000`0675b570 00000000`678a6a50 symsrv!RunDllEntry+0x8291 00000000`0675b5c0 00000000`678a7d05 symsrv+0x6a50 00000000`0675b7e0 00000000`678a7a66 symsrv!SymbolServerByIndexW+0x185 00000000`0675be80 00000000`67daffd8 symsrv!SymbolServerW+0xc6 00000000`0675c0f0 00000000`67d9591a dbghelp!SymGetFileLineOffsets64+0x1248 00000000`0675c980 00000000`67d96d75 dbghelp+0x2591a 00000000`0675d6d0 00000000`67dc5234 dbghelp+0x26d75 00000000`0675d9e0 00000000`67dc2ee6 dbghelp!ImagehlpApiVersionEx+0x28b4 00000000`0675dc70 00000000`67dc2add dbghelp!ImagehlpApiVersionEx+0x566 00000000`0675e180 00000000`67db7011 dbghelp!ImagehlpApiVersionEx+0x15d 00000000`0675e1c0 00000000`68200484 dbghelp!SymSetScopeFromAddr+0x81 00000000`0675e200 00000000`680aba61 dbgeng!DebugCreate+0x1a1274 00000000`0675e240 00000000`680af90e dbgeng!DebugCreate+0x4c851 00000000`0675e270 00000000`68159441 dbgeng!DebugCreate+0x506fe 00000000`0675e2b0 00000000`6815aae0 dbgeng!DebugCreate+0xfa231 00000000`0675e3c0 00000000`68067134 dbgeng!DebugCreate+0xfb8d0 00000000`0675e410 00000000`68067420 dbgeng!DebugCreate+0x7f24 00000000`0675e8d0 00007ff7`9c433beb dbgeng!DebugCreate+0x8210 00000000`0675e930 00007ff7`9c4342eb windbg+0x33beb 00000000`0675ea70 00007ff7`9c436d35 windbg+0x342eb 00000000`0675fae0 00007ff9`34427bd4 windbg+0x36d35 00000000`0675fb20 00007ff9`3520ce71 KERNEL32!BaseThreadInitThunk+0x14 00000000`0675fb50 00000000`00000000 ntdll!RtlUserThreadStart+0x21 SymbolServer函数 符号服务器API 功能,向服务器请求指定的符号文件,返回文件的完整路径 典型实现 在下游符号库中查找符号文件 找到,则返回完整路径 未找到,则进行远程查找 若找到,则下载到下游符号库中,后返回完整路径 函数原型 BOOL CALLBACK SymbolServer( [in] LPCSTR params, [in] LPCSTR filename, [in] PVOID id, [in] DWORD two, [in] DWORD three, [out] LPSTR path ); params 符号服务器参数信息 DownstreamStore和ServerPath filename 符号文件名 id 符号文件第一标识信息 .dbg和pe文件(.exe和.dll) PE文件头定义的映像时间戳(TimeDateStamp) .pdb PDB签名 two 符号文件第二标识信息 .dbg和pe文件(.exe和.dll) PE文件头定义的映像文件大小()SizeOfImage .pdb PDB年龄(Age) three 符号文件第三标识信息 .dbg和pe文件(.exe和.dll)和.pdb 未使用为0 path 符号文件的完整路径 最大长度为MAX_PATH 流程 使用文件特征标识,调用SymbolServerGetIndexStringW函数,生成索引串 文件特征标识的唯一性序列化 调用SymbolServerByIndexW函数,获取文件名和索引串指定的符号文件 调用cascade函数 调用StoreUNC函数,在下游符号库中查找 使用StoreWinInet类,在中央符号库中查找 触发调试器加载符号 ld .reload 其他使用符号的命令,如 栈回溯命令(k*) 反汇编命令 windbg采用懒惰式符号加载策略(lazy symbol loading) 故在查看模块列表时,会发现许多模块的符号状态为deferred,即推迟加载 30.8.5 观察模块信息 lm lm(list loaded module),模块概要信息列表 例子 lm start end module name 00007ff7`90e80000 00007ff7`90ea8000 Test C (deferred) 00007ff8`dad10000 00007ff8`daec9000 ucrtbased (deferred) 00007ff8`f2300000 00007ff8`f23f7000 MSVCP140D (deferred) 00007ff9`1b650000 00007ff9`1b673000 VCRUNTIME140D (deferred) 00007ff9`31ab0000 00007ff9`31abc000 CRYPTBASE (deferred) 00007ff9`32150000 00007ff9`321d1000 bcryptPrimitives (deferred) 00007ff9`32680000 00007ff9`32922000 KERNELBASE (deferred) 00007ff9`33450000 00007ff9`33570000 RPCRT4 (deferred) 00007ff9`34410000 00007ff9`344c2000 KERNEL32 (private pdb symbols) d:\symbols\kernel32.pdb\47A44F0CC47FB6A1F009E4343B711F231\kernel32.pdb 00007ff9`34700000 00007ff9`34797000 sechost (deferred) 00007ff9`35010000 00007ff9`350ae000 msvcrt (deferred) 00007ff9`350b0000 00007ff9`35153000 ADVAPI32 (deferred)
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章