windbg 常用命令详解 |
您所在的位置:网站首页 › DLL命令大全 › windbg 常用命令详解 |
一、 1、 !address eax 查看对应内存页的属性 2、 vertarget 显示当前进程的大致信息 ![]() 显示process Environment Block
4、 lmvm 可以查看任意一个dll的详细信息 例如:我们查看cyusb.sys的信息 5.reload !sym 加载符号文件 6、 lmf列出当前进程中加载的所有dll文件和对应的路径 命令显示和修改寄存器上的值 r命令显示和修改寄存器上的值 命令显示esp寄存器指向的内存 如下 注意:第二个d表示DWORD格式,此外还有db(byte),du(Unicode),dc(char)等等。 数据查看指令 d{a|b|c|d|D|f|p|q|u|w|W} d{b|c|d|D|f|p|q}分别是显示: byte&ASCII, double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word数据; DA用于显示ASCII,DU用于显示UNICODE; BYB,BYD,显示binary和Byte及binary和DWORD 补充一个DV,用于查看本地变量用的 9、 e命令可以用来修改内存地址 跟d命令一样,e命令后面也可以跟类型后缀,比如ed命 令表示用DWORD的方式修改。下面的命令把054efc14地址上的值修改为11112222。 0:018>ed 054efc14 11112222 修改后可以用dd命令来查看内存。 0:018>dd 0543fc14 L4 L4参数指定内存区间的长度为4个DWORD,这样输出只有1行, 而不是8行了。 10、s命令用来搜索内存具体见help文档 11!runaway 可以显示每一个线程的cpu消耗 0:018> !runaway 结果如下: 0:83c 0 days 0:00:00.406 13:bd4 0 days 0:00:00.046 10:ac8 0 days 0:00:00.046 24:4f4 0 days 0:00:00.031 上面输出的第一列是线程的编号和线程ID,后一列对应的是该线程在用户态模式中的 总的繁忙时间。 在该命令加上f参数,还可以看到内核态的繁忙时间,当进程内存占用率比较高的时候 ,通过该命令可以方便的找到对应的繁忙线程。 12、 ~ 命令是用来切换目标线程0:018> ~ 可以显示线程的信息 0:018> ~0s 把当前的线程切换到0号线程,也就是主线程,切换后提示符会变为0:000. 13 、~* 命令列出当前进程中的所有线程的详细信息 14、~*kb 命令列出所有线程的堆栈 15、 k 命令用来显示当前线程的堆栈,如下0:018> k 跟d命令一样,k后面也可以跟很多后缀,比如kb kp,kn,kv,kl等,这些后缀控制了显示的格式和信息。 栈指令k[b|p|P|v] 这四条指令显示的内容类似,但是每个指令都有特色; KB显示三个参数; Kp显示所有的参数,但需要Full Symbols或Private PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了; Kv用于显示FPO和调用约定; KD,用于显示Stack的Dump,在跟踪栈时比较有用。 这些指令区分大小。 16 、u 命令把指定地址上的代码翻译成汇编输出0:018> u 7739d023 USER32!NtUserWaitMessage: 7739d023 b84a120000 mov eax,0x124a 7739d028 ba0003fe7f mov edx,0x7ffe0300 7739d02d ff12 call dword ptr [edx] 7739d02f c3 ret 如果符号文件加载正确,可以用uf命令直接反汇编整个函数,比如uf USER32! NtUserWaitMessage 17 、x 查找符号的二进制地址如下0:018> x msvcr!printf 77bd27c2 msvcrt!printf = 上面的命令找到了printf函数的入口地址在77bd27c2 0:001> x ntdll!GlobalCounter 7c99f72c ntdll!GlobalCounter = 上面的命令表示ntdll!GlobalCounter这个变量保存的地址是7c99f72c。 注意:符号对应的是变量和变量所在的地址,不是变量的值,上面只是找到GlobalCounter这个变量的值是7c99f72,要找到变量的值,需要用d命令读取内存地址来获取。 X命令还支持通配符,比如x ntdll !*命令列出ntdll模块中的所有的符号,以及对应的二进制地址。 18、 dds 打印内存地址上的二进制值同时自动搜索二进制值对应的符号。 比如要看看当前**中保存了那些函数地址,就可以检查ebp指向的内存 0:018>dds ebp 0013ed98 0013ee24 0013ed9c 75ecb30f BROWSEUI!BrowserProtectedThreadProc+0x44 0013eda0 00163820 0013eda4 0013ee50 0013eda8 00163820 0013edac 00000000 0013edb0 0013ee10 0013edb4 75ece83a BROWSEUI!__delayLoadHelper2+0x23a 0013edb8 00000005 0013edbc 0013edcc 0013edc0 0013ee50 0013edc4 00163820 0013edc8 00000000 0013edcc 00000024 0013edd0 75f36d2c BROWSEUI!_DELAY_IMPORT_DESCRIPTOR_SHELL32 0013edd4 75f3a184 BROWSEUI!_imp__SHGetInstanceExplorer 0013edd8 75f36e80 BROWSEUI!_sz_SHELL32 0013eddc 00000001 0013ede0 75f3726a BROWSEUI!urlmon_NULL_THUNK_DATA_DLN+0x116 0013ede4 7c8d0000 SHELL32!_imp__RegCloseKey (SHELL32+0x0) 0013ede8 7c925b34 SHELL32!SHGetInstanceExplorer 这里dds命令从ebp指向的内存地址0013ed98开始打印,第一列是内存地址的值,第二列是地址上对应的二进制数据,第三列是二进制对应的符号。上面的命令自动找到了75ecb390f对应的符号是BROWSEUI!BrowserProtectedThreadProc +0x44. Com interface 和c++ vtable里面的成员函数都是顺序排列的。所以,dds命令可以方便的找到虚函数表中的具体的函数地址,比如用下面的命令可以找到OpaqueDatinfo类型中虚函数的实际函数地址。 首先通过x命令找到OpaqueDataInfo虚函数地址 0:000> x ole32!OpaqueDataInfo::vftable’ 7768265c ole32!OpaqueDataInfo::`vftable'' = 77682680 ole32!OpaqueDataInfo::`vftable'' = 接下来dds命令可以打印出虚函数表中的函数名字 0:000> dds 7768265c 19 .frame命令在栈中切换以便检查局部变量。 要查看局部变量的需要如下: 19、1 查看线程的callstack 19、3 然后调用 x 显示当前frame的局部变量,比如这个函数中有两个局部变量pcls和rawptr 0:018> x 0012fced pcls = 0x0039ba80 0012fcd8 rawptr = 0x0039ba80 20、 dt 格式化显示资料Dt 命令格式化显示变量的资料和结构 0:000> dt pcls Local var @ 0x12fce4 Type MyCls* 0x0039ba80 +0x000 str : 0x00416648 'abcd' +0x004 inobj : inner 上面的命令打印出pcls的类型是MyCls指针,指向的地址是0x0039ba80,其中的两个class成员的偏移分别在+0和+4,对应的值在第2列显示。加上-b -r参数可以显示inner class和数组的信息: 0:000> dt pcls -b -r Local var @ 0x12fce4 Type MyCls* 0x0039ba80 +0x000 str : 0x00416648 'abcd' +0x004 inobj : innner +0x000 arr : 'abcd' [00] 97 ''a'' [01] 98 ''b'' [02] 99 ''c'' [03] 100 ''d'' [04] 0 '''' [05] 0 '''' [06] 0 '''' [07] 0 '''' [08] 0 '''' [09] 0 '''' 对于任意的地址,也可以手动指定符号类型来格式化显示。比如把0x0039ba80地址上的数据用MyCls类型来显示: 0:000> dt 0x0039ba80 MyCls +0x000 str : 0x00416648 'abcd' +0x004 inobj : innner 21、 bp 设定调试断点(1)比如可以这样写:0:018>bp notepad!WinMain 在notepade的winmain函数处下断点。 断点的位置可以用符号来表示,如上,也可以直接用地址以及windbg的Pseudo_Register(虚拟寄存器)。 比如,我们用$exentry表示进程的入口,那么可以用bp @$exentry在进程的入口设置断点。 (2)如果notepade的winmain的入口地址为01006420,那么断点也可以这么写: Bp 01006420 bp mysource.cpp:143` 'j (poi(MyVar)”0x20) ''''; ''g'' ' 意思就是:当myvar的值等于0x20时,g命令继续执行; (3)下面一个设置条件断点 0:001> bp exceptioninject!foo3 “k; .echo ‘breaks’ ; g” 在exceptioninject!foo3上设置断点后,每次断下来后,先用k显示callstack,然后用.echo命令输出简单的字符串‘breaks’,最后g命令继续执行。 (4)下面看一个更复杂的设置条件断点的例子: ba w4 execptioninject!i ”j(poi(exceptioninject!i) ln 8046e100 (8046e100) nt!KeServiceDescriptorTableShadow | (8046e140) nt!MmSectionExtendResource Exact matches: nt!KeServiceDescriptorTableShadow = 31、!gle 查看LastError值32、指定进制的形式0x/0n/0t/y 分别表示 16/10/8/2进制 ? 0x12345678+0n10 Evaluate expression: 305419906 = 12345682 33、!sym noice/quiet symbol prompts开关 34、srcpath 设置源代码的路径35、dv查看本地变量 36、!teb 显示当前线程的执行块(execution block) 37、!peb 显示当前进程的执行块(execution block) 38、ln[Address] 显示当前地址上的对象类型 39、!locks 显示死锁 40、!handle可以获取整个进程或者某一个handle的详细信息 首先运行以下!handle,可以看到当前进程的每个一个handle的类型,以及统计信息 0:002>!handle Handle 4 Type key Handle c Type keyEvent ……. 然后找到一个key,查看详细信息 0:001>!handle 4 f 就会列出这个handle的详细信息。 41!htrace命令检查操作句柄的历史记录 !htrace命令可以打印出指定的handle的最近几次调用堆栈 0:001>!htrace 384 42、!cs列出CriticalSection的详细信息43、!threadpool能看到完成端口,线城池工作线程和timer回调占线程池的情况 44、time 可以看到进程跑了多长时间 45、 !dso 查看当前线程中有哪些对象,分析泄露时用到 46、dump保存进程的dump文件 Dump文件是进程的内存镜像, 可当在调试器中打开dump文件时,使用上面的命令检查,看到的结果跟用调试检查进程看到的一样 .dump /ma c://testdump.dmp 这个命令把当前进程的镜像保存为c://testdump.dmp,其中/ms参数表示dump的文件应该包含进程的完整信息。 在windbg中,通过file—open---open Crash dump菜单打开dump文件进行分析。打开文件后,运行调试命令看到的信息和状态就是dump文件保存时进程的状态。通过dump文件能够方便的保存发生问题时进程的状态,方便事后分析。 47、 0: kd> !idt //查看中断向量表内容 0: kd> dt nt!_KINTERRUPT 89c03bb0 //查看对应中断向量的详细内容 0: kd> !ioapic //显示I/O APIC(即连接至设备的中断控制部件) 0: kd> !pic // 0: kd> !apic //有关PIC的配置情况 kd> !idt运行后显示为 0: kd> !idt Dumping IDT: 37: 806e7864 hal!PicSpuriousService37 3d: 806e8e2c hal!HalpApcInterrupt 41: 806e8c88 hal!HalpDispatchInterrupt 50: 806e793c hal!HalpApicRebootService 63: 89ac57e4 USBPORT!USBPORT_InterruptService (KINTERRUPT 89ac57a8) USBPORT!USBPORT_InterruptService (KINTERRUPT 8982abb0) 73: 89d6767c atapi!IdePortInterrupt (KINTERRUPT 89d67640) atapi!IdePortInterrupt (KINTERRUPT 89dc4bb0) 83: 89c1471c VIDEOPRT!pVideoPortInterrupt (KINTERRUPT 89c146e0) HDAudBus!AzController::Isr (KINTERRUPT 89c16ac8) NDIS!ndisMIsr (KINTERRUPT 89847bb0) 94: 8976fbec USBPORT!USBPORT_InterruptService (KINTERRUPT 8976fbb0) a4: 89770bec USBPORT!USBPORT_InterruptService (KINTERRUPT 89770bb0) b1: 89d859e4 ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 89d859a8) b4: 89c03bec USBPORT!USBPORT_InterruptService (KINTERRUPT 89c03bb0) c1: 806e7ac0 hal!HalpBroadcastCallService d1: 806e6e54 hal!HalpClockInterrupt e1: 806e8048 hal!HalpIpiHandler e3: 806e7dac hal!HalpLocalApicErrorService fd: 806e85a8 hal!HalpProfileInterrupt fe: 806e8748 hal!HalpPerfInterrupt //前部分是使用的中断类型号。例如83号中断是有三个硬件复用。
2.0: kd> dt nt!_KINTERRUPT 89c03bb0,运行后显示为 0: kd> dt nt!_KINTERRUPT 89c03bb0 +0x000 Type : 0n22 +0x002 Size : 0n484 +0x004 InterruptListEntry : _LIST_ENTRY [ 0x89c03bb4 - 0x89c03bb4 ] +0x00c ServiceRoutine : 0xb9159e54 unsigned char USBPORT!USBPORT_InterruptService+0 +0x010 ServiceContext : 0x89c38028 Void +0x014 SpinLock : 0 +0x018 TickCount : 0xffffffff +0x01c ActualLock : 0x89c03e14 -> 0 +0x020 DispatchAddress : 0x805466d0 void nt!KiInterruptDispatch+0 +0x024 Vector : 0x1b4 +0x028 Irql : 0xa '' +0x029 SynchronizeIrql : 0xa '' +0x02a FloatingSave : 0 '' +0x02b Connected : 0x1 '' +0x02c Number : 0 '' +0x02d ShareVector : 0x1 '' +0x030 Mode : 0 ( LevelSensitive ) +0x034 ServiceCount : 0 +0x038 DispatchCount : 0xffffffff +0x03c DispatchCode : [106] 0x56535554
3.0: kd> !ioapic,运行后显示 0: kd> !ioapic IoApic @ FEC00000 ID:8 (20) Arb:170020 Inti00.: 52000000`000100ff Vec:FF FixedDel Ph:52000000 edg high m Inti01.: 00c00000`000100ff Vec:FF FixedDel Ph:00C00000 edg high m Inti02.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti03.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti04.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti05.: 52c00000`000100ff Vec:FF FixedDel Ph:52C00000 edg high m Inti06.: 00c00000`000100ff Vec:FF FixedDel Ph:00C00000 edg high m Inti07.: 02000000`000100ff Vec:FF FixedDel Ph:02000000 edg high m Inti08.: 01000000`000008d1 Vec:D1 FixedDel Lg:01000000 edg high Inti09.: 03000000`0000d9b1 Vec:B1 LowestDl Lg:03000000-Pend lvl high rirr Inti0A.: 00c00000`000100ff Vec:FF FixedDel Ph:00C00000 edg high m Inti0B.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti0C.: 42000000`000100ff Vec:FF FixedDel Ph:42000000 edg high m Inti0D.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti0E.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti0F.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti10.: 03000000`0000f983 Vec:83 LowestDl Lg:03000000-Pend lvl low rirr Inti11.: 00000000`000100ff Vec:FF FixedDel Ph:00000000 edg high m Inti12.: 03000000`0000a994 Vec:94 LowestDl Lg:03000000 lvl low Inti13.: 00c00000`000100ff Vec:FF FixedDel Ph:00C00000 edg high m Inti14.: 03000000`0000a973 Vec:73 LowestDl Lg:03000000 lvl low Inti15.: 03000000`0000a963 Vec:63 LowestDl Lg:03000000 lvl low Inti16.: 03000000`0000a9a4 Vec:A4 LowestDl Lg:03000000 lvl low Inti17.: 03000000`0000f9b4 Vec:B4 LowestDl Lg:03000000-Pend lvl low rirr
4.0: kd> !pic ,运行后显示 0: kd> !pic ----- IRQ Number ----- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Physically in service: . . . . . . . . . . . . . . . . Physically masked: Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Physically requested: Y . . Y . Y . . Y Y Y Y . . . .
5.0: kd> !apic,运行后显示 0: kd> !apic Apic @ fffe0000 ID:0 (50014) LogDesc:01000000 DestFmt:ffffffff TPR FF TimeCnt: 0fdad680clk SpurVec:1f FaultVec:e3 error:40 Ipi Cmd: 02000000`000008e1 Vec:E1 FixedDel Lg:02000000 edg high Timer..: 00000000`000300fd Vec:FD FixedDel Dest=Self edg high m Linti0.: 00000000`0001001f Vec:1F FixedDel Dest=Self edg high m Linti1.: 00000000`000084ff Vec:FF NMI Dest=Self lvl high TMR: 63, 73, 83, 94, A4, B1, B4 IRR: 41, B1, D1 ISR: D1 48、.cls.cls用于清屏 注意:得在windbg处于命令行模式时才可用(即按了Ctro+Break) 或者直接使用工具栏: 二、
Windbg断点命令 1. 设置断点命令bu bp bm ba1) bu bp bm设置软件断点 a). bp设置地址关联的断点 b). bu设置符号关联的断点 c). bm支持设置含通配符的断点,可以一次创建一个或多个bu或bp (bm /d)断点 bp和bu的主要区别 a) bp所设断点和地址关联,如果模块把该地址的指令移到其它地方,断点不会随之移动,而是依然关联在在原来的地址上; 而bu所设断点是和符号关联,如果符号的地址改变了,断点依然保持和原来的符号关联。 b) 如果bp所设断点的地址在加载的模块中被找到,后来软件模块被卸载,断点会被自动移除;而bu所设断点则会一直存在。 c) bp设置的断点不会被保存windbg的workspace中,bu设置的断点会则会被保存下来。
2)ba设置硬件断点(数据断点) 硬件断点是指当一个内存地址被访问(读、写、执行)或IO端口被访问时触发的断点。 2. 其它命令bl bc bd be .bpcmds bl 列举所有断点和它们的状态 bc 删除对应断点 bd 禁用对应断点 be 启用对应断点 .bmcmds 列举所有断点以及创建它们的命令 3. 软件断点和硬件断点 1) 软件断点 - 调试工具控制的断点。当调试器在某个地址设置一个断点,它会首先把该地址的内容保存,零时插入一条中断指令(如int3 (0xCC)),当程序执行到该地址是cpu进入调试状态,当调试结束,程序重新载入该地址原先的指令重新执行下去。
2) 硬件断点 - 又称为数据断点,是处理器控制的断点,可以用来监控某个内存地址的访问(读、写、执行)和IO地址的访问(读、写)。处理器中有相应的调试寄存器,用来记录数据断点的地址,当该地址(内存地址或IO端口地址)被访问时,断点将被触发,cpu进入调试状态。
3) 软件断点和硬件断点的区别 a)理论上我们可以设置无穷多个软件断点,但设置软件断点会使程序变慢,尤其在内核态影响比较大,调试器大多会对断点数量加以限制。例如Windbg在内核态最多支持32个软件断点,在用户态则支持任意多个;硬件断点数量取决于处理器,例如X86支持四个断点(80386有八个调试寄存器-DR0~DR3用于断点,DR4~DR5保留,DR6~DR7用于控制)。 b)软件断点需要修改相应代码,所以它不能调试时flash和rom中的代码;而硬件则没有这个限制。 3. 参考资料 1. http://www.lslnet.com/linux/dosc1/59/linux-389058.htm 2. http://blog.csdn.net/wingeek/article/details/4025475 3. http://embexperts.com/viewthread.php?tid=69 4. http://msdn.microsoft.com/en-us/library/ff538903%28v=VS.85%29.aspx 5. http://msdn.microsoft.com/en-us/library/ff538165%28v=VS.85%29.aspx 6. http://msdn.microsoft.com/en-us/library/ff553451%28v=VS.85%29.aspx
1. 使用!process 0 0 获取用户空间的所有的进程的信息 如果有多个相同进程名,!process 0 0 SampleExe.exe kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** PROCESS fe5039e0 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000 DirBase: 00030000 ObjectTable: fe529b68 TableSize: 50. Image: System 2.使用.process /i 指定进程地址 因为要对用户态代码下断点,这里不用/p,而使用/i If you want to use the kernel debugger to set breakpoints in user space, use the/i option to switch the target to the correct process context. 3. g继续,再次发生int 3中断后,进程Context就已切换,使用!process查看确认。 4. reload符号文件。 5. bu, bp下用户态断点。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |