Watch & Learn

Debugwar Blog

Step in or Step over, this is a problem ...

蓝屏Dump分析两例:PageFault与栈越界(DoubleFault)

2023-12-30 @ UTC+0

近期手头收到了不少蓝屏崩溃的dump,其中有两个比较离谱所以特意将分析过程记录一下。接下来废话不多说,咱们直接开始。

Page Fault

首先祭出万能的!analyze -v命令,让windbg自动为我们跑一下dump的现场:
  1. 0: kd> !analyze -v  
  2. *******************************************************************************  
  3. *                                                                             *  
  4. *                        Bugcheck Analysis                                    *  
  5. *                                                                             *  
  6. *******************************************************************************  
  7.   
  8. PAGE_FAULT_IN_NONPAGED_AREA (50)  
  9. Invalid system memory was referenced.  This cannot be protected by try-except.  
  10. Typically the address is just plain bad or it is pointing at freed memory.  
  11. Arguments:  
  12. Arg1: ffffba84023d5000, memory referenced.  
  13. Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.  
  14. Arg3: fffff8077ec91174, If non-zero, the instruction address which referenced the bad memory  
  15.     address.  
  16. Arg4: 0000000000000002, (reserved)  
  17.   
  18. Debugging Details:  
  19. ------------------  
  20.   
  21. Unable to load image \??\C:\Windows\system32\drivers\TargetSys64.sys, Win32 error 0n2  
  22.   
  23. "C:\Windows\System32\KERNELBASE.dll" was not found in the image list.  
  24. Debugger will attempt to load "C:\Windows\System32\KERNELBASE.dll" at given base 00000000`00000000.  
  25.   
  26. Please provide the full image name, including the extension (i.e. kernel32.dll)  
  27. for more reliable results.Base address and size overrides can be given as  
  28. .reload <image.ext>=<base>,<size>.  
  29. Unable to add module at 00000000`00000000  
  30.   
  31. KEY_VALUES_STRING: 1  
  32.   
  33.     Key  : AV.Type  
  34.     Value: Read  
  35.   
  36.     Key  : Analysis.CPU.mSec  
  37.     Value: 3640  
  38.   
  39.     Key  : Analysis.DebugAnalysisManager  
  40.     Value: Create  
  41.   
  42.     Key  : Analysis.Elapsed.mSec  
  43.     Value: 127157  
  44.   
  45.     Key  : Analysis.Init.CPU.mSec  
  46.     Value: 2968  
  47.   
  48.     Key  : Analysis.Init.Elapsed.mSec  
  49.     Value: 87184  
  50.   
  51.     Key  : Analysis.Memory.CommitPeak.Mb  
  52.     Value: 119  
  53.   
  54.     Key  : WER.OS.Branch  
  55.     Value: vb_release  
  56.   
  57.     Key  : WER.OS.Timestamp  
  58.     Value: 2019-12-06T14:06:00Z  
  59.   
  60.     Key  : WER.OS.Version  
  61.     Value: 10.0.19041.1  
  62.   
  63.   
  64. FILE_IN_CAB:  App.dmp  
  65.   
  66. VIRTUAL_MACHINE:  VMware  
  67.   
  68. BUGCHECK_CODE:  50  
  69.   
  70. BUGCHECK_P1: ffffba84023d5000  
  71.   
  72. BUGCHECK_P2: 0  
  73.   
  74. BUGCHECK_P3: fffff8077ec91174  
  75.   
  76. BUGCHECK_P4: 2  
  77.   
  78. READ_ADDRESS:  ffffba84023d5000 Nonpaged pool  
  79.   
  80. MM_INTERNAL_CODE:  2  
  81.   
  82. IMAGE_NAME:  TargetSys64.sys  
  83.   
  84. MODULE_NAME: TargetSys64  
  85.   
  86. FAULTING_MODULE: fffff8077ec70000 TargetSys64  
  87.   
  88. PROCESS_NAME:  App.exe  
  89.   
  90. TRAP_FRAME:  fffffe8727a9ab70 -- (.trap 0xfffffe8727a9ab70)  
  91. NOTE: The trap frame does not contain all registers.  
  92. Some register values may be zeroed or incorrect.  
  93. rax=ffff994ca6532701 rbx=0000000000000000 rcx=8a000000a5282863  
  94. rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000  
  95. rip=fffff8077ec91174 rsp=fffffe8727a9ad00 rbp=0000000000000208  
  96.  r8=fffffe8727a9c000  r9=ffff995d42011ea0 r10=ffffba84023d4ff9  
  97. r11=ffff994ca6532000 r12=0000000000000000 r13=0000000000000000  
  98. r14=0000000000000000 r15=0000000000000000  
  99. iopl=0         nv up ei pl nz na pe nc  
  100. TargetSys64+0x21174:  
  101. fffff807`7ec91174 488b07          mov     rax,qword ptr [rdi] ds:00000000`00000000=????????????????  
  102. Resetting default scope  
  103.   
  104. STACK_TEXT:    
  105. fffffe87`27a9a118 fffff805`23b2af82     : fffffe87`27a9a280 fffff805`23990f60 fffff807`7ec70000 00000000`00000000 : nt!DbgBreakPointWithStatus  
  106. fffffe87`27a9a120 fffff805`23b2a566     : fffff807`00000003 fffffe87`27a9a280 fffff805`23a27a90 fffffe87`27a9a7d0 : nt!KiBugCheckDebugBreak+0x12  
  107. fffffe87`27a9a180 fffff805`23a10747     : 00000000`00000000 00000000`00000000 ffffba84`023d5000 ffffba84`023d5000 : nt!KeBugCheck2+0x946  
  108. fffffe87`27a9a890 fffff805`23a4bcbf     : 00000000`00000050 ffffba84`023d5000 00000000`00000000 fffffe87`27a9ab70 : nt!KeBugCheckEx+0x107  
  109. fffffe87`27a9a8d0 fffff805`23843730     : fffff805`23613000 00000000`00000000 fffffe87`27a9abf0 00000000`00000000 : nt!MiSystemFault+0x1de34f  
  110. fffffe87`27a9a9d0 fffff805`23a201d8     : 00000000`00000000 00000000`70503454 00000000`00000080 00000000`00000657 : nt!MmAccessFault+0x400  
  111. fffffe87`27a9ab70 fffff807`7ec91174     : ffffba84`0ccf0600 00000000`000007d4 ffffba84`0ccf0600 00000000`00000000 : nt!KiPageFault+0x358  
  112. fffffe87`27a9ad00 fffff807`7fe11fca     : ffffba83`f8c7e890 ffffba84`00000103 ffffba83`f5eb1814 ffffba84`0cef6790 : TargetSys64+0x21174  
  113. fffffe87`27a9ad90 fffff807`7fe12c8e     : 00000000`00040246 00000000`00000008 fffff807`7ec74b98 00000000`00000000 : TargetSys64+0x11a1fca  
  114. fffffe87`27a9b660 fffff805`23984777     : ffffba84`00646e50 fffff805`23fe81be 00000000`00000000 ffffba83`fb7cb7d0 : TargetSys64+0x11a2c8e  
  115. fffffe87`27a9b700 fffff805`23fdbf2a     : ffffba84`00646e50 ffffba83`fb7cb7d0 00000000`20206f49 00000000`00000000 : nt!IopfCallDriver+0x53  
  116. fffffe87`27a9b740 fffff805`23a35c6f     : 00000000`00000002 ffffba84`07446d80 00000000`00000028 ffffba84`01884af0 : nt!IovCallDriver+0x266  
  117. fffffe87`27a9b780 fffff805`23c1442c     : 00000000`00000001 ffffba84`00646f20 ffffba84`07446d80 fffffe87`27a9bb00 : nt!IofCallDriver+0x21265f  
  118. fffffe87`27a9b7c0 fffff805`23c14081     : ffffba84`00646f20 fffffe87`27a9bb00 00000000`00010000 ffffba84`00646f20 : nt!IopSynchronousServiceTail+0x34c  
  119. fffffe87`27a9b860 fffff805`23c133f6     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0xc71  
  120. fffffe87`27a9b9a0 fffff805`23a23ef5     : 00000000`00000670 00000000`09d0e678 00000000`09d0e688 00000000`00000008 : nt!NtDeviceIoControlFile+0x56  
  121. fffffe87`27a9ba10 00000000`77231cfc     : 00000000`77231933 00000023`772b2e1c 00000000`00000023 00000000`00000004 : nt!KiSystemServiceCopyEnd+0x25  
  122. 00000000`09d0ef88 00000000`77231933     : 00000023`772b2e1c 00000000`00000023 00000000`00000004 00000000`09e0edc4 : wow64cpu!CpupSyscallStub+0xc  
  123. 00000000`09d0ef90 00000000`772311b9     : 00000000`09e0f788 00007fff`18fa3a74 00000000`00000000 00007fff`18fa3b6f : wow64cpu!DeviceIoctlFileFault+0x31  
  124. 00000000`09d0f040 00007fff`18fa3989     : 00000000`077b8020 00000000`00000000 00000000`00000000 00000000`09d0f480 : wow64cpu!BTCpuSimulate+0x9  
  125. 00000000`09d0f080 00007fff`18fa337d     : 00000000`00000000 00000000`00000001 00000000`00000000 00000000`00000000 : wow64!RunCpuSimulation+0xd  
  126. 00000000`09d0f0b0 00007fff`1a405059     : 00000000`00000000 00000000`00000000 00000000`00000001 00000000`00000000 : wow64!Wow64LdrpInitialize+0x12d  
  127. 00000000`09d0f360 00007fff`1a404c43     : 00000000`00000000 00007fff`1a390000 00000000`00000000 00000000`051e0000 : ntdll!LdrpInitialize+0x3fd  
  128. 00000000`09d0f400 00007fff`1a404bee     : 00000000`09d0f480 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrpInitialize+0x3b  
  129. 00000000`09d0f430 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe  
  130.   
  131.   
  132. SYMBOL_NAME:  TargetSys64+21174  
  133.   
  134. STACK_COMMAND:  .cxr; .ecxr ; kb  
  135.   
  136. BUCKET_ID_FUNC_OFFSET:  21174  
  137.   
  138. FAILURE_BUCKET_ID:  AV_VRF_R_(null)_TargetSys64!unknown_function  
  139.   
  140. OS_VERSION:  10.0.19041.1  
  141.   
  142. BUILDLAB_STR:  vb_release  
  143.   
  144. OSPLATFORM_TYPE:  x64  
  145.   
  146. OSNAME:  Windows 10  
  147.   
  148. FAILURE_ID_HASH:  {202d262d-2ca9-029e-2e1d-9bf74e9fa6df}  
  149.   
  150. Followup:     MachineOwner  
  151. ---------  
