用户态上下文有额外典型的两种,Session会话上下文和Process进程上下文,由于用户态进程访问的都是虚拟内存,要想调试用户态代码,就必须切换到相应的会话上下文和进程上下文,进行相关的设置。要注意的一件事是,上下文的切换,只对当前的调试空间有效,也就是说,当F5或者g之后,绝大部分的切换都将被重置。以下:
1.会话上下文(SessionContext),关联的是登录会话。比如:
1: kd> !session
Sessions on machine: 2
Valid Sessions: 0 1
Error in reading current session
由于第一次使用!session,没有保存过session上下文,所以有Error in reading current session出现。
1: kd> .cache forcedecodeptes
Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 0 bytes (0 KB)
Number of regions cached: 0
0 full reads broken into 0 partial reads
counts: 0 cached/0 uncached, 0.00% cached
bytes : 0 cached/0 uncached, 0.00% cached
** Transition PTEs are implicitly decoded
** Virtual addresses are translated to physical addresses before access
** Prototype PTEs are implicitly decoded
上面的.cache forcedecodeptes命令强制刷新所有缓存的虚拟内存,将虚拟内存转换为物理内存。
如果出现了涉及虚拟内存的上下文切换,比如.process,.thread,!session等,每次都必须进行强制转换,否则将访问无效的虚拟内存。后面在进程上下文里也会有提及。而另一个同等作用的forcedecodeuser将用户层虚拟内存无效化,强制转换。
1: kd> !session /s 1
Sessions on machine: 2
Implicit process is now 85827750
Using session 1
设置当前的会话为Session1,在Vista之后,由于会话隔离机制的存在,默认存在2个Session。
1: kd> !sprocess
Dumping Session 1
_MM_SESSION_SPACE 8f8d9000
_MMSESSION 8f8d9d00
PROCESS 85827750 SessionId: 1 Cid: 019c Peb: 7ffdd000 ParentCid: 018c
DirBase: 2fed6040 ObjectTable: 94210fc0 HandleCount: 162.
Image: csrss.exe
PROCESS 88fa7d40 SessionId: 1 Cid: 01b8 Peb: 7ffd3000 ParentCid: 018c
DirBase: 2fed60c0 ObjectTable: 9434af18 HandleCount: 113.
Image: winlogon.exe
//...
你也可以直接使用1: kd> !sprocess 1 0来查看会话中的进程信息。
2.进程上下文(Process Context),关联的是进程信息。
对于进程来说,访问的内存都是虚拟内存,进程使用页目录将虚拟内存翻译成物理内存,这样,要想调试进程,就必须将上下文切换到目标进程的空间中,这个可以使用.process来办到。对于安腾Itanium处理器,一个进程可以有多个页目录,这种情况可以使用.cache forcedecodeuser加上.context (DirBase)进行地址切换。
下面是一个示例:
首先枚举出当前的进程,可以使用!sprocess或者!process 0 0或者!for_each_process,比如:
0: kd> !for_each_process
PROCESS 83bffa20 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00185000 ObjectTable: 85601c50 HandleCount: 449.
Image: System
//...
PROCESS 88fb0c38 SessionId: 1 Cid: 0de8 Peb: 7ffd8000 ParentCid: 0648
DirBase: 2fed62c0 ObjectTable: 9dafa868 HandleCount: 59.
Image: notepad.exe
然后可以使用.process进行上下文切换:
0: kd> !process -1 0
PROCESS 83bffa20 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00185000 ObjectTable: 85601c50 HandleCount: 449.
Image: System
查看当前的进程空间,在System。
1: kd> .process /r /p 88fb0c38
Implicit process is now 88fb0c38
.cache forcedecodeuser done
Loading User Symbols
.........................
/r结合/p参数强制加载用户态模块的符号文件。起到的作用是.reload /user。
/p参数和.cache forcedecodeuser是一样的作用,如果不指定/p,那就需要手动设置.cache。
这个命令在分析Dump的时候很有用,因为Dump中无法使用下面的/i参数进行断点设置。
0: kd> .process /i 88fb0c38
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
.process加上/i参数进行侵入式切换,这样才能在目标进程空间进行断点等操作。当目标进程获得CPU时间时,切换就会完成。
0: kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
82684394 cc int 3
0: kd> !process -1 0
PROCESS 88fb0c38 SessionId: 1 Cid: 0de8 Peb: 7ffd8000 ParentCid: 0648
DirBase: 2fed62c0 ObjectTable: 9dafa868 HandleCount: 59.
Image: notepad.exe
切换完成。注意此时如果使用.context看到的结果是空,如果不使用/i参数,看到的.context就是DirBase的值2fed62c0。
0: kd> .reload /user
Loading User Symbols
.........................
0: kd> lmu
然后可以设置断点,比如:
0: kd> bp /p @$proc ntdll!RtlAllocateHeap "!process -1 0;g"
0: kd> g
PROCESS 88fb0c38 SessionId: 1 Cid: 0de8 Peb: 7ffd8000 ParentCid: 0648
DirBase: 2fed62c0 ObjectTable: 9dafa868 HandleCount: 59.
Image: notepad.exe
这里使用伪寄存器$proc来指定当前的进程,当目标进程有函数调用时就会中断下来,不过因为刷新的原因,时间可能要略微久点...
文章来自: http://www.newkernel.com/1/post/2009/05/081.html