读书笔记:调试软件 张银奎
生活随笔
收集整理的這篇文章主要介紹了
读书笔记:调试软件 张银奎
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
版本第一版 2021年02月06日 11:53:06 2021年3月9日22:22:25windbg下載x64,http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup/WinSDKDebuggingTools_amd64/dbg_amd64.msix86,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寄存器通用寄存器,rMSR寄存器,rdmsr,wtmsr設置顯示掩碼,rmIO端口ib,iw,idob,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][<bps>] - clear/disable/enable breakpoint(s)BL - list breakpointsBA <access> <size> <addr> - set processor breakpointBP <address> - set soft breakpointD[type][<range>] - dump memoryDT [-n|y] [[mod!]name] [[-n|y]fields][address] [-l list] [-a[]|c|i|o|r[#]|v] - dump using type informationDV [<name>] - dump local variablesE[type] <address> [<values>] - enter memory valuesG[H|N] [=<address> [<address>...]] - goK <count> - stacktraceKP <count> - stacktrace with source argumentsLM[k|l|u|v] - list modulesLN <expr> - list nearest symbolsP [=<addr>] [<value>] - step overQ - quitR [[<reg> [= <expr>]]] - view or set registersS[<opts>] <range> <values> - search memorySX [{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2"] [-h] {Exception|Event|*}] - event filterT [=<address>] [<expr>] - trace intoU [<range>] - unassembleversion - show debuggee and debugger versionX [<*|module>!]<*|symbol> - view symbols? <expr> - display expression?? <expr> - display C++ expression$< <filename> - take input from a command file30.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 [<options>] - add current data breakpoint state to aregister context.asm [<options>] - set disassembly options.asm- [<options>] - clear disassembly options.attach <proc> - attach to <proc> at next execution.block { <commands> } - 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 [<options>] - virtual memory cache control.call <fn>(<arg1>, <arg2>, ...) - run a function in the debuggee.catch { <commands> } - catch failures in commands.chain - list current extensions.childdbg <0|1> - turn child process debugging on or off.clients - list currently active clients.closehandle [<options>] [<handle>] - close the given handle.continue - continue the enclosing loop.copysym [<options>] <path> - copy current symbol files to a directory.create <command line> - create a new process.createdir [<options>] [<path>] - control process creation options.cxr <address> - dump context record at specified addressk* 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 <file> - output DML content from file.dml_flow <start> <addr> - show basic block code flow.dml_start [<options>] - navigable overview of debugger activities.do { <commands> } (<cond>) - execute <commands> until <cond> is zero.drivers - This command was removed -- use 'lm' or .reload -l).dump [<options>] <filename> - create a dump file on the host system.dvalloc [<options>] <bytes> - VirtualAlloc memory in the debuggee.dvfree [<options>] <offset> <bytes> - VirtualFree memory in the debuggee.echo ["<string>"|<string>] - echo string.echotime - output debugger time.echotimestamps [0|1] - toggle timestamp output on events.ecxr - dump context record for current exception.effmach [<machine>] - change current machine type.else { <commands> } - if/then/else conditional execution.elsif (<cond>) { <commands> } [<else clauses>] - if/then/else conditionalexecution.enable_long_status [0|1] - dump LONG types in default base.enable_unicode [0|1] - dump USHORT array/pointers and unicode strings.endsrv <id> - 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 [<dir>[;...]] - set executable search path.exepath+ [<dir>[;...]] - append executable search path.expr - control expression evaluator.exptr <address> - do .exr and .cxr for EXCEPTION_POINTERS.exr <address> - dump exception record at specified address.extmatch [<opts>] <pattern> - display all extensions matching pattern.extpath <opts> [<dir>[;...]] - set extension search path.extpath+ <opts> [<dir>[;...]] - 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 <address> - sets context of fiber at addressresets context if no address specified.fiximports <pattern> - attempts to link imports for images.fnent <address> - dump function entry for the given code address.fnret <fnaddr> [<retval>] - display formatted return value.for ( <init> ; <cond> ; <step> ) { <commands> } - execute <commands> and<step> until <cond> iszero.force_radix_output [0|1] - dump integer types in default base.force_system_init [<options>] - force pending systems to initialize if possible.force_tb - forcibly allow branch tracing.foreach [opts] ( <alias> { <tcmds> } ) { <ecmds> } - execute <ecmds> foreach token in theoutput of <tcmds>.fpo <options> - control override FPO information.frame [<frame>] - set current stack frame for locals.formats <expr> - displays expression result in many formats.help [<options>] - display this help.holdmem <options> [range] - hold and compare memory data.if (<cond>) { <commands> } [<else clauses>] - if/then/else conditionalexecution.ignore_missing_pages [0|1] - control kernel summary dump missingpage error message.imgscan <options> - scan memory for PE images.jdinfo <jdi_addr> - interpret AeDebug information.kframes <count> - 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 <name> - add this extension DLL to the extension chain.loadby <name> <mod> - add the extension DLL in the moduledirectory to the extension chain.locale [<locale>] - set the current locale.logfile - display log status.logopen [<file>] - open new log file.logappend [<file>] - append to log file.logclose - close log file.netsyms [0|1] - allow/disallow net symbol paths.netuse [<options>] - manage net connections.noshell - disable shell commands.noversion - disable extension version checking.ofilter <pattern> - filter debuggee output against the given pattern.ocommand <prefix> - treat output with the given prefix as a command.opendump <file> - open a dump file.outmask <mask> - set bits in the current output mask.outmask- <mask> - clear bits in the current output mask.pcmd [<options>] - control per-prompt command.pop [<options>] - pop state.prefer_dml [0|1] - control DML mode default.printf "<format>", <args...> - formatted output.process [<address>] - sets implicit processresets default if no address specified.process_info - display security related information of current process.prompt_allow [<options>] - control what information can be displayedat the prompt.push [<options>] - push state.quit_lock [<options>] - locks session against unexpected quit.readmem <file> <range> - read raw memory from a file.record_branches [0|1] - controls recording of processor branching.reload [<image.ext>[=<address>,<size>]] - reload symbols.restart - request a session restart.remote <pipename> - start remote.exe server.secure [0|1] - disallow operations dangerous for the host.send_file <options> - send files to remote server.server <options> - start engine server.servers - list active remoting servers.setdll <name> - debugger will search for extensions in this DLL first.shell [<command>] - execute shell command.show_read_failures [<opts>] - control extra read failure output.show_sym_failures [<opts>] - control extra symbol failure output.sleep <milliseconds> - debugger sleeps for given durationuseful for allowing access to a machine that'sbroken in on an ntsd -d.srcfix [<path extra>] - fix source search path.srcfix+ [<path extra>] - append fixed source search path.srcnoisy [0|1] - control verbose source loading output.srcpath [<dir>[;...]] - set source search path.srcpath+ [<dir>[;...]] - append source search path.step_filter [<opts>] ["<pattern>[;<pattern>...]"] - Set symbol patternsto skip when stepping.symfix [<localsym>] - fix symbol search path.symfix+ [<localsym>] - append fixed symbol search path.symopt <flags> - set symbol options.symopt+ <flags> - set symbol options.symopt- <flags> - clear symbol options.sympath [<dir>[;...]] - set symbol search path.sympath+ [<dir>[;...]] - append symbol search path.thread [<address>] - sets context of thread at addressresets 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 <flags> - set/clear type options.unload <name> - 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 (<cond>) { <commands> } - execute <commands> while <cond> is non-zero.writemem <file> <range> - write raw memory to a fileUse ".hh <command>" or open debugger.chm in the debuggers directory to getdetailed 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,!dregrpcexts.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.help30.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線程序號,始于0processor_index處理器序號,始于0線程序號和處理器序號,統一編號每個內核態目標,被分配一個進程序號切換系統||system_index s進程或處理器|process_or_processor_index s自動切換系統線程~thread_index s只能在統一系統內切換調試目標繁忙命令提示符,*BUSY*命令編輯框,Debuggee is runningWinDBG執行命令繁忙命令提示符,*BUSY*命令編輯框,空執行.abandon放棄調試目標命令提示符,NoTarget>命令編輯框,空等待用戶輸入命令提示符,Input>命令編輯框,空30.4 輸入和執行命令30.4.1 要點命令分隔符,;重復命令,回車鍵歷史命令,方向鍵終止命令,Ctrl+Break使用KD或CDB時,使用Ctrl+C詳細輸出模式切換,Ctrl+Alt+V顯示WinDBG與內核調試引擎之間的數據通信,Ctrl+Alt+D幫助,F1或.hh command30.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 SyntaxWinDGB定義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=2r 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; command2j expression 'commands1'; 'commands2'.if.elif.else.if (expression) {commands1} .elif (expression) {commands2} .else {commands3}30.4.6 進程和線程限定符條件 進程 線程當前 |. ~.導致當前調試事件 |# ~#當前系統所有 |* ~*序號 |Number ~numberID |~ID ~~ID30.4.7 記錄到文件.logopen,打開日志文件.logfile,查看日志文件狀態.logclose,關閉日志文件30.5 建立調試會話30.5.1 附加到已有進程菜單方式File > Attach a Process設置為JIT調試器WinDBG.exe -I當程序崩潰后,在錯誤對話框中選擇Debug,便會啟動WinDBG并附加命令行方式WinDBG.exe -p PIDWinDBG.exe -pn namewindbg的命令行選項幫助文檔中搜索,WinDbg Command-Line Optionswindbg [ -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 KeyStringwindbg -IA[S] .attach需要已經有一個調試會話常用于同時調試多個目標時被.abandon拋棄的被調試進程,可以重新附加WinDBG.exe -pe -p PID30.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端口,速度快但不穩定USB22. 啟用目標系統的內核調試引擎Vista之前的系統,修改boot.iniVista之后的系統,使用BCDEdit工具修改啟動選項3. 啟動調試會話菜單方式File > Kernel Debug命令行方式windbg -k com:port=Com1, baud=1152004. 后續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_nametcp:port=port_number,password=password啟動客戶端命令行方式windbg -remote 客戶端通信字符串菜單方式File > Connect to Remote Session輸入客戶端通信字符串或直接瀏覽客戶端通信字符串npipe:server=pc_name,pipe=pipe_nametcp:server=pc_name,port=port_number,password=password30.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在調試用戶態轉儲文件時,可將其中保存的異常上下文設置為寄存器上下文在不同寄存器上下文中,觀察到的寄存器和棧不同rkv30.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查看函數參數和局部變量dv30.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.exeVDbgEng.dllVDbgHelp.dllV符號服務器Dll(SymSrv.dll)||------------> 下游符號庫|----(網絡)--> 中央符號庫(centralized store)(符號服務器)DbgHelp.dllWindows操作系統的調試輔助庫模塊windbg通過它,讀取和解析調試符號符號服務器Dll符號服務器的本地模塊負責從符號服務器查找、下載和管理符號文件具體dll不固定,只要實現了DbgHelp.dll依賴的符號服務器APIwindbg開發工具包中DbgHelp幫助文檔(sdk\help\dbghelp.chm),描述了符號服務器API用戶可以自己實現符號服務器dllwindbg工具包中包含了一個符號服務器(SymSrv.dll)下游符號庫(downstream store)用于緩存從符號服務器下載的符號文件工作流程DbgHelp請求符號服務器Dll,獲取指定符號文件符號服務器Dll先在下游符號庫查找,失敗后在中央符號庫查找路徑表示完整表示symsrv*ServerDll*[DownstreamStore*]ServerPath基于SymSrv.dll的表示symsrv*SymSrv.dll*[DownstreamStore*]ServerPath簡寫為srv*[DownstreamStore*]ServerPath30.8.4 加載符號文件設置符號路徑.sympath srv*D:\Symbols*http://msdl.microsoft.com/download/symbols調試windbg的.reload命令Child-SP RetAddr Call Site00000000`0675af58 00007ff9`326b8ba3 ntdll!ZwWaitForSingleObject+0x1400000000`0675af60 00007ff9`20e34af4 KERNELBASE!WaitForSingleObjectEx+0x9300000000`0675b000 00007ff9`20e2f737 WININET!InternetFindNextFileW+0xe9d400000000`0675b030 00007ff9`20dc69bc WININET!InternetFindNextFileW+0x961700000000`0675b060 00007ff9`20d1f069 WININET!UrlCacheServer+0x2cb7c00000000`0675b1f0 00000000`678b80d2 WININET!InternetReadFile+0xd900000000`0675b290 00000000`678b2040 symsrv!EulaDlgProc+0x174200000000`0675b2c0 00000000`678b15d1 symsrv!RunDllEntry+0x8d0000000000`0675b570 00000000`678a6a50 symsrv!RunDllEntry+0x829100000000`0675b5c0 00000000`678a7d05 symsrv+0x6a5000000000`0675b7e0 00000000`678a7a66 symsrv!SymbolServerByIndexW+0x18500000000`0675be80 00000000`67daffd8 symsrv!SymbolServerW+0xc600000000`0675c0f0 00000000`67d9591a dbghelp!SymGetFileLineOffsets64+0x124800000000`0675c980 00000000`67d96d75 dbghelp+0x2591a00000000`0675d6d0 00000000`67dc5234 dbghelp+0x26d7500000000`0675d9e0 00000000`67dc2ee6 dbghelp!ImagehlpApiVersionEx+0x28b400000000`0675dc70 00000000`67dc2add dbghelp!ImagehlpApiVersionEx+0x56600000000`0675e180 00000000`67db7011 dbghelp!ImagehlpApiVersionEx+0x15d00000000`0675e1c0 00000000`68200484 dbghelp!SymSetScopeFromAddr+0x8100000000`0675e200 00000000`680aba61 dbgeng!DebugCreate+0x1a127400000000`0675e240 00000000`680af90e dbgeng!DebugCreate+0x4c85100000000`0675e270 00000000`68159441 dbgeng!DebugCreate+0x506fe00000000`0675e2b0 00000000`6815aae0 dbgeng!DebugCreate+0xfa23100000000`0675e3c0 00000000`68067134 dbgeng!DebugCreate+0xfb8d000000000`0675e410 00000000`68067420 dbgeng!DebugCreate+0x7f2400000000`0675e8d0 00007ff7`9c433beb dbgeng!DebugCreate+0x821000000000`0675e930 00007ff7`9c4342eb windbg+0x33beb00000000`0675ea70 00007ff7`9c436d35 windbg+0x342eb00000000`0675fae0 00007ff9`34427bd4 windbg+0x36d3500000000`0675fb20 00007ff9`3520ce71 KERNEL32!BaseThreadInitThunk+0x1400000000`0675fb50 00000000`00000000 ntdll!RtlUserThreadStart+0x21SymbolServer函數符號服務器API功能,向服務器請求指定的符號文件,返回文件的完整路徑典型實現在下游符號庫中查找符號文件找到,則返回完整路徑未找到,則進行遠程查找若找到,則下載到下游符號庫中,后返回完整路徑函數原型BOOL CALLBACK SymbolServer( [in] LPCSTR params, [in] LPCSTR filename, [in] PVOID id, [in] DWORD two, [in] DWORD three, [out] LPSTR path );params符號服務器參數信息DownstreamStore和ServerPathfilename符號文件名id符號文件第一標識信息.dbg和pe文件(.exe和.dll)PE文件頭定義的映像時間戳(TimeDateStamp).pdbPDB簽名two符號文件第二標識信息.dbg和pe文件(.exe和.dll)PE文件頭定義的映像文件大小()SizeOfImage.pdbPDB年齡(Age)three符號文件第三標識信息.dbg和pe文件(.exe和.dll)和.pdb未使用為0path符號文件的完整路徑最大長度為MAX_PATH流程使用文件特征標識,調用SymbolServerGetIndexStringW函數,生成索引串文件特征標識的唯一性序列化調用SymbolServerByIndexW函數,獲取文件名和索引串指定的符號文件調用cascade函數調用StoreUNC函數,在下游符號庫中查找使用StoreWinInet類,在中央符號庫中查找觸發調試器加載符號ld.reload其他使用符號的命令,如棧回溯命令(k*)反匯編命令windbg采用懶惰式符號加載策略(lazy symbol loading)故在查看模塊列表時,會發現許多模塊的符號狀態為deferred,即推遲加載30.8.5 觀察模塊信息lmlm(list loaded module),模塊概要信息列表例子lmstart end module name00007ff7`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.pdb00007ff9`34700000 00007ff9`34797000 sechost (deferred) 00007ff9`35010000 00007ff9`350ae000 msvcrt (deferred) 00007ff9`350b0000 00007ff9`35153000 ADVAPI32 (deferred) 00007ff9`351a0000 00007ff9`35390000 ntdll (private pdb symbols) d:\symbols\ntdll.pdb\B54F3499813EBCF139AEFDD664E98FDD1\ntdll.pdb含義start,模塊在進程空間中的起始地址end,模塊在進程空間中的結束地址module name,模塊名稱符號文件加載狀態縮寫 含義deferred 模塊已加載,但尚未嘗試加載符號# 符號文件和可執行文件之間的時間戳或校驗和不匹配T 時間戳,丟失、不可訪問、等于零C 校驗和,丟失、不可訪問、等于零DIA 通過調試接口訪問(DIA,debug interface access)加載了符號文件Export 未找到符號文件,使用映像文件的輸出信息(如dll的export)作為符號M 符號文件和可執行文件之間的時間戳或校驗和不匹配,但仍然加載了該符號文件PERF 執行文件包含性能優化代碼。對地址的加減運算可能出錯Stripped 調試信息是從映像文件中抽取出來的PDB 符號文件是.pdb格式的COFF 符號文件是COFF格式的(Common Object File Format)符號文件完整路徑或空白PDB文件分為私有(private)PDB文件和公共(public)PDB文件公共 = 私有 - 私有信息lm v,模塊詳細信息列表例子lm vstart end module name00007ff7`90e80000 00007ff7`90ea8000 Test C (deferred) Image path: Test.exeImage name: Test.exeTimestamp: Sun Feb 21 13:59:10 2021 (6031F6AE)CheckSum: 00000000ImageSize: 00028000Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e400007ff8`dad10000 00007ff8`daec9000 ucrtbased (deferred) Image path: C:\Windows\SYSTEM32\ucrtbased.dllImage name: ucrtbased.dllTimestamp: Wed Jun 17 13:23:10 2015 (5581043E)CheckSum: 001C1915ImageSize: 001B9000File version: 10.0.10150.0Product version: 10.0.10150.0File flags: 0 (Mask 3F)File OS: 40004 NT Win32File type: 2.0 DllFile date: 00000000.00000000Translations: 0409.04b0CompanyName: Microsoft CorporationProductName: Microsoft? Windows? Operating SystemInternalName: ucrtbase.dllOriginalFilename: ucrtbase.dllProductVersion: 10.0.10150.0FileVersion: 10.0.10150.0 (th1.150616-1659)FileDescription: Microsoft? C Runtime LibraryLegalCopyright: ? Microsoft Corporation. All rights reserved....模塊過濾m 名稱模式M 路徑o,已加載的模塊l,已加載符號的模塊e,有符號問題的模塊!lmi module_name顯示模塊最詳細信息例子!lmi TestLoaded Module Info: [test] Module: TestBase Address: 00007ff790e80000Image Name: Test.exeMachine Type: 34404 (X64)Time Stamp: 6031f6ae Sun Feb 21 13:59:10 2021Size: 28000CheckSum: 0Characteristics: 22 Debug Data Dirs: Type Size VA PointerCODEVIEW 3f, 1f2e8, d8e8 RSDS - GUID: {FAE50400-BD21-47AC-99E6-79A9B7D92FB1}Age: 1, Pdb: G:\user\vs2015\Test\x64\Debug\Test.pdb?? 14, 1f328, d928 [Data not mapped]Symbol Type: DEFERRED - No error - symbol load deferredLoad Report: no symbols loaded菜單,Debug > Modules模塊概要信息列表30.8.6 檢查符號語法x [option] module_name!symbol_name名稱支持通配符? 任意符號出現一次* 任意符號出現0次或多次# 指定符號出現[]# 指定符號串出現選項控制結果顯示順序/a,/A,地址升序和降序/n,/N,名稱升序和降序/z,/Z,符號大小升序和降序顯示符號的數據類型/t條件,需要私有符號,否則顯示<NoType>顯示符號的符號類型和符號大小/v符號類型訪問種類prv,private,私有符號pub,public,公共符號信息種類localglobalparameterfunctionunknown符號大小函數類符號,函數在內存中的大小其他類型符號,數據類型的大小條件,需要私有符號,否則顯示0按大小過濾符號/s size控制顯示格式/p,去掉函數名與括號間的空格/q,符號名的引號格式,@!"符號名"結果含義[符號類型]符號地址函數的入口地址變量的起始地址[符號大小][符號數據類型]module_name!symbol_name符號的類型或取值例子x /t /v Test!test*prv func 00007ff7`90e93b40 3f <function> Test!test_windbg (int)x /t /v Test!g_*prv global 00007ff7`90e9d220 8 <function> * Test!g_MyClass$initializer$ = 0x00007ff7`90e91870prv global 00007ff7`90ea1170 1 class MyClass Test!g_MyClass = class MyClass30.8.7 搜索符號ln(list nearest symbols)例子ln 00007ff790e9d220(00007ff7`90e9d220) Test!g_MyClass$initializer$ | (00007ff7`90e9d330) Test!__xc_zExact matches:Test!g_MyClass$initializer$ = 0x00007ff7`90e9187030.8.8 設置符號選項符號選項windbg使用32的dword記錄符號選項標志 選項名 含義 默認值0x1 SYMOPT_CASE_INSENSITIVE 不分大小寫 On0x2 SYMOPT_UNDNAME 顯示未裝飾的符號名 On0x4 SYMOPT_DEFERRED_LOADS 延遲加載符號 On0x8 SYMOPT_NO_CPP 關閉C++翻譯(使用時,類成員的__或被替換成::) Off0x10 SYMOPT_LOAD_LINES 加載源碼行信息 KD和CDB中為Off,WinDbg 中為On0x20 SYMOPT_OMAP_FIND_NEAREST 允許為優化過的代碼使用最相近的符號 On0x40 SYMOPT_LOAD_ANYTHING 降低匹配符號的挑剔度 Off0x80 SYMOPT_IGNORE_CVREC 忽略映像文件的cv記錄 Off0x100 SYMOPT_NO_UNQUALIFIED_LOADS 禁止符號處理器自動加載模塊 Off0x200 SYMOPT_FAIL_CRITICAL_ERRORS 顯示關鍵錯誤 On0x400 SYMOPT_EXACT_SYMBOLS 嚴格評估所有符號文件 Off0x800 SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 允許位于內存絕對地址的符號 Off0x1000 SYMOPT_IGNORE_NT_SYMPATH 忽略環境變量中的符號和鏡像路徑 Off0x2000 SYMOPT_INCLUDE_32BIT_MODULES 對于安騰處理器,強制列舉32位模塊 Off0x4000 SYMOPT_PUBLICS_ONLY 忽略全局、局部和作用域相關的符號 Off0x8000 SYMOPT_NO_PUBLICS 不搜索公共符號表 Off0x10000 SYMOPT_AUTO_PUBLICS 其他方法失敗時,才使用PDB文件中的公共符號 On0x20000 SYMOPT_NO_IMAGE_SEARCH 不搜索鏡像文件 On0x40000 SYMOPT_SECURE (內核調試)Secure Mode Off0x80000 SYMOPT_NO_PROMPTS (遠程調試)不顯示代理服務器的認證對話框 KD和CDB中為On,WinDbg 中為Off0x80000000 SYMOPT_DEBUG 顯示符號加載過程 Off增加設置.symopt + option_valueoption_value為十六進制標志位,如0x1,0x2,0x4取消設置.symopt - option_value顯示設置.symopt友好設置!sym!sym noisy,即+ 0x80000000!sym quiet,即- 0x80000000!sym prompts,即+ 0x80000!sym prompts off,即- 0x8000030.8.9 加載不嚴格匹配的符號文件方式.reload /i module_name設置符號選項,.symopt +0x40注意加載前,最好開啟"嘈雜"模式(!sym noisy),以觀察加載細節30.9 事件處理30.9.0 概述Windows的調試模型是事件驅動的整個調試過程,就是調試事件的產生、發送、接收和處理調試目標,產生調試事件調試器,接收和處理調試事件調試子系統,發送調試事件給調試器,為調試器提供服務30.9.1 調試事件和異常的關系Windows定義了9類調試事件EXCEPTION_DEBUG_EVENT(1)CREATE_THREAD_DEBUG_EVENT(2)CREATE_PROCESS_DEBUG_EVENT(3)EXIT_THREAD_DEBUG_EVENT (4)EXIT_PROCESS_DEBUG_EVENT(5)LOAD_DLL_DEBUG_EVENT(6)UNLOAD_DLL_DEBUG_EVENT(7)OUTPUT_DEBUG_STRING_EVENT(8)RIP_EVENT(9)其他的調試器事件專供調試使用 異常是一種調試事件,EXCEPTION_DEBUG_EVENT(1)異常調試事件,包含子類,其他類型調試事件不包含Win32異常Windows操作系統定義的類型CPU產生的異常系統內核定義的異常典型非法訪問、除零等異常代碼ntstatus.h Visual C++異常Visual C++編譯器的throw關鍵字所拋出的異常throw關鍵字調用RaiseException API產生異常異常代碼都是 0xe06d7363(.msc) 托管異常.Net程序使用托管方法拋出的異常異常代碼都是0xe0636f6d(.com) 其它異常類型用戶程序直接調用RaiseException API拋出的異常其它C++編譯器拋出的異常等 30.9.2 兩輪機會Windows的異常分發流程第一輪分發給調試器,調試器判斷接收和返回處理結果調試器通常返回沒有處理異常,使之繼續分發對于斷點異常和調試異常,調試器會返回已經處理嘗試分發給異常處理器(VEH、SEH)第二輪分發給調試器,調試器判斷接收和返回處理結果調試器通常返回已經處理,讓系統恢復程序執行,通常會導致重復循環分發終極處理異常源自應用程序,系統啟動"應用程序錯誤報告過程",終止應用程序異常源自內核代碼,系統啟動"藍屏機制"其他調試事件只有一輪機會分發流程,實現了一個異常處理鏈調試用異常,實現調試目的有處理器的異常,實現程序邏輯無處理器的異常,攔截未處理的異常所有異常,實現異常的兜底處理30.9.3 定制事件處理方式每個異常事件都存在四個選項第一輪機會是否中斷到調試器第一輪機會的處理結果第二輪機會是否中斷到調試器第二輪機會的處理結果Visual C++和Visual Studio都有異常設置windbg圖形界面Debug > Event FiltersExecution組單選,控制是否中斷Enabled異常事件兩次都中斷,其他調試事件會中斷Disabled異常事件第二次中斷,其他調試事件不中斷Output輸出信息通知用戶Ignore忽略Continue組單選,控制第一次異常事件的處理結果Handled,返回已處理Not Handled,返回未處理大多異常默認設置為未處理對于第二次異常事件的處理結果默認設置為返回已處理在調試時,可使用gn命令,表示異常未處理支持為事件定義關聯命令(Commands)異常事件有兩次關聯,其他調試事件有一次關聯支持設置事件參數以細化過濾條件(Arguments)支持事件處理方式的增刪命令配置信息要素條件對象事件和參數中斷方式Enabled,Disabled,Output,Ignore處理結果已處理和未處理關聯命令第一次和第二次命令設置中斷方式和關聯命令sx{e|d|i|n} [-c "cmd1"] [-c2 "cmd2"] {Exception|Event|*}設置處理結果已處理,sxe -h {Exception|Event|*}未處理,sx{d|i|n} -h {Exception|Event|*}查看當前設置sx恢復默認設置sxrException|Event的表示事件碼,Event Codesx命令查看幫助文檔搜索"Controlling Exceptions and Events"30.9.4 GH和GN命令在調試中,使用g命令恢復調試目標的執行,此時調試器會返回配置的或默認的處理結果可使用命令臨時指定返回的處理結果已處理(handled),gh未處理(Not Handled),gn30.9.5 實驗程序(dbgee.exe)int _tmain(int argc, _TCHAR* argv[]){if (argc == 1){*(int*)0 = 1;printf("test\n");}return 0;}運行,windbg dbgee.exe43f4.4988): Break instruction exception - code 80000003 (first chance)*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ntdll!LdrInitShimEngineDynamic+0x35c:00007ff9`352711dc cc int 3sxe av,設置兩輪中斷sxd -h av,設置第一輪返回不處理sx,查看設置av - Access violation - break - not handledg,恢復執行,觸發第一次中斷(43f4.4988): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.*** WARNING: Unable to verify checksum for dbgee.exedbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????gh,臨時返回已處理,由于異常條件仍存在,導致循環重復觸發第一次中斷(43f4.4988): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????g,恢復執行,按配置返回未處理由于沒有在程序中找到異常處理器(VEH、SEH等),系統會執行缺省的異常處理器(kernel32.dll中UnhandledExceptionFilter函數)判斷當前程序是否處于調試狀態否,啟動應用程序錯誤對話框,通知用戶終止程序是,返回EXCEPTION_CONTINUE_SEARCH,導致進入異常的第二次分發(43f4.4988): Access violation - code c0000005 (!!! second chance !!!)dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????g,恢復執行,按配置返回已處理,由于異常條件仍存在,導致循環重復觸發第一次中斷(43f4.4988): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????g,進入異常的二次分發(43f4.4988): Access violation - code c0000005 (!!! second chance !!!)dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????gn,返回未處理,系統終止調試目標30.10 控制調試目標30.10.1 初始斷點目的,為了讓調試人員盡早分析調試目標手段Windows操作系統的進程加載器支持在完成最基本的用戶態初始化工作后系統的模塊加載函數,主動執行斷點指令,觸發斷點,讓調試目標中斷到調試器中初始斷點,進入后的首個默認斷點創建調試目標的情況分析創建新進程時,會在父進程的環境中完成很多創建工作進程對象,進程空間,初始線程,通知子系統等初始線程在新進程環境中執行內核態的KiThreadStartup將線程的IRQL(中斷級別)降到APC級別調用PspUserThreadStartup,為線程在用戶態執行做準備初始化一個對用戶態代碼的異步過程調用(APC),并插入APC隊列等待APC完成將線程的IRQL降到0(PASSIVE)調用線程上下文中的進程啟動函數BaseProcessStartBaseProcessStart調用應用程序入口函數異步過程調用該APC調用NTDLL.dll中的LdrpInitialize函數LdrpInitialize函數,算是新進程的初始化線程,在用戶態執行的最早代碼LdrpInitialize工作初始化加載器和讀取執行選項調用LdrpInitializeProcess函數加載Exe文件依賴的動態鏈接庫判斷是否處于調試狀態,是則調用DbgBreakPoint通知調試器注意,此時還未調用DLL的DllMain函數異步過程調用結束后KiUserApcDispatcher調用ZwContinue,返回到內核態的PspUserThreadStartup函數中附加調試目標的情況分析windbg在目標進程中,創建一個遠程線程,來觸發一個初始斷點初始斷點發生在新建線程的上下文中kn# Child-SP RetAddr Call Site00 0000006c`7a27f8f8 00007ff9`3526d4db ntdll!DbgBreakPoint01 0000006c`7a27f900 00007ff9`34427bd4 ntdll!DbgUiRemoteBreakin+0x4b02 0000006c`7a27f930 00007ff9`3520ce71 KERNEL32!BaseThreadInitThunk+0x1403 0000006c`7a27f960 00000000`00000000 ntdll!RtlUserThreadStart+0x21注意,該線程不是目標進程的自建線程而是調試器為了達到調試目的而創建的恢復執行后,線程結束其他當windbg使用-g選項啟動時對于新建調試windbg收到初始斷點事件,不中斷對于附加調試windbg不創建遠程線程來觸發斷點初始斷點不是最早的中斷機會但是足夠使用,初始斷點可用于跟蹤和分析程序和DLL的入口函數設置斷點等準備工作其他較早的中斷機會進程創建事件EXE模塊的加載事件30.10.2 俘獲調試目標中斷調試目標的方式windbg中主動中斷快捷鍵,Ctrl+Break菜單,Bebug > Break調試目標中主動中斷對于調試中的圖形界面程序,按F12調試目標,遇到斷點和觸發異常windbg中主動中斷的分析方式,windbg調試windbg的調試啟動新windbg附加舊windbg設置符號路徑(符號服務器)重新加載模塊符號,確保相關符號下載完成windbg.pdbdbgeng.pdb注意下載部分就失敗的情形下游符號庫中,出現未下載完整的符號文件注意開啟"顯示符號加載過程",!sym noisy有下載的加載失敗SYMSRV: dbgeng.pdb from https://msdl.microsoft.com/download/symbols: 4213760 bytes - 34 percentSYMSRV: /download/symbols/dbgeng.pdb/3905A3278DCD49AEA0C08989F59DB6D91/dbgeng.pdb函數不正確。DBGHELP: C:\Program Files\Debugging Tools for Windows (x64)\sym\dbgeng.pdb\3905A3278DCD49AEA0C08989F59DB6D91\dbgeng.pdb - drive not readyDBGHELP: C:\Program Files\Debugging Tools for Windows (x64)\dbgeng.pdb - file not foundDBGHELP: dbgeng.pdb - file not found*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Debugging Tools for Windows (x64)\dbgeng.dll - DBGHELP: dbgeng - export symbols無下載的加載失敗DBGHELP: d:\symbols\dbgeng.pdb\3905A3278DCD49AEA0C08989F59DB6D91\dbgeng.pdb - drive not readyDBGHELP: C:\Program Files\Debugging Tools for Windows (x64)\dbgeng.pdb - file not foundDBGHELP: dbgeng.pdb - file not found*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Debugging Tools for Windows (x64)\dbgeng.dll - DBGHELP: dbgeng - export symbols有下載的加載成功SYMSRV: dbgeng.pdb from https://msdl.microsoft.com/download/symbols: 4213760 bytes - copied DBGHELP: dbgeng - public symbols d:\symbols\dbgeng.pdb\3905A3278DCD49AEA0C08989F59DB6D91\dbgeng.pdb加載模塊的符號狀態失敗情形lmstart end module name... 00000000`67f70000 00000000`683f5000 dbgeng (export symbols) C:\Program Files\Debugging Tools for Windows (x64)\dbgeng.dll成功情形lmstart end module name... 00007ff7`5a300000 00007ff7`5a3b1000 windbg (pdb symbols) d:\symbols\windbg.pdb\83321AFD3A334F6FA751209AC0F960E91\windbg.pdb...設置斷點bu ntdll!RtlpCreateUserThreadEx bu ntdll!NtCreateThreadEx 普通情況(創建遠程線程中斷目標)windbg執行Break命令的過程knkn# Child-SP RetAddr Call Site00 00000000`00f7c7c8 00007ff9`351a589c ntdll!NtCreateThreadEx01 00000000`00f7c7d0 00007ff9`3526d463 ntdll!RtlpCreateUserThreadEx+0x13c02 00000000`00f7c910 00007ff9`344430aa ntdll!DbgUiIssueRemoteBreakin+0x4303 00000000`00f7c990 00000000`68300d56 KERNEL32!DebugBreakProcess+0xa04 00000000`00f7c9c0 00000000`6828eecf dbgeng!LiveUserDebugServices::RequestBreakIn+0x2605 00000000`00f7ca40 00000000`680c105b dbgeng!LiveUserTargetInfo::RequestBreakIn+0x6f06 00000000`00f7ca80 00007ff7`5a34fe28 dbgeng!DebugClient::SetInterrupt+0x13b07 00000000`00f7cac0 00007ff9`3415681d windbg!FrameWndProc+0x1ae808 00000000`00f7d8c0 00007ff9`341563ec USER32!UserCallWinProcCheckWow+0x2bd09 00000000`00f7da50 00007ff9`34162d03 USER32!DispatchClientMessage+0x9c0a 00000000`00f7dab0 00007ff9`3523fdb4 USER32!_fnDWORD+0x330b 00000000`00f7db10 00007ff9`329912c4 ntdll!KiUserCallbackDispatcherContinue0c 00000000`00f7db98 00007ff7`5a363d92 win32u!ZwUserTranslateAccelerator+0x140d 00000000`00f7dba0 00007ff7`5a364120 windbg!ProcessNonDlgMessage+0x220e 00000000`00f7dbf0 00007ff7`5a36b053 windbg!ProcessPendingMessages+0x700f 00000000`00f7dc60 00007ff7`5a3766e6 windbg!wmain+0x2c310 00000000`00f7fd50 00007ff9`34427bd4 windbg!_CxxFrameHandler3+0x28a11 00000000`00f7fd90 00007ff9`3520ce71 KERNEL32!BaseThreadInitThunk+0x1412 00000000`00f7fdc0 00000000`00000000 ntdll!RtlUserThreadStart+0x21窗口過程函數收到Break命令后,調用全局變量g_DbgClient的方法SetInterruptHRESULT IDebugControl::SetInterrupt(IN ULONG Flags);Flags取值DEBUG_INTERRUPT_PASSIVE(1)希望中斷到命令模式,但不強制函數內部將dbgeng!g_UserInterruptCount加一,將dbgeng!g_EngStatus設置為0x1005DEBUG_INTERRUPT_EXIT(2)讓調試引擎取消等待調試事件,強制返回通常會導致沒有調試目標將dbgeng!g_EngStatus設置為0x1008DEBUG_INTERRUPT_ACTIVE(0)通過全局變量dbgeng!g_CmdState,判斷調試器是否處于命令模式否,則要求調試目標中斷到調試器以進入命令模式是,則遞增dbgeng!g_UserInterruptCountUI線程使用的是0遠程線程的線程函數,DbgUiRemoteBreakin調用DbgBreakPoint函數,執行斷點指令,產生斷點異常極限情況(超時則強制掛起)遠程線程一產生,還未執行斷點指令,就被掛起windbg的處理等待一段時間后,顯示提示信息Break-in sent,waiting 30 seconds再等待30秒,windbg產生一個異常事件(事件碼為 0x8000 0007)SynthesizeWakeEvent這個事件觸發調試器等待函數返回,并處理該事件會引發dbgeng!SyspendExecution函數調用掛起調試目標所有線程,使調試目標被中斷調試器進入命令模式并顯示信息Wake debugger - code 80000007 (first chance)30.10.3 繼續運行從指定地址繼續,同時設定臨時斷點g [a] [= start_address] [break_address ... [; break_commands]]指定地址,start_address斷點硬件斷點與普通斷點,有無a斷點地址,break_address斷點觸發后命令,break_commands可實現執行到光標g,缺省時,從當前地址繼續,無斷點繼續并指定異常處理結果g,返回配置的或默認的處理結果gh,已處理(handled)gn,未處理(Not Handled)繼續到上一級函數gu條件斷點中的繼續gc30.11 單步執行30.11.1 概覽單步的單位源碼模式,一次執行一行源碼Debug > Source Mode 被選中l+t匯編模式,一次執行一條匯編指令Debug > Source Mode 未被選中l-t單步的對象為函數調用時單步進入,step into,p命令單步越過,step over,t命令,trace非函數調用時,p和t作用相同實現匯編模式下的單步執行通過CPU的陷阱機制實現,對于x86CPU,就是設置標志寄存器的T標志t命令過程windbg收到t命令工作線程解析命令(ParseStepTrace),調用SetExecStep和SetNextStepTraceState函數兩個函數將用戶命令,轉化并設置到內部對象、變量和線程的上下文結構中調試引擎報告命令執行完成,最后由ProcessEngineCommands返回到EngineLoopEngineLoop繼續執行,調用DebugClient::WaitForEvent以等待下一調試事件恢復目標運行,調試引擎會將線程上下文通過KERNELBASE!SetThreadContext設置到系統設置過程Child-SP RetAddr : Args to Child : Call Site00000000`0961e628 00000000`6830059f : 00000000`0961e6c0 00000000`680ad865 00000000`0961e6d0 00000001`680ae0aa : KERNELBASE!SetThreadContext00000000`0961e630 00000000`680f8aa8 : 00000000`04373970 00000000`000007b8 00000000`043839e0 00000003`000004d0 : dbgeng!LiveUserDebugServices::SetContext+0xaf00000000`0961eb60 00000000`680f5de7 : 00000000`043a6bc0 00000000`043b3220 00000000`000007b8 00000000`043839e0 : dbgeng!LiveUserTargetInfo::SetTargetContext+0x7800000000`0961eba0 00000000`6819f1b9 : 00000000`043a6bc0 00000000`043b3220 00000000`000007b8 00000000`043839e0 : dbgeng!TargetInfo::SetContext+0xe700000000`0961f660 00000000`6819efec : 00000000`043838e0 00000000`0961f6a0 00000001`00000001 00000001`00000000 : dbgeng!ArmCeMachineInfo::KdSetContext+0x4900000000`0961f690 00000000`68281314 : 00000000`043838e0 00000000`043b3fa0 00000000`043b3220 00000000`0961f700 : dbgeng!MachineInfo::SetContext+0x18c00000000`0961f6d0 00000000`68282672 : 00000000`043a6bc0 00000000`00000000 00001946`00000001 00000000`0961f740 : dbgeng!TargetInfo::ChangeRegContext+0xe400000000`0961f720 00000000`6814a5a9 : 00000000`043a6bc0 00000000`043b3f00 00007ff9`3523fd90 00000000`0961f790 : dbgeng!TargetInfo::PrepareForExecution+0x2200000000`0961f760 00000000`6814a862 : 00000000`043a6b00 00000000`681a4145 00000000`043838e0 00000e07`af20b559 : dbgeng!PrepareOrFlushPerExecution+0x4900000000`0961f7a0 00000000`6814b55f : 00000000`0961f860 00000000`043b3fa0 00000000`0961f830 00000000`00000000 : dbgeng!ResumeExecution+0x3200000000`0961f7e0 00000000`6814a355 : 00000000`0437c3c0 00007ff9`00000005 00000000`00000000 00007ff9`326b8c64 : dbgeng!PrepareForExecution+0x6df00000000`0961f900 00000000`680ca97b : 00000000`0437c3c0 00000000`00000000 00000000`0961f970 00000e07`00000001 : dbgeng!PrepareForWait+0x3500000000`0961f940 00000000`680caf8e : 00000000`0437c3c0 00007ff7`00000000 00000e07`ffffffff 00000000`00000246 : dbgeng!RawWaitForEvent+0x2b00000000`0961f9c0 00007ff7`5a336aba : 00000000`0437c3d0 00007ff7`00000000 00007ff7`ffffffff 00000000`00000000 : dbgeng!DebugClient::WaitForEvent+0xce00000000`0961fa00 00007ff9`34427bd4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : windbg!EngineLoop+0x16a00000000`0961fa40 00007ff9`3520ce71 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x1400000000`0961fa70 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21查看設置參數SetThreadContext的參數MSVCR90!_CONTEXTdt MSVCR90!_CONTEXT 043839e0 +0x044 EFlags : 0x344.formats 0x344Evaluate expression:Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000011 01000100位8為跟蹤標志,當前為1,代表單步執行位8為中斷標志,當前為1,代表啟用中斷事件代碼為8000 0003,為斷點異常事件代碼為8000 0004,為單步異常,由t命令和非越過的p命令觸發針對CALL指令單步越過的p命令是在CALL指令的下一相鄰指令,設置臨時軟件斷點源碼模式下的單步執行通過多次設置陷阱標志實現,即多次匯編模式下的單步執行完整命令p|t [r] [= start_address] [count] ["command"][r],是否顯示寄存器,缺省為顯示[= start_address],指定執行的起始地址,缺省為當前地址[count],指定單步執行的次數,缺省為1["command"],指定每次單步執行后的命令,缺省為空30.11.2 單步執行到指定地址語法pa [r] [=start_address] stop_address反復執行單步越過,直到stop_addresspa,step to addressta [r] [=start_address] stop_address反復執行單步進入,直到stop_addressta,trace to address實現gu,繼續到上一級函數pa $ra$ra,代表當前函數的返回地址被中斷的情形單步中遇到斷點或異常30.11.3 單步執行到下一個函數調用語法pc [r] [=start_address] [Count]反復執行單步越過,直到CALL指令pc,step to calltc [r] [=start_address] [Count]反復執行單步進入,直到CALL指令ta,trace to call[count],指定單步執行到函數調用的次數,缺省為1當處理CALL指令時,當作普通單步執行pc,執行完CALL指令tc,進入函數30.11.4 執行到下一分支語法tb [r] [=start_address] [Count]一次執行到下一分支指令tb,trace to branch實現設置好標志寄存器和MSR寄存器后,便恢復程序運行當CPU執行到分支指令時,便報告異常停下來注意在安騰系統和x64系統上,tb可用于內核調試和用戶態調試在x86系統上,tb僅用于內核調試,使用ph和th可克服局限ph|th [r] [=start_address] [Count]分別用來單步執行和單步追蹤到下一分支指令兩者處理CALL指令的方式不同30.11.5 追蹤并監視wt(trace and watch data)執行函數,打印統計使用在函數入口處執行,否則功能為單步執行統計含義第一部分,追蹤目標目標函數名稱和返回地址第二部分,執行路徑一次函數棧切換(CALL和RET),一次執行狀態記錄第一列,當前函數執行的指令數可能情形[函數首指令,函數中CALL指令][函數首指令,函數中RET指令]第二列,當前函數調用的指令數= 內部函數的執行指令數 + 內部函數的調用指令數第三列,函數調用深度第四列,調用深度縮進+函數名稱第三部分,統計指令數和調試事件數第四部分,統計函數的指令執行情況調用總次數單次最大指令執行數單次最小指令執行數單次平均指令執行數第五部分,系統服務調用情況第六部分,追蹤完成后的狀態寄存器狀態當前程序指針位置注意使用wt追蹤復雜函數或頂層函數時,由于范圍廣,可能需要較長的時間為了提高效率,可以限制追蹤范圍-l,最大調用深度,基于目標函數-m,指定追蹤的模塊-i,指定忽略的模塊wt命令,可被各種調試事件中斷 例子源碼(wtee.cpp)#include <windows.h>#pragma warning(disable: 4996)int GetRandom(int n){int m = 2 * n, nTick;nTick = GetTickCount();m *= nTick;m *= GetVersion();return m*n;}int main(int argc, char* argv[]){int n = argc * 100;n = GetRandom(n);return n;}測試windbg /wtee.exebp wtee!maingwt -m wteeTracing wtee!main to return address 00007ff7`c6d012785 0 [ 0] wtee!main6 0 [ 1] KERNEL32!GetTickCountKernel327 6 [ 0] wtee!main1 0 [ 1] KERNEL32!GetVersionStub21 0 [ 1] KERNELBASE!GetVersion15 28 [ 0] wtee!main43 instructions were executed in 42 events (0 from other threads)Function Name Invocations MinInst MaxInst AvgInstKERNEL32!GetTickCountKernel32 1 6 6 6KERNEL32!GetVersionStub 1 1 1 1KERNELBASE!GetVersion 1 21 21 21wtee!main 1 15 15 150 system calls were executedwtee!__scrt_common_main_seh+0x124:00007ff7`c6d01278 8bd8 mov ebx,eax30.11.6 程序指針飛躍調試時,可以修改程序指針cs:$eip或cs:$rip下一指令的地址實現windbg會把地址,設置到線程上下文的程序指令寄存器中當恢復目標程序時,系統會完成線程上下文的設置使用g命令和單步命令,支持設置起始執行地址寄存器命令r,直接修改程序指針寄存器注意由于修改了程序指針,導致部分指令重復執行或跳過可能導致程序邏輯出錯,如棧操作和對象析構操作等30.11.7 歸納標準命令p stept tracepa step to addressta trace to addresspc step to next calltc trace to next calltb trace to next branchpt step to next returntt trace to next returnph step to next branchth trace to next branchwt trace and watch datag gogh go handledgn go not handledgu go up注意調試目標必須是活動目標windbg設計了元命令和擴展命令,輔助使用標準命令連續單步跟蹤時,界面更新速度頻繁,影響速度和讓人眼花繚亂,可暫停刷新界面.suspend_ui30.12 使用斷點30.12.0 概述設斷點,即埋地雷,講究埋設的地點和時機30.12.1 軟件斷點實現中斷指令(INT3,0xCC)運行時設置(中斷指令)中斷時恢復(原本指令)繼續時,當前指令先執行后設置 驗證試驗源程序(test_bp)int main(){printf("please set breakpoint at start");getchar();return 0;}調試查看test_bpwindbg .\test_bp.exeu test_bp!maintest_bp!main [g:\user\vs2015\test\test_bp\test_bp.cpp @ 8]:00007ff7`017b1000 4883ec28 sub rsp,28h00007ff7`017b1004 488d0d15120000 lea rcx,[test_bp!`string' (00007ff7`017b2220)]00007ff7`017b100b e820000000 call test_bp!printf (00007ff7`017b1030)00007ff7`017b1010 ff1562110000 call qword ptr [test_bp!_imp_getchar (00007ff7`017b2178)]00007ff7`017b1016 33c0 xor eax,eax00007ff7`017b1018 4883c428 add rsp,28h00007ff7`017b101c c3 ret00007ff7`017b101d cc int 3bp test_bp!maing查看test_bp內存使用64位WinHexTools > Open Memorytest_bp > test_bp.exe查看00007ff7`017b1000附近的內存Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F7FF7017B1000 CC 83 EC 28 48 8D 0D 15 12 00 00 E8 20 00 00 00 虄?H ? 7FF7017B1010 FF 15 62 11 00 00 33 C0 48 83 C4 28 C3 CC CC CC b 3繦兡(錳燙7FF7017B1020 48 8D 05 01 26 00 00 C3 CC CC CC CC CC CC CC CC H & 錳燙燙燙?可以發現運行時,原指令被替換00007ff7`017b1000 4883ec28 sub rsp,28h7FF7017B1000 CC 83 EC 28中斷查看test_bpCtrl + Breakwindbg代碼恢復winhex4883EC28488D0D15120000E820000000FF156211000033C04883C428C3CCCCCC488D0501260000C3CCCCCCCCCCCCCCCC可以發現中斷時,中斷指令被恢復注意為了避免破壞數據和代碼,只能在指令首字節位置設置斷點語法bp [id] [options] [address [passes]] ["command_string"]address,斷點地址,缺省為當前程序指針passes,第幾次遇到時觸發中斷,缺省為1command_string,中斷觸發后執行的命令,多個命令使用分號分隔bu [id] [options] [address [passes]] ["command_string"]設置一個以后落實的斷點用于對一個尚未加載的模塊設置斷點如調試動態加載模塊的入口函數或初始化代碼bm [options] symbol_pattern [passes] ["command_string"]設置一批斷點,如同執行多次的bp和bu支持通配符*注意背景,在數據區設置軟件斷點,會導致數據意外變化bm命令在設置斷點時,只對函數類型的匹配符號設置斷點這要求調試符號有類型信息,這通常需要私有符號,但若只有公共符號文件將報錯方法一,\a,強制匹配bm不檢查符號類型,由用戶保證方法二為模塊使用完全或DLL輸出符號options/1臨時斷點,一次命中斷點命中一次后自動刪除/p EPROCESS_ADDRESS僅當斷點事件發生在對應進程中,才中斷僅用在內核調試時/t ETHREAD_ADDRESS僅當斷點事件發生在對應線程中,才中斷僅用在內核調試時/c Number僅當斷點事件發生的函數調用深度,小于Number時才中斷/C Number僅當斷點事件發生的函數調用深度,大于Number時才中斷id,不設置則自動編排30.12.2 硬件斷點定義,通過設置CPU寄存器而實現的斷點在x86 CPU中,就是DR0~DR7特點數量有限可實現軟件斷點不具有的功能,如監視數據訪問和I/O訪問等語法ba [id] access size [options] [address [passes]] ["command_string"]觸發斷點的訪問方式e,對目標內存的執行,被稱為代碼訪問斷點r,對目標內存的讀寫,被稱為數據訪問斷點w,對目標內存的寫,被稱為數據訪問斷點i,對目標內存的輸入輸出訪問,被稱為I/O訪問斷點觸發斷點的目標內存size對于e,為1對于其他,依賴于平臺x86,1、2、4x64,1、2、4、8觸發條件實際訪問包含目標內存address需要按照size對齊注意1硬件斷點數量有限在恢復目標執行時才把硬件斷點落實到上下文的寄存器中所以數量超過限制時,ba不會報錯,恢復執行時會報錯注意2在初始斷點觸發時,不能設置硬件斷點設置會報錯提示初始斷點后,系統會重新設置線程上下文,故不能設置硬件斷點建議在程序入口點或初始化代碼處設置30.12.3 條件斷點背景基本中斷條件(如地址)范圍太廣,導致頻繁中斷希望在滿足指定條件時,才中斷方法利用中斷設置命令中的命令參數中斷觸發時,會先執行命令參數不合條件則直接恢復(gc)"command_string""jc (condition) 'optional_commands'; 'gc'"".if (condition) {option_commands} .else {gc}"condition中讀取變量數據對地址按指定長度進行解引用poi,by,wo,dwo,qwo幫助文檔搜索,MASM Numbers and Operators30.12.4 地址表達方法內存地址模塊符號,module!function[+N]源碼行,`module!file:line`,注意使用重音符號源碼類方法,class__method或class::method30.12.5 設置針對線程的斷點線程限定符 斷點設置命令~.,~#,~*,~number,~~ID30.12.6 管理斷點顯示,blbreak list列1 斷點序號,N列2 斷點狀態,(e|d)[u],分別表示enable,disable,unresolved列3 斷點描述,斷點地址[訪問方式 訪問長度]列4 剩余穿越次數,N列5 初始穿越次數,(N)列6 關聯的進程和線程,進程號:線程號,線程號表示為****(任意)或~NNN(指定)列7 斷點地址的符號表示列8 關聯命令,可能不存在取消,bc 斷點號break cancel斷點號指定單個 N指定集合 N1,N2,N3任意 *范圍 N-M組合 N1,N2-N3啟用和禁用,be|bd 斷點號break enable|disable30.13 控制進程和線程30.13.0 概述討論多進程和多線程的調試知識30.13.1 MulThrds功能創建線程,CreateThread掛起線程,SuspendThread增加其掛起計數(Suspend Count)恢復線程,ResumeThread降低其掛起計數(Suspend Count)調試中斷,DebugBreak當程序處于被調試狀態,調用DebugBreak會中斷到調試器,否則會觸發異常導致關閉掛起計數線程的一個自帶屬性掛起計數大于0,則線程處于掛起狀態(Suspended),不會被執行掛起計數最多降低到-130.13.2 控制線程執行通常情況當進程中斷到調試器時,所有線程會掛起當調試目標中斷到調試器時,windbg會對所有線程調用SuspendThread當進程恢復時,所有線程會恢復當調試目標恢復時,windbg會對所有線程調用ResumeThread調試需求,獨立控制各個線程的執行方法,控制線程的掛起計數方式一,修改掛起計數掛起計數+1,線程限定符 n實現,調用SuspendThread掛起計數-1,線程限定符 m實現,調用ResumeThread方式二,修改線程的凍結狀態(windbg為線程記錄的)調試器引擎內部,調用ThreadInfo::ChangeFreeze方法凍結(freeze),線程限定符 f解凍(unfreeze),線程限定符 u實現當調試目標恢復時,windbg只會為未凍結的線程調用ResumeThread方式三,恢復指定線程線程限定符 g實現windbg對指定線程調用ResumeThread注意當調試含多線程的進程時,在只恢復當個線程的情況下,執行Ctrl+Break默認使用的遠程中斷線程方法會失敗,超時后windbg會使用掛起方法windbg收到Ctrl+Break命令,會在目標進程中創建一個遠程線程windbg收到新線程創建事件打印信息,當前只有兩個線程未被凍結windbg恢復調試目標繼續執行時由于調試目標只恢復了一個線程所以調試器不會對新建線程調用ResumeThread,新建線程也被凍結windbg等待超時后,會強行掛起調試目標,后進入命令模式類似的,對指定線程進行單步執行如,線程限定符 t相關命令~,查看所有線程線程序號 Id: 進程ID.線程ID Suspend: 掛起計數 Teb: ted_address (Unfrozen|Frozen)Teb,線程環境塊30.13.3 多進程調試增加新的調試目標.attach [-premote RemoteOptions] AttachOptions PID .create [-premote RemoteOptions] [-f] CommandLine 其他調試命令查看所有的進程和線程|*~和~*查看當前的進程和線程|進程和線程的切換|N s~N s線程執行控制~N g|t30.14 觀察棧30.14.0 概述當今使用的計算機系統都是基于棧架構棧是進行函數調用的基礎30.14.1 顯示棧回溯函數棧的使用情形和內容創建局部變量函數調用時,參數入棧和返回地址入棧寄存器的入棧和出棧其他信息,如中斷保護(CC)棧回溯(stack backtrace)從棧頂到棧底遍歷棧幀,追溯函數調用過程基于子rsp,通過代碼反推父rsp,棧頂棧幀的rsp在寄存器中函數調用棧宏觀上,是棧幀組成的棧結構微觀上,是棧數據組成的棧結構棧回溯通過定位棧幀sp,以分離棧幀,進而分析棧數據棧幀,記錄了一個運行中函數的調用輸入、運行狀態、返回地址主要包含了(自底向上看)其他信息局部變量寄存器返回地址棧參數典型sp操作初始化sp指向棧底調用線程入口函數入棧返回地址(0)和寄存器,創建局部變量調用子函數入棧棧參數、返回地址(父函數call指令的下一相鄰指令的地址)、寄存器創建局部變量sp定位方法從棧頂到棧底回溯棧頂sp,反算自寄存器sp父棧幀sp,反算自子棧幀sp例子int main(){printf("please set breakpoint at start");getchar();return 0;}kChild-SP RetAddr Call Site0000003c`ac33f518 00007ff8`d2925227 ntdll!ZwReadFile+0x140000003c`ac33f520 00007ff8`d35960ad KERNELBASE!ReadFile+0x770000003c`ac33f5a0 00007ff8`d35961e2 ucrtbase!_read_nolock+0x1190000003c`ac33f640 00007ff8`d3595308 ucrtbase!_read+0xa20000003c`ac33f680 00007ff8`d359752e ucrtbase!common_refill_and_read_nolock<char>+0x700000003c`ac33f6b0 00007ff7`017b1016 ucrtbase!fgetc+0xce0000003c`ac33f6f0 00007ff7`017b12c8 test_bp!main+0x16 [g:\user\vs2015\test\test_bp\test_bp.cpp @ 12]0000003c`ac33f720 00007ff8`d4337bd4 test_bp!__scrt_common_main_seh+0x124 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 264]0000003c`ac33f760 00007ff8`d57ace71 KERNEL32!BaseThreadInitThunk+0x140000003c`ac33f790 00000000`00000000 ntdll!RtlUserThreadStart+0x21調用棧解釋每一行,描述當前線程的用戶態棧上的一個棧幀函數調用,自底向上棧回溯過程,從子棧幀到父棧幀,直到返回地址為0查看線程在當前棧幀的執行狀態rrax=0000000000000006 rbx=0000003cac33f658 rcx=0000000000000054rdx=0000000000000000 rsi=0000000000000054 rdi=0000000000000000rip=00007ff8d57dc124 rsp=0000003cac33f518 rbp=0000000000001000r8=0000000000000000 r9=0000000000000000 r10=000001d9fc781fc0r11=0000003cac33f590 r12=0000000000000000 r13=0000000000001000r14=0000000000000000 r15=000001d9fc781fc0iopl=0 nv up ei pl zr na po nccs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000244ntdll!ZwReadFile+0x14:00007ff8`d57dc124 c3 ret當前棧rspchild rsp為 0000003cac33f518當前即將返回,說明當前rsp指向返回地址u ntdll!ZwReadFilentdll!NtReadFile:00007ff8`d57dc110 4c8bd1 mov r10,rcx00007ff8`d57dc113 b806000000 mov eax,600007ff8`d57dc118 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],100007ff8`d57dc120 7503 jne ntdll!ZwReadFile+0x15 (00007ff8`d57dc125)00007ff8`d57dc122 0f05 syscall00007ff8`d57dc124 c3 ret查看函數調用,發現沒有棧參數dd 0000003cac33f5180000003c`ac33f518 d2925227 00007ff8 00001000 00000000ln 00007ff8d2925227(00007ff8`d29251b0) KERNELBASE!ReadFile+0x77u KERNELBASE!ReadFileKERNELBASE!ReadFile+0x54:00007ff8`d2925204 4489442430 mov dword ptr [rsp+30h],r8d00007ff8`d2925209 4c89542428 mov qword ptr [rsp+28h],r1000007ff8`d292520e 488d442450 lea rax,[rsp+50h]00007ff8`d2925213 4889442420 mov qword ptr [rsp+20h],rax00007ff8`d2925218 4533c9 xor r9d,r9d00007ff8`d292521b 4533c0 xor r8d,r8d00007ff8`d292521e 33d2 xor edx,edx00007ff8`d2925220 48ff1519171800 call qword ptr [KERNELBASE!_imp_NtReadFile (00007ff8`d2aa6940)]0:000> KERNELBASE!ReadFile+0x77:00007ff8`d2925227 0f1f440000 nop dword ptr [rax+rax]當前棧rsp = 返回值地址 + 8 = 0000003cac33f518 + 8 = 0000003cac33f520查看當前棧幀的數據棧基址通常情況下,附近的數據棧基址 父棧幀RBP棧基址+8*1 返回地址棧基址+8*2 第一個棧參數棧基址+8*N 第N個棧參數產生的棧幀信息Child-SP 0000003cac33f518因為未執行"sub rsp, N",所以子棧幀RSP等于當前ESPRetAddr 00007ff8 d2925227Call Site ntdll!ZwReadFile+0x14cs:ripcs=0033rip=00007ff8d57dc124ntdll!ZwReadFile+0x14u ntdll!ZwReadFilentdll!NtReadFile:00007ff8`d57dc110 4c8bd1 mov r10,rcx00007ff8`d57dc113 b806000000 mov eax,600007ff8`d57dc118 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],100007ff8`d57dc120 7503 jne ntdll!ZwReadFile+0x15 (00007ff8`d57dc125)00007ff8`d57dc122 0f05 syscall00007ff8`d57dc124 c3 retcs選擇子,指向的段描述符,段基址為000007ff8d57dc124 = 00007ff8`d57dc110 + 0x14 = ntdll!ZwReadFile+0x14恢復和查看線程在上一棧幀的執行狀態當前棧rspchild rsp為 0000003cac33f520查看函數體,發現有寄存器入棧和局部變量,共0x78u KERNELBASE!ReadFileKERNELBASE!ReadFile:00007ff8`d29251b0 48895c2410 mov qword ptr [rsp+10h],rbx00007ff8`d29251b5 4c894c2420 mov qword ptr [rsp+20h],r900007ff8`d29251ba 56 push rsi00007ff8`d29251bb 57 push rdi00007ff8`d29251bc 4156 push r1400007ff8`d29251be 4883ec60 sub rsp,60h00007ff8`d29251c2 498bd9 mov rbx,r900007ff8`d29251c5 4c8bd2 mov r10,rdx查看函數調用,發現沒有棧參數返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 0000003cac33f520 + 78= 0000003cac33f598返回地址的值dd 0000003cac33f5980000003c`ac33f598 d35960ad 00007ff8 00000000 00000000函數調用ln 00007ff8d35960ad(00007ff8`d3595f94) ucrtbase!_read_nolock+0x119 | (00007ff8`d3596140) ucrtbase!_readu ucrtbase!_read_nolock+0x110ucrtbase!_read_nolock+0x110:00007ff8`d35960a4 498bd7 mov rdx,r1500007ff8`d35960a7 ff15b3000a00 call qword ptr [ucrtbase!_imp_ReadFile (00007ff8`d3636160)]00007ff8`d35960ad 85c0 test eax,eax當前棧rsp = 返回值地址 + 8 = 0000003cac33f598 + 8 = 0000003cac33f5a0查看上一棧幀的數據當前棧,包含寄存器入棧和局部變量,沒有棧參數產生的棧幀信息Child-SP 0000003cac33f520RetAddr 00007ff8d35960adCall Site KERNELBASE!ReadFile+0x77子函數返回地址恢復和查看線程在上二棧幀的執行狀態當前棧rspchild rsp為 0000003cac33f5a0查看函數體,發現有寄存器入棧和局部變量,共0x98u ucrtbase!_read_nolockucrtbase!_read_nolock:00007ff8`d3595f94 4889542410 mov qword ptr [rsp+10h],rdx00007ff8`d3595f99 53 push rbx00007ff8`d3595f9a 55 push rbp00007ff8`d3595f9b 57 push rdi00007ff8`d3595f9c 4154 push r1200007ff8`d3595f9e 4155 push r1300007ff8`d3595fa0 4156 push r1400007ff8`d3595fa2 4157 push r150:000> uucrtbase!_read_nolock+0x10:00007ff8`d3595fa4 4883ec60 sub rsp,60h查看函數調用,發現沒有棧參數返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 0000003cac33f5a0 + 98= 0000003cac33f638返回地址的值dd 0000003cac33f6380000003c`ac33f638 d35961e2 00007ff8 00001000 00000000函數調用ln 00007ff8d35961e2(00007ff8`d3596140) ucrtbase!_read+0xa2 | (00007ff8`d3596230) ucrtbase!_acrt_stdio_free_buffer_nolocku ucrtbase!_read+0x92ucrtbase!_read+0x92:00007ff8`d35961d2 01741145 add dword ptr [rcx+rdx+45h],esi00007ff8`d35961d6 8bc7 mov eax,edi00007ff8`d35961d8 498bd5 mov rdx,r1300007ff8`d35961db 8bce mov ecx,esi00007ff8`d35961dd e8b2fdffff call ucrtbase!_read_nolock (00007ff8`d3595f94)00007ff8`d35961e2 8bd8 mov ebx,eax00007ff8`d35961e4 eb13 jmp ucrtbase!_read+0xb9 (00007ff8`d35961f9)00007ff8`d35961e6 e8c5adffff call ucrtbase!_errno (00007ff8`d3590fb0)當前棧rsp = 返回值地址 + 8 = 0000003cac33f638 + 8 = 0000003cac33f640查看上二棧幀的數據當前棧,包含寄存器入棧和局部變量,沒有棧參數產生的棧幀信息Child-SP 0000003cac33f5a0RetAddr 00007ff8d35961e2Call Site ucrtbase!_read_nolock+0x119子函數返回地址列含義第一列,Child-SP,子棧幀開始的棧地址相鄰SP,之間構成一個棧幀第二列,RetAddr,返回地址棧幀開始后,顯示棧參數,然后是返回地址第三列,Call Site,函數名+偏移棧頂,當前執行的函數位置,源自ripln rip棧中,調用子函數的函數位置,源自子函數的返回地址ln child_ret相關命令k,棧查看基本命令kL,不顯示源碼行數kb,顯示三個棧參數,與調用協議相關kp,顯示所有棧參數,包括類型、名稱、數值,需要有完全的調試符號(私有符號)kP,類似kp,但每個棧參數各占一行kv,在kb的基礎上,顯示FPO(frame pointer omission,棧指針省略)和調用協議kn,會顯示棧幀的序號kf,會顯示棧幀間sp差值,或每個棧幀的長度30.14.2 觀察棧變量dbgee.exeTCHAR g_szGlobal[] = _T("A global var.");int _tmain(int argc, _TCHAR* argv[]){int nRet = 0;TCHAR szBuffer[MAX_PATH];printf("dbgee enters main.\n");if (argc == 1){*(int *)0 = 1;printf("test\n");nRet = -1;}for (int i = 0; i<argc; i++){_stprintf(szBuffer, _T("Arg [%d]: %s"), i, argv[i]);_tprintf(szBuffer);}printf("dbgee exits.\n");return nRet;}有私有符號,dv查看查看當前棧幀的棧變量,dv /i/t/V符號屬性(prv或pub)符號類型(param或local)變量首地址的絕對表示變量首地址的sp偏移表示變量數據類型變量名變量值切換棧幀,.frame frame_index可使用kn查看棧幀索引例子命令查看局部變量windbg .\dbgee.exebp `dbgee!dbgee.cpp:11`注意斷點打在函數首條語句處,而非函數入口運行到此處時,參數已經初始化,局部變量已經開辟但未初始化bl0 e 00007ff6`f3c3102b [g:\user\vs2015\test\dbgee\dbgee.cpp @ 11] 0001 (0001) 0:**** dbgee!wmain+0x2bkn# Child-SP RetAddr Call Site00 000000ca`5c30fc20 00007ff6`f3c31438 dbgee!wmain+0x2b [g:\user\vs2015\test\dbgee\dbgee.cpp @ 11]01 000000ca`5c30fe70 00007ff8`d4337bd4 dbgee!__scrt_common_main_seh+0x124 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 264]02 000000ca`5c30feb0 00007ff8`d57ace71 KERNEL32!BaseThreadInitThunk+0x1403 000000ca`5c30fee0 00000000`00000000 ntdll!RtlUserThreadStart+0x21dv /i/t/VValue unavailable error for nRetValue unavailable error for iprv param @esi @esi int argc = 0n1prv param @rdx @rdx wchar_t ** argv = 0x0000022c`2a78b8d0prv local 000000ca`5c30fc40 @rsp+0x20 wchar_t [260] szBuffer = wchar_t [260] "\Release\dbgee.exe"當前棧幀位置,[000000ca`5c30fc20, 000000ca`5c30fe70)db 000000ca`5c30fc20 000000ca`5c30fe6f000000ca`5c30fc20 5c 00 76 00 73 00 32 00-30 00 31 00 35 00 5c 00 \.v.s.2.0.1.5.\.000000ca`5c30fc30 54 00 65 00 73 00 74 00-5c 00 78 00 36 00 34 00 T.e.s.t.\.x.6.4.000000ca`5c30fc40 5c 00 52 00 65 00 6c 00-65 00 61 00 73 00 65 00 \.R.e.l.e.a.s.e.000000ca`5c30fc50 5c 00 64 00 62 00 67 00-65 00 65 00 2e 00 65 00 \.d.b.g.e.e...e.000000ca`5c30fc60 78 00 65 00 00 00 00 00-a0 00 00 00 00 00 00 00 x.e.............000000ca`5c30fc70 00 00 00 00 00 00 00 00-60 fd 30 5c ca 00 00 00 ........`.0\....000000ca`5c30fc80 a0 1f 79 2a 2c 02 00 00-40 14 00 00 00 00 00 00 ..y*,...@.......000000ca`5c30fc90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fca0 30 24 79 2a 2c 02 00 00-00 00 00 00 00 00 00 00 0$y*,...........000000ca`5c30fcb0 00 00 00 00 00 00 00 00-cd 07 78 d5 f8 7f 00 00 ..........x.....000000ca`5c30fcc0 00 00 78 2a 2c 02 00 00-00 00 78 2a 2c 02 00 00 ..x*,.....x*,...000000ca`5c30fcd0 30 24 79 2a 2c 02 00 00-40 24 79 2a 2c 02 00 00 0$y*,...@$y*,...000000ca`5c30fce0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fcf0 00 00 00 00 00 00 00 00-79 50 75 d5 f8 7f 00 00 ........yPu.....000000ca`5c30fd00 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fd10 00 00 00 00 00 00 00 00-70 35 79 d5 f8 7f 00 00 ........p5y.....000000ca`5c30fd20 02 00 00 00 00 00 00 00-01 00 00 00 00 00 00 00 ................000000ca`5c30fd30 a8 f0 78 2a 2c 02 00 00-dc 37 79 2a 2c 02 00 00 ..x*,....7y*,...000000ca`5c30fd40 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fd50 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fd60 40 24 79 2a 2c 02 00 00-a1 fb 77 d5 f8 7f 00 00 @$y*,.....w.....000000ca`5c30fd70 00 00 00 00 00 00 00 00-00 00 78 2a 2c 02 00 00 ..........x*,...000000ca`5c30fd80 00 00 00 00 00 00 00 00-70 35 79 d5 f8 7f 00 00 ........p5y.....000000ca`5c30fd90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fda0 00 00 00 00 00 00 00 00-db 1e 92 d2 f8 7f 00 00 ................000000ca`5c30fdb0 40 24 79 2a 2c 02 00 00-00 00 00 00 00 00 00 00 @$y*,...........000000ca`5c30fdc0 2a 2e 51 8b 26 ce 00 00-00 00 00 00 00 00 00 00 *.Q.&...........000000ca`5c30fdd0 00 00 00 00 00 00 00 00-96 20 59 d3 f8 7f 00 00 ......... Y.....000000ca`5c30fde0 00 00 00 00 2c 02 00 00-00 00 00 00 00 00 00 00 ....,...........000000ca`5c30fdf0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fe00 c0 21 c3 f3 f6 7f 00 00-26 d5 59 d3 f8 7f 00 00 .!......&.Y.....000000ca`5c30fe10 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ca`5c30fe20 02 00 00 00 00 00 00 00-00 00 00 40 00 04 00 bc ...........@....000000ca`5c30fe30 01 00 00 00 00 00 00 00-29 18 c3 f3 f6 7f 00 00 ........).......000000ca`5c30fe40 1f 00 00 00 00 00 00 00-01 00 00 00 00 00 00 00 ................000000ca`5c30fe50 c8 76 5c 80 88 db 00 00-00 00 00 00 00 00 00 00 .v\.............000000ca`5c30fe60 00 c0 66 d3 f8 7f 00 00-38 14 c3 f3 f6 7f 00 00 ..f.....8.......棧回溯u dbgee!wmaindbgee!wmain [g:\user\vs2015\test\dbgee\dbgee.cpp @ 10]:00007ff6`f3c31000 48895c2408 mov qword ptr [rsp+8],rbx00007ff6`f3c31005 48896c2418 mov qword ptr [rsp+18h],rbp00007ff6`f3c3100a 4889742420 mov qword ptr [rsp+20h],rsi00007ff6`f3c3100f 57 push rdi00007ff6`f3c31010 4881ec40020000 sub rsp,240hchild sp為 000000ca5c30fc20在父棧幀分配完棧變量后,child sp指向父棧幀棧頂所以child sp指向的棧空間,屬于父棧幀,下一位置才屬于子棧幀查看函數體,發現有寄存器入棧和局部變量,共0x248查看函數調用,發現沒有棧參數返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 000000ca5c30fc20 + 248= 000000ca5c30fe68返回地址的值dd 000000ca5c30fe68000000ca`5c30fe68 f3c31438 00007ff6 d366b590 00007ff8函數調用ln 00007ff6f3c31438f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl(264)+0x22(00007ff6`f3c31314) dbgee!__scrt_common_main_seh+0x124 | (00007db 000000ca`5c30fc20 000000ca`5c30fe6fff6`f3c3149c) dbgee!wmainCRTStartupu dbgee!__scrt_common_main_seh+0x114dbgee!__scrt_common_main_seh+0x114 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 264]:00007ff6`f3c31428 0a00 or al,byte ptr [rax]00007ff6`f3c3142a 004c8bc0 add byte ptr [rbx+rcx*4-40h],cl00007ff6`f3c3142e 488b17 mov rdx,qword ptr [rdi]00007ff6`f3c31431 8b0b mov ecx,dword ptr [rbx]00007ff6`f3c31433 e8c8fbffff call dbgee!wmain (00007ff6`f3c31000)00007ff6`f3c31438 8bd8 mov ebx,eax00007ff6`f3c3143a 33c9 xor ecx,ecx00007ff6`f3c3143c e8050a0000 call dbgee!_telemetry_main_return_trigger (00007ff6`f3c31e46)當前棧rsp = 返回值地址 + 8 = 000000ca5c30fe68 + 8 = 000000ca5c30fe70棧變量分析反匯編 dbgee!wmainu dbgee!wmaindbgee!wmain [g:\user\vs2015\test\dbgee\dbgee.cpp @ 10]:00007ff6`f3c31000 48895c2408 mov qword ptr [rsp+8],rbx00007ff6`f3c31005 48896c2418 mov qword ptr [rsp+18h],rbp00007ff6`f3c3100a 4889742420 mov qword ptr [rsp+20h],rsi00007ff6`f3c3100f 57 push rdi00007ff6`f3c31010 4881ec40020000 sub rsp,240h00007ff6`f3c31017 488b05e21f0000 mov rax,qword ptr [dbgee!__security_cookie (00007ff6`f3c33000)]00007ff6`f3c3101e 4833c4 xor rax,rsp00007ff6`f3c31021 4889842430020000 mov qword ptr [rsp+230h],rax0:000> udbgee!wmain+0x29 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 10]:00007ff6`f3c31029 8bf1 mov esi,ecx00007ff6`f3c3102b 33db xor ebx,ebx00007ff6`f3c3102d 488d0dec110000 lea rcx,[dbgee!`string' (00007ff6`f3c32220)]00007ff6`f3c31034 8beb mov ebp,ebx00007ff6`f3c31036 488bfa mov rdi,rdx00007ff6`f3c31039 e862010000 call dbgee!printf (00007ff6`f3c311a0)00007ff6`f3c3103e 83fe01 cmp esi,100007ff6`f3c31041 7516 jne dbgee!wmain+0x59 (00007ff6`f3c31059)0:000> dbgee!wmain+0x43 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 18]:00007ff6`f3c31043 488d0dea110000 lea rcx,[dbgee!`string' (00007ff6`f3c32234)]00007ff6`f3c3104a 89342500000000 mov dword ptr [0],esi00007ff6`f3c31051 e84a010000 call dbgee!printf (00007ff6`f3c311a0)00007ff6`f3c31056 83cdff or ebp,0FFFFFFFFh00007ff6`f3c31059 85f6 test esi,esi00007ff6`f3c3105b 7e2e jle dbgee!wmain+0x8b (00007ff6`f3c3108b)00007ff6`f3c3105d 0f1f00 nop dword ptr [rax]00007ff6`f3c31060 4c8b0f mov r9,qword ptr [rdi]0:000> dbgee!wmain+0x63 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 23]:00007ff6`f3c31063 488d15d6110000 lea rdx,[dbgee!`string' (00007ff6`f3c32240)]00007ff6`f3c3106a 448bc3 mov r8d,ebx00007ff6`f3c3106d 488d4c2420 lea rcx,[rsp+20h]00007ff6`f3c31072 e8b9000000 call dbgee!_swprintf (00007ff6`f3c31130)00007ff6`f3c31077 488d4c2420 lea rcx,[rsp+20h]00007ff6`f3c3107c e84f000000 call dbgee!wprintf (00007ff6`f3c310d0)00007ff6`f3c31081 ffc3 inc ebx00007ff6`f3c31083 488d7f08 lea rdi,[rdi+8]0:000> dbgee!wmain+0x87 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 24]:00007ff6`f3c31087 3bde cmp ebx,esi00007ff6`f3c31089 7cd5 jl dbgee!wmain+0x60 (00007ff6`f3c31060)00007ff6`f3c3108b 488d0dce110000 lea rcx,[dbgee!`string' (00007ff6`f3c32260)]00007ff6`f3c31092 e809010000 call dbgee!printf (00007ff6`f3c311a0)00007ff6`f3c31097 8bc5 mov eax,ebp00007ff6`f3c31099 488b8c2430020000 mov rcx,qword ptr [rsp+230h]00007ff6`f3c310a1 4833cc xor rcx,rsp00007ff6`f3c310a4 e867010000 call dbgee!__security_check_cookie (00007ff6`f3c31210)0:000> udbgee!wmain+0xa9 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 28]:00007ff6`f3c310a9 4c8d9c2440020000 lea r11,[rsp+240h]00007ff6`f3c310b1 498b5b10 mov rbx,qword ptr [r11+10h]00007ff6`f3c310b5 498b6b20 mov rbp,qword ptr [r11+20h]00007ff6`f3c310b9 498b7328 mov rsi,qword ptr [r11+28h]00007ff6`f3c310bd 498be3 mov rsp,r1100007ff6`f3c310c0 5f pop rdi00007ff6`f3c310c1 c3 ret00007ff6`f3c310c2 cc int 30:000> udbgee!wmain+0xc3:00007ff6`f3c310c3 cc int 300007ff6`f3c310c4 cc int 300007ff6`f3c310c5 cc int 300007ff6`f3c310c6 cc int 300007ff6`f3c310c7 cc int 300007ff6`f3c310c8 cc int 300007ff6`f3c310c9 cc int 300007ff6`f3c310ca cc int 3可以發現可以看出這里使用的_fastcall從右至左壓棧,第二一參分別存入xdx和xcx,被調清棧nRet,使用ebp存儲szBuffer,首地址rsp+20h(000000ca5c30fc40),長度260(0x104)[000000ca5c30fc40, 000000ca5c30fd44)i,使用ebx存儲argc,通過rcx傳入,后保存在esi中argv,通過rdx傳入,后保存在edi中棧的初始化和收尾分析初始化代碼dbgee!wmain [g:\user\vs2015\test\dbgee\dbgee.cpp @ 10]:00007ff6`f3c31000 48895c2408 mov qword ptr [rsp+8],rbx00007ff6`f3c31005 48896c2418 mov qword ptr [rsp+18h],rbp00007ff6`f3c3100a 4889742420 mov qword ptr [rsp+20h],rsi00007ff6`f3c3100f 57 push rdi00007ff6`f3c31010 4881ec40020000 sub rsp,240h00007ff6`f3c31017 488b05e21f0000 mov rax,qword ptr [dbgee!__security_cookie (00007ff6`f3c33000)]00007ff6`f3c3101e 4833c4 xor rax,rsp00007ff6`f3c31021 4889842430020000 mov qword ptr [rsp+230h],rax工作寄存器入棧,保存即將使用到的寄存器00007ff6`f3c31000 48895c2408 mov qword ptr [rsp+8],rbx00007ff6`f3c31005 48896c2418 mov qword ptr [rsp+18h],rbp00007ff6`f3c3100a 4889742420 mov qword ptr [rsp+20h],rsi00007ff6`f3c3100f 57 push rdi分配局部空間00007ff6`f3c31010 4881ec40020000 sub rsp,240h計算和存儲棧幀特征值目的__security_cookie機制,防止棧溢出動作子棧幀sp與模塊特征值(dbgee!__security_cookie)的異或設計判斷棧破壞函數調用棧是否運行正常,體現為sp值變化是否正常棧幀初始化后的sp和棧幀收尾前的sp,應該一致方法初始化后,記錄當前sp到當前棧幀中收尾前,比較當前的sp和棧中記錄的sp是否一致方式初始化后,記錄當前棧幀特征值(子棧幀sp(當前sp)與模塊特征值的異或),到當前棧幀中收尾前,計算模塊特征值(子棧幀sp(當前sp)與棧中存儲的當前棧幀特征值的異或),判斷是否一致規律處于異或關系的三個數,其中任意兩個數,能夠異或出第三個數代碼00007ff6`f3c31017 488b05e21f0000 mov rax,qword ptr [dbgee!__security_cookie (00007ff6`f3c33000)]00007ff6`f3c3101e 4833c4 xor rax,rsp00007ff6`f3c31021 4889842430020000 mov qword ptr [rsp+230h],rax分析dq 00007ff6`f3c3300000007ff6`f3c33000 0000db42`dc6c8ae8 ffff24bd`23937517rsp 此時為 000000ca`5c30fc20xor rax,rsphex(int('0000db42dc6c8ae8', 16)^int('000000ca5c30fc20', 16))0xdb88805c76c8dq 000000ca5c30fe50000000ca`5c30fe50 0000db88`805c76c8 00000000`00000000收尾代碼00007ff6`f3c31099 488b8c2430020000 mov rcx,qword ptr [rsp+230h]00007ff6`f3c310a1 4833cc xor rcx,rsp00007ff6`f3c310a4 e867010000 call dbgee!__security_check_cookie (00007ff6`f3c31210)dbgee!wmain+0xa9 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 28]:00007ff6`f3c310a9 4c8d9c2440020000 lea r11,[rsp+240h]00007ff6`f3c310b1 498b5b10 mov rbx,qword ptr [r11+10h]00007ff6`f3c310b5 498b6b20 mov rbp,qword ptr [r11+20h]00007ff6`f3c310b9 498b7328 mov rsi,qword ptr [r11+28h]00007ff6`f3c310bd 498be3 mov rsp,r1100007ff6`f3c310c0 5f pop rdi00007ff6`f3c310c1 c3 ret00007ff6`f3c310c2 cc int 3工作使用棧幀特征值,判斷棧破壞計算模塊特征值(子棧幀sp(當前sp)與棧中存儲的當前棧幀特征值的異或),判斷是否一致代碼00007ff6`f3c31099 488b8c2430020000 mov rcx,qword ptr [rsp+230h]00007ff6`f3c310a1 4833cc xor rcx,rsp00007ff6`f3c310a4 e867010000 call dbgee!__security_check_cookie (00007ff6`f3c31210)回收局部空間00007ff6`f3c310a9 4c8d9c2440020000 lea r11,[rsp+240h]...00007ff6`f3c310c0 5f pop rdi寄存器入棧,保存即將使用到的寄存器00007ff6`f3c310b1 498b5b10 mov rbx,qword ptr [r11+10h]00007ff6`f3c310b5 498b6b20 mov rbp,qword ptr [r11+20h]00007ff6`f3c310b9 498b7328 mov rsi,qword ptr [r11+28h]...00007ff6`f3c310c0 5f pop rdi沒有私有符號,手動推斷查看棧幀內存內存觀察窗口內存查看命令查看代碼局部變量一般引用方式[rsp + N]安全Cookie值(棧幀特征值)位置[rsp + local_length - 0x10]獲取變量指針lea xxx, [rsp + N]其他遍歷對象,執行命令!for_each_local遍歷局部變量,通過@#Local訪問例子!for_each_local dv @#Localargc = 0n1argv = 0x0000022c`2a78b8d0i = 0n0nRet = 0n0szBuffer = wchar_t [260] "\Release\dbgee.exe"!for_each_frame遍歷棧幀例子!for_each_frame dv30.15 分析內存30.15.1 顯示內存區域按數據格式顯示內存區域語法d{a|b|c|d|Df|p|q|u|w|W|yb|yd|} [options] [Range]數據格式字節a,ASCII碼b,字節和ASCII碼yb,二進制和字節字w,WORD(uint16)W,WORD和ASCII碼u,UNICODE字符UNICODE,一種字符的數值映射方案utf8,一種UNICODE的編碼方案,常用于保存uint16,一種UNICODE的編碼方案,常用于計算雙字c,DWORD和ASCII碼d,DWORD(uint32)f,單精度浮點數yd,二進制和雙字四字q,uint64D,雙精度浮點數指針寬度p省略最近使用的數據格式內存范圍,Rangestart_address end_addressstart_address {L|l}NN,表示元素個數end_address {L|l}-N例子windbg dbgeebp dbgee!wmaingu dbgee!wmain+0x87dbgee!wmain+0x87 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 24]:00007ff7`aa911087 3bde cmp ebx,esi00007ff7`aa911089 7cd5 jl dbgee!wmain+0x60 (00007ff7`aa911060)00007ff7`aa91108b 488d0dce110000 lea rcx,[dbgee!`string' (00007ff7`aa912260)]00007ff7`aa911092 e809010000 call dbgee!printf (00007ff7`aa9111a0)00007ff7`aa911097 8bc5 mov eax,ebp00007ff7`aa911099 488b8c2430020000 mov rcx,qword ptr [rsp+230h]00007ff7`aa9110a1 4833cc xor rcx,rsp00007ff7`aa9110a4 e867010000 call dbgee!__security_check_cookie (00007ff7`aa911210)db 00007ff7`aa91226000007ff7`aa912260 64 62 67 65 65 20 65 78-69 74 73 2e 0a 00 00 00 dbgee exits.....00007ff7`aa912270 00 00 00 00 8e f6 42 60-00 00 00 00 02 00 00 00 ......B`........00007ff7`aa912280 42 00 00 00 74 23 00 00-74 17 00 00 00 00 00 00 B...t#..t.......00007ff7`aa912290 8e f6 42 60 00 00 00 00-0c 00 00 00 14 00 00 00 ..B`............00007ff7`aa9122a0 b8 23 00 00 b8 17 00 00-00 00 00 00 8e f6 42 60 .#............B`00007ff7`aa9122b0 00 00 00 00 0d 00 00 00-6c 02 00 00 cc 23 00 00 ........l....#..00007ff7`aa9122c0 cc 17 00 00 00 00 00 00-8e f6 42 60 00 00 00 00 ..........B`....00007ff7`aa9122d0 0e 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................30.15.2 顯示字符串簡單字符串da 以0結尾的ASCII字符串的地址du 以0結尾的UNICODE字符串的地址ntdll!_STRING變量ds 變量地址ntdll!_UNICODE_STRING變量dS 變量地址例子da 00007ff7`aa91226000007ff7`aa912260 "dbgee exits.."30.15.3 顯示數據類型符號列舉dt [module_name!]symbol結果可能多個支持通配符*符號顯示dt [options] [module_name!]symbol結果唯一省略module_name,則自動搜索symbol數據類型及其typedef別名、全局變量、靜態變量、函數options-rN,顯示數據類型時,指定顯示深度-ny name,顯示數據類型時,顯示name開頭的字段變量顯示dt [options] [module_name!]symbol address按指定數據類型,解釋變量鏈表遍歷顯示例子dt dbgee!wmainwmain int (int argc = 1, wchar_t** argv = 00000254`afbddcc0 )dt dbgee!g_szGlobalSymbol dbgee!g_szGlobal not found.由于生成的是Release版的程序,同時全局變量g_szGlobal定義了但并未使用,導致其未被生成嘗試使用Debug版本程序調試dt dbgee!g_szGlobal[14] "A global var."du dbgee!g_szGlobal00007ff6`1994c000 "A global var."!address dbgee!g_szGlobal Usage: ImageAllocation Base: 00007ff6`19930000Base Address: 00007ff6`1994c000End Address: 00007ff6`1994d000Region Size: 00000000`00001000Type: 01000000 MEM_IMAGEState: 00001000 MEM_COMMITProtect: 00000004 PAGE_READWRITEMore info: lmv m dbgeeMore info: !lmi dbgeeMore info: ln 0x7ff61994c00030.15.4 搜索內存在指定范圍內,搜索字符串s-[[Flags]]sa|su RangeRange,內存范圍sa|su,搜索ASCII字符串或UNICODE字符串FlagslN,指定最小長度在指定范圍內,搜索與指定對象類型相同的對象s-[[Flags]]v Range ObjectObject,含虛函數表的使用面向對象語言編寫的類型的對象在指定范圍內,搜索數組s[-[[Flags]]Type] Range data_arrayType,數組元素類型b字節,w字,d雙字,q四字,aASCII字符,uUNICODE字符默認為bdata_array,數組內容例子對于 printf("dbgee exits.\n");字符串"dbgee exits.\n",作為字符串常量,放在代碼段中lmstart end module name00007ff7`aa910000 00007ff7`aa917000 dbgee C (private pdb symbols) G:\user\vs2015\Test\x64\Release\dbgee.pdbs-a 00007ff7`aa910000 00007ff7`aa917000 "dbgee exits."00007ff7`aa912260 64 62 67 65 65 20 65 78-69 74 73 2e 0a 00 00 00 dbgee exits.....!for_each_module s-a @#Base @#End "dbgee exits.\n"00007ff7`aa912260 64 62 67 65 65 20 65 78-69 74 73 2e 0a 00 00 00 dbgee exits.....!for_each_XXX命令!for_each_frame!for_each_local!for_each_module!for_each_process!for_each_thread30.15.5 修改內存寫內存內存區間待寫入數據寫字符串e{a|u|za|zu} address "string"a|u,按照ASCII或UNICODE方式寫入,結尾不加0za|zu,按照ASCII或UNICODE方式寫入,結尾要加0內存區間,[address, address+字符串實際字節長度)待寫入數據,"string"例子da 00007ff7`aa912260 00007ff7`aa912260 "dbgee exits.."eza 00007ff7`aa912260 "test1 exits.\n"^ Memory access error in 'eza 00007ff7`aa912260 "test1 exits.'錯誤,試圖修改只讀的代碼段pu dbgee!wmain+0x63dbgee!wmain+0x63 [g:\user\vs2015\test\dbgee\dbgee.cpp @ 23]:00007ff7`aa911063 488d15d6110000 lea rdx,[dbgee!`string' (00007ff7`aa912240)]00007ff7`aa91106a 448bc3 mov r8d,ebx00007ff7`aa91106d 488d4c2420 lea rcx,[rsp+20h]00007ff7`aa911072 e8b9000000 call dbgee!_swprintf (00007ff7`aa911130)00007ff7`aa911077 488d4c2420 lea rcx,[rsp+20h]00007ff7`aa91107c e84f000000 call dbgee!wprintf (00007ff7`aa9110d0)00007ff7`aa911081 ffc3 inc ebx00007ff7`aa911083 488d7f08 lea rdi,[rdi+8]db [rsp+20h]000000dc`15b8f830 5c 00 52 00 65 00 6c 00-65 00 61 00 73 00 65 00 \.R.e.l.e.a.s.e.000000dc`15b8f840 5c 00 64 00 62 00 67 00-65 00 65 00 2e 00 65 00 \.d.b.g.e.e...e.000000dc`15b8f850 78 00 65 00 00 00 00 00-a0 00 00 00 00 00 00 00 x.e.............000000dc`15b8f860 00 00 00 00 00 00 00 00-50 f9 b8 15 dc 00 00 00 ........P.......000000dc`15b8f870 a0 84 be af 54 02 00 00-50 35 00 00 00 00 00 00 ....T...P5......000000dc`15b8f880 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000dc`15b8f890 30 95 be af 54 02 00 00-00 00 00 00 00 00 00 00 0...T...........000000dc`15b8f8a0 00 00 00 00 00 00 00 00-cd 07 ea bf fe 7f 00 00 ................da [rsp+20h]000000dc`15b8f830 "\"eza [rsp+20h] "write data in szBuffer"db [rsp+20h]000000dc`15b8f830 77 72 69 74 65 20 64 61-74 61 20 69 6e 20 73 7a write data in sz000000dc`15b8f840 42 75 66 66 65 72 00 00-65 00 65 00 2e 00 65 00 Buffer..e.e...e.000000dc`15b8f850 78 00 65 00 00 00 00 00-a0 00 00 00 00 00 00 00 x.e.............000000dc`15b8f860 00 00 00 00 00 00 00 00-50 f9 b8 15 dc 00 00 00 ........P.......000000dc`15b8f870 a0 84 be af 54 02 00 00-50 35 00 00 00 00 00 00 ....T...P5......000000dc`15b8f880 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000dc`15b8f890 30 95 be af 54 02 00 00-00 00 00 00 00 00 00 00 0...T...........000000dc`15b8f8a0 00 00 00 00 00 00 00 00-cd 07 ea bf fe 7f 00 00 ................da [rsp+20h]000000dc`15b8f830 "write data in szBuffer"寫數組e{b|w|d|p|q|D|f} address data_array b字節,w字,d雙字,p指針長度,q四字,D雙精度浮點,f單精度浮點例子ed [rsp+20h] 1 2 3 4 5交互式寫字符串和數組30.15.6 使用物理內存地址命令,虛擬地址相關命令前加!條件,內核模式30.15.7 觀察內存屬性!address address顯示指定內存區的屬性含義行1,Usage,內存區的用途VAR,虛擬分配塊、SBH堆、自定義分配器分配的內存、其他分類的區域Free,未被預留的內存區域 Image,存儲可執行文件映像 Stack,函數棧Teb,thread environment blocks (TEBs)Peb,process environment block (PEB)Heap,堆PageHeap,整頁堆(full-page heap) CSR,CSR shared memory Actx,激活上下文數據的內存NLS,用于National Language Support (NLS) tables FileMap,內存映射文件行2,Allocation Base,較大內存區的開始地址行3,Base Address,較小內存區的開始地址行4,End Address,較小內存區的結束地址行5,Region Size,內存區大小行6,Type,內存區的類型MEM_IMAGE,映射可執行文件映像 MEM_MAPPED,映射其他類型文件MEM_PRIVATE,非映射私有內存,不共享行7,State,內存區的狀態MEM_COMMIT,已提交MEM_FREE,釋放的內存,含未保留的內存MEM_RESERVE,保留的內存行8,Protect,內存區的訪問保護PAGE_NOACCESS,不可訪問PAGE_READONLY,只讀PAGE_READWRITE,可讀可寫PAGE_WRITECOPY,寫時會復制PAGE_EXECUTE,可執行,不可讀寫PAGE_EXECUTE_READ,可執行,只讀PAGE_EXECUTE_READWRITE,可執行,可讀可寫PAGE_EXECUTE_WRITECOPY,可執行寫時會復制PAGE_GUARD,哨兵頁PAGE_NOCACHE,讀不可緩存PAGE_WRITECOMBINE,啟用了寫聯合訪問例子!address dbgee!wmainUsage: ImageAllocation Base: 00007ff7`aa910000Base Address: 00007ff7`aa911000End Address: 00007ff7`aa912000Region Size: 00000000`00001000Type: 01000000 MEM_IMAGEState: 00001000 MEM_COMMITProtect: 00000020 PAGE_EXECUTE_READMore info: lmv m dbgeeMore info: !lmi dbgeeMore info: ln 0x7ff7aa911000!address顯示當前進程所有內存區的屬性!address -summary顯示當前進程所有內存區的統計其他類似命令顯示指定內存區的屬性!vprot dbgee!wmainBaseAddress: 00007ff7aa911000AllocationBase: 00007ff7aa910000AllocationProtect: 00000080 PAGE_EXECUTE_WRITECOPYRegionSize: 0000000000001000State: 00001000 MEM_COMMITProtect: 00000020 PAGE_EXECUTE_READType: 01000000 MEM_IMAGE顯示當前進程所有內存區的屬性!vadump30.16 遍歷鏈表30.16.0 背景Windows操作系統中,很多重要信息使用鏈表方式組織查看鏈表類型dt ntdll!*List*30.16.1 結構定義鏈表節點組成鏈接結構,用于節點連接鏈接結構中的指針,指向下一鏈接結構,而非指向鏈表節點負載,用于數據保存鏈表分類雙向鏈表鏈接結構dt ntdll!_LIST_ENTRY+0x000 Flink : Ptr64 _LIST_ENTRY+0x008 Blink : Ptr64 _LIST_ENTRY單項鏈表鏈接結構dt ntdll!_SINGLE_LIST_ENTRY+0x000 Next : Ptr64 _SINGLE_LIST_ENTRY30.16.2 雙向鏈表示例Windows內核使用雙向鏈表,管理所有進程的EPROCESS結構30.16.3 單項鏈表示例TEB結構使用單向鏈表,保存異常處理器遍歷單向鏈表dt 鏈表節點類型 -l 下一節點地址的符號表示 頭結點地址例子dt -r2 _PEBdbgee!_PEB+0x000 Reserved1 : [2] UChar+0x002 BeingDebugged : UChar+0x003 Reserved2 : [1] UChar+0x008 Reserved3 : [2] Ptr64 Void+0x018 Ldr : Ptr64 _PEB_LDR_DATA+0x000 Reserved1 : [8] UChar+0x008 Reserved2 : [3] Ptr64 Void+0x020 InMemoryOrderModuleList : _LIST_ENTRY+0x000 Flink : Ptr64 _LIST_ENTRY+0x008 Blink : Ptr64 _LIST_ENTRY!pebPEB at 000000dc15cbf000InheritedAddressSpace: NoReadImageFileExecOptions: NoBeingDebugged: YesImageBaseAddress: 00007ff7aa910000Ldr 00007ffebffc53c0Ldr.Initialized: YesLdr.InInitializationOrderModuleList: 00000254afbd4f80 . 00000254afbdb6b0Ldr.InLoadOrderModuleList: 00000254afbd5130 . 00000254afbdb690Ldr.InMemoryOrderModuleList: 00000254afbd5140 . 00000254afbdb6a0Base TimeStamp Module7ff7aa910000 6042f68e Mar 06 11:27:10 2021 G:\user\vs2015\Test\x64\Release\dbgee.exe7ffebfe60000 a52b7c6a Oct 24 03:22:18 2057 C:\Windows\SYSTEM32\ntdll.dll7ffebe160000 2e3dfcea Aug 02 15:59:38 1994 C:\Windows\System32\KERNEL32.DLL7ffebd010000 1a30e11b Dec 05 02:36:11 1983 C:\Windows\System32\KERNELBASE.dll7ffebdf20000 96f604e5 Apr 05 01:18:29 2050 C:\Windows\System32\ADVAPI32.DLL7ffebf6d0000 f5bdefd7 Aug 25 16:27:03 2100 C:\Windows\System32\msvcrt.dll7ffebee30000 f7e420f7 Oct 17 00:23:19 2101 C:\Windows\System32\sechost.dll7ffebef50000 0530c620 Oct 05 05:35:28 1972 C:\Windows\System32\RPCRT4.dll7ffebce70000 5cbddb81 Apr 22 23:19:29 2019 C:\Windows\System32\ucrtbase.dll7ffea83c0000 5c82fae2 Mar 09 07:29:38 2019 C:\Windows\SYSTEM32\VCRUNTIME140.dlldt _PEB_LDR_DATA -l InMemoryOrderModuleList.Flink poi(000000dc15cbf018)dbgee!_PEB_LDR_DATAInMemoryOrderModuleList.Flink at 0x7ffebffc53c0---------------------------------------------+0x000 Reserved1 : [8] "X"+0x008 Reserved2 : [3] (null) +0x020 InMemoryOrderModuleList : [ 0x00000254`afbd5140 - 0x254`afbdb6a0 ]+0x000 Flink : 0x00000254`afbd5140 _LIST_ENTRY [ 0x00000254`afbd4f70 - 0x7ffe`bffc53e0 ]+0x008 Blink : 0x00000254`afbdb6a0 _LIST_ENTRY [ 0x00007ffe`bffc53e0 - 0x254`afbdb7f0 ]InMemoryOrderModuleList.Flink at 0x254afbd5120---------------------------------------------+0x000 Reserved1 : [8] ""+0x008 Reserved2 : [3] 0x3000afdb`fe1e8a7e Void+0x020 InMemoryOrderModuleList : [ 0x00000254`afbd4f70 - 0x7ffe`bffc53e0 ]+0x000 Flink : 0x00000254`afbd4f70 _LIST_ENTRY [ 0x00000254`afbd5690 - 0x254`afbd5140 ]+0x008 Blink : 0x00007ffe`bffc53e0 _LIST_ENTRY [ 0x00000254`afbd5140 - 0x254`afbdb6a0 ]InMemoryOrderModuleList.Flink at 0x254afbd4f50---------------------------------------------+0x000 Reserved1 : [8] "???"+0x008 Reserved2 : [3] 0x3000afd9`fe1e8a7e Void+0x020 InMemoryOrderModuleList : [ 0x00000254`afbd5690 - 0x254`afbd5140 ]+0x000 Flink : 0x00000254`afbd5690 _LIST_ENTRY [ 0x00000254`afbd5d50 - 0x254`afbd4f70 ]+0x008 Blink : 0x00000254`afbd5140 _LIST_ENTRY [ 0x00000254`afbd4f70 - 0x7ffe`bffc53e0 ]30.16.4 DI命令dl[b] Address MaxCount Size Address,鏈表起始地址,指向_LIST_ENTRY或_SINGLE_LIST_ENTRYMaxCount,鏈表節點最大個數Size,鏈表節點負載大小(單位為指針長度),負載位于鏈接結構后例子dl 0x7ffebffc53e0 5 200007ffe`bffc53e0 00000254`afbd5140 00000254`afbdb6a000000254`afbd5140 00000254`afbd4f70 00007ffe`bffc53e000000254`afbd4f70 00000254`afbd5690 00000254`afbd514000000254`afbd5690 00000254`afbd5d50 00000254`afbd4f7000000254`afbd5d50 00000254`afbd58e0 00000254`afbd569030.16.5!list -t [Module!]Type.Field -x "Commands" [-a "Arguments"] [Options] StartAddress !list " -t [Module!]Type.Field -x \"Commands\" [-a \"Arguments\"] [Options] StartAddress " -t [Module!]Type.Field描述鏈表節點類型,[Module!]Type描述鏈接字段,Field-x "Commands" [-a "Arguments"]描述對每個節點的操作命令偽寄存器$extret表示當前節點的地址[Options]-e,回顯對每個節點執行的操作-m N,遍歷的最大節點數目StartAddress鏈接頭節點的地址 例子!list -t _PEB_LDR_DATA.InMemoryOrderModuleList.Flink -x "db @$extret l40" -e -m3 poi(000000dc15cbf018)db @$extret l40 00007ffe`bffc53c0 58 00 00 00 01 00 00 00-00 00 00 00 00 00 00 00 X...............00007ffe`bffc53d0 30 51 bd af 54 02 00 00-90 b6 bd af 54 02 00 00 0Q..T.......T...00007ffe`bffc53e0 40 51 bd af 54 02 00 00-a0 b6 bd af 54 02 00 00 @Q..T.......T...00007ffe`bffc53f0 80 4f bd af 54 02 00 00-b0 b6 bd af 54 02 00 00 .O..T.......T...db @$extret l40 00000254`afbd5120 00 00 00 00 00 00 00 00-7e 8a 1e fe db af 00 30 ........~......000000254`afbd5130 60 4f bd af 54 02 00 00-d0 53 fc bf fe 7f 00 00 `O..T....S......00000254`afbd5140 70 4f bd af 54 02 00 00-e0 53 fc bf fe 7f 00 00 pO..T....S......00000254`afbd5150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................db @$extret l40 00000254`afbd4f50 ee fe ee fe ee fe ee fe-7e 8a 1e fe d9 af 00 30 ........~......000000254`afbd4f60 80 56 bd af 54 02 00 00-30 51 bd af 54 02 00 00 .V..T...0Q..T...00000254`afbd4f70 90 56 bd af 54 02 00 00-40 51 bd af 54 02 00 00 .V..T...@Q..T...00000254`afbd4f80 60 5d bd af 54 02 00 00-f0 53 fc bf fe 7f 00 00 `]..T....S......30.17 調用目標程序的函數30.17.1 調用實例windbg dbgee.exebp wmaing?poi(rdx)*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\System32\ADVAPI32.DLL - Evaluate expression: 2450935962848 = 0000023a`a72adce0從字符串數組argv中,獲取第一個字符串的地址即argv[0]的值,*(argv+0),poi(argv)由于argv存放在rdx,由于_fastcall調用約定windbg使用C++表達式評估器,來解析函數參數.call dbgee!wprintf(0x23aa72adce0)Value unavailable error for _FormatValue unavailable error for _ResultValue unavailable error for _StreamValue unavailable error for _FormatThread is set up for call, 'g' will execute.WARNING: This can have serious side-effects,including deadlocks and corruption of the debuggee.設置函數調用~.gSystem 0: 3 of 4 threads are frozenSystem 0: 3 of 4 threads were frozen.call returns:int 0n9dbgee!wmain:00007ff7`aa911000 48895c2408 mov qword ptr [rsp+8],rbx ss:000000ee`bdbff780=0000000000000000執行函數調用30.17.2 工作原理方法修改線程的執行環境,使調用指定函數調用完成后,恢復線程的執行環境方式在棧頂寫入,函數返回后執行的代碼用于再次中斷到調試器,以恢復線程的執行環境 在棧頂建立新棧幀為子函數開辟空間入棧參數和返回地址(指向新寫入的代碼)修改程序指針,指向指定函數入口例子.call執行前kChild-SP RetAddr Call Site000000ee`bdbff778 00007ff7`aa911438 dbgee!wmain [g:\user\vs2015\test\dbgee\dbgee.cpp @ 10]000000ee`bdbff780 00007ffe`be177bd4 dbgee!__scrt_common_main_seh+0x124 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 264]000000ee`bdbff7c0 00007ffe`bfecce71 KERNEL32!BaseThreadInitThunk+0x14000000ee`bdbff7f0 00000000`00000000 ntdll!RtlUserThreadStart+0x21rrax=0000023aa72b3c00 rbx=00007ffebcf5b590 rcx=0000000000000001rdx=0000023aa72adcd0 rsi=0000000000000000 rdi=00007ffebcf5c000rip=00007ff7aa911000 rsp=000000eebdbff778 rbp=0000000000000000r8=0000023aa72b3c00 r9=00007ffebd031ec0 r10=0000000000000013r11=0000023aa72a8040 r12=0000000000000000 r13=0000000000000000r14=0000000000000000 r15=0000000000000000iopl=0 nv up ei pl nz na po nccs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206dbgee!wmain:00007ff7`aa911000 48895c2408 mov qword ptr [rsp+8],rbx ss:000000ee`bdbff780=0000000000000000db esp000000ee`bdbff778 38 14 91 aa f7 7f 00 00-00 00 00 00 00 00 00 00 8...............000000ee`bdbff788 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff798 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7a8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7b8 d4 7b 17 be fe 7f 00 00-00 00 00 00 00 00 00 00 .{..............000000ee`bdbff7c8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7d8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7e8 71 ce ec bf fe 7f 00 00-00 00 00 00 00 00 00 00 q................call dbgee!wprintf(0x23aa72adce0)kChild-SP RetAddr Call Site000000ee`bdbff748 000000ee`bdbff770 dbgee!wprintf [c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\corecrt_wstdio.h @ 609]000000ee`bdbff750 0000023a`a72adce0 0xee`bdbff770000000ee`bdbff758 0000023a`a72adcd0 0x23a`a72adce0000000ee`bdbff760 0000023a`a72b3c00 0x23a`a72adcd0000000ee`bdbff768 00007ffe`bd031ebf 0x23a`a72b3c00000000ee`bdbff770 cccccccc`ccfdebcc KERNELBASE!BasepLoadLibraryAsDataFileInternal+0x6bf000000ee`bdbff778 00007ff7`aa911438 0xcccccccc`ccfdebcc000000ee`bdbff780 00007ffe`be177bd4 dbgee!__scrt_common_main_seh+0x124 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 264]000000ee`bdbff7c0 00007ffe`bfecce71 KERNEL32!BaseThreadInitThunk+0x14000000ee`bdbff7f0 00000000`00000000 ntdll!RtlUserThreadStart+0x21rrax=0000023aa72b3c00 rbx=00007ffebcf5b590 rcx=0000023aa72adce0rdx=0000023aa72adcd0 rsi=0000000000000000 rdi=00007ffebcf5c000rip=00007ff7aa9110d0 rsp=000000eebdbff748 rbp=0000000000000000r8=0000023aa72b3c00 r9=00007ffebd031ec0 r10=0000000000000013r11=0000023aa72a8040 r12=0000000000000000 r13=0000000000000000r14=0000000000000000 r15=0000000000000000iopl=0 nv up ei pl nz na po nccs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206dbgee!wprintf:00007ff7`aa9110d0 48894c2408 mov qword ptr [rsp+8],rcx ss:000000ee`bdbff750=0000023aa72adce0db esp000000ee`bdbff748 70 f7 bf bd ee 00 00 00-e0 dc 2a a7 3a 02 00 00 p.........*.:...000000ee`bdbff758 d0 dc 2a a7 3a 02 00 00-00 3c 2b a7 3a 02 00 00 ..*.:....<+.:...000000ee`bdbff768 c0 1e 03 bd fe 7f 00 00-cc eb fd cc cc cc cc cc ................000000ee`bdbff778 38 14 91 aa f7 7f 00 00-00 00 00 00 00 00 00 00 8...............000000ee`bdbff788 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff798 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7a8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................000000ee`bdbff7b8 d4 7b 17 be fe 7f 00 00-00 00 00 00 00 00 00 00 .{..............查看變化棧變化db esp000000ee`bdbff748 70 f7 bf bd ee 00 00 00-e0 dc 2a a7 3a 02 00 00 p.........*.:...000000ee`bdbff758 d0 dc 2a a7 3a 02 00 00-00 3c 2b a7 3a 02 00 00 ..*.:....<+.:...000000ee`bdbff768 c0 1e 03 bd fe 7f 00 00-cc eb fd cc cc cc cc cc ................dq esp000000ee`bdbff748 000000ee`bdbff770 0000023a`a72adce0000000ee`bdbff758 0000023a`a72adcd0 0000023a`a72b3c00000000ee`bdbff768 00007ffe`bd031ec0 cccccccc`ccfdebcc新棧幀返回地址,000000ee`bdbff770參數,放在rcx中為子函數開辟空間u dbgee!wprintfdbgee!wprintf [c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\corecrt_wstdio.h @ 609]:00007ff7`aa9110d0 48894c2408 mov qword ptr [rsp+8],rcx00007ff7`aa9110d5 4889542410 mov qword ptr [rsp+10h],rdx00007ff7`aa9110da 4c89442418 mov qword ptr [rsp+18h],r800007ff7`aa9110df 4c894c2420 mov qword ptr [rsp+20h],r9長度0x20查看函數返回后的執行代碼u 000000ee`bdbff770000000ee`bdbff770 cc int 3000000ee`bdbff771 ebfd jmp 000000ee`bdbff770000000ee`bdbff773 cc int 3000000ee`bdbff773 cc int 3000000ee`bdbff774 cc int 3000000ee`bdbff775 cc int 3000000ee`bdbff776 cc int 3000000ee`bdbff777 cc int 3一共八字節,以對齊寄存器程序指針,rip原rip=00007ff7aa911000dbgee!wmain:00007ff7`aa911000 48895c2408 mov qword ptr [rsp+8],rbx ss:000000ee`bdbff780=0000000000000000新rip=00007ff7aa9110d0dbgee!wprintf:00007ff7`aa9110d0 48894c2408 mov qword ptr [rsp+8],rcx ss:000000ee`bdbff750=0000023aa72adce0棧指針,rsp執行指定函數~.gSystem 0: 3 of 4 threads are frozenSystem 0: 3 of 4 threads were frozen.call returns:int 0n9dbgee!wmain:00007ff7`aa911000 48895c2408 mov qword ptr [rsp+8],rbx ss:000000ee`bdbff780=0000000000000000查看變化k,恢復r,恢復db esp,恢復30.17.3 限制條件和常見錯誤.call命令只能調試,用戶態活動目標被調函數,有私有符號,即包含類型信息的函數符號每個線程一次只能設置一個函數,設置后,要么取消,要么執行.call /C,清除當前線程設置的函數30.18 命令程序30.18.0 概述調試器命令程序,Debuger Command Program概念,調試器命令集合,形成的文件組成調試器命令,標準命令、元命令、擴展命令流程控制符號變量30.18.1 流程控制符號(control flow token)分支.if, .else, .elseif循環.do, .while, !for_each_xxx, .break, .continue異常.catch,捕獲異常.leave,退出.catch塊代碼塊.block30.18.2 變量分類偽寄存器自動的偽寄存器由windbg定義和賦值如$ip用戶賦值的偽寄存器$t0~$t19指定為整數類型并賦值r $txx = expression指定為值的類型并賦值r? $txx = expression別名用戶定義的別名as,增加別名ad,刪除別名自動別名$ntsym、$CurrentDump等固定名稱的別名$u0~$u9定義,r $.ux = expression引用偽寄存器MASM表達式評估器,@$xxx或$xxxC++表達式評估器,@$xxx別名${$xxx}30.18.3 命令程序示例代碼$$ Get module list LIST_ENTRY in $t0r? $t0 = &@$peb->Ldr->InMemoryOrderModuleList$$ Iterate over all module in list.for (r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t0;(@$t1 != 0) & (@$t1 != @$t0);r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t1->InLoadOrderLinks.Flink){$$ Get base address in $Baseas /x ${/v:$Base} @@c++(@$t1->DllBase)$$ Get full name into $Modeas /msu ${/v:$Mod} @@c++(&@$t1->FullDllName).block{.echo ${$Mod} at ${$Base}}ad ${/v:$Base}ad ${/v:$Mod}}解釋$$和*,行注釋$$也可以分號結束注釋常用$$,因為將程序合并成一行時,換行符會被替換成分號使用$$可以正常注釋使用*不能正常注釋當前進程_PEB結構的地址,使用偽寄存器$peb表示r? $t0 = &@$peb->Ldr->InMemoryOrderModuleList$t0,存儲地址,指向@$peb->Ldr->InMemoryOrderModuleListdt -r2 _PEBdbgee!_PEB+0x000 Reserved1 : [2] UChar+0x002 BeingDebugged : UChar+0x003 Reserved2 : [1] UChar+0x008 Reserved3 : [2] Ptr64 Void+0x018 Ldr : Ptr64 _PEB_LDR_DATA+0x000 Reserved1 : [8] UChar+0x008 Reserved2 : [3] Ptr64 Void+0x020 InMemoryOrderModuleList : _LIST_ENTRY+0x000 Flink : Ptr64 _LIST_ENTRY+0x008 Blink : Ptr64 _LIST_ENTRYr? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t0;$t1,存儲地址,與$t0相同$t0,指向_LIST_ENTRY,位于_PEB_LDR_DATA中$t1,指向_LIST_ENTRY,位于_LDR_DATA_TABLE_ENTRY中也是指向_LDR_DATA_TABLE_ENTRYdt ntdll!_LDR_DATA_TABLE_ENTRY+0x000 InLoadOrderLinks : _LIST_ENTRY+0x010 InMemoryOrderLinks : _LIST_ENTRY+0x020 InInitializationOrderLinks : _LIST_ENTRY+0x030 DllBase : Ptr64 Void+0x038 EntryPoint : Ptr64 Void+0x040 SizeOfImage : Uint4B+0x048 FullDllName : _UNICODE_STRING+0x058 BaseDllName : _UNICODE_STRING(@$t1 != 0) & (@$t1 != @$t0);鏈表遍歷,判斷結束r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t1->InLoadOrderLinks.Flink)獲取下一節點的地址as /x ${/v:$Base} @@c++(@$t1->DllBase)/x,取表達式64位值/v,阻止別名替換,不管其是否已經定義@@c++,強制使用C++表達式評估器as /msu ${/v:$Mod} @@c++(&@$t1->FullDllName)/msu,使別名等價于地址表達式指向的UNICODE_STRING.block;{;.echo ${$Mod} at ${$Base};}強制評估別名并回顯30.18.4 執行命令程序$<Filename 讀一行,執行一行若一行中命令不完整,則會出錯$><Filename合并程序成一行(分號替換換行符),然后執行 $$< Filename 同"$$<Filename",但允許文件名前加空格,使用雙引號包圍文件名$$>< Filename 同"$$><Filename",但允許文件名前加空格,使用雙引號包圍文件名$$>a< Filename [arg1 arg2 arg3 ... ] 支持參數30.19 本章總結本章內容,介紹調試任務所需的一般知識是對windbg幫助文檔的補充對幫助文檔進行了歸納和濃縮,便于入門介紹幫助文檔中較少或較難的內容windbg中的文檔debugger.chm根目錄windbg幫助文檔kernel_debugging_tutorial.doc根目錄介紹內核調試symhttp.docsymproxy子目錄介紹如何建立符號服務器srcsrv.docsrcsrv子目錄介紹源文件服務器的概況以及如何建立和配置源文件服務器dml.doc根目錄介紹DML(Debugger Markup Language)的用途和編寫方法DML是一種標記語言,用于標記windbg或擴展命令的信息輸出themes.docthemes子目錄介紹了主題(theme)的概念一個主題,代表一套特定風格的界面布局和工作空間配置介紹了如何加載及使用該目錄中的四套主題配置adplus.docpooltag.txttriage子目錄包含了Windows內核模塊和驅動程序所使用的內存分配標記(Pool Tag)在啟用了Windows操作系統的內存池標記(Pool Tagging)功能后,系統會為每個內存塊維護一個分配標記,以標識其使用者用于顯示內存池使用情況的擴展命令!poolused,就是使用該文件來查找每個分配標記對應的模塊
?
總結
以上是生活随笔為你收集整理的读书笔记:调试软件 张银奎的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html设计学校网站,基于HTML5的学
- 下一篇: 国家计算机考试一级难不难,国家计算机一级