如何在X64上查找用户模式异常的上下文记录

Kje*_*nar 5 64-bit windbg

我有一个来自Win 8.1/64的用户模式转储,转储是在Wer对话时附加Windbg.然后.ecxr显示了Windbg注入线程的ntdll!DbgBreakPoint.(像平常一样)

我已经通过检查所有堆栈来识别线程,并找到具有以下内容的线程:

# Call Site
00 ntdll!NtWaitForMultipleObjects
01 KERNELBASE!WaitForMultipleObjectsEx
02 kernel32!WerpReportFaultInternal
03 kernel32!WerpReportFault
04 KERNELBASE!UnhandledExceptionFilter
05 ntdll!RtlUserThreadStart$filt$0
06 ntdll!_C_specific_handler
07 ntdll!RtlpExecuteHandlerForException
08 ntdll!RtlDispatchException
09 ntdll!KiUserExceptionDispatch
10 <My faulty code which generated the exception>
Run Code Online (Sandbox Code Playgroud)

kvn aslo发布一个TrapFrame @ 00000000`0379ed28)

09 00000000`0379e900 00000000`00250bc8 : 00000000`00000000 00000000`0026ca09 00000000`0379f160 00000000`0379f168 : ntdll!KiUserExceptionDispatch+0x2e (TrapFrame @ 00000000`0379ed28)
Run Code Online (Sandbox Code Playgroud)

有没有办法使用陷阱框架来获取上下文记录以输入.cxr?或者是找到异常上下文的其他可能性?

Sea*_*ine 10

KERNELBASE!UnhandledExceptionFilter在堆栈上看到了一个.这似乎是一件值得关注的好事.

如果这是x86,您可以轻松地EXCEPTION_POINTERS从第一个参数中获取结构KERNELBASE!UnhandledExceptionFilter.从那里,你可以访问EXCEPTION_RECORDCONTEXT.该知识库文章中描述了该过程.

相同的方法适用于x64进程,但有一点需要注意.由于x64调用约定的性质,检索实际参数更难,KERNELBASE!UnhandledExceptionFilter因为它存储在寄存器而不是堆栈中.

我最近发现了一个调用器调用扩展CMKD,它可以自动执行在x64调用约定中搜索前4个args的任务,而不是盲目地显示像kb和的堆栈值kv.这可以手工完成,但这是一个相当冗长且容易出错的过程 - 最好让扩展首先对其进行破解.

有了它,你可以这样做:

0:000> !cmkd.stack -p
Call Stack : 15 frames
## Stack-Pointer    Return-Address   Call-Site       
[...]
03 000000aea3dae7e0 00007fff1e906b14 KERNELBASE!UnhandledExceptionFilter+196 
    Parameter[0] = 000000aea3dae930
    Parameter[1] = (unknown)       
    Parameter[2] = (unknown)       
    Parameter[3] = (unknown)       
[...]
Run Code Online (Sandbox Code Playgroud)

而且,现在我们有一个EXCEPTION_POINTERS*Parameter[0].

0:000> dt 000000ae`a3dae930 EXCEPTION_POINTERS
ConsoleApplication2!EXCEPTION_POINTERS
   +0x000 ExceptionRecord  : 0x000000ae`a3daf850 _EXCEPTION_RECORD
   +0x008 ContextRecord    : 0x000000ae`a3daf240 _CONTEXT
Run Code Online (Sandbox Code Playgroud)

在我的例子中我们可以看到抛出了一个C++异常......

0:000> .exr 000000ae`a3daf850
ExceptionAddress: 00007fff1bfeab78 (KERNELBASE!RaiseException+0x0000000000000068)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 4
   Parameter[0]: 0000000019930520
   Parameter[1]: 000000aea3daf9b0
   Parameter[2]: 00007ff6f50024a8
   Parameter[3]: 00007ff6f5000000
  pExceptionObject: 000000aea3daf9b0
  _s_ThrowInfo    : 00007ff6f50024a8
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助.祝好运.:)


Vas*_*kin 5

x64情况下的另一种方法不需要扩展,但是依赖于两个不稳定的事实:

  • windbg重建特定帧寄存器的能力
  • WerpReportFault在将EXCEPTION_POINTERS地址传递给WerpReportFaultInternal之前将其存储在rdi中的事实(至少对于kernel32.dll 6.1.7601.23915(win7sp1_ldr.170913-0600)就是这种情况

可以将异常指针提取为WerpReportFault帧的rdi值:

0:007> k
 # Child-SP          RetAddr           Call Site
00 00000000`0868dcd8 000007fe`fcf61430 ntdll!NtWaitForMultipleObjects+0xa
01 00000000`0868dce0 00000000`76fb16e3 KERNELBASE!WaitForMultipleObjectsEx+0xe8
02 00000000`0868dde0 00000000`7702b8b5 kernel32!WaitForMultipleObjectsExImplementation+0xb3
03 00000000`0868de70 00000000`7702ba37 kernel32!WerpReportFaultInternal+0x215
Run Code Online (Sandbox Code Playgroud)
04 00000000`0868df10 00000000`7702ba8f kernel32!WerpReportFault + 0x77
05 00000000`0868df40 00000000`7702bcac kernel32!BasepReportFault+0x1f
06 00000000`0868df70 00000000`77230108 kernel32!UnhandledExceptionFilter+0x1fc
07 00000000`0868e050 00000000`771c7958 ntdll! ?? ::FNODOBFM::`string'+0x2025
08 00000000`0868e080 00000000`771d812d ntdll!_C_specific_handler+0x8c
09 00000000`0868e0f0 00000000`771c855f ntdll!RtlpExecuteHandlerForException+0xd
0a 00000000`0868e120 00000000`771fbcb8 ntdll!RtlDispatchException+0x45a
0b 00000000`0868e800 000007fe`fe03df54 ntdll!KiUserExceptionDispatch+0x2e
0c 00000000`0868ef00 000007fe`fe03e1b6 gdi32!pmfAllocMF+0x2b0
0d 00000000`0868ef70 000007fe`fb10a646 gdi32!GetEnhMetaFileW+0x32
0e 00000000`0868efb0 000007fe`fb0c4959 GdiPlus!GpMetafile::GpMetafile+0x1c6
0f 00000000`0868f150 00000001`40001c35 GdiPlus!GdipCreateBitmapFromFile+0xc5

0:007> .frame /r 04
    04 00000000`0868df10 00000000`7702ba8f kernel32!WerpReportFault+0x77
    rax=00000000c0000001 rbx=0000000000000000 rcx=0000000002660000
Run Code Online (Sandbox Code Playgroud)
    rdx = 0000000000000001 rsi = 0000000000000001 rdi = 000000000868e0b0
    rip=000000007702ba37 rsp=000000000868df10 rbp=000000000868ff90
     r8=000000000868d3f8  r9=000000000868d560 r10=0000000000000000
    r11=0000000000000246 r12=000000000868e0b0 r13=0000000000000000
    r14=0000000000000002 r15=0000000000000000
    iopl=0         nv up ei pl zr na po nc
    cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000244
    kernel32!WerpReportFault+0x77:
    00000000`7702ba37 8b0d27ff0600    mov     ecx,dword ptr [kernel32!RestrictedUserHandle+0xc (00000000`7709b964)] ds:00000000`7709b964=00000000

0:007> .exptr 000000000868e0b0

----- Exception record at 00000000`0868ecf0:
ExceptionAddress: 000007fefe03df54 (gdi32!pmfAllocMF+0x00000000000002b0)
   ExceptionCode: c0000006 (In-page I/O error)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 0000000000000000
   Parameter[1]: 0000000002610028
   Parameter[2]: 00000000c00000be
Inpage operation failed at 0000000002610028, due to I/O error 00000000c00000be

----- Context record at 00000000`0868e800:
rax=0000000002610000 rbx=000000000e5fe7c0 rcx=0000000000006894
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=000007fefe03df54 rsp=000000000868ef00 rbp=0000000000000104
 r8=000000000868ee38  r9=0000000000000104 r10=0000000000000000
r11=0000000000000286 r12=0000000000000001 r13=000000006d9cf760
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
gdi32!pmfAllocMF+0x2b0:
000007fe`fe03df54 81782820454d46  cmp     dword ptr [rax+28h],464D4520h ds:00000000`02610028=????????
Run Code Online (Sandbox Code Playgroud)