This page looks best with JavaScript enabled

Windows Dump Analysis

 ·  ☕ 5 min read · 👀... views

The analysis of crash is a very common and difficult problem while programming or testing. I have recorded some of useful tricks to analyze Windows dump. In this blog, I will use a demo crash dump of a Windows kernel shellcode to share some analysis tricks.

windows_kernel_shellcode_dump.dmp

Basic

When we open a dump using windbg, the software will print some basic info about crash automatically. This includes some crucial information. Such as ntoskrnl base address, system startup time and the time from system startup to crash.

Kernel base = 0xfffff801`38e00000 PsLoadedModuleList = 0xfffff801`39a2a2d0

Debug session time: Mon Mar 25 17:12:56.339 2024 (UTC + 8:00)
System Uptime: 0 days 0:20:05.299

This message will be printed when windbg successfully opens the dump file. We can use the command !analyze -v to automatically receive crash information analyzed by windbg.

.................
For analysis of this file, run !analyze -v
nt!KeBugCheckEx:
fffff801`391f7620 48894c2408      mov     qword ptr [rsp+8],rcx ss:0018:ffffc10c`e8e4f2a0=000000000000007f

There are lots of information about this crash, and I will introduce some of other tricks to get more and more accurate information.

stack

We can get stack trace by !analyze -v or kb, and .reload -i to load symbols. However, in some cases, we may need to retrieve the full stack. We can achieve this by using dps to print the memory pointed by @rsp, allowing us to view memory in units of 8 bytes. Additionally, we can include the argument l100 to indicate printing 100 layers.

dqs rsp l100

register

It is important to obtain register values when an exception has been raised. However, the Registers view window of windbg records register information at last time, rather than the time when the exception occurred. We need to retrieve the exception context to help us clarify the reason behind the exception.