初步看上去仅仅是一次平平无奇的PAGE_FAULT_IN_NONPAGED_AREA错误,继续关注一下产生该错误的指令如下:
  1. rax=ffff994ca6532701 rbx=0000000000000000 rcx=8a000000a5282863    
  2. rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000    
  3. rip=fffff8077ec91174 rsp=fffffe8727a9ad00 rbp=0000000000000208    
  4.  r8=fffffe8727a9c000  r9=ffff995d42011ea0 r10=ffffba84023d4ff9    
  5. r11=ffff994ca6532000 r12=0000000000000000 r13=0000000000000000    
  6. r14=0000000000000000 r15=0000000000000000    
  7. iopl=0         nv up ei pl nz na pe nc    
  8. TargetSys64+0x21174:    
  9. fffff807`7ec91174 488b07          mov     rax,qword ptr [rdi] ds:00000000`00000000=????????????????    
其现场看上去是对rdi地址做解引用操作,而rdi的值——也就是解引用的地址——为0,常识告诉我们对0地址做读操作会产生BSOD。

到目前为止,一切都看上去都很正常,可是当笔者尝试进一步分析为何指针会是0的时候,发现事情没有想象中那么简单。让我们先来看一下产生异常的指令附近的代码:
  1. 0: kd> ub fffff807`7ec91174  
  2. fffff807`7ec91160 33f6            xor     esi,esi  
  3. fffff807`7ec91162 4885ff          test    rdi,rdi  
  4. fffff807`7ec91165 7430            je      TargetSys64+0x21197 (fffff807`7ec91197)  
  5. fffff807`7ec91167 488bcf          mov     rcx,rdi  
  6. fffff807`7ec9116a 52              push    rdx  
  7. fffff807`7ec9116b e8e6e45600      call    TargetSys64+0x58f656 (fffff807`7f1ff656)  
  8. fffff807`7ec91170 84c0            test    al,al  
  9. fffff807`7ec91172 7423            je      TargetSys64+0x21197 (fffff807`7ec91197)  
  10. 0: kd> u fffff807`7ec91174   
  11. fffff807`7ec91174 488b07          mov     rax,qword ptr [rdi]  
  12. fffff807`7ec91177 4839442420      cmp     qword ptr [rsp+20h],rax  
  13. fffff807`7ec9117c 750a            jne     TargetSys64+0x21188 (fffff807`7ec91188)  
  14. fffff807`7ec9117e 4989b424a0000000 mov     qword ptr [r12+0A0h],rsi  
  15. fffff807`7ec91186 eb0f            jmp     TargetSys64+0x21197 (fffff807`7ec91197)  
  16. fffff807`7ec91188 4839442428      cmp     qword ptr [rsp+28h],rax  
  17. fffff807`7ec9118d 7508            jne     TargetSys64+0x21197 (fffff807`7ec91197)  
  18. fffff807`7ec9118f 4989b42498000000 mov     qword ptr [r12+98h],rsi  
fffff807`7ec91162处的test rdi,rdi这里已经判断了rdi是否为零,如果是零的话则会跳转到fffff807`7ec91197处(函数结尾)。而且笔者翻遍了所有反汇编代码,也没有发现可以绕开这条检查指令的跳转。

此时冲突就来了:既然有检查指针是否为空的地方,那么导致蓝屏的这条对0地址的解引用指令中rdi的值0,是如何产生的呢?

经过长时间瞎猫碰死耗子式的折腾,突然发现windbg有这么几行提示:
  1. TRAP_FRAME:  fffffe8727a9ab70 -- (.trap 0xfffffe8727a9ab70)    
  2. NOTE: The trap frame does not contain all registers.    
  3. Some register values may be zeroed or incorrect.    
原来TrapFramRecord中记录的寄存器还可以是不对的吗?

经过查阅张银奎老师的《软件调试》可知,当发生PageFault异常时CR2寄存器会存放导致异常的内存地址,我们来看一下此时该寄存器中的值是多少:
  1. 0: kd> r @cr2  
  2. cr2=ffffba84023d5000  
  3. 0: kd> db @cr2  
  4. ffffba84`023d5000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????  
  5. ffffba84`023d5010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????  
可知cr2目前的值为ffffba84023d5000——也就是说导致本次PageFault的地址是ffffba84023d5000

那么接下来的问题就是搞清楚rdi的值应该是多少,这需要我们分析异常上下文的代码:
  1. 0: kd> uf fffff8077ec91174  
  2. ……  
  3. fffff807`7ec9113b 65488b3c2588010000 mov   rdi,qword ptr gs:[188h]  
  4. ……  
  5. fffff807`7ec91154 4c8daf00100000  lea     r13,[rdi+1000h]  
  6. fffff807`7ec9115b 493bfd          cmp     rdi,r13  
  7. fffff807`7ec9115e 7342            jae     TargetSys64+0x211a2 (fffff807`7ec911a2)  Branch  
  8. ……  
  9. fffff807`7ec91162 4885ff          test    rdi,rdi  
  10. fffff807`7ec91165 7430            je      TargetSys64+0x21197 (fffff807`7ec91197)  Branch  
  11. ……  
  12. fffff807`7ec91174 488b07          mov     rax,qword ptr [rdi]  
  13. ……  
  14. fffff807`7ec91197 48ffc7          inc     rdi  
  15. ……  
  16. fffff807`7ec9119d 493bfd          cmp     rdi,r13  
  17. fffff807`7ec911a0 72c0            jb      TargetSys64+0x21162 (fffff807`7ec91162)  Branch  
在X86_64下,gs:[188h]其实就是ETHREAD


阅读上述反汇编代码,等价于下面的C代码:
  1. struct _ETHREAD* CurrentThread = KeGetCurrentThread();  
  2.   
  3. for (PUCHAR CurrentPointer = (PUCHAR)CurrentThread; CurrentPointer <= (PUCHAR)CurrentThread + 0x1000; ++CurrentPointer)  
  4. {  
  5.     ……
  6.     auto rax = *(QWORD *)CurrentPointer;
  7.     ……
  8. }  
说人话就是从当前线程结构搜索一个页(0x1000也就是4kb)大小的内存。

那么当前线程是多少?由windbg可知:
  1. 0: kd> .thread  
  2. Implicit thread is now ffffba84`023d4080  
  3. 0: kd> dp gs:[0x188]  
  4. 002b:00000000`00000188  ffffba84`023d4080 00000000`00000000  
  5. 002b:00000000`00000198  fffff805`2433aa00 00000000`01010100  
使用.thread命令或直接查看寄存器相对偏移处的值均可得到相同的值,即当前线程是ffffba84`023d4080,程序将会从这个地址开始,遍历一个内存页大小的数据。

ffffba84`023d4080这个地址属于如下页范围: 
  1. >> rax2 =16 '0xffffba84023d4080/0x1000*0x1000'
  2. 0xffffba84023d4000
  3. >> rax2 =16 '0xffffba84023d4080/0x1000*0x1000+0x1000-1'
  4. 0xffffba84023d4fff
既当前遍历的是从地址ffffba84`023d4080开始至0xffffba84023d5080为止,这个地址范围产生了跨页,跨页的地点位于ffffba84`023d4fff,接下来看一下这个地点的内存情况:
  1. 0: kd> db ffffba84`023d4fff  
  2. ffffba84`023d4fff  ff ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  .???????????????  
  3. ffffba84`023d500f  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????  
  4. ffffba84`023d501f  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????  
可见从ffffba84`023d4fff+1,也就是ffffba84`023d5000开始内存就变为不可用了,而此地址正是上文中我们分析得到的位于CR2中存储的导致Page Fault的地址。

至此,这个dump成因已经明确:
  1. 程序遍历从当前线程的ETHREAD开始、大小为0x1000的地址
  2. 地址以1递增,每次取一个QWORD长度的数据进行操作
  3. 当地址递增到ffffba84`023d4ff9时,取一个QWORD长度,此时会访问ffffba84`023d5000地址
  4. ffffba84`023d5000地址为跨页后的第一个地址,为无效地址,导致Page Fault发生
因此,这个bug的解决方案为,二选一即可:
  1. 限定搜索范围为起始地址至当前地址所属页的最后一个地址
  2. 判断跨页的情况

Double Fault

ZwQueryVirtualMemory引发的异常

照例先上现场的!analyze -v日志:
  1. *** Fatal System Error: 0x0000007f  
  2.                        (0x00000008,0x80F4F000,0x00000000,0x00000000)  
  3.   
  4. Break instruction exception - code 80000003 (first chance)  
  5.   
  6. A fatal system error has occurred.  
  7. Debugger entered on first try; Bugcheck callbacks have not been invoked.  
  8.   
  9. A fatal system error has occurred.  
  10.   
  11. For analysis of this file, run !analyze -v  
  12. WARNING: Process directory table base D77EB060 doesn't match CR3 001A8000  
  13. WARNING: Process directory table base D77EB060 doesn't match CR3 001A8000  
  14. nt!RtlpBreakWithStatusInstruction:  
  15. 81945064 cc              int     3  
  16. kd> !analyze -v  
  17. Connected to Windows 10 14393 x86 compatible target at (Wed Dec 27 12:19:59.494 2023 (UTC + 8:00)), ptr64 FALSE  
  18. Loading Kernel Symbols  
  19. ...............................................................  
  20. ................................................................  
  21. ...........................  
  22. Loading User Symbols  
  23. ...............  
  24. Loading unloaded module list  
  25. .............ReadVirtual: 12f40000 not properly sign extended  
  26.   
  27. *******************************************************************************  
  28. *                                                                             *  
  29. *                        Bugcheck Analysis                                    *  
  30. *                                                                             *  
  31. *******************************************************************************  
  32.   
  33. UNEXPECTED_KERNEL_MODE_TRAP (7f)  
  34. This means a trap occurred in kernel mode, and it's a trap of a kind  
  35. that the kernel isn't allowed to have/catch (bound trap) or that  
  36. is always instant death (double fault).  The first number in the  
  37. BugCheck params is the number of the trap (8 = double fault, etc)  
  38. Consult an Intel x86 family manual to learn more about what these  
  39. traps are. Here is a *portion* of those codes:  
  40. If kv shows a taskGate  
  41.         use .tss on the part before the colon, then kv.  
  42. Else if kv shows a trapframe  
  43.         use .trap on that value  
  44. Else  
  45.         .trap on the appropriate frame will show where the trap was taken  
  46.         (on x86, this will be the ebp that goes with the procedure KiTrap)  
  47. Endif  
  48. kb will then show the corrected stack.  
  49. Arguments:  
  50. Arg1: 00000008, EXCEPTION_DOUBLE_FAULT  
  51. Arg2: 80f4f000  
  52. Arg3: 00000000  
  53. Arg4: 00000000  
  54.   
  55. Debugging Details:  
  56. ------------------  
  57.   
  58. ReadVirtual: 14100000 not properly sign extended  
  59. *************************************************************************  
  60. ***                                                                   ***  
  61. ***                                                                   ***  
  62. ***    Either you specified an unqualified symbol, or your debugger   ***  
  63. ***    doesn't have full symbol information.  Unqualified symbol      ***  
  64. ***    resolution is turned off by default. Please either specify a   ***  
  65. ***    fully qualified symbol module!symbolname, or enable resolution ***  
  66. ***    of unqualified symbols by typing ".symopt- 100". Note that     ***  
  67. ***    enabling unqualified symbol resolution with network symbol     ***  
  68. ***    server shares in the symbol path may cause the debugger to     ***  
  69. ***    appear to hang for long periods of time when an incorrect      ***  
  70. ***    symbol name is typed or the network symbol server is down.     ***  
  71. ***                                                                   ***  
  72. ***    For some commands to work properly, your symbol path           ***  
  73. ***    must point to .pdb files that have full type information.      ***  
  74. ***                                                                   ***  
  75. ***    Certain .pdb files (such as the public OS symbols) do not      ***  
  76. ***    contain the required information.  Contact the group that      ***  
  77. ***    provided you with these symbols if you need this command to    ***  
  78. ***    work.                                                          ***  
  79. ***                                                                   ***  
  80. ***    Type referenced: kernelbase!gpServerNlsUserInfo                ***  
  81. ***                                                                   ***  
  82. *************************************************************************  
  83.   
  84. KEY_VALUES_STRING: 1  
  85.   
  86.     Key  : Analysis.CPU.mSec  
  87.     Value: 5405  
  88.   
  89.     Key  : Analysis.DebugAnalysisManager  
  90.     Value: Create  
  91.   
  92.     Key  : Analysis.Elapsed.mSec  
  93.     Value: 16078  
  94.   
  95.     Key  : Analysis.Init.CPU.mSec  
  96.     Value: 21530  
  97.   
  98.     Key  : Analysis.Init.Elapsed.mSec  
  99.     Value: 81099  
  100.   
  101.     Key  : Analysis.Memory.CommitPeak.Mb  
  102.     Value: 78  
  103.   
  104.     Key  : WER.OS.Branch  
  105.     Value: rs1_release  
  106.   
  107.     Key  : WER.OS.Timestamp  
  108.     Value: 2016-07-15T16:16:00Z  
  109.   
  110.     Key  : WER.OS.Version  
  111.     Value: 10.0.14393.0  
  112.   
  113.   
  114. BUGCHECK_CODE:  7f  
  115.   
  116. BUGCHECK_P1: 8  
  117.   
  118. BUGCHECK_P2: ffffffff80f4f000  
  119.   
  120. BUGCHECK_P3: 0  
  121.   
  122. BUGCHECK_P4: 0  
  123.   
  124. TSS:  00000028 -- (.tss 0x28)  
  125. eax=0006b090 ebx=81a41200 ecx=81a41200 edx=00000010 esi=88a8e1c0 edi=00000010  
  126. eip=818c4c59 esp=a5dd9000 ebp=a5dd9008 iopl=0         nv up ei pl nz na po cy  
  127. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010203  
  128. nt!MiDecreaseAvailablePages+0x9:  
  129. 818c4c59 57              push    edi  
  130. Resetting default scope  
  131.   
  132. PROCESS_NAME:  csrss.exe  
  133.   
  134. DEVICE_OBJECT: 899fda60  
  135.   
  136. DRIVER_OBJECT: 00000000  
  137.   
  138. TRAP_FRAME:  a5dd9478 -- (.trap 0xffffffffa5dd9478)  
  139. ErrCode = 00000000  
  140. eax=00000000 ebx=8a8b0000 ecx=bfffff00 edx=92a22100 esi=c0019a08 edi=00000000  
  141. eip=8187663b esp=a5dd94ec ebp=a5dd9524 iopl=0         nv up ei pl zr na pe nc  
  142. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246  
  143. nt!MiQueryAddressState+0x1ab:  
  144. 8187663b 8b0b            mov     ecx,dword ptr [ebx]  ds:0023:8a8b0000=????????  
  145. Resetting default scope  
  146.   
  147. STACK_TEXT:    
  148. a5dd9008 818c4ba9     ffffffff 00000000 87c2e680 nt!MiDecreaseAvailablePages+0x9  
  149. a5dd9030 818c4a1b     00000001 00000000 81a41200 nt!MiUnlinkNodeLargePageHelper+0xb9  
  150. a5dd9060 8187d822     02000000 00000000 87c2e680 nt!MiUnlinkNodeLargePage+0x11b  
  151. a5dd90e4 8187d2a5     00000002 00000000 00000001 nt!MiGetFreeOrZeroPage+0x452  
  152. a5dd9124 8187cfd0     00000002 00454580 a5dd9244 nt!MiGetPage+0x55  
  153. a5dd91d4 8187b3b3     00000000 00000004 00000042 nt!MiGetPageChain+0x130  
  154. a5dd9230 8187a1bf     8a8b0000 a5dd9478 a5dd92f8 nt!MiResolvePrivateZeroFault+0x93  
  155. a5dd9294 818bb043     00000000 81a40090 a5dd9478 nt!MiResolveDemandZeroFault+0x15f  
  156. a5dd92f8 8187794a     a5dd9478 8a8b0000 a5dd9360 nt!MiSystemFault+0x8d3  
  157. a5dd93d8 819558cc     00000000 8a8b0000 00000000 nt!MmAccessFault+0x78a  
  158.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  159. a5dd93d8 8187663b (T) 00000000 8a8b0000 00000000 nt!KiTrap0E+0xec  
  160.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  161. a5dd9524 818763ec (T) 92a22100 c0019a00 00002000 nt!MiQueryAddressState+0x1ab  
  162. a5dd9570 81ad8f03     03340000 9424b4b8 a5dd967c nt!MiQueryAddressSpan+0x9c  
  163. a5dd9640 81ad8a96     00000000 a5dd9790 0000001c nt!MmQueryVirtualMemory+0x463  
  164. a5dd965c 819522c7     80000d24 03140000 00000000 nt!NtQueryVirtualMemory+0x1e  
  165.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  166. a5dd965c 81942665 (T) 80000d24 03140000 00000000 nt!KiSystemServicePostCall  
  167.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  168. a5dd96ec bf444f6e (T) 80000d24 03140000 00000000 nt!ZwQueryVirtualMemory+0x11  
  169. WARNING: Stack unwind information not available. Following frames may be wrong.  
  170. a5dd97f8 bf444a0a     b6337440 80000d24 92a22100 TargetSys32+0x34f6e  
  171. a5dd9908 bf444a0a     b6337440 80000d24 9a54b008 TargetSys32+0x34a0a  
  172. a5dd9a18 bf444a0a     b6337440 80000d24 90ad62a0 TargetSys32+0x34a0a  
  173. a5dd9b28 bf444b9b     b6337440 80000d24 92a295c0 TargetSys32+0x34a0a  
  174. a5dd9c38 bf444b9b     b6337440 80000d24 912de488 TargetSys32+0x34b9b  
  175. a5dd9d48 bf444a0a     b6337440 80000d24 a4661a58 TargetSys32+0x34b9b  
  176. a5dd9e58 bf445bdd     b6337440 80000d24 8ef9ce4c TargetSys32+0x34a0a  
  177. a5dda12c bf445fd2     b6337440 8ef9cbc0 a5ddba4c TargetSys32+0x35bdd  
  178. a5dda13c bf414fe9     b6337440 8ef9cbc0 0022010e TargetSys32+0x35fd2  
  179. a5ddba4c bf4163d9     abd30040 00000004 00000000 TargetSys32+0x4fe9  
  180. a5ddba80 818864a3     8fefc830 a47bbd80 00220108 TargetSys32+0x63d9  
  181. a5ddba9c 81ac7d83     a47bbe14 a47bbd80 0022e208 nt!IofCallDriver+0x43  
  182. a5ddbaf0 81ac77f0     899fda60 00000000 81b34f01 nt!IopSynchronousServiceTail+0x133  
  183. a5ddbbb8 81ac73fa     00000000 00000000 049bf570 nt!IopXxxControlFile+0x3e0  
  184. a5ddbbe4 819522c7     0000040c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a  
  185.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  186. a5ddbbe4 770d38b0 (T) 0000040c 00000000 00000000 nt!KiSystemServicePostCall  
  187.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  188. 049bf590 00000000 (T) 00000000 00000000 00000000 ntdll!KiFastSystemCallRet  
  189.   
  190.   
  191. STACK_COMMAND:  .tss 0x28 ; kb  
  192.   
  193. SYMBOL_NAME:  TargetSys32+34f6e  
  194.   
  195. MODULE_NAME: TargetSys32  
  196.   
  197. IMAGE_NAME:  TargetSys32.sys  
  198.   
  199. BUCKET_ID_FUNC_OFFSET:  34f6e  
  200.   
  201. FAILURE_BUCKET_ID:  0x7f_8_TargetSys32!unknown_function  
  202.   
  203. OS_VERSION:  10.0.14393.0  
  204.   
  205. BUILDLAB_STR:  rs1_release  
  206.   
  207. OSPLATFORM_TYPE:  x86  
  208.   
  209. OSNAME:  Windows 10  
  210.   
  211. FAILURE_ID_HASH:  {00fcc8ef-033e-c4ad-af92-bd9b0e8be063}  
  212.   
  213. Followup:     MachineOwner  
  214. ---------  
可以看到分析出的结论其实是UNEXPECTED_KERNEL_MODE_TRAP(后面还有更具体的原因,在Arg1中,为EXCEPTION_DOUBLE_FAULT),而导致dump的原因是下面这个调用:
  1. nt!MiQueryAddressState+0x1ab:    
  2. 8187663b 8b0b            mov     ecx,dword ptr [ebx]  ds:0023:8a8b0000=????????    
然而问题是,上面的调用不应该是触发一个Page Fault么, 为什么现在系统提示是UNEXPECTED_KERNEL_MODE_TRAP或者是DOUBLE_FAULT?笔者一开始也没搞懂为什么,不过既然导致异常的语句是因为内存非法访问产生的, 那笔者一开始想的是将ZwQueryVirtualMemory的调用注释掉,看一下传入到ZwQueryVirtualMemory中查询的内存是哪块,然后再追踪有异常的内存是如何产生的。

于是笔者将产生问题的相关代码修改成了如下样子:
  1. StartAddress *= PAGE_SIZE;  
  2. EndingAddress *= PAGE_SIZE;  
  3.   
  4. DbgPrint("Start: %X\r\n", StartAddress);  
  5.   
  6. /* 
  7. Status = ZwQueryVirtualMemory(HandleProcess, (PVOID)BaseAddress, 0, \ 
  8.     &MemoryBasicInformation, sizeof(MEMORY_BASIC_INFORMATION), &ReturnLength); 
  9. */  

DbgPrint引发的异常

然后,笔者得到了另外一个更加离谱的dump(为了方便说明问题,笔者对dump内容做了删减):
  1. UNEXPECTED_KERNEL_MODE_TRAP (7f)  
  2. kb will then show the corrected stack.  
  3. Arguments:  
  4. Arg1: 00000008, EXCEPTION_DOUBLE_FAULT  
  5. Arg2: 80f4f000  
  6. Arg3: 00000000  
  7. Arg4: 00000000  
  8.   
  9. Debugging Details:  
  10.   
  11. TSS:  00000028 -- (.tss 0x28)  
  12. eax=00000000 ebx=00000000 ecx=d2a71b40 edx=00000000 esi=a999b0d0 edi=a999a000  
  13. eip=818771ce esp=a999affc ebp=a999b0b8 iopl=0         nv up ei ng nz ac pe nc  
  14. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010296  
  15. nt!MmAccessFault+0xe:  
  16. 818771ce 53              push    ebx  
  17. Resetting default scope  
  18.   
  19. PROCESS_NAME:  App.exe  
  20.   
  21. DEVICE_OBJECT: b2360788  
  22.   
  23. TRAP_FRAME:  a999b720 -- (.trap 0xffffffffa999b720)  
  24. ErrCode = 00000000  
  25. eax=00000001 ebx=00000065 ecx=a999b7d0 edx=0000000f esi=81a26c70 edi=00000003  
  26. eip=81957d06 esp=a999b794 ebp=a999b7b0 iopl=0         nv up ei ng nz ac po nc  
  27. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000292  
  28. nt!DebugService+0x24:  
  29. 81957d06 5b              pop     ebx  
  30. Resetting default scope  
  31.   
  32. STACK_TEXT:    
  33. a999b0b8 819558cc     00000000 a999a000 00000000 nt!MmAccessFault+0xe  
  34.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  35. a999b0b8 81946543 (T) 00000000 a999a000 00000000 nt!KiTrap0E+0xec  
  36.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  37. a999b1fc 818a2adf (T) a999b720 00000000 a999b210 nt!_alloca_probe+0x27  
  38. a999b628 81953085     a999b644 00000000 a999b720 nt!KiDispatchException+0xd5  
  39. a999b694 819539e0     0000000f 00000000 00000000 nt!KiDispatchTrapException+0x51  
  40.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  41. a999b694 81957d06 (T) 0000000f 00000000 00000000 nt!KiTrap03+0xf4  
  42.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  43. a999b7b0 818bd37c (T) 0000000f 00000065 00000003 nt!DebugService+0x24  
  44. a999b7c4 818bd305     00000003 72617453 33203a74 nt!DebugPrint+0x18  
  45. a999b894 818bd1ff     00000003 d5869bb0 a999b8b8 nt!vDbgPrintExWithPrefixInternal+0xd9  
  46. a999b8ac d5834aba     d5869bb0 00300000 01000000 nt!DbgPrint+0x1d  
  47. WARNING: Stack unwind information not available. Following frames may be wrong.  
  48. a999b950 d583465c     d7004460 80000c84 9a4c0220 TargetSys32+0x34aba  
  49. a999ba08 d583465c     d7004460 80000c84 8ff9b540 TargetSys32+0x3465c  
这次蓝屏,直接蓝在了DbgPrint函数上!到这里笔者已经没有任何思路了,于是决定去请教公司的其他大佬,大佬看到dump截图后(对,都没跟我要dump文件)轻飘飘来了一句——栈爆了……

栈爆了

短短三个字,却犹如安静之处听惊雷——瞬间打开了笔者的思路,让我们先用上面DbgPrint的蓝屏快速来看一下。

DbgPrint引发的异常Dump分析

首先是当前栈的状态:
  1. kd> !thread  
  2. THREAD d2a71b40  Cid 135c.0c9c  Teb: 002d6000 Win32Thread: 89954530 RUNNING on processor 0  
  3. IRP List:  
  4.     ae659490: (0006,0094) Flags: 00060030  Mdl: 00000000  
  5. Not impersonating  
  6. DeviceMap                 96fd8d58  
  7. Owning Process            d70ae680       Image:         App.exe  
  8. Attached Process          N/A            Image:         N/A  
  9. Wait Start TickCount      18379          Ticks: 1 (0:00:00:00.015)  
  10. Context Switch Count      1021           IdealProcessor: 0               
  11. UserTime                  00:00:00.000  
  12. KernelTime                00:00:00.015  
  13. Win32 Start Address ntdll!TppWorkerThread (0x7708b050)  
  14. Stack Init a999dca0 Current a999bcfc Base a999e000 Limit a999b000 Call 00000000  
  15. Priority 11 BasePriority 8 PriorityDecrement 2 IoPriority 2 PagePriority 5  
  16. ChildEBP RetAddr      Args to Child                
  17. 81a2a694 819c50ee     00000003 b05b8410 00000065 nt!RtlpBreakWithStatusInstruction (FPO: [1,0,0])  
  18. 81a2a6e8 819c4b3b     8b51f340 81a2ab04 00000000 nt!KiBugCheckDebugBreak+0x1f (FPO: [Non-Fpo])  
  19. 81a2aad8 81943eda     0000007f 00000008 80f4f000 nt!KeBugCheck2+0x73a (FPO: [6,247,4])  
  20. 81a2aafc 819546c8     0000007f 00000008 80f4f000 nt!KiBugCheck2+0xc6  
  21.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  22. 81a2aafc 818771ce (T) 0000007f 00000008 80f4f000 nt!KiTrap08+0x6e (FPO: TSS 28:0)  
  23.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  24. a999b0b8 819558cc (T) 00000000 a999a000 00000000 nt!MmAccessFault+0xe (FPO: [4,47,4])  
  25.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  26. a999b0b8 81946543 (T) 00000000 a999a000 00000000 nt!KiTrap0E+0xec (FPO: [0,0] TrapFrame @ a999b15c)  
  27.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  28. a999b1fc 818a2adf (T) a999b720 00000000 a999b210 nt!_alloca_probe+0x27  
  29. a999b628 81953085     a999b644 00000000 a999b720 nt!KiDispatchException+0xd5 (FPO: [Non-Fpo])  
  30. a999b694 819539e0     0000000f 00000000 00000000 nt!KiDispatchTrapException+0x51  
  31.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  32. a999b694 81957d06 (T) 0000000f 00000000 00000000 nt!KiTrap03+0xf4 (FPO: [0,0] TrapFrame @ a999b720)  
  33.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  34. a999b7b0 818bd37c (T) 0000000f 00000065 00000003 nt!DebugService+0x24 (FPO: [Non-Fpo])  
  35. a999b7c4 818bd305     00000003 72617453 33203a74 nt!DebugPrint+0x18 (FPO: [Non-Fpo])  
  36. a999b894 818bd1ff     00000003 d5869bb0 a999b8b8 nt!vDbgPrintExWithPrefixInternal+0xd9 (FPO: [Non-Fpo])  
  37. a999b8ac d5834aba     d5869bb0 00300000 01000000 nt!DbgPrint+0x1d (FPO: [Non-Fpo])  
  38. WARNING: Stack unwind information not available. Following frames may be wrong.  
  39. a999b950 d583465c     d7004460 80000c84 9a4c0220 TargetSys32+0x34aba  
  40. a999ba08 d583465c     d7004460 80000c84 8ff9b540 TargetSys32+0x3465c  
  41. a999bac0 d58347af     d7004460 80000c84 8ee6ce68 TargetSys32+0x3465c  
可见当前栈的Limita999b000,也就是说栈(esp的值)不可能比这个值更小。由栈回溯可知,DbgPrint这个dump导致蓝屏的最直接原因是KiTrap08抛出的DOUBLE FAULT异常,那么既然是DOUBLE那么肯定有FIRST,FIRST在哪里呢?答案是nt!KiTrap0E+0xec这里,我们看下导致第一次异常的现场是什么样子的:
  1. kd> .trap a999b15c  
  2. ReadVirtual: a999b15c not properly sign extended  
  3. ErrCode = 00000000  
  4. eax=a999a000 ebx=a999b210 ecx=a999afbc edx=00000000 esi=a999b720 edi=00010037  
  5. eip=81946543 esp=a999b1d0 ebp=a999b1fc iopl=0         nv up ei ng nz na pe nc  
  6. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010286  
  7. nt!_alloca_probe+0x27:  
  8. 81946543 8500            test    dword ptr [eax],eax  ds:0023:a999a000=????????  
可见产生了一个非法地址访问,这也与栈上的nt!MmAccessFault访问能对的上。

那么第二次异常是如何产生的呢?我们顺着上文中的nt!MmAccessFault调用找,有两种方法, 一种是借用TSS任务段选择子(TSS 28:0)定位, 或者直接对nt!MmAccessFault+0xe做反汇编,其结果是一样的:
  1. kd> .tss 28  
  2. eax=00000000 ebx=00000000 ecx=d2a71b40 edx=00000000 esi=a999b0d0 edi=a999a000  
  3. eip=818771ce esp=a999affc ebp=a999b0b8 iopl=0         nv up ei ng nz ac pe nc  
  4. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010296  
  5. nt!MmAccessFault+0xe:  
  6. 818771ce 53              push    ebx  
  7. kd> ub nt!MmAccessFault+0xe  
  8. nt!MiObtainReferencedVad+0x4dd:  
  9. 818771bd cc              int     3  
  10. 818771be cc              int     3  
  11. 818771bf cc              int     3  
  12. nt!MmAccessFault:  
  13. 818771c0 8bff            mov     edi,edi  
  14. 818771c2 55              push    ebp  
  15. 818771c3 8bec            mov     ebp,esp  
  16. 818771c5 83e4f8          and     esp,0FFFFFFF8h  
  17. 818771c8 81ecbc000000    sub     esp,0BCh  
  18. kd> u nt!MmAccessFault+0xe  
  19. nt!MmAccessFault+0xe:  
  20. 818771ce 53              push    ebx  
  21. 818771cf 8b5d08          mov     ebx,dword ptr [ebp+8]  
  22. 818771d2 8bc3            mov     eax,ebx  
  23. 818771d4 83e009          and     eax,9  
  24. 818771d7 56              push    esi  
  25. 818771d8 57              push    edi  
  26. 818771d9 3c09            cmp     al,9  
可以看到tss 28nt!MmAccessFault+0xe的地址是一致的,而且通过ub命令可知,此时MmAccessFault尝试开辟0xbc大小的栈帧:
  1. 818771c8 81ecbc000000    sub     esp,0BCh    
此时根据栈回溯可知,EBPa999b0b8
  1. 81a2aafc 819546c8     0000007f 00000008 80f4f000 nt!KiBugCheck2+0xc6    
  2.     <Intermediate frames may have been skipped due to lack of complete unwind>    
  3. 81a2aafc 818771ce (T) 0000007f 00000008 80f4f000 nt!KiTrap08+0x6e (FPO: TSS 28:0)    
  4.     <Intermediate frames may have been skipped due to lack of complete unwind>    
  5. a999b0b8 819558cc (T) 00000000 a999a000 00000000 nt!MmAccessFault+0xe (FPO: [4,47,4])    
  6.     <Intermediate frames may have been skipped due to lack of complete unwind>    
  7. a999b0b8 81946543 (T) 00000000 a999a000 00000000 nt!KiTrap0E+0xec (FPO: [0,0] TrapFrame @ a999b15c)    
那么a999b0b8 - 0xbc = 0xa999affc——这个值已经小于上文中提到的Limit(0xa999b000)了——如果继续执行818771ce地址处的push ebx指令必然会产生第二次异常,这也是DOUBLE FAULT的真正由来。

ZwQueryVirtualMemory引发的异常Dump分析

我们依葫芦画瓢,先看下当前线程的Stack Limit是多少:
  1. kd> !thread  
  2. THREAD 9a573b40  Cid 097c.1088  Teb: 00b7c000 Win32Thread: 8f2d9e80 RUNNING on processor 0  
  3. IRP List:  
  4.     92a28e38: (0006,0094) Flags: 00060030  Mdl: 00000000  
  5. Not impersonating  
  6. DeviceMap                 8ba03168  
  7. Owning Process            b22eb040       Image:         App.exe  
  8. Attached Process          8ef9cbc0       Image:         csrss.exe  
  9. Wait Start TickCount      18358          Ticks: 1 (0:00:00:00.015)  
  10. Context Switch Count      1077           IdealProcessor: 0               
  11. UserTime                  00:00:00.000  
  12. KernelTime                00:00:00.031  
  13. Win32 Start Address ntdll!TppWorkerThread (0x7708b050)  
  14. Stack Init 90e5eca0 Current 90e5ccfc Base 90e5f000 Limit 90e5c000 Call 00000000  
  15. Priority 11 BasePriority 8 PriorityDecrement 2 IoPriority 2 PagePriority 5  
  16. ChildEBP RetAddr      Args to Child                
  17. 81a2a694 819c50ee     00000003 b05b8410 00000065 nt!RtlpBreakWithStatusInstruction (FPO: [1,0,0])  
  18. 81a2a6e8 819c4b3b     8b51f340 81a2ab04 00000000 nt!KiBugCheckDebugBreak+0x1f (FPO: [Non-Fpo])  
  19. 81a2aad8 81943eda     0000007f 00000008 80f4f000 nt!KeBugCheck2+0x73a (FPO: [6,247,4])  
  20. 81a2aafc 819546c8     0000007f 00000008 80f4f000 nt!KiBugCheck2+0xc6  
  21.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  22. 81a2aafc 818c4c59 (T) 0000007f 00000008 80f4f000 nt!KiTrap08+0x6e (FPO: TSS 28:0)  
  23.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  24. 90e5c008 818c4ba9 (T) ffffffff 00000000 87fc7e40 nt!MiDecreaseAvailablePages+0x9 (FPO: [Non-Fpo])  
  25. 90e5c030 818c4a1b     00000001 00000000 81a41200 nt!MiUnlinkNodeLargePageHelper+0xb9 (FPO: [Non-Fpo])  
  26. 90e5c060 8187d822     02000000 00000000 87fc7e40 nt!MiUnlinkNodeLargePage+0x11b (FPO: [Non-Fpo])  
  27. 90e5c0e4 8187d2a5     00000002 00000000 0000000f nt!MiGetFreeOrZeroPage+0x452 (FPO: [1,24,0])  
  28. 90e5c124 8187cfd0     00000002 00454580 90e5c244 nt!MiGetPage+0x55 (FPO: [Non-Fpo])  
  29. 90e5c1d4 8187b3b3     00000000 00000004 00000042 nt!MiGetPageChain+0x130 (FPO: [Non-Fpo])  
  30. 90e5c230 8187a1bf     8a8b0000 90e5c478 90e5c2f8 nt!MiResolvePrivateZeroFault+0x93 (FPO: [Non-Fpo])  
  31. 90e5c294 818bb043     00000000 81a40090 90e5c478 nt!MiResolveDemandZeroFault+0x15f (FPO: [Non-Fpo])  
  32. 90e5c2f8 8187794a     90e5c478 8a8b0000 90e5c360 nt!MiSystemFault+0x8d3 (FPO: [Non-Fpo])  
  33. 90e5c3d8 819558cc     00000000 8a8b0000 00000000 nt!MmAccessFault+0x78a (FPO: [4,47,4])  
  34.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  35. 90e5c3d8 8187663b (T) 00000000 8a8b0000 00000000 nt!KiTrap0E+0xec (FPO: [0,0] TrapFrame @ 90e5c478)  
  36.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  37. 90e5c524 818763ec (T) 92a22100 c0019a00 00002000 nt!MiQueryAddressState+0x1ab (FPO: [Non-Fpo])  
  38. 90e5c570 81ad8f03     03340000 a11ce4b8 90e5c67c nt!MiQueryAddressSpan+0x9c (FPO: [Non-Fpo])  
  39. 90e5c640 81ad8a96     00000000 90e5c790 0000001c nt!MmQueryVirtualMemory+0x463 (FPO: [Non-Fpo])  
  40. 90e5c65c 819522c7     80000c94 03140000 00000000 nt!NtQueryVirtualMemory+0x1e (FPO: [Non-Fpo])  
  41.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  42. 90e5c65c 81942665 (T) 80000c94 03140000 00000000 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ 90e5c67c)  
  43.     <Intermediate frames may have been skipped due to lack of complete unwind>  
  44. 90e5c6ec c5e34f6e (T) 80000c94 03140000 00000000 nt!ZwQueryVirtualMemory+0x11 (FPO: [6,0,0])  
  45. WARNING: Stack unwind information not available. Following frames may be wrong.  
  46. 90e5c7f8 c5e34a0a     91200308 80000c94 92a22100 TargetSys32+0x34f6e  
  47. 90e5c908 c5e34a0a     91200308 80000c94 9a54b008 TargetSys32+0x34a0a  
  48. 90e5ca18 c5e34a0a     91200308 80000c94 9a569b18 TargetSys32+0x34a0a  
  49. 90e5cb28 c5e34b9b     91200308 80000c94 92a295c0 TargetSys32+0x34a0a  
Limit90e5c000,先记下来,然后分析堆栈状态,第一次异常:
  1. kd> .trap 90e5c478  
  2. ErrCode = 00000000  
  3. eax=00000000 ebx=8a8b0000 ecx=bfffff00 edx=92a22100 esi=c0019a08 edi=00000000  
  4. eip=8187663b esp=90e5c4ec ebp=90e5c524 iopl=0         nv up ei pl zr na pe nc  
  5. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246  
  6. nt!MiQueryAddressState+0x1ab:  
  7. 8187663b 8b0b            mov     ecx,dword ptr [ebx]  ds:0023:8a8b0000=????????  
可见的确是在访问一块非法内存,通过后续的堆栈可以看到系统在进行一些列内存操作后调用到了MiDecreaseAvailablePages+0x9,看下此处的反汇编代码:
  1. kd> .frame /r 0  
  2. 00 90e5c008 818c4ba9     nt!MiDecreaseAvailablePages+0x9  
  3. eax=0005d6e0 ebx=81a41200 ecx=81a41200 edx=00000010 esi=88a8e1c0 edi=00000010  
  4. eip=818c4c59 esp=90e5c000 ebp=90e5c008 iopl=0         nv up ei pl nz na po cy  
  5. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010203  
  6. nt!MiDecreaseAvailablePages+0x9:  
  7. 818c4c59 57              push    edi  
  8. kd> .tss 28  
  9. eax=0005d6e0 ebx=81a41200 ecx=81a41200 edx=00000010 esi=88a8e1c0 edi=00000010  
  10. eip=818c4c59 esp=90e5c000 ebp=90e5c008 iopl=0         nv up ei pl nz na po cy  
  11. cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010203  
  12. nt!MiDecreaseAvailablePages+0x9:  
  13. 818c4c59 57              push    edi  
可见tss 28和栈顶是同一现场,注意此时esp的值为90e5c000,正好为Limit的下限,此时如果再次push的话,会导致esp-4,会超出上面的Limit范围因此引发第二次异常。

总结

本文分析了两例非常规dump,这两个dump的特殊之处在于其第一现场并不能直接反映出dump原因,真正原因需要进一步分析才能得到。在分析的过程中,我们需要综合运用操作系统的知识才能找到问题的根本。dump产生的原因很蠢,发出来博大家一笑~
目录
Page Fault
Double Fault
ZwQueryVirtualMemory引发的异常
DbgPrint引发的异常
DbgPrint引发的异常Dump分析
ZwQueryVirtualMemory引发的异常Dump分析
总结

版权所有 (c) 2020 - 2025 Debugwar.com

由 Hacksign 设计