读书笔记:调试软件 张银奎
生活随笔
收集整理的這篇文章主要介紹了
读书笔记:调试软件 张银奎
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
版本第一版 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學(xué)習(xí)windbg時使用幫助文檔可使用windbg調(diào)試windbg第30章 WindDBG用法詳解30.0 概述WinDBG支持多種調(diào)試服務(wù)用戶態(tài)調(diào)試內(nèi)核態(tài)調(diào)試轉(zhuǎn)儲文件調(diào)試遠程調(diào)試非常好的靈活性和擴展性30.1 工作空間workspace描述和存儲,調(diào)試項目的屬性、參數(shù)、調(diào)試器設(shè)置等分類默認(rèn)的工作空間基礎(chǔ)工作空間(base workspace),調(diào)試會話尚未建立默認(rèn)的內(nèi)核態(tài)工作空間(default kernel-mode workspace),開始內(nèi)核調(diào)試但未連接調(diào)試目標(biāo)默認(rèn)的遠程調(diào)試工作空間(remote default workspace),通過調(diào)試服務(wù)器(DbgSrv或KdSrv)進行遠程調(diào)試時特定處理器的工作空間(processor-specific workspace),開始內(nèi)核調(diào)試且已連接調(diào)試目標(biāo),并知道對方處理器類型后默認(rèn)的用戶態(tài)工作空間(default user-mode workspace),附加到進程時命名的工作空間(顯式的工作空間,explicit)包含的信息調(diào)試會話狀態(tài)斷點、打開的源文件、自定義別名調(diào)試器設(shè)置符號文件路徑,可執(zhí)行映像文件路徑,源文件路徑源文件選項,日志文件設(shè)置,內(nèi)核調(diào)試連接設(shè)置打開文件對話框使用的設(shè)置WinDBG圖形界面信息工作空間的保存和打開使用注冊表保存配置路徑,HKEY_CURRENT_USER\Software\Microsoft\WinDBG\Workspace子鍵表示類型,User,Kernel,Dump,Explicit保存到文件WinDBG,以增量的方式來應(yīng)用配置30.2 命令概覽30.2.1 標(biāo)準(zhǔn)命令基本調(diào)試功能實現(xiàn)在WinDBG內(nèi)部分類(按相關(guān)對象分類)調(diào)試目標(biāo)控制恢復(fù)執(zhí)行,g系列跟蹤執(zhí)行,t系列,trace into單步執(zhí)行,p系列,step over追蹤監(jiān)視,wt寄存器通用寄存器,rMSR寄存器,rdmsr,wtmsr設(shè)置顯示掩碼,rmIO端口ib,iw,idob,ow,od內(nèi)存查看,d編輯,e搜索,s棧,k系列斷點設(shè)置,bp軟件斷點,ba硬件斷點列舉,bl控制,bc、bd、be,參數(shù)、禁用、啟用線程,~,控制和顯示進程,|,顯示表達式評估?,匯編??,C++匯編控制a,匯編u,反匯編段選擇子,dg,顯示命令文件,$,執(zhí)行選項設(shè)置調(diào)試事件處理方式,sx靜默模式的禁用和啟用,sq內(nèi)核選項,so符號后綴,ss版本version,調(diào)試器和調(diào)試目標(biāo)vertarget,調(diào)試目標(biāo)所在系統(tǒng)符號,x,檢查源程序,ls,控制和顯示結(jié)束調(diào)試會話基本,q結(jié)束遠程,qq結(jié)束調(diào)試會話,分離調(diào)試目標(biāo),qd其他ld,加載調(diào)試符號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常用調(diào)試功能實現(xiàn)在WinDBG內(nèi)部分類(按相關(guān)對象分類)調(diào)試會話和調(diào)試器選項,顯示和設(shè)置符號選型,.symopt符號路徑,.sympath和.symfix源文件,.srcpath,.srcnoise,.srcfix擴展命令模塊路徑,.extpath匹配擴展命令,.extmatch可執(zhí)行文件,.exepath反匯編,.asm表達式評估器,.expr調(diào)試會話和調(diào)試目標(biāo),控制創(chuàng)建新進程,.create附加舊進程,.attach打開轉(zhuǎn)儲文件,.opendump分離附加目標(biāo),.detach殺掉進程,.kill重新開始調(diào)試會話,.restart放棄用戶態(tài)調(diào)試目標(biāo)(進程),.abandon擴展命令模塊,管理加載,.load卸載,.unload,.unloadall顯示,.chain調(diào)試器日志文件,管理新建打開,.logopen追加打開,.logappend打開狀態(tài),.logfile關(guān)閉,.logclose遠程調(diào)試遠程調(diào)試客戶端,remote.exe啟動,.remote遠程調(diào)試服務(wù)器,調(diào)試引擎服務(wù)器啟動服務(wù)器,.server列舉服務(wù)器,.servers向服務(wù)器發(fā)送文件,.send_file結(jié)束服務(wù)器,.endsrv遠程進程服務(wù)器結(jié)束服務(wù)器,.endpsrv調(diào)試器,控制睡眠,.sleep喚醒,.wake啟動新調(diào)試器,調(diào)試當(dāng)前調(diào)試器,.dbgdbg命令程序,編寫類似于C語言的關(guān)鍵字.if, .else, .elif.foreach, .do, .while, .continue, .break.catch, .leave, .printf, .block其他產(chǎn)生轉(zhuǎn)儲文件,.dump保存內(nèi)存數(shù)據(jù),.writemem顯示調(diào)試會話時間,.time顯示線程時間,.ttime顯示任務(wù)列表,.tlist格式化數(shù)字,.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,則自動搜索特殊調(diào)試功能,針對特殊調(diào)試目標(biāo)實現(xiàn)在動態(tài)鏈接庫(DLL)中利用WinDBG的SDK,編寫擴展模塊和擴展命令WinDBG程序包中,包含了常用的擴展命令模塊NT4CHK目錄,調(diào)試目標(biāo)為Windows NT 4.0 Checked版本時的擴展命令模塊NT4FRE目錄,調(diào)試目標(biāo)為Windows NT 4.0 Free版本時的擴展命令模塊W2KCHK目錄,調(diào)試目標(biāo)為Windows 2000 Checked版本時的擴展命令模塊W2KFRE目錄,調(diào)試目標(biāo)為Windows 2000 Free版本時的擴展命令模塊WINXP目錄,調(diào)試目標(biāo)為Windows XP或者更高版本時的擴展命令模塊acpikd.dll,用于ACPI調(diào)試,追蹤調(diào)用ASL程序的過程,顯示ACPI對象exts.dll,關(guān)于堆(!heap),進程/線程結(jié)構(gòu)(!teb/!peb),安全信息(!token,!sid,!acl),應(yīng)用程序驗證(!avrf)等kdexts.dll,用于調(diào)試內(nèi)核fltkd.dll,用于調(diào)試過濾驅(qū)動程序(FsFilter)minipkd.dll,用于調(diào)試AIC78xx小端口(miniport)驅(qū)動程序ndiskd.dll,用于調(diào)試網(wǎng)絡(luò)有關(guān)驅(qū)動程序ntsdexts.dll,實現(xiàn)了!handle,!locks,!dp,!dregrpcexts.dll,用于RPC調(diào)試scsikd.dll,用于調(diào)試SCSI有關(guān)的驅(qū)動程序traceprt.dll,用于格式化ETW信息vdmexts.dll,調(diào)試運行在VDM中的DOS程序和WOW程序wow64exts.dll,調(diào)試運行在64位Windows中的32位程序wmitrace.dll,顯示W(wǎng)MI追蹤有關(guān)的數(shù)據(jù)結(jié)構(gòu)、緩沖區(qū)和日志文件WINEXT目錄,適用于所有Windows版本的擴展命令模塊ext.dll,適用于所有調(diào)試目標(biāo)的常用擴展命令kext.dll,適用于內(nèi)核態(tài)調(diào)試的常用擴展命令uext.dll,適用于用戶態(tài)調(diào)試的常用擴展命令logexts.dll,用于監(jiān)視和記錄API調(diào)用sos.dll,用于調(diào)試托管代碼和.Net程序ks.dll,用于調(diào)試內(nèi)核流(kernel stream)wdfkd.dll,調(diào)試使用WDF(Windows Driver Foundation)編寫的驅(qū)動程序擴展模塊的加載自動加載當(dāng)調(diào)試目標(biāo)被激活時,WinDBG會根據(jù)以下條件自動加載命令空間中指定的擴展模塊調(diào)試目標(biāo)的類型當(dāng)前的工作空間完整語法方式!extension_module.extension_command自動搜索和加載手動加載.load 模塊完整路徑.load 模塊名稱,會在擴展模塊搜索路徑(EXTPATH)中尋找.loadby target_module refer_module在已加載模塊(refer_module)所在目錄,搜索和加載target_module列舉已經(jīng)加載的擴展模塊.chain擴展模塊的卸載.unload.unloadall查詢模塊信息!extension_module.help30.3 用戶界面30.3.1 窗口概述框架窗口(Frame Window)菜單和工具欄工作窗口Command,命令輸入和顯示結(jié)果Watch,觀察指定變量Locals,觀察局部變量Registers,觀察寄存器Memory,觀察內(nèi)存CallStack,觀察調(diào)用棧Disassembly,反匯編ScratchPad,白板,做調(diào)試筆記ProcessesAndThreads,觀察進程和線程CommandBrowser,執(zhí)行和瀏覽命令狀態(tài)欄30.3.2 命令窗口組成信息顯示區(qū)命令橫條命令提示符,命令編輯框信息顯示區(qū)展示的信息包含命令執(zhí)行結(jié)果調(diào)試事件錯誤信息調(diào)試引擎的提示信息命令橫條未連接調(diào)試目標(biāo)時命令提示符,空命令編輯框,Debuggee not connected等待命令輸入時命令提示符,調(diào)試目標(biāo)描述>用戶態(tài)目標(biāo)[||system_index:]process_index:thread_index>內(nèi)核態(tài)目標(biāo)或內(nèi)核態(tài)轉(zhuǎn)儲文件目標(biāo)[||system_index:][processor_index:]kd>本地內(nèi)核態(tài)調(diào)試[||system_index:][processor_index:]lkd>其中system_index同一Windows中多個用戶態(tài)目標(biāo),同屬于一個系統(tǒng)每個內(nèi)核目標(biāo),獨屬于一個系統(tǒng)process_index線程序號,始于0processor_index處理器序號,始于0線程序號和處理器序號,統(tǒng)一編號每個內(nèi)核態(tài)目標(biāo),被分配一個進程序號切換系統(tǒng)||system_index s進程或處理器|process_or_processor_index s自動切換系統(tǒng)線程~thread_index s只能在統(tǒng)一系統(tǒng)內(nèi)切換調(diào)試目標(biāo)繁忙命令提示符,*BUSY*命令編輯框,Debuggee is runningWinDBG執(zhí)行命令繁忙命令提示符,*BUSY*命令編輯框,空執(zhí)行.abandon放棄調(diào)試目標(biāo)命令提示符,NoTarget>命令編輯框,空等待用戶輸入命令提示符,Input>命令編輯框,空30.4 輸入和執(zhí)行命令30.4.1 要點命令分隔符,;重復(fù)命令,回車鍵歷史命令,方向鍵終止命令,Ctrl+Break使用KD或CDB時,使用Ctrl+C詳細輸出模式切換,Ctrl+Alt+V顯示W(wǎng)inDBG與內(nèi)核調(diào)試引擎之間的數(shù)據(jù)通信,Ctrl+Alt+D幫助,F1或.hh command30.4.2 表達式參考幫助文檔,MASM Numbers and Operators語言?宏匯編語法??C++表達式運算符基本,加減乘除、移位、求余、比較、位操作、正負(fù)號特殊hi或low,取得32位數(shù)的高16位或低16位by或wo或dwo或qwo,從指定地址讀數(shù)單字節(jié)或單字或雙字或四字poi,從指定地址讀數(shù)指針長度類函數(shù)運算符$iment(Address),返回參數(shù)代表模塊的入口地址$scmp("String1", "String2"),比較字符串$sicmp("String1", "String2"),比較字符串,忽略大小寫$spat("String", "Pattern"),判斷字符串符合模式$vvalid(Address, Length),判斷有效內(nèi)存區(qū)$fnsucc(FnAddress, RetVal, Flag),判斷函數(shù)執(zhí)行成功注釋可被記到日志中*之后皆注釋*中間皆注釋;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,可保存任意整數(shù)值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 內(nèi)核態(tài)下為nt,用戶態(tài)下為ntdll $ntwsym ntdll32,ntdll$ntsym 與當(dāng)前調(diào)試目標(biāo)的機器模型匹配的NT模塊名稱$CurrentDumpFile 轉(zhuǎn)儲文件名稱$CurrentDumpPath 轉(zhuǎn)出文件路徑$CurrentDumpArchiveFile 最近加載的CAB文件名稱$CurrentDumpArchivePath 最近加載的CAB文件路徑查看別名的取值.echo別名引用的形式寬度,適合固定名稱別名空格,適合所有分隔符,${alias},適合用戶定義別名和自動定義別名30.4.5 循環(huán)和分支z命令語法,z(condition)功能,condition不為0和false,則重新執(zhí)行命令例子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 進程和線程限定符條件 進程 線程當(dāng)前 |. ~.導(dǎo)致當(dāng)前調(diào)試事件 |# ~#當(dāng)前系統(tǒng)所有 |* ~*序號 |Number ~numberID |~ID ~~ID30.4.7 記錄到文件.logopen,打開日志文件.logfile,查看日志文件狀態(tài).logclose,關(guān)閉日志文件30.5 建立調(diào)試會話30.5.1 附加到已有進程菜單方式File > Attach a Process設(shè)置為JIT調(diào)試器WinDBG.exe -I當(dāng)程序崩潰后,在錯誤對話框中選擇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需要已經(jīng)有一個調(diào)試會話常用于同時調(diào)試多個目標(biāo)時被.abandon拋棄的被調(diào)試進程,可以重新附加WinDBG.exe -pe -p PID30.5.2 創(chuàng)建進程并調(diào)試菜單方式File > Open Executable命令行方式windbg executable.create需要已經(jīng)有一個調(diào)試會話常用于同時調(diào)試多個目標(biāo)時30.5.3 非侵入式調(diào)試調(diào)試用戶態(tài)進程的一種特殊方式windbg與目標(biāo)進程,沒有真正建立調(diào)試與被調(diào)試的關(guān)系,不能接收到任何調(diào)試事件不能使用控制調(diào)試目標(biāo)執(zhí)行的命令,如單步、繼續(xù)等只能使用行觀目標(biāo)進程的命令好處減少調(diào)試器對目標(biāo)進程的干預(yù),最大程度減少海森伯效應(yīng)不影響其他調(diào)試器附加到目標(biāo)進程進行調(diào)試方式只能用于附加方式菜單方式復(fù)選Noninvasive命令行方式WinDBG.exe -pv PID.attach加上-v開光JIT不支持該方式用途W(wǎng)indows NT和Windows 2000不支持調(diào)試器和調(diào)試目標(biāo)分離(detach)一旦建立調(diào)試關(guān)系,結(jié)束調(diào)試會話將會結(jié)束調(diào)試進程若使用非侵入方式附加調(diào)試,分析結(jié)束時只需執(zhí)行分離命令,即可恢復(fù) 30.5.4 雙機內(nèi)核調(diào)試步驟1. 選擇通信方式串口方式,兼容性好,可靠性高1394端口,速度快但不穩(wěn)定USB22. 啟用目標(biāo)系統(tǒng)的內(nèi)核調(diào)試引擎Vista之前的系統(tǒng),修改boot.iniVista之后的系統(tǒng),使用BCDEdit工具修改啟動選項3. 啟動調(diào)試會話菜單方式File > Kernel Debug命令行方式windbg -k com:port=Com1, baud=1152004. 后續(xù)windbg顯示"Waiting to reconnect..."并進入等待狀態(tài)等待目標(biāo)系統(tǒng)的調(diào)試數(shù)據(jù)并按照一定時間間隔(10s)發(fā)送復(fù)位數(shù)據(jù)包(PACKET_TYPE_KD_RESET)目標(biāo)系統(tǒng)在啟動早期,初始化內(nèi)核調(diào)試引擎時,會向調(diào)試器發(fā)送信息windbg收到信息后,開始與目標(biāo)系統(tǒng)對話,并建立調(diào)試連接30.5.5 本地內(nèi)核調(diào)試系統(tǒng)條件Windows 2000或更早的系統(tǒng),不支持Windows XP沒有要求Windows Vista,需要以調(diào)試選項啟動系統(tǒng)啟動方式菜單File > Kernel Debug > Local命令行windbg -kl.attach -k需要已經(jīng)有一個調(diào)試會話常用于同時調(diào)試多個目標(biāo)時30.5.6 調(diào)試轉(zhuǎn)儲文件菜單File > Open Crash Dump命令行windbg -z.opendump需要已經(jīng)有一個調(diào)試會話常用于同時調(diào)試多個目標(biāo)時30.5.7 遠程調(diào)試本質(zhì),本地調(diào)試+遠程通信實現(xiàn)方式方式一服務(wù)器DbgSrv(遠程用戶態(tài)調(diào)試)KdSrv(遠程內(nèi)核態(tài)調(diào)試)客戶端windbg方式二(使用)服務(wù)器和客戶端,都是windbg啟動服務(wù)器命令行方式windbg -server 服務(wù)器通信字符串命令方式建立調(diào)試會話.server 服務(wù)器通信字符串服務(wù)器通信字符串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 終止調(diào)試會話30.6.1 停止調(diào)試方式菜單debug > stop debugging命令q結(jié)果windbg恢復(fù)到賦閑(dormant)狀態(tài)調(diào)試目標(biāo)活動的用戶態(tài)目標(biāo),被終止活動的內(nèi)核目標(biāo),保持被中斷到調(diào)試器的狀態(tài),可重新與其建立連接30.6.2 分離調(diào)試目標(biāo)目的,使調(diào)試目標(biāo)繼續(xù)運行方式菜單debug > detach debuggee命令.detach結(jié)果windbg沒有其他調(diào)試目標(biāo)時,則恢復(fù)到賦閑(dormant)狀態(tài)調(diào)試目標(biāo)繼續(xù)運行對于進程,系統(tǒng)會修改進程屬性,使其脫離被調(diào)試狀態(tài)而成為普通進程條件Windows XP或更高版本依賴于Windows XP才引入的操作系統(tǒng)支持(DebugSetProcessKillOnExit API)30.6.3 拋棄被調(diào)試進程目的,重新附加調(diào)試目標(biāo)方式命令.abandon結(jié)果windbg沒有其他調(diào)試目標(biāo)時,則恢復(fù)到無調(diào)試目標(biāo)狀態(tài)被調(diào)試進程被拋棄后,仍處于掛起狀態(tài)調(diào)試器中僅執(zhí)行了注銷操作,沒有恢復(fù)進程狀態(tài)重新附加windbg -pe -p PID注意沒有-pe,調(diào)試器附加失敗,并報告DebugPort不為空有了-pe,調(diào)試器不會報錯,調(diào)試器引擎會產(chǎn)生一個異常,觸發(fā)調(diào)試器進入命令模式,使繼續(xù)調(diào)試30.6.4 殺死被調(diào)試進程方式命令.kill,會調(diào)用系統(tǒng)TerminateProcess API來終止進程結(jié)果windbg仍可觀察調(diào)試目標(biāo)的數(shù)據(jù)執(zhí)行g(shù)時,會結(jié)束當(dāng)前調(diào)試會話沒有其他調(diào)試目標(biāo)時,則恢復(fù)到賦閑(dormant)狀態(tài)被調(diào)試進程被終止30.6.5 調(diào)試器終止或僵死調(diào)試器終止建立的調(diào)試會話會被終止活動的被調(diào)試進程,被終止調(diào)試器僵死可使用-pe -p PID啟動windbg,重新附加被調(diào)試進程,后終止僵死的調(diào)試器30.6.6 重新開始調(diào)試方式菜單debug > restart命令.restart結(jié)果對于調(diào)試會話源于"創(chuàng)建進程并調(diào)試",關(guān)閉被調(diào)試進程并重新運行和調(diào)試對于調(diào)試會話源于"附加到已有進程",不支持對于內(nèi)核態(tài)調(diào)試.restart,重啟調(diào)試器后再建立調(diào)試連接.reboot,目標(biāo)系統(tǒng)重啟30.7 理解上下文30.7.0 概述上下文,操作的執(zhí)行環(huán)境,討論的背景信息30.7.1 登錄會話上下文(Login Session Context)含義,登錄會話語境,當(dāng)前操作或陳述的Windows支持同時多個登錄對話,每個對話擁有自身的輸入輸出設(shè)備和桌面例子Windows XP系統(tǒng)中,一般只有一個會話,被遠程桌面登錄后就會有兩個Windows Vista引入對話隔離技術(shù)(Session Isolation),所有系統(tǒng)服務(wù)運行在會話0以增強系統(tǒng)服務(wù)安全性,故至少存在兩個會話目前會話上下文僅在內(nèi)核調(diào)試時有意義,相關(guān)擴展命令僅在調(diào)試內(nèi)核目標(biāo)時有意義!session!session,顯示狀態(tài)!session -s index,切換改變會話后,默認(rèn)進程會變成新會話中的進程,以前緩存的用戶空間數(shù)據(jù)不再有效為了避免用戶觀察到錯誤的數(shù)據(jù),可使用.cache命令在緩存選項中加入forcedecodeuser或forcedecodeptes選項禁止緩存功能,讓調(diào)試器每次都重新讀取內(nèi)存數(shù)據(jù)!spross,列出會話中所有進程進程的EPROCESS結(jié)構(gòu)的Session字段記錄著進程的所屬會話每個會話都包含了Windows子系統(tǒng)服務(wù)器進程(CSRSS)會話管理器不屬于任一會話30.7.2 進程上下文含義,進程語境,當(dāng)前操作或陳述的在Windows操作系統(tǒng)中所有進程的內(nèi)核空間是共享的,用戶空間是獨立的在32系統(tǒng)中,單個進程共4GB進程空間,低2GB是用戶空間,高2GB是內(nèi)核空間在內(nèi)核調(diào)試時觀察內(nèi)核數(shù)據(jù),不需要關(guān)心當(dāng)前進程觀察用戶空間數(shù)據(jù),需要注意當(dāng)前進程,同一用戶態(tài)地址對不同進程的含義不同(實際的物理地址不同)當(dāng)調(diào)試目標(biāo)中斷到調(diào)試器中后,WinDBG會根據(jù)調(diào)試事件設(shè)置默認(rèn)進程若要觀察其他進程的用戶空間,需要先切換進程上下文.process process_EPROCESS_address,根據(jù)進程的EPROCESS結(jié)構(gòu)切換進程.process 0 0,列出所有進程的基本信息.context設(shè)置和顯示頁目錄基址(base of page directory)(用于翻譯用戶態(tài)地址)頁目錄基址是進程的一個重要屬性,使用.process設(shè)置進程上下文時自動設(shè)置對于x86系統(tǒng),cr3寄存器存放頁目錄基址,一個進程只有一個頁目錄基址對于安騰系統(tǒng),一個進程可使用多個頁目錄基址.process和.context僅用在內(nèi)核調(diào)試中調(diào)試用戶態(tài)目標(biāo)時所有虛地址都是基于當(dāng)前進程的,不需要切換進程上下文在一個調(diào)試會話中調(diào)試多個用戶態(tài)目標(biāo)時,應(yīng)使用"lNumber s"切換進程30.7.3 寄存器上下文(register context)含義,寄存器語境,當(dāng)前操作或陳述的在多任務(wù)系統(tǒng)中CPU寄存器保存的是當(dāng)前正在執(zhí)行的線程的寄存器值對于沒執(zhí)行的線程,其寄存器值保存在內(nèi)存中,當(dāng)線程恢復(fù)執(zhí)行時,寄存器值從內(nèi)存加載到寄存器中在調(diào)試器中觀察一個線程的寄存器(不含MSR)時,該線程處于掛起狀態(tài),觀察和修改的寄存器值源于內(nèi)存系統(tǒng)會在以下情況中,將寄存器值保存到當(dāng)前線程的上下文記錄(context record)中線程切換時,該上下文常被稱為線程上下文中斷或異常時,該上下文常被稱為異常上下文.thread.thread thread_ETHREAD_address,根據(jù)線程的ETHREAD結(jié)構(gòu)切換線程.thread,查看當(dāng)前線程.process process_EPROCESS_address f列出一個進程的所有線程.crx或.thread將線程上下文恢復(fù)成以前的情況.ecrx在調(diào)試用戶態(tài)轉(zhuǎn)儲文件時,可將其中保存的異常上下文設(shè)置為寄存器上下文在不同寄存器上下文中,觀察到的寄存器和棧不同rkv30.7.4 局部(變量)上下文(local context)含義,局部變量語境,當(dāng)前操作或陳述的一個運行中的函數(shù),對應(yīng)一個局部上下文運行中的函數(shù),其局部變量信息存放在調(diào)用棧中使用棧幀號代表局部上下文.frame.frame,觀察當(dāng)前局部上下文.frame frame_index(十六進制),切換當(dāng)前局部上下文到指定棧幀dv,查看當(dāng)前局部上下文中的參數(shù)和局部變量例子源碼void test_windbg(int a){int b = 2;getchar();}int main(){test_windbg(1);return 0;}啟動windbg -g .\Test.exe線程查看和切換~* 查看所有線程~0 s 切換到0號線程~. 查看當(dāng)前線程棧幀查看和切換k.frame.frame a查看函數(shù)參數(shù)和局部變量dv30.7.5 上下文的關(guān)系操作或陳述核心,作為操作或陳述的主體操作或陳述語境,作為操作或陳述的客體兩者是多對多或一對多的關(guān)系,兩者的組合整體作為新的上一層次的可標(biāo)識實體(操作或陳述核心)關(guān)系會話進程會話上下文進程進程上下文線程(多個)線程上下文寄存器上下文調(diào)用棧局部(變量)上下文(多個)線程變量CPU時間片30.8 調(diào)試符號30.8.1 重要意義調(diào)試符號(debug symbols)其有無和版本是否準(zhǔn)確,嚴(yán)重影響調(diào)試器的工作30.8.2 符號搜索路徑背景一個調(diào)試目標(biāo),可能存在多個符號文件,且不在同一位置需要告訴調(diào)試器多個目錄并按一定順序搜索符號文件符號搜索路徑符號文件搜索路徑的列表多個路徑使用分號分隔簡稱符號路徑(symbol path)路徑種類文件系統(tǒng)路徑符號服務(wù)器設(shè)置方法符號環(huán)境變量_NT_SYMBOL_PATH_NT_ALT_SYMBOL_PATH命令行參數(shù),-y.sympath命令,增刪顯示.symfix命令,自動設(shè)置菜單,File>Symbol File Path顯示,.sympath命令30.8.3 符號服務(wù)器背景一個調(diào)試目標(biāo),可能存在多個模塊,一個模塊可能包含多個版本,每個版本對應(yīng)一個符號文件這項符號文件查詢工作,無聊和繁瑣,可以交給程序完成符號服務(wù)器(symbol server),存儲符號文件的文件服務(wù)器可以從中獲取指定特征(名稱和版本)的符號文件符號服務(wù)器架構(gòu)示意圖windbg.exeVDbgEng.dllVDbgHelp.dllV符號服務(wù)器Dll(SymSrv.dll)||------------> 下游符號庫|----(網(wǎng)絡(luò))--> 中央符號庫(centralized store)(符號服務(wù)器)DbgHelp.dllWindows操作系統(tǒng)的調(diào)試輔助庫模塊windbg通過它,讀取和解析調(diào)試符號符號服務(wù)器Dll符號服務(wù)器的本地模塊負(fù)責(zé)從符號服務(wù)器查找、下載和管理符號文件具體dll不固定,只要實現(xiàn)了DbgHelp.dll依賴的符號服務(wù)器APIwindbg開發(fā)工具包中DbgHelp幫助文檔(sdk\help\dbghelp.chm),描述了符號服務(wù)器API用戶可以自己實現(xiàn)符號服務(wù)器dllwindbg工具包中包含了一個符號服務(wù)器(SymSrv.dll)下游符號庫(downstream store)用于緩存從符號服務(wù)器下載的符號文件工作流程DbgHelp請求符號服務(wù)器Dll,獲取指定符號文件符號服務(wù)器Dll先在下游符號庫查找,失敗后在中央符號庫查找路徑表示完整表示symsrv*ServerDll*[DownstreamStore*]ServerPath基于SymSrv.dll的表示symsrv*SymSrv.dll*[DownstreamStore*]ServerPath簡寫為srv*[DownstreamStore*]ServerPath30.8.4 加載符號文件設(shè)置符號路徑.sympath srv*D:\Symbols*http://msdl.microsoft.com/download/symbols調(diào)試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函數(shù)符號服務(wù)器API功能,向服務(wù)器請求指定的符號文件,返回文件的完整路徑典型實現(xiàn)在下游符號庫中查找符號文件找到,則返回完整路徑未找到,則進行遠程查找若找到,則下載到下游符號庫中,后返回完整路徑函數(shù)原型BOOL CALLBACK SymbolServer( [in] LPCSTR params, [in] LPCSTR filename, [in] PVOID id, [in] DWORD two, [in] DWORD three, [out] LPSTR path );params符號服務(wù)器參數(shù)信息DownstreamStore和ServerPathfilename符號文件名id符號文件第一標(biāo)識信息.dbg和pe文件(.exe和.dll)PE文件頭定義的映像時間戳(TimeDateStamp).pdbPDB簽名two符號文件第二標(biāo)識信息.dbg和pe文件(.exe和.dll)PE文件頭定義的映像文件大小()SizeOfImage.pdbPDB年齡(Age)three符號文件第三標(biāo)識信息.dbg和pe文件(.exe和.dll)和.pdb未使用為0path符號文件的完整路徑最大長度為MAX_PATH流程使用文件特征標(biāo)識,調(diào)用SymbolServerGetIndexStringW函數(shù),生成索引串文件特征標(biāo)識的唯一性序列化調(diào)用SymbolServerByIndexW函數(shù),獲取文件名和索引串指定的符號文件調(diào)用cascade函數(shù)調(diào)用StoreUNC函數(shù),在下游符號庫中查找使用StoreWinInet類,在中央符號庫中查找觸發(fā)調(diào)試器加載符號ld.reload其他使用符號的命令,如棧回溯命令(k*)反匯編命令windbg采用懶惰式符號加載策略(lazy symbol loading)故在查看模塊列表時,會發(fā)現(xiàn)許多模塊的符號狀態(tài)為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,模塊在進程空間中的結(jié)束地址module name,模塊名稱符號文件加載狀態(tài)縮寫 含義deferred 模塊已加載,但尚未嘗試加載符號# 符號文件和可執(zhí)行文件之間的時間戳或校驗和不匹配T 時間戳,丟失、不可訪問、等于零C 校驗和,丟失、不可訪問、等于零DIA 通過調(diào)試接口訪問(DIA,debug interface access)加載了符號文件Export 未找到符號文件,使用映像文件的輸出信息(如dll的export)作為符號M 符號文件和可執(zhí)行文件之間的時間戳或校驗和不匹配,但仍然加載了該符號文件PERF 執(zhí)行文件包含性能優(yōu)化代碼。對地址的加減運算可能出錯Stripped 調(diào)試信息是從映像文件中抽取出來的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名稱支持通配符? 任意符號出現(xiàn)一次* 任意符號出現(xiàn)0次或多次# 指定符號出現(xiàn)[]# 指定符號串出現(xiàn)選項控制結(jié)果顯示順序/a,/A,地址升序和降序/n,/N,名稱升序和降序/z,/Z,符號大小升序和降序顯示符號的數(shù)據(jù)類型/t條件,需要私有符號,否則顯示<NoType>顯示符號的符號類型和符號大小/v符號類型訪問種類prv,private,私有符號pub,public,公共符號信息種類localglobalparameterfunctionunknown符號大小函數(shù)類符號,函數(shù)在內(nèi)存中的大小其他類型符號,數(shù)據(jù)類型的大小條件,需要私有符號,否則顯示0按大小過濾符號/s size控制顯示格式/p,去掉函數(shù)名與括號間的空格/q,符號名的引號格式,@!"符號名"結(jié)果含義[符號類型]符號地址函數(shù)的入口地址變量的起始地址[符號大小][符號數(shù)據(jù)類型]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 設(shè)置符號選項符號選項windbg使用32的dword記錄符號選項標(biāo)志 選項名 含義 默認(rèn)值0x1 SYMOPT_CASE_INSENSITIVE 不分大小寫 On0x2 SYMOPT_UNDNAME 顯示未裝飾的符號名 On0x4 SYMOPT_DEFERRED_LOADS 延遲加載符號 On0x8 SYMOPT_NO_CPP 關(guān)閉C++翻譯(使用時,類成員的__或被替換成::) Off0x10 SYMOPT_LOAD_LINES 加載源碼行信息 KD和CDB中為Off,WinDbg 中為On0x20 SYMOPT_OMAP_FIND_NEAREST 允許為優(yōu)化過的代碼使用最相近的符號 On0x40 SYMOPT_LOAD_ANYTHING 降低匹配符號的挑剔度 Off0x80 SYMOPT_IGNORE_CVREC 忽略映像文件的cv記錄 Off0x100 SYMOPT_NO_UNQUALIFIED_LOADS 禁止符號處理器自動加載模塊 Off0x200 SYMOPT_FAIL_CRITICAL_ERRORS 顯示關(guān)鍵錯誤 On0x400 SYMOPT_EXACT_SYMBOLS 嚴(yán)格評估所有符號文件 Off0x800 SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 允許位于內(nèi)存絕對地址的符號 Off0x1000 SYMOPT_IGNORE_NT_SYMPATH 忽略環(huán)境變量中的符號和鏡像路徑 Off0x2000 SYMOPT_INCLUDE_32BIT_MODULES 對于安騰處理器,強制列舉32位模塊 Off0x4000 SYMOPT_PUBLICS_ONLY 忽略全局、局部和作用域相關(guān)的符號 Off0x8000 SYMOPT_NO_PUBLICS 不搜索公共符號表 Off0x10000 SYMOPT_AUTO_PUBLICS 其他方法失敗時,才使用PDB文件中的公共符號 On0x20000 SYMOPT_NO_IMAGE_SEARCH 不搜索鏡像文件 On0x40000 SYMOPT_SECURE (內(nèi)核調(diào)試)Secure Mode Off0x80000 SYMOPT_NO_PROMPTS (遠程調(diào)試)不顯示代理服務(wù)器的認(rèn)證對話框 KD和CDB中為On,WinDbg 中為Off0x80000000 SYMOPT_DEBUG 顯示符號加載過程 Off增加設(shè)置.symopt + option_valueoption_value為十六進制標(biāo)志位,如0x1,0x2,0x4取消設(shè)置.symopt - option_value顯示設(shè)置.symopt友好設(shè)置!sym!sym noisy,即+ 0x80000000!sym quiet,即- 0x80000000!sym prompts,即+ 0x80000!sym prompts off,即- 0x8000030.8.9 加載不嚴(yán)格匹配的符號文件方式.reload /i module_name設(shè)置符號選項,.symopt +0x40注意加載前,最好開啟"嘈雜"模式(!sym noisy),以觀察加載細節(jié)30.9 事件處理30.9.0 概述Windows的調(diào)試模型是事件驅(qū)動的整個調(diào)試過程,就是調(diào)試事件的產(chǎn)生、發(fā)送、接收和處理調(diào)試目標(biāo),產(chǎn)生調(diào)試事件調(diào)試器,接收和處理調(diào)試事件調(diào)試子系統(tǒng),發(fā)送調(diào)試事件給調(diào)試器,為調(diào)試器提供服務(wù)30.9.1 調(diào)試事件和異常的關(guān)系Windows定義了9類調(diào)試事件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)其他的調(diào)試器事件專供調(diào)試使用 異常是一種調(diào)試事件,EXCEPTION_DEBUG_EVENT(1)異常調(diào)試事件,包含子類,其他類型調(diào)試事件不包含Win32異常Windows操作系統(tǒng)定義的類型CPU產(chǎn)生的異常系統(tǒng)內(nèi)核定義的異常典型非法訪問、除零等異常代碼ntstatus.h Visual C++異常Visual C++編譯器的throw關(guān)鍵字所拋出的異常throw關(guān)鍵字調(diào)用RaiseException API產(chǎn)生異常異常代碼都是 0xe06d7363(.msc) 托管異常.Net程序使用托管方法拋出的異常異常代碼都是0xe0636f6d(.com) 其它異常類型用戶程序直接調(diào)用RaiseException API拋出的異常其它C++編譯器拋出的異常等 30.9.2 兩輪機會Windows的異常分發(fā)流程第一輪分發(fā)給調(diào)試器,調(diào)試器判斷接收和返回處理結(jié)果調(diào)試器通常返回沒有處理異常,使之繼續(xù)分發(fā)對于斷點異常和調(diào)試異常,調(diào)試器會返回已經(jīng)處理嘗試分發(fā)給異常處理器(VEH、SEH)第二輪分發(fā)給調(diào)試器,調(diào)試器判斷接收和返回處理結(jié)果調(diào)試器通常返回已經(jīng)處理,讓系統(tǒng)恢復(fù)程序執(zhí)行,通常會導(dǎo)致重復(fù)循環(huán)分發(fā)終極處理異常源自應(yīng)用程序,系統(tǒng)啟動"應(yīng)用程序錯誤報告過程",終止應(yīng)用程序異常源自內(nèi)核代碼,系統(tǒng)啟動"藍屏機制"其他調(diào)試事件只有一輪機會分發(fā)流程,實現(xiàn)了一個異常處理鏈調(diào)試用異常,實現(xiàn)調(diào)試目的有處理器的異常,實現(xiàn)程序邏輯無處理器的異常,攔截未處理的異常所有異常,實現(xiàn)異常的兜底處理30.9.3 定制事件處理方式每個異常事件都存在四個選項第一輪機會是否中斷到調(diào)試器第一輪機會的處理結(jié)果第二輪機會是否中斷到調(diào)試器第二輪機會的處理結(jié)果Visual C++和Visual Studio都有異常設(shè)置windbg圖形界面Debug > Event FiltersExecution組單選,控制是否中斷Enabled異常事件兩次都中斷,其他調(diào)試事件會中斷Disabled異常事件第二次中斷,其他調(diào)試事件不中斷Output輸出信息通知用戶Ignore忽略Continue組單選,控制第一次異常事件的處理結(jié)果Handled,返回已處理Not Handled,返回未處理大多異常默認(rèn)設(shè)置為未處理對于第二次異常事件的處理結(jié)果默認(rèn)設(shè)置為返回已處理在調(diào)試時,可使用gn命令,表示異常未處理支持為事件定義關(guān)聯(lián)命令(Commands)異常事件有兩次關(guān)聯(lián),其他調(diào)試事件有一次關(guān)聯(lián)支持設(shè)置事件參數(shù)以細化過濾條件(Arguments)支持事件處理方式的增刪命令配置信息要素條件對象事件和參數(shù)中斷方式Enabled,Disabled,Output,Ignore處理結(jié)果已處理和未處理關(guān)聯(lián)命令第一次和第二次命令設(shè)置中斷方式和關(guān)聯(lián)命令sx{e|d|i|n} [-c "cmd1"] [-c2 "cmd2"] {Exception|Event|*}設(shè)置處理結(jié)果已處理,sxe -h {Exception|Event|*}未處理,sx{d|i|n} -h {Exception|Event|*}查看當(dāng)前設(shè)置sx恢復(fù)默認(rèn)設(shè)置sxrException|Event的表示事件碼,Event Codesx命令查看幫助文檔搜索"Controlling Exceptions and Events"30.9.4 GH和GN命令在調(diào)試中,使用g命令恢復(fù)調(diào)試目標(biāo)的執(zhí)行,此時調(diào)試器會返回配置的或默認(rèn)的處理結(jié)果可使用命令臨時指定返回的處理結(jié)果已處理(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,設(shè)置兩輪中斷sxd -h av,設(shè)置第一輪返回不處理sx,查看設(shè)置av - Access violation - break - not handledg,恢復(fù)執(zhí)行,觸發(fā)第一次中斷(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,臨時返回已處理,由于異常條件仍存在,導(dǎo)致循環(huán)重復(fù)觸發(fā)第一次中斷(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,恢復(fù)執(zhí)行,按配置返回未處理由于沒有在程序中找到異常處理器(VEH、SEH等),系統(tǒng)會執(zhí)行缺省的異常處理器(kernel32.dll中UnhandledExceptionFilter函數(shù))判斷當(dāng)前程序是否處于調(diào)試狀態(tài)否,啟動應(yīng)用程序錯誤對話框,通知用戶終止程序是,返回EXCEPTION_CONTINUE_SEARCH,導(dǎo)致進入異常的第二次分發(fā)(43f4.4988): Access violation - code c0000005 (!!! second chance !!!)dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????g,恢復(fù)執(zhí)行,按配置返回已處理,由于異常條件仍存在,導(dǎo)致循環(huán)重復(fù)觸發(fā)第一次中斷(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,進入異常的二次分發(fā)(43f4.4988): Access violation - code c0000005 (!!! second chance !!!)dbgee!wmain+0x36:00007ff6`945118f6 c704250000000001000000 mov dword ptr [0],1 ds:00000000`00000000=????????gn,返回未處理,系統(tǒng)終止調(diào)試目標(biāo)30.10 控制調(diào)試目標(biāo)30.10.1 初始斷點目的,為了讓調(diào)試人員盡早分析調(diào)試目標(biāo)手段Windows操作系統(tǒng)的進程加載器支持在完成最基本的用戶態(tài)初始化工作后系統(tǒng)的模塊加載函數(shù),主動執(zhí)行斷點指令,觸發(fā)斷點,讓調(diào)試目標(biāo)中斷到調(diào)試器中初始斷點,進入后的首個默認(rèn)斷點創(chuàng)建調(diào)試目標(biāo)的情況分析創(chuàng)建新進程時,會在父進程的環(huán)境中完成很多創(chuàng)建工作進程對象,進程空間,初始線程,通知子系統(tǒng)等初始線程在新進程環(huán)境中執(zhí)行內(nèi)核態(tài)的KiThreadStartup將線程的IRQL(中斷級別)降到APC級別調(diào)用PspUserThreadStartup,為線程在用戶態(tài)執(zhí)行做準(zhǔn)備初始化一個對用戶態(tài)代碼的異步過程調(diào)用(APC),并插入APC隊列等待APC完成將線程的IRQL降到0(PASSIVE)調(diào)用線程上下文中的進程啟動函數(shù)BaseProcessStartBaseProcessStart調(diào)用應(yīng)用程序入口函數(shù)異步過程調(diào)用該APC調(diào)用NTDLL.dll中的LdrpInitialize函數(shù)LdrpInitialize函數(shù),算是新進程的初始化線程,在用戶態(tài)執(zhí)行的最早代碼LdrpInitialize工作初始化加載器和讀取執(zhí)行選項調(diào)用LdrpInitializeProcess函數(shù)加載Exe文件依賴的動態(tài)鏈接庫判斷是否處于調(diào)試狀態(tài),是則調(diào)用DbgBreakPoint通知調(diào)試器注意,此時還未調(diào)用DLL的DllMain函數(shù)異步過程調(diào)用結(jié)束后KiUserApcDispatcher調(diào)用ZwContinue,返回到內(nèi)核態(tài)的PspUserThreadStartup函數(shù)中附加調(diào)試目標(biāo)的情況分析windbg在目標(biāo)進程中,創(chuàng)建一個遠程線程,來觸發(fā)一個初始斷點初始斷點發(fā)生在新建線程的上下文中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注意,該線程不是目標(biāo)進程的自建線程而是調(diào)試器為了達到調(diào)試目的而創(chuàng)建的恢復(fù)執(zhí)行后,線程結(jié)束其他當(dāng)windbg使用-g選項啟動時對于新建調(diào)試windbg收到初始斷點事件,不中斷對于附加調(diào)試windbg不創(chuàng)建遠程線程來觸發(fā)斷點初始斷點不是最早的中斷機會但是足夠使用,初始斷點可用于跟蹤和分析程序和DLL的入口函數(shù)設(shè)置斷點等準(zhǔn)備工作其他較早的中斷機會進程創(chuàng)建事件EXE模塊的加載事件30.10.2 俘獲調(diào)試目標(biāo)中斷調(diào)試目標(biāo)的方式windbg中主動中斷快捷鍵,Ctrl+Break菜單,Bebug > Break調(diào)試目標(biāo)中主動中斷對于調(diào)試中的圖形界面程序,按F12調(diào)試目標(biāo),遇到斷點和觸發(fā)異常windbg中主動中斷的分析方式,windbg調(diào)試windbg的調(diào)試啟動新windbg附加舊windbg設(shè)置符號路徑(符號服務(wù)器)重新加載模塊符號,確保相關(guān)符號下載完成windbg.pdbdbgeng.pdb注意下載部分就失敗的情形下游符號庫中,出現(xiàn)未下載完整的符號文件注意開啟"顯示符號加載過程",!sym noisy有下載的加載失敗SYMSRV: dbgeng.pdb from https://msdl.microsoft.com/download/symbols: 4213760 bytes - 34 percentSYMSRV: /download/symbols/dbgeng.pdb/3905A3278DCD49AEA0C08989F59DB6D91/dbgeng.pdb函數(shù)不正確。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加載模塊的符號狀態(tài)失敗情形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...設(shè)置斷點bu ntdll!RtlpCreateUserThreadEx bu ntdll!NtCreateThreadEx 普通情況(創(chuàng)建遠程線程中斷目標(biāo))windbg執(zhí)行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窗口過程函數(shù)收到Break命令后,調(diào)用全局變量g_DbgClient的方法SetInterruptHRESULT IDebugControl::SetInterrupt(IN ULONG Flags);Flags取值DEBUG_INTERRUPT_PASSIVE(1)希望中斷到命令模式,但不強制函數(shù)內(nèi)部將dbgeng!g_UserInterruptCount加一,將dbgeng!g_EngStatus設(shè)置為0x1005DEBUG_INTERRUPT_EXIT(2)讓調(diào)試引擎取消等待調(diào)試事件,強制返回通常會導(dǎo)致沒有調(diào)試目標(biāo)將dbgeng!g_EngStatus設(shè)置為0x1008DEBUG_INTERRUPT_ACTIVE(0)通過全局變量dbgeng!g_CmdState,判斷調(diào)試器是否處于命令模式否,則要求調(diào)試目標(biāo)中斷到調(diào)試器以進入命令模式是,則遞增dbgeng!g_UserInterruptCountUI線程使用的是0遠程線程的線程函數(shù),DbgUiRemoteBreakin調(diào)用DbgBreakPoint函數(shù),執(zhí)行斷點指令,產(chǎn)生斷點異常極限情況(超時則強制掛起)遠程線程一產(chǎn)生,還未執(zhí)行斷點指令,就被掛起windbg的處理等待一段時間后,顯示提示信息Break-in sent,waiting 30 seconds再等待30秒,windbg產(chǎn)生一個異常事件(事件碼為 0x8000 0007)SynthesizeWakeEvent這個事件觸發(fā)調(diào)試器等待函數(shù)返回,并處理該事件會引發(fā)dbgeng!SyspendExecution函數(shù)調(diào)用掛起調(diào)試目標(biāo)所有線程,使調(diào)試目標(biāo)被中斷調(diào)試器進入命令模式并顯示信息Wake debugger - code 80000007 (first chance)30.10.3 繼續(xù)運行從指定地址繼續(xù),同時設(shè)定臨時斷點g [a] [= start_address] [break_address ... [; break_commands]]指定地址,start_address斷點硬件斷點與普通斷點,有無a斷點地址,break_address斷點觸發(fā)后命令,break_commands可實現(xiàn)執(zhí)行到光標(biāo)g,缺省時,從當(dāng)前地址繼續(xù),無斷點繼續(xù)并指定異常處理結(jié)果g,返回配置的或默認(rèn)的處理結(jié)果gh,已處理(handled)gn,未處理(Not Handled)繼續(xù)到上一級函數(shù)gu條件斷點中的繼續(xù)gc30.11 單步執(zhí)行30.11.1 概覽單步的單位源碼模式,一次執(zhí)行一行源碼Debug > Source Mode 被選中l(wèi)+t匯編模式,一次執(zhí)行一條匯編指令Debug > Source Mode 未被選中l(wèi)-t單步的對象為函數(shù)調(diào)用時單步進入,step into,p命令單步越過,step over,t命令,trace非函數(shù)調(diào)用時,p和t作用相同實現(xiàn)匯編模式下的單步執(zhí)行通過CPU的陷阱機制實現(xiàn),對于x86CPU,就是設(shè)置標(biāo)志寄存器的T標(biāo)志t命令過程windbg收到t命令工作線程解析命令(ParseStepTrace),調(diào)用SetExecStep和SetNextStepTraceState函數(shù)兩個函數(shù)將用戶命令,轉(zhuǎn)化并設(shè)置到內(nèi)部對象、變量和線程的上下文結(jié)構(gòu)中調(diào)試引擎報告命令執(zhí)行完成,最后由ProcessEngineCommands返回到EngineLoopEngineLoop繼續(xù)執(zhí)行,調(diào)用DebugClient::WaitForEvent以等待下一調(diào)試事件恢復(fù)目標(biāo)運行,調(diào)試引擎會將線程上下文通過KERNELBASE!SetThreadContext設(shè)置到系統(tǒng)設(shè)置過程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查看設(shè)置參數(shù)SetThreadContext的參數(shù)MSVCR90!_CONTEXTdt MSVCR90!_CONTEXT 043839e0 +0x044 EFlags : 0x344.formats 0x344Evaluate expression:Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000011 01000100位8為跟蹤標(biāo)志,當(dāng)前為1,代表單步執(zhí)行位8為中斷標(biāo)志,當(dāng)前為1,代表啟用中斷事件代碼為8000 0003,為斷點異常事件代碼為8000 0004,為單步異常,由t命令和非越過的p命令觸發(fā)針對CALL指令單步越過的p命令是在CALL指令的下一相鄰指令,設(shè)置臨時軟件斷點源碼模式下的單步執(zhí)行通過多次設(shè)置陷阱標(biāo)志實現(xiàn),即多次匯編模式下的單步執(zhí)行完整命令p|t [r] [= start_address] [count] ["command"][r],是否顯示寄存器,缺省為顯示[= start_address],指定執(zhí)行的起始地址,缺省為當(dāng)前地址[count],指定單步執(zhí)行的次數(shù),缺省為1["command"],指定每次單步執(zhí)行后的命令,缺省為空30.11.2 單步執(zhí)行到指定地址語法pa [r] [=start_address] stop_address反復(fù)執(zhí)行單步越過,直到stop_addresspa,step to addressta [r] [=start_address] stop_address反復(fù)執(zhí)行單步進入,直到stop_addressta,trace to address實現(xiàn)gu,繼續(xù)到上一級函數(shù)pa $ra$ra,代表當(dāng)前函數(shù)的返回地址被中斷的情形單步中遇到斷點或異常30.11.3 單步執(zhí)行到下一個函數(shù)調(diào)用語法pc [r] [=start_address] [Count]反復(fù)執(zhí)行單步越過,直到CALL指令pc,step to calltc [r] [=start_address] [Count]反復(fù)執(zhí)行單步進入,直到CALL指令ta,trace to call[count],指定單步執(zhí)行到函數(shù)調(diào)用的次數(shù),缺省為1當(dāng)處理CALL指令時,當(dāng)作普通單步執(zhí)行pc,執(zhí)行完CALL指令tc,進入函數(shù)30.11.4 執(zhí)行到下一分支語法tb [r] [=start_address] [Count]一次執(zhí)行到下一分支指令tb,trace to branch實現(xiàn)設(shè)置好標(biāo)志寄存器和MSR寄存器后,便恢復(fù)程序運行當(dāng)CPU執(zhí)行到分支指令時,便報告異常停下來注意在安騰系統(tǒng)和x64系統(tǒng)上,tb可用于內(nèi)核調(diào)試和用戶態(tài)調(diào)試在x86系統(tǒng)上,tb僅用于內(nèi)核調(diào)試,使用ph和th可克服局限ph|th [r] [=start_address] [Count]分別用來單步執(zhí)行和單步追蹤到下一分支指令兩者處理CALL指令的方式不同30.11.5 追蹤并監(jiān)視wt(trace and watch data)執(zhí)行函數(shù),打印統(tǒng)計使用在函數(shù)入口處執(zhí)行,否則功能為單步執(zhí)行統(tǒng)計含義第一部分,追蹤目標(biāo)目標(biāo)函數(shù)名稱和返回地址第二部分,執(zhí)行路徑一次函數(shù)棧切換(CALL和RET),一次執(zhí)行狀態(tài)記錄第一列,當(dāng)前函數(shù)執(zhí)行的指令數(shù)可能情形[函數(shù)首指令,函數(shù)中CALL指令][函數(shù)首指令,函數(shù)中RET指令]第二列,當(dāng)前函數(shù)調(diào)用的指令數(shù)= 內(nèi)部函數(shù)的執(zhí)行指令數(shù) + 內(nèi)部函數(shù)的調(diào)用指令數(shù)第三列,函數(shù)調(diào)用深度第四列,調(diào)用深度縮進+函數(shù)名稱第三部分,統(tǒng)計指令數(shù)和調(diào)試事件數(shù)第四部分,統(tǒng)計函數(shù)的指令執(zhí)行情況調(diào)用總次數(shù)單次最大指令執(zhí)行數(shù)單次最小指令執(zhí)行數(shù)單次平均指令執(zhí)行數(shù)第五部分,系統(tǒng)服務(wù)調(diào)用情況第六部分,追蹤完成后的狀態(tài)寄存器狀態(tài)當(dāng)前程序指針位置注意使用wt追蹤復(fù)雜函數(shù)或頂層函數(shù)時,由于范圍廣,可能需要較長的時間為了提高效率,可以限制追蹤范圍-l,最大調(diào)用深度,基于目標(biāo)函數(shù)-m,指定追蹤的模塊-i,指定忽略的模塊wt命令,可被各種調(diào)試事件中斷 例子源碼(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 程序指針飛躍調(diào)試時,可以修改程序指針cs:$eip或cs:$rip下一指令的地址實現(xiàn)windbg會把地址,設(shè)置到線程上下文的程序指令寄存器中當(dāng)恢復(fù)目標(biāo)程序時,系統(tǒng)會完成線程上下文的設(shè)置使用g命令和單步命令,支持設(shè)置起始執(zhí)行地址寄存器命令r,直接修改程序指針寄存器注意由于修改了程序指針,導(dǎo)致部分指令重復(fù)執(zhí)行或跳過可能導(dǎo)致程序邏輯出錯,如棧操作和對象析構(gòu)操作等30.11.7 歸納標(biāo)準(zhǔn)命令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注意調(diào)試目標(biāo)必須是活動目標(biāo)windbg設(shè)計了元命令和擴展命令,輔助使用標(biāo)準(zhǔn)命令連續(xù)單步跟蹤時,界面更新速度頻繁,影響速度和讓人眼花繚亂,可暫停刷新界面.suspend_ui30.12 使用斷點30.12.0 概述設(shè)斷點,即埋地雷,講究埋設(shè)的地點和時機30.12.1 軟件斷點實現(xiàn)中斷指令(INT3,0xCC)運行時設(shè)置(中斷指令)中斷時恢復(fù)(原本指令)繼續(xù)時,當(dāng)前指令先執(zhí)行后設(shè)置 驗證試驗源程序(test_bp)int main(){printf("please set breakpoint at start");getchar();return 0;}調(diào)試查看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內(nèi)存使用64位WinHexTools > Open Memorytest_bp > test_bp.exe查看00007ff7`017b1000附近的內(nèi)存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 & 錳燙燙燙?可以發(fā)現(xiàn)運行時,原指令被替換00007ff7`017b1000 4883ec28 sub rsp,28h7FF7017B1000 CC 83 EC 28中斷查看test_bpCtrl + Breakwindbg代碼恢復(fù)winhex4883EC28488D0D15120000E820000000FF156211000033C04883C428C3CCCCCC488D0501260000C3CCCCCCCCCCCCCCCC可以發(fā)現(xiàn)中斷時,中斷指令被恢復(fù)注意為了避免破壞數(shù)據(jù)和代碼,只能在指令首字節(jié)位置設(shè)置斷點語法bp [id] [options] [address [passes]] ["command_string"]address,斷點地址,缺省為當(dāng)前程序指針passes,第幾次遇到時觸發(fā)中斷,缺省為1command_string,中斷觸發(fā)后執(zhí)行的命令,多個命令使用分號分隔bu [id] [options] [address [passes]] ["command_string"]設(shè)置一個以后落實的斷點用于對一個尚未加載的模塊設(shè)置斷點如調(diào)試動態(tài)加載模塊的入口函數(shù)或初始化代碼bm [options] symbol_pattern [passes] ["command_string"]設(shè)置一批斷點,如同執(zhí)行多次的bp和bu支持通配符*注意背景,在數(shù)據(jù)區(qū)設(shè)置軟件斷點,會導(dǎo)致數(shù)據(jù)意外變化bm命令在設(shè)置斷點時,只對函數(shù)類型的匹配符號設(shè)置斷點這要求調(diào)試符號有類型信息,這通常需要私有符號,但若只有公共符號文件將報錯方法一,\a,強制匹配bm不檢查符號類型,由用戶保證方法二為模塊使用完全或DLL輸出符號options/1臨時斷點,一次命中斷點命中一次后自動刪除/p EPROCESS_ADDRESS僅當(dāng)斷點事件發(fā)生在對應(yīng)進程中,才中斷僅用在內(nèi)核調(diào)試時/t ETHREAD_ADDRESS僅當(dāng)斷點事件發(fā)生在對應(yīng)線程中,才中斷僅用在內(nèi)核調(diào)試時/c Number僅當(dāng)斷點事件發(fā)生的函數(shù)調(diào)用深度,小于Number時才中斷/C Number僅當(dāng)斷點事件發(fā)生的函數(shù)調(diào)用深度,大于Number時才中斷id,不設(shè)置則自動編排30.12.2 硬件斷點定義,通過設(shè)置CPU寄存器而實現(xiàn)的斷點在x86 CPU中,就是DR0~DR7特點數(shù)量有限可實現(xiàn)軟件斷點不具有的功能,如監(jiān)視數(shù)據(jù)訪問和I/O訪問等語法ba [id] access size [options] [address [passes]] ["command_string"]觸發(fā)斷點的訪問方式e,對目標(biāo)內(nèi)存的執(zhí)行,被稱為代碼訪問斷點r,對目標(biāo)內(nèi)存的讀寫,被稱為數(shù)據(jù)訪問斷點w,對目標(biāo)內(nèi)存的寫,被稱為數(shù)據(jù)訪問斷點i,對目標(biāo)內(nèi)存的輸入輸出訪問,被稱為I/O訪問斷點觸發(fā)斷點的目標(biāo)內(nèi)存size對于e,為1對于其他,依賴于平臺x86,1、2、4x64,1、2、4、8觸發(fā)條件實際訪問包含目標(biāo)內(nèi)存address需要按照size對齊注意1硬件斷點數(shù)量有限在恢復(fù)目標(biāo)執(zhí)行時才把硬件斷點落實到上下文的寄存器中所以數(shù)量超過限制時,ba不會報錯,恢復(fù)執(zhí)行時會報錯注意2在初始斷點觸發(fā)時,不能設(shè)置硬件斷點設(shè)置會報錯提示初始斷點后,系統(tǒng)會重新設(shè)置線程上下文,故不能設(shè)置硬件斷點建議在程序入口點或初始化代碼處設(shè)置30.12.3 條件斷點背景基本中斷條件(如地址)范圍太廣,導(dǎo)致頻繁中斷希望在滿足指定條件時,才中斷方法利用中斷設(shè)置命令中的命令參數(shù)中斷觸發(fā)時,會先執(zhí)行命令參數(shù)不合條件則直接恢復(fù)(gc)"command_string""jc (condition) 'optional_commands'; 'gc'"".if (condition) {option_commands} .else {gc}"condition中讀取變量數(shù)據(jù)對地址按指定長度進行解引用poi,by,wo,dwo,qwo幫助文檔搜索,MASM Numbers and Operators30.12.4 地址表達方法內(nèi)存地址模塊符號,module!function[+N]源碼行,`module!file:line`,注意使用重音符號源碼類方法,class__method或class::method30.12.5 設(shè)置針對線程的斷點線程限定符 斷點設(shè)置命令~.,~#,~*,~number,~~ID30.12.6 管理斷點顯示,blbreak list列1 斷點序號,N列2 斷點狀態(tài),(e|d)[u],分別表示enable,disable,unresolved列3 斷點描述,斷點地址[訪問方式 訪問長度]列4 剩余穿越次數(shù),N列5 初始穿越次數(shù),(N)列6 關(guān)聯(lián)的進程和線程,進程號:線程號,線程號表示為****(任意)或~NNN(指定)列7 斷點地址的符號表示列8 關(guān)聯(lián)命令,可能不存在取消,bc 斷點號break cancel斷點號指定單個 N指定集合 N1,N2,N3任意 *范圍 N-M組合 N1,N2-N3啟用和禁用,be|bd 斷點號break enable|disable30.13 控制進程和線程30.13.0 概述討論多進程和多線程的調(diào)試知識30.13.1 MulThrds功能創(chuàng)建線程,CreateThread掛起線程,SuspendThread增加其掛起計數(shù)(Suspend Count)恢復(fù)線程,ResumeThread降低其掛起計數(shù)(Suspend Count)調(diào)試中斷,DebugBreak當(dāng)程序處于被調(diào)試狀態(tài),調(diào)用DebugBreak會中斷到調(diào)試器,否則會觸發(fā)異常導(dǎo)致關(guān)閉掛起計數(shù)線程的一個自帶屬性掛起計數(shù)大于0,則線程處于掛起狀態(tài)(Suspended),不會被執(zhí)行掛起計數(shù)最多降低到-130.13.2 控制線程執(zhí)行通常情況當(dāng)進程中斷到調(diào)試器時,所有線程會掛起當(dāng)調(diào)試目標(biāo)中斷到調(diào)試器時,windbg會對所有線程調(diào)用SuspendThread當(dāng)進程恢復(fù)時,所有線程會恢復(fù)當(dāng)調(diào)試目標(biāo)恢復(fù)時,windbg會對所有線程調(diào)用ResumeThread調(diào)試需求,獨立控制各個線程的執(zhí)行方法,控制線程的掛起計數(shù)方式一,修改掛起計數(shù)掛起計數(shù)+1,線程限定符 n實現(xiàn),調(diào)用SuspendThread掛起計數(shù)-1,線程限定符 m實現(xiàn),調(diào)用ResumeThread方式二,修改線程的凍結(jié)狀態(tài)(windbg為線程記錄的)調(diào)試器引擎內(nèi)部,調(diào)用ThreadInfo::ChangeFreeze方法凍結(jié)(freeze),線程限定符 f解凍(unfreeze),線程限定符 u實現(xiàn)當(dāng)調(diào)試目標(biāo)恢復(fù)時,windbg只會為未凍結(jié)的線程調(diào)用ResumeThread方式三,恢復(fù)指定線程線程限定符 g實現(xiàn)windbg對指定線程調(diào)用ResumeThread注意當(dāng)調(diào)試含多線程的進程時,在只恢復(fù)當(dāng)個線程的情況下,執(zhí)行Ctrl+Break默認(rèn)使用的遠程中斷線程方法會失敗,超時后windbg會使用掛起方法windbg收到Ctrl+Break命令,會在目標(biāo)進程中創(chuàng)建一個遠程線程windbg收到新線程創(chuàng)建事件打印信息,當(dāng)前只有兩個線程未被凍結(jié)windbg恢復(fù)調(diào)試目標(biāo)繼續(xù)執(zhí)行時由于調(diào)試目標(biāo)只恢復(fù)了一個線程所以調(diào)試器不會對新建線程調(diào)用ResumeThread,新建線程也被凍結(jié)windbg等待超時后,會強行掛起調(diào)試目標(biāo),后進入命令模式類似的,對指定線程進行單步執(zhí)行如,線程限定符 t相關(guān)命令~,查看所有線程線程序號 Id: 進程ID.線程ID Suspend: 掛起計數(shù) Teb: ted_address (Unfrozen|Frozen)Teb,線程環(huán)境塊30.13.3 多進程調(diào)試增加新的調(diào)試目標(biāo).attach [-premote RemoteOptions] AttachOptions PID .create [-premote RemoteOptions] [-f] CommandLine 其他調(diào)試命令查看所有的進程和線程|*~和~*查看當(dāng)前的進程和線程|進程和線程的切換|N s~N s線程執(zhí)行控制~N g|t30.14 觀察棧30.14.0 概述當(dāng)今使用的計算機系統(tǒng)都是基于棧架構(gòu)棧是進行函數(shù)調(diào)用的基礎(chǔ)30.14.1 顯示棧回溯函數(shù)棧的使用情形和內(nèi)容創(chuàng)建局部變量函數(shù)調(diào)用時,參數(shù)入棧和返回地址入棧寄存器的入棧和出棧其他信息,如中斷保護(CC)棧回溯(stack backtrace)從棧頂?shù)綏5妆闅v棧幀,追溯函數(shù)調(diào)用過程基于子rsp,通過代碼反推父rsp,棧頂棧幀的rsp在寄存器中函數(shù)調(diào)用棧宏觀上,是棧幀組成的棧結(jié)構(gòu)微觀上,是棧數(shù)據(jù)組成的棧結(jié)構(gòu)棧回溯通過定位棧幀sp,以分離棧幀,進而分析棧數(shù)據(jù)棧幀,記錄了一個運行中函數(shù)的調(diào)用輸入、運行狀態(tài)、返回地址主要包含了(自底向上看)其他信息局部變量寄存器返回地址棧參數(shù)典型sp操作初始化sp指向棧底調(diào)用線程入口函數(shù)入棧返回地址(0)和寄存器,創(chuàng)建局部變量調(diào)用子函數(shù)入棧棧參數(shù)、返回地址(父函數(shù)call指令的下一相鄰指令的地址)、寄存器創(chuàng)建局部變量sp定位方法從棧頂?shù)綏5谆厮輻m攕p,反算自寄存器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調(diào)用棧解釋每一行,描述當(dāng)前線程的用戶態(tài)棧上的一個棧幀函數(shù)調(diào)用,自底向上棧回溯過程,從子棧幀到父棧幀,直到返回地址為0查看線程在當(dāng)前棧幀的執(zhí)行狀態(tài)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當(dāng)前棧rspchild rsp為 0000003cac33f518當(dāng)前即將返回,說明當(dāng)前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查看函數(shù)調(diào)用,發(fā)現(xiàn)沒有棧參數(shù)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]當(dāng)前棧rsp = 返回值地址 + 8 = 0000003cac33f518 + 8 = 0000003cac33f520查看當(dāng)前棧幀的數(shù)據(jù)棧基址通常情況下,附近的數(shù)據(jù)棧基址 父棧幀RBP棧基址+8*1 返回地址棧基址+8*2 第一個棧參數(shù)棧基址+8*N 第N個棧參數(shù)產(chǎn)生的棧幀信息Child-SP 0000003cac33f518因為未執(zhí)行"sub rsp, N",所以子棧幀RSP等于當(dāng)前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恢復(fù)和查看線程在上一棧幀的執(zhí)行狀態(tài)當(dāng)前棧rspchild rsp為 0000003cac33f520查看函數(shù)體,發(fā)現(xiàn)有寄存器入棧和局部變量,共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查看函數(shù)調(diào)用,發(fā)現(xiàn)沒有棧參數(shù)返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 0000003cac33f520 + 78= 0000003cac33f598返回地址的值dd 0000003cac33f5980000003c`ac33f598 d35960ad 00007ff8 00000000 00000000函數(shù)調(diào)用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當(dāng)前棧rsp = 返回值地址 + 8 = 0000003cac33f598 + 8 = 0000003cac33f5a0查看上一棧幀的數(shù)據(jù)當(dāng)前棧,包含寄存器入棧和局部變量,沒有棧參數(shù)產(chǎn)生的棧幀信息Child-SP 0000003cac33f520RetAddr 00007ff8d35960adCall Site KERNELBASE!ReadFile+0x77子函數(shù)返回地址恢復(fù)和查看線程在上二棧幀的執(zhí)行狀態(tài)當(dāng)前棧rspchild rsp為 0000003cac33f5a0查看函數(shù)體,發(fā)現(xiàn)有寄存器入棧和局部變量,共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查看函數(shù)調(diào)用,發(fā)現(xiàn)沒有棧參數(shù)返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 0000003cac33f5a0 + 98= 0000003cac33f638返回地址的值dd 0000003cac33f6380000003c`ac33f638 d35961e2 00007ff8 00001000 00000000函數(shù)調(diào)用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)當(dāng)前棧rsp = 返回值地址 + 8 = 0000003cac33f638 + 8 = 0000003cac33f640查看上二棧幀的數(shù)據(jù)當(dāng)前棧,包含寄存器入棧和局部變量,沒有棧參數(shù)產(chǎn)生的棧幀信息Child-SP 0000003cac33f5a0RetAddr 00007ff8d35961e2Call Site ucrtbase!_read_nolock+0x119子函數(shù)返回地址列含義第一列,Child-SP,子棧幀開始的棧地址相鄰SP,之間構(gòu)成一個棧幀第二列,RetAddr,返回地址棧幀開始后,顯示棧參數(shù),然后是返回地址第三列,Call Site,函數(shù)名+偏移棧頂,當(dāng)前執(zhí)行的函數(shù)位置,源自ripln rip棧中,調(diào)用子函數(shù)的函數(shù)位置,源自子函數(shù)的返回地址ln child_ret相關(guān)命令k,棧查看基本命令kL,不顯示源碼行數(shù)kb,顯示三個棧參數(shù),與調(diào)用協(xié)議相關(guān)kp,顯示所有棧參數(shù),包括類型、名稱、數(shù)值,需要有完全的調(diào)試符號(私有符號)kP,類似kp,但每個棧參數(shù)各占一行kv,在kb的基礎(chǔ)上,顯示FPO(frame pointer omission,棧指針省略)和調(diào)用協(xié)議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查看查看當(dāng)前棧幀的棧變量,dv /i/t/V符號屬性(prv或pub)符號類型(param或local)變量首地址的絕對表示變量首地址的sp偏移表示變量數(shù)據(jù)類型變量名變量值切換棧幀,.frame frame_index可使用kn查看棧幀索引例子命令查看局部變量windbg .\dbgee.exebp `dbgee!dbgee.cpp:11`注意斷點打在函數(shù)首條語句處,而非函數(shù)入口運行到此處時,參數(shù)已經(jīng)初始化,局部變量已經(jīng)開辟但未初始化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"當(dāng)前棧幀位置,[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指向的棧空間,屬于父棧幀,下一位置才屬于子棧幀查看函數(shù)體,發(fā)現(xiàn)有寄存器入棧和局部變量,共0x248查看函數(shù)調(diào)用,發(fā)現(xiàn)沒有棧參數(shù)返回地址的棧地址= child rsp + 寄存器入棧長度 + 局部變量長度= 000000ca5c30fc20 + 248= 000000ca5c30fe68返回地址的值dd 000000ca5c30fe68000000ca`5c30fe68 f3c31438 00007ff6 d366b590 00007ff8函數(shù)調(diào)用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)當(dāng)前棧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可以發(fā)現(xiàn)可以看出這里使用的_fastcall從右至左壓棧,第二一參分別存入xdx和xcx,被調(diào)清棧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)的異或設(shè)計判斷棧破壞函數(shù)調(diào)用棧是否運行正常,體現(xiàn)為sp值變化是否正常棧幀初始化后的sp和棧幀收尾前的sp,應(yīng)該一致方法初始化后,記錄當(dāng)前sp到當(dāng)前棧幀中收尾前,比較當(dāng)前的sp和棧中記錄的sp是否一致方式初始化后,記錄當(dāng)前棧幀特征值(子棧幀sp(當(dāng)前sp)與模塊特征值的異或),到當(dāng)前棧幀中收尾前,計算模塊特征值(子棧幀sp(當(dāng)前sp)與棧中存儲的當(dāng)前棧幀特征值的異或),判斷是否一致規(guī)律處于異或關(guān)系的三個數(shù),其中任意兩個數(shù),能夠異或出第三個數(shù)代碼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(當(dāng)前sp)與棧中存儲的當(dāng)前棧幀特征值的異或),判斷是否一致代碼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沒有私有符號,手動推斷查看棧幀內(nèi)存內(nèi)存觀察窗口內(nèi)存查看命令查看代碼局部變量一般引用方式[rsp + N]安全Cookie值(棧幀特征值)位置[rsp + local_length - 0x10]獲取變量指針lea xxx, [rsp + N]其他遍歷對象,執(zhí)行命令!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 分析內(nèi)存30.15.1 顯示內(nèi)存區(qū)域按數(shù)據(jù)格式顯示內(nèi)存區(qū)域語法d{a|b|c|d|Df|p|q|u|w|W|yb|yd|} [options] [Range]數(shù)據(jù)格式字節(jié)a,ASCII碼b,字節(jié)和ASCII碼yb,二進制和字節(jié)字w,WORD(uint16)W,WORD和ASCII碼u,UNICODE字符UNICODE,一種字符的數(shù)值映射方案utf8,一種UNICODE的編碼方案,常用于保存uint16,一種UNICODE的編碼方案,常用于計算雙字c,DWORD和ASCII碼d,DWORD(uint32)f,單精度浮點數(shù)yd,二進制和雙字四字q,uint64D,雙精度浮點數(shù)指針寬度p省略最近使用的數(shù)據(jù)格式內(nèi)存范圍,Rangestart_address end_addressstart_address {L|l}NN,表示元素個數(shù)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結(jié)尾的ASCII字符串的地址du 以0結(jié)尾的UNICODE字符串的地址ntdll!_STRING變量ds 變量地址ntdll!_UNICODE_STRING變量dS 變量地址例子da 00007ff7`aa91226000007ff7`aa912260 "dbgee exits.."30.15.3 顯示數(shù)據(jù)類型符號列舉dt [module_name!]symbol結(jié)果可能多個支持通配符*符號顯示dt [options] [module_name!]symbol結(jié)果唯一省略module_name,則自動搜索symbol數(shù)據(jù)類型及其typedef別名、全局變量、靜態(tài)變量、函數(shù)options-rN,顯示數(shù)據(jù)類型時,指定顯示深度-ny name,顯示數(shù)據(jù)類型時,顯示name開頭的字段變量顯示dt [options] [module_name!]symbol address按指定數(shù)據(jù)類型,解釋變量鏈表遍歷顯示例子dt dbgee!wmainwmain int (int argc = 1, wchar_t** argv = 00000254`afbddcc0 )dt dbgee!g_szGlobalSymbol dbgee!g_szGlobal not found.由于生成的是Release版的程序,同時全局變量g_szGlobal定義了但并未使用,導(dǎo)致其未被生成嘗試使用Debug版本程序調(diào)試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 搜索內(nèi)存在指定范圍內(nèi),搜索字符串s-[[Flags]]sa|su RangeRange,內(nèi)存范圍sa|su,搜索ASCII字符串或UNICODE字符串FlagslN,指定最小長度在指定范圍內(nèi),搜索與指定對象類型相同的對象s-[[Flags]]v Range ObjectObject,含虛函數(shù)表的使用面向?qū)ο笳Z言編寫的類型的對象在指定范圍內(nèi),搜索數(shù)組s[-[[Flags]]Type] Range data_arrayType,數(shù)組元素類型b字節(jié),w字,d雙字,q四字,aASCII字符,uUNICODE字符默認(rèn)為bdata_array,數(shù)組內(nèi)容例子對于 printf("dbgee exits.\n");字符串"dbgee exits.\n",作為字符串常量,放在代碼段中l(wèi)mstart 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 修改內(nèi)存寫內(nèi)存內(nèi)存區(qū)間待寫入數(shù)據(jù)寫字符串e{a|u|za|zu} address "string"a|u,按照ASCII或UNICODE方式寫入,結(jié)尾不加0za|zu,按照ASCII或UNICODE方式寫入,結(jié)尾要加0內(nèi)存區(qū)間,[address, address+字符串實際字節(jié)長度)待寫入數(shù)據(jù),"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"寫數(shù)組e{b|w|d|p|q|D|f} address data_array b字節(jié),w字,d雙字,p指針長度,q四字,D雙精度浮點,f單精度浮點例子ed [rsp+20h] 1 2 3 4 5交互式寫字符串和數(shù)組30.15.6 使用物理內(nèi)存地址命令,虛擬地址相關(guān)命令前加!條件,內(nèi)核模式30.15.7 觀察內(nèi)存屬性!address address顯示指定內(nèi)存區(qū)的屬性含義行1,Usage,內(nèi)存區(qū)的用途VAR,虛擬分配塊、SBH堆、自定義分配器分配的內(nèi)存、其他分類的區(qū)域Free,未被預(yù)留的內(nèi)存區(qū)域 Image,存儲可執(zhí)行文件映像 Stack,函數(shù)棧Teb,thread environment blocks (TEBs)Peb,process environment block (PEB)Heap,堆PageHeap,整頁堆(full-page heap) CSR,CSR shared memory Actx,激活上下文數(shù)據(jù)的內(nèi)存NLS,用于National Language Support (NLS) tables FileMap,內(nèi)存映射文件行2,Allocation Base,較大內(nèi)存區(qū)的開始地址行3,Base Address,較小內(nèi)存區(qū)的開始地址行4,End Address,較小內(nèi)存區(qū)的結(jié)束地址行5,Region Size,內(nèi)存區(qū)大小行6,Type,內(nèi)存區(qū)的類型MEM_IMAGE,映射可執(zhí)行文件映像 MEM_MAPPED,映射其他類型文件MEM_PRIVATE,非映射私有內(nèi)存,不共享行7,State,內(nèi)存區(qū)的狀態(tài)MEM_COMMIT,已提交MEM_FREE,釋放的內(nèi)存,含未保留的內(nèi)存MEM_RESERVE,保留的內(nèi)存行8,Protect,內(nèi)存區(qū)的訪問保護PAGE_NOACCESS,不可訪問PAGE_READONLY,只讀PAGE_READWRITE,可讀可寫PAGE_WRITECOPY,寫時會復(fù)制PAGE_EXECUTE,可執(zhí)行,不可讀寫PAGE_EXECUTE_READ,可執(zhí)行,只讀PAGE_EXECUTE_READWRITE,可執(zhí)行,可讀可寫PAGE_EXECUTE_WRITECOPY,可執(zhí)行寫時會復(fù)制PAGE_GUARD,哨兵頁PAGE_NOCACHE,讀不可緩存PAGE_WRITECOMBINE,啟用了寫聯(lián)合訪問例子!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顯示當(dāng)前進程所有內(nèi)存區(qū)的屬性!address -summary顯示當(dāng)前進程所有內(nèi)存區(qū)的統(tǒng)計其他類似命令顯示指定內(nèi)存區(qū)的屬性!vprot dbgee!wmainBaseAddress: 00007ff7aa911000AllocationBase: 00007ff7aa910000AllocationProtect: 00000080 PAGE_EXECUTE_WRITECOPYRegionSize: 0000000000001000State: 00001000 MEM_COMMITProtect: 00000020 PAGE_EXECUTE_READType: 01000000 MEM_IMAGE顯示當(dāng)前進程所有內(nèi)存區(qū)的屬性!vadump30.16 遍歷鏈表30.16.0 背景Windows操作系統(tǒng)中,很多重要信息使用鏈表方式組織查看鏈表類型dt ntdll!*List*30.16.1 結(jié)構(gòu)定義鏈表節(jié)點組成鏈接結(jié)構(gòu),用于節(jié)點連接鏈接結(jié)構(gòu)中的指針,指向下一鏈接結(jié)構(gòu),而非指向鏈表節(jié)點負(fù)載,用于數(shù)據(jù)保存鏈表分類雙向鏈表鏈接結(jié)構(gòu)dt ntdll!_LIST_ENTRY+0x000 Flink : Ptr64 _LIST_ENTRY+0x008 Blink : Ptr64 _LIST_ENTRY單項鏈表鏈接結(jié)構(gòu)dt ntdll!_SINGLE_LIST_ENTRY+0x000 Next : Ptr64 _SINGLE_LIST_ENTRY30.16.2 雙向鏈表示例Windows內(nèi)核使用雙向鏈表,管理所有進程的EPROCESS結(jié)構(gòu)30.16.3 單項鏈表示例TEB結(jié)構(gòu)使用單向鏈表,保存異常處理器遍歷單向鏈表dt 鏈表節(jié)點類型 -l 下一節(jié)點地址的符號表示 頭結(jié)點地址例子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,鏈表節(jié)點最大個數(shù)Size,鏈表節(jié)點負(fù)載大小(單位為指針長度),負(fù)載位于鏈接結(jié)構(gòu)后例子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描述鏈表節(jié)點類型,[Module!]Type描述鏈接字段,Field-x "Commands" [-a "Arguments"]描述對每個節(jié)點的操作命令偽寄存器$extret表示當(dāng)前節(jié)點的地址[Options]-e,回顯對每個節(jié)點執(zhí)行的操作-m N,遍歷的最大節(jié)點數(shù)目StartAddress鏈接頭節(jié)點的地址 例子!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 調(diào)用目標(biāo)程序的函數(shù)30.17.1 調(diào)用實例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從字符串?dāng)?shù)組argv中,獲取第一個字符串的地址即argv[0]的值,*(argv+0),poi(argv)由于argv存放在rdx,由于_fastcall調(diào)用約定windbg使用C++表達式評估器,來解析函數(shù)參數(shù).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.設(shè)置函數(shù)調(diào)用~.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執(zhí)行函數(shù)調(diào)用30.17.2 工作原理方法修改線程的執(zhí)行環(huán)境,使調(diào)用指定函數(shù)調(diào)用完成后,恢復(fù)線程的執(zhí)行環(huán)境方式在棧頂寫入,函數(shù)返回后執(zhí)行的代碼用于再次中斷到調(diào)試器,以恢復(fù)線程的執(zhí)行環(huán)境 在棧頂建立新棧幀為子函數(shù)開辟空間入棧參數(shù)和返回地址(指向新寫入的代碼)修改程序指針,指向指定函數(shù)入口例子.call執(zhí)行前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參數(shù),放在rcx中為子函數(shù)開辟空間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查看函數(shù)返回后的執(zhí)行代碼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一共八字節(jié),以對齊寄存器程序指針,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執(zhí)行指定函數(shù)~.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,恢復(fù)r,恢復(fù)db esp,恢復(fù)30.17.3 限制條件和常見錯誤.call命令只能調(diào)試,用戶態(tài)活動目標(biāo)被調(diào)函數(shù),有私有符號,即包含類型信息的函數(shù)符號每個線程一次只能設(shè)置一個函數(shù),設(shè)置后,要么取消,要么執(zhí)行.call /C,清除當(dāng)前線程設(shè)置的函數(shù)30.18 命令程序30.18.0 概述調(diào)試器命令程序,Debuger Command Program概念,調(diào)試器命令集合,形成的文件組成調(diào)試器命令,標(biāo)準(zhǔn)命令、元命令、擴展命令流程控制符號變量30.18.1 流程控制符號(control flow token)分支.if, .else, .elseif循環(huán).do, .while, !for_each_xxx, .break, .continue異常.catch,捕獲異常.leave,退出.catch塊代碼塊.block30.18.2 變量分類偽寄存器自動的偽寄存器由windbg定義和賦值如$ip用戶賦值的偽寄存器$t0~$t19指定為整數(shù)類型并賦值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}}解釋$$和*,行注釋$$也可以分號結(jié)束注釋常用$$,因為將程序合并成一行時,換行符會被替換成分號使用$$可以正常注釋使用*不能正常注釋當(dāng)前進程_PEB結(jié)構(gòu)的地址,使用偽寄存器$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);鏈表遍歷,判斷結(jié)束r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t1->InLoadOrderLinks.Flink)獲取下一節(jié)點的地址as /x ${/v:$Base} @@c++(@$t1->DllBase)/x,取表達式64位值/v,阻止別名替換,不管其是否已經(jīng)定義@@c++,強制使用C++表達式評估器as /msu ${/v:$Mod} @@c++(&@$t1->FullDllName)/msu,使別名等價于地址表達式指向的UNICODE_STRING.block;{;.echo ${$Mod} at ${$Base};}強制評估別名并回顯30.18.4 執(zhí)行命令程序$<Filename 讀一行,執(zhí)行一行若一行中命令不完整,則會出錯$><Filename合并程序成一行(分號替換換行符),然后執(zhí)行 $$< Filename 同"$$<Filename",但允許文件名前加空格,使用雙引號包圍文件名$$>< Filename 同"$$><Filename",但允許文件名前加空格,使用雙引號包圍文件名$$>a< Filename [arg1 arg2 arg3 ... ] 支持參數(shù)30.19 本章總結(jié)本章內(nèi)容,介紹調(diào)試任務(wù)所需的一般知識是對windbg幫助文檔的補充對幫助文檔進行了歸納和濃縮,便于入門介紹幫助文檔中較少或較難的內(nèi)容windbg中的文檔debugger.chm根目錄windbg幫助文檔kernel_debugging_tutorial.doc根目錄介紹內(nèi)核調(diào)試symhttp.docsymproxy子目錄介紹如何建立符號服務(wù)器srcsrv.docsrcsrv子目錄介紹源文件服務(wù)器的概況以及如何建立和配置源文件服務(wù)器dml.doc根目錄介紹DML(Debugger Markup Language)的用途和編寫方法DML是一種標(biāo)記語言,用于標(biāo)記windbg或擴展命令的信息輸出themes.docthemes子目錄介紹了主題(theme)的概念一個主題,代表一套特定風(fēng)格的界面布局和工作空間配置介紹了如何加載及使用該目錄中的四套主題配置adplus.docpooltag.txttriage子目錄包含了Windows內(nèi)核模塊和驅(qū)動程序所使用的內(nèi)存分配標(biāo)記(Pool Tag)在啟用了Windows操作系統(tǒng)的內(nèi)存池標(biāo)記(Pool Tagging)功能后,系統(tǒng)會為每個內(nèi)存塊維護一個分配標(biāo)記,以標(biāo)識其使用者用于顯示內(nèi)存池使用情況的擴展命令!poolused,就是使用該文件來查找每個分配標(biāo)記對應(yīng)的模塊
?
總結(jié)
以上是生活随笔為你收集整理的读书笔记:调试软件 张银奎的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html设计学校网站,基于HTML5的学
- 下一篇: 国家计算机考试一级难不难,国家计算机一级