windbg内核环境切换到用户环境.doc_第1页
windbg内核环境切换到用户环境.doc_第2页
windbg内核环境切换到用户环境.doc_第3页
windbg内核环境切换到用户环境.doc_第4页
windbg内核环境切换到用户环境.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

今天遇到个问题,想从内核模式对用户模式的ntdll下断点,可是对于我这样的菜鸟,貌似事件不容易的事,于是翻了很多资料,但是最终还是不解,在驱网群中询问了下,一个好心人找了个连接给我,后来才看懂了,同时转载过来:使用内核调试会话也可以执行一些用户态调试任务,比如向位于用户态的模块设置断点。但这样做与使用用户态调试器有什么不同呢?我们就以向NTDLL.dll模块的ZwTerminateProcess函数(Stub)为例谈谈二者的区别。区别一、在内核调试会话中设置这个断点的“难度”略大些。这是因为NTDLL不属于内核态的模块,所以内核会话通常不会加载这个模块(的符号),因此当执行bp命令时很可能被自动蜕化为bu命令。0: kd bp ntdll!ZwTerminateProcessBp expression ntdll!ZwTerminateProcess could not be resolved, adding deferred bp恢复执行后,一般的操作也不会触发调试器来加载NTDLL模块和解决这个未决的断点。因此再中断下来,重新加载符号也可能没有用:2: kd .reloadConnected to Windows Vista 6000 x86 compatible target, ptr64 FALSELoading Kernel Symbols.Loading User SymbolsLoading unloaded module list.2: kd bl0 eu 0001 (0001) (ntdll!ZwTerminateProcess)使用.reload命令强制加载这个模块也不那么容易:0: kd .reload /s /f ntdll.dllntdll.dll was not found in the image list.Debugger will attempt to load ntdll.dll at given base 00000000.Please provide the full image name, including the extension (i.e. kernel32.dll)for more reliable results.Base address and size overrides can be given as.reload =,.Unable to add module at 00000000那么该如何设置呢?方法一需要以下几步:1.A 使用!process命令显示当前进程:kd !processPROCESS 80af22a0 SessionId: none Cid: 0000 Peb: 00000000 ParentCid: 0000 DirBase: 00039000 ObjectTable: e1001e38 HandleCount: 240. Image: Idle如果像上面这样是IDLE进程或者是System这些没有用户态的进程,那么就需要执行下面一步,否则跳到1.C。1.B 使用!process 0 0命令列出所有进程,然后选一个普通的Windows进程,并切换到这个进程:kd !process 0 0 * NT ACTIVE PROCESS DUMP *.PROCESS 82748330 SessionId: 0 Cid: 0110 Peb: 7ffde000 ParentCid: 059c DirBase: 13076000 ObjectTable: e1a55640 HandleCount: 72. Image: notepad.exekd .PROCESS 82748330Implicit process is now 82748330WARNING: .cache forcedecodeuser is not enabled1.C 执行.reload或.reload /user重新加载符号:kd .reloadConnected to Windows XP 2600 x86 compatible target, ptr64 FALSELoading Kernel Symbols.Loading User Symbols.Loading unloaded module list.kd lm m ntdllstart end module name7c800000 7c8c3000 ntdll (pdb symbols) d:symbolsntdll.pdb9A2A73EBE81940590B01ntdll.pdb第二种看起来可能更费事的方法就是在系统服务的内核函数设置断点,断点命中后,执行栈回溯这样的命令,再执行.reload(加/user会省些时间,不是必须)。例如:0: kd bp nt!NtTerminateProcess0: kd gBreakpoint 2 hitnt!NtTerminateProcess:81a1b043 8bff mov edi,edi0: kd kvChildEBP RetAddr Args to Child 9f272d54 8188c96a 00000000 00000000 0021f998 nt!NtTerminateProcess9f272d54 77c20f34 00000000 00000000 0021f998 nt!KiFastCallEntry+0x12a (FPO: 0,3 TrapFrame 9f272d64)WARNING: Frame IP not in any known module. Following frames may be wrong.0021f998 7682d873 00000000 77e8f3b0 ffffffff 0x77c20f34.0: kd .reloadConnected to Windows Vista 6000 x86 compatible target, ptr64 FALSELoading Kernel Symbols.Loading User Symbols.再执行kv:0: kd kvChildEBP RetAddr Args to Child 9f272d54 8188c96a 00000000 00000000 0021f998 nt!NtTerminateProcess9f272d54 77c20f34 00000000 00000000 0021f998 nt!KiFastCallEntry+0x12a (FPO: 0,3 TrapFrame 9f272d64)0021f978 77c20580 77bfa35f 00000000 00000000 ntdll!KiFastSystemCallRet (FPO: 0,0,0)0021f97c 77bfa35f 00000000 00000000 00af0e70 ntdll!NtTerminateProcess+0xc (FPO: 2,0,0)0021f998 7682d872 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x39 (FPO: Non-Fpo)此时可以确信内核调试会话已经加载NTDLL的符号了,再显示断点:0: kd bl0 e 77c20574 0001 (0001) ntdll!NtTerminateProcess2 e 81a1b043 0001 (0001) nt!NtTerminateProcess这个显示表明内核调试会话已经落实了这个用户态的断点。如果是在加载NTDLL模块后再执行bp命令,恢复执行后,KD会有一个提示告诉我们它成功的向断点位置写入了INT 3。0: kd bp ntdll!ZwTerminateProcess0: kd bl0 e 77c20574 0001 (0001) ntdll!NtTerminateProcess0: kd gKD: write to 77c20574 ok相对而言,如果是在用户态调试会话中,因为NTDLL会被映射到所有用户态进程中,而且ZwTerminateProcess是导出的函数,所以bp ntdll!ZwTerminateProcess会非常顺利的执行。区别二、断点的作用范围不同,在内核调试会话中设置的ntdll!NtTerminateProcess断点会影响所有进程(可能有特例),而在用户态调试中对这个位置设置的断点只对当前进程有效。举例来说,刚才在内核调试会话中设置bp断点时的当前进程是notepad,但是当我们关闭计算器进程时这个断点也会命中。甚至当我们新启动一个WinMine程序,然后关闭它时,断点也会命中。相对而言,如果是在调试notepad进程的用户态调试会话中对ntdll!NtTerminateProcess设置一个断点,那么这绝不会影响其它进程。那么为什么有这个差异呢?首先解释一下,为什么在内核调试会话中设置的断点会影响所有进程。还是通过试验来说明,我们先想办法观察到我们设置的断点所对应的INT 3指令。当KD落实我们的断点后,将目标再中断到调试器,这时无论是直接观察线性地址还是物理地址,都看不到INT 3:1: kd dd 77c2057477c20574 000152cc 0300ba00 12ff7ffe 900008c277c20584 000153b8 0300ba00 12ff7ffe 900008c277c20594 000154b8 0300ba00 12ff7ffe 00498dc377c205a4 000155b8 0300ba00 12ff7ffe 00498dc377c205b4 000156b8 0300ba00 12ff7ffe 00498dc377c205c4 000157b8 0300ba00 12ff7ffe 900010c277c205d4 000158b8 0300ba00 12ff7ffe 900018c277c205e4 000159b8 0300ba00 12ff7ffe 900010c20: kd !pte 77c20574 VA 77c20574PDE at 00000000C0601DF0 PTE at 00000000C03BE100contains 000000001C9AC867 contains 000000001DDDD025pfn 1c9ac -DA-UWEV pfn 1dddd -A-UREV0: kd !dd 1dddd574 #1dddd574 000152b8 0300ba00 12ff7ffe 900008c2#1dddd584 000153b8 0300ba00 12ff7ffe 900008c2#1dddd594 000154b8 0300ba00 12ff7ffe 00498dc3#1dddd5a4 000155b8 0300ba00 12ff7ffe 00498dc3#1dddd5b4 000156b8 0300ba00 12ff7ffe 00498dc3#1dddd5c4 000157b8 0300ba00 12ff7ffe 900010c2#1dddd5d4 000158b8 0300ba00 12ff7ffe 900018c2#1dddd5e4 000159b8 0300ba00 12ff7ffe 900010c2这是因为调试器在将目标中断到调试器之前会恢复已经设置的断点,按Ctrl+Alt+D启用WinDBG与KD的通信过程后就可以看到这样的信息:DbgKdRestoreBreakPoint(1) returns 00000000当恢复执行时,WinDBG会重新把断点写入:DbgKdWriteBreakPoint(77c20574) returns 00000000, 1那么如何观察到写入的INT 3呢?一种很惬意的方法就是使用ITP这样的硬件调试器,用了ITP,对付这样的任务真是手到擒来(图1)。图1 使用硬件调试器观察断点指令(0xCC)因为NTDLL是映射到所有进程中的,所以每个进程执行NtTerminateProcess函数时都会撞见这个0xCC,于是乎这个断点对所有进程都起作用也就在情理之中了。下面再说说另一种情况,也就是在用户态调试器中对ntdll!NtTerminateProcess设置断点,难道这时就没有把0xCC写在大家都会“撞见”的地方么?的确如此。我们在内核调试会话中使用bc *命令清除所有断点,并恢复执行一次,而且通过ITP观察确保刚才的0xcc已经不在。然后在目标系统中启动系统中自带的NTSD来调试计算器程序,并使用bp ntdll!NtTerminateProcess设置一个断点。恢复执行一次,以便让调试器写入这个断点。然后退出计算器程序,这时计算器程序会中断到NTSD,NTSD中不做分析,直接用g命令恢复执行,这下,我们前面设置的nt!NtTerminateProcess断点会命中,也就是中断到内核调试器中。在内核调试器中,观察nt!NtTerminateProcess所对应的线性地址:1: kd dd 77c2057477c20574 000152cc 0300ba00 12ff7ffe 900008c277c20584 000153b8 0300ba00 12ff7ffe 900008c277c20594 000154b8 0300ba00 12ff7ffe 00498dc377c205a4 000155b8 0300ba00 12ff7ffe 00498dc377c205b4 000156b8 0300ba00 12ff7ffe 00498dc377c205c4 000157b8 0300ba00 12ff7ffe 900010c277c205d4 000158b8 0300ba00 12ff7ffe 900018c277c205e4 000159b8 0300ba00 12ff7ffe 900010c2睁大眼睛看那个0xCC,对的,这里的确有0xCC。因为内核断点已经取消了,这一定是用户态调试器写入的。接下来的问题是,既然这里有0xCC,那么为什么不影响其它进程呢?注意这个线性地址与前面的一模一样。其中的奥妙在于这个线性地址已经不再是前面那个物理地址了:1: kd !pte 77c20574 VA 77c20574PDE at 00000000C0601DF0 PTE at 00000000C03BE100contains 00000000012E0867 contains 00000000049BD025pfn 12e0 -DA-UWEV pfn 49bd -A-UREV虽然还同是一个线性地址,但是它现在对应的物理地址变成了49bd574。观察这个物理地址,其内容与刚才使用线性地址的得到的结果是一样的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论