5: kd> !thread
Win32 Start Address nt!PopIrpWorkerControl (0xfffff801391c8ba0)
Stack Init ffffc10ce8e4fb90 Current ffffc10ce8e4f3d0
Base ffffc10ce8e50000 Limit ffffc10ce8e49000 Call 0000000000000000
Priority 8  BasePriority 8  IoPriority 2  PagePriority 5
Child-SP          RetAddr               : Args to Child                                                           : Call Site
ffffc10c`e8e4f298 fffff801`39209569     : 00000000`0000007f 00000000`00000010 00000000`80050033 00000000`00370678 : nt!KeBugCheckEx
ffffc10c`e8e4f2a0 fffff801`39205dcc     : 00000000`00000000 00000000`67727453 00000000`00000020 00000000`00000b32 : nt!KiBugCheckDispatch+0x69
ffffc10c`e8e4f3e0 ffffb104`5f033b59     : ffffc10c`e8e4f620 fffff801`00000008 b10459ce`b040fb01 ffffe60c`00000008 : nt!KiFloatingErrorFault+0x38c (TrapFrame @ ffffc10c`e8e4f3e0)
ffffc10c`e8e4f570 ffffc10c`e8e4f620     : fffff801`00000008 b10459ce`b040fb01 ffffe60c`00000008 ffffffff`00000000 : 0xffffb104`5f033b59
ffffc10c`e8e4f578 fffff801`00000008     : b10459ce`b040fb01 ffffe60c`00000008 ffffffff`00000000 ffff0001`bb1827ff : 0xffffc10c`e8e4f620
ffffc10c`e8e4f580 b10459ce`b040fb01     : ffffe60c`00000008 ffffffff`00000000 ffff0001`bb1827ff ffffb104`6e8ab1c0 : 0xfffff801`00000008

We can see "(TrapFrame @ ffffc10c`e8e4f3e0)" at stack trace. This is Windows exception trap frame structure pointer recording exception context.

5: kd> dt _KTRAP_FRAME ffffc10c`e8e4f3e0
nt!_KTRAP_FRAME
   +0x000 P1Home           : 0
   +0x008 P2Home           : 0x67727453
   +0x010 P3Home           : 0x20
   +0x018 P4Home           : 0xb32
   +0x020 P5               : 3
   +0x028 PreviousMode     : 64 '@'
   +0x028 InterruptRetpolineState : 0x40 '@'
   +0x029 PreviousIrql     : 0xb1 ''
   +0x02a FaultIndicator   : 0xcf ''
   +0x02a NmiMsrIbrs       : 0xcf ''
   +0x02b ExceptionActive  : 0x1 ''
   +0x02c MxCsr            : 0x1f80
   +0x030 Rax              : 0x118
   +0x038 Rcx              : 0x118
   +0x040 Rdx              : 0
   +0x048 R8               : 0xffffe60c`13cfb072
   +0x050 R9               : 2
   +0x058 R10              : 0
   +0x060 R11              : 6
   +0x068 GsBase           : 0
   +0x068 GsSwap           : 0
   +0x070 Xmm0             : _M128A
   +0x080 Xmm1             : _M128A
   +0x090 Xmm2             : _M128A
   +0x0a0 Xmm3             : _M128A
   +0x0b0 Xmm4             : _M128A
   +0x0c0 Xmm5             : _M128A
   +0x0d0 FaultAddress     : 0x103
   +0x0d0 ContextRecord    : 0x103
   +0x0d8 Dr0              : 0
   +0x0e0 Dr1              : 0
   +0x0e8 Dr2              : 0
   +0x0f0 Dr3              : 0
   +0x0f8 Dr6              : 0
   +0x100 Dr7              : 0xacacacac`acacacac
   +0x108 DebugControl     : 0xffffc480`d0d9f000
   +0x110 LastBranchToRip  : 0
   +0x118 LastBranchFromRip : 0xffffc10c`e8e4f620
   +0x120 LastExceptionToRip : 0xffffc10c`e8e4f620
   +0x128 LastExceptionFromRip : 0xfffff801`397b2149
   +0x130 SegDs            : 0
   +0x132 SegEs            : 0
   +0x134 SegFs            : 0xc10c
   +0x136 SegGs            : 0xffff
   +0x138 KTrapFrame        : 9
   +0x140 Rbx              : 0x10
   +0x148 Rdi              : 0x01000000`00100000
   +0x150 Rsi              : 0
   +0x158 Rbp              : 0xffffc10c`e8e4f5f0
   +0x160 ErrorCode        : 0xffffc10c`e8e4f620
   +0x160 ExceptionFrame   : 0xffffc10c`e8e4f620
   +0x168 Rip              : 0xffffb104`5f033b59
   +0x170 SegCs            : 0x10
   +0x172 Fill0            : 0 ''
   +0x173 Logging          : 0 ''
   +0x174 Fill1            : [2] 0
   +0x178 EFlags           : 0x50246
   +0x17c Fill2            : 0
   +0x180 Rsp              : 0xffffc10c`e8e4f570
   +0x188 SegSs            : 0x18
   +0x18a Fill3            : 0
   +0x18c Fill4            : 0

Okey, we can use this method to obtain the complete exception context information. However, there are situations where WinDBG cannot analyze the KTrapFrame pointer in the stack, especially when the exception occurs in shellcode. Looking back at the structure and stack trace above, we can know that the exception occurred at 0xffffb104`5f033b59, and nt!KiFloatingErrorFault caught this exception, which is a Windows exception handler. The _KTRAP_FRAME includes certain fields that can help us identify the KTrapFrame pointer.

+0x170 SegCs            : 0x10
+0x188 SegSs            : 0x18

By disassembling the exception handler function, we can observe that this function has allocated 0x158 bytes of stack space. Additionally, by using the command !thread, we can determine that the value of Child-SP is 0xffffc10c`e8e4f3e0.

5: kd> u KiFloatingErrorFault
nt!KiFloatingErrorFault:
fffff801`39205a40 4883ec08        sub     rsp,8
fffff801`39205a44 55              push    rbp
fffff801`39205a45 4881ec58010000  sub     rsp,158h
fffff801`39205a4c 488dac2480000000 lea     rbp,[rsp+80h]
fffff801`39205a54 c645ab01        mov     byte ptr [rbp-55h],1
fffff801`39205a58 488945b0        mov     qword ptr [rbp-50h],rax
fffff801`39205a5c 48894db8        mov     qword ptr [rbp-48h],rcx
fffff801`39205a60 488955c0        mov     qword ptr [rbp-40h],rdx

By printing the stack space we can identify the _KTRAP_FRAME.SegCs at 0xffffc10c`e8e4f550, allowing us to determine that the pointer of KTrapFrame is 0xffffc10ce8e4f550-0x170=0xffffc10ce8e4f3e0

5: kd> dq ffffc10c`e8e4f3e0+0x158
ffffc10c`e8e4f538  ffffc10c`e8e4f5f0 ffffc10c`e8e4f620
ffffc10c`e8e4f548  ffffb104`5f033b59 00000000`00000010
ffffc10c`e8e4f558  00000000`00050246 ffffc10c`e8e4f570
ffffc10c`e8e4f568  00000000`00000018 ffffc10c`e8e4f620
ffffc10c`e8e4f578  fffff801`00000008 b10459ce`b040fb01
ffffc10c`e8e4f588  ffffe60c`00000008 ffffffff`00000000
ffffc10c`e8e4f598  ffff0001`bb1827ff ffffb104`6e8ab1c0
ffffc10c`e8e4f5a8  ffffb104`6e8ab1c0 79727473`69676552
Share on

Qfrost
WRITTEN BY
Qfrost
CTFer, Anti-Cheater, LLVM Committer