Archive for October 5th, 2021

Crash Dump Analysis Patterns (Part 36b)

Tuesday, October 5th, 2021

When we added Local Buffer Overflow in 2007, we only added a short WinDbg output snippet of a user space example and didn’t elaborate much on stack reconstruction (although we wrote a separate modeling example, albeit 32-bit). Instead, we referenced a book on that topic that was available at that time. When working on the new exercise for the 5th edition of Accelerated Windows Memory Dump Analysis we realized the missing kernel space example. Many other patterns have both space analysis variants separately.

In addition to Incorrect Stack Traces we may also have Truncated Stack Traces:

1: kd> kc
# Call Site
00 nt!KeBugCheckEx
01 nt!KiDispatchException
02 nt!KiExceptionDispatch
03 nt!KiPageFault

For our try to reconstruct stack trace we need the boundaries of the stack region: its base (upper address, the stack grows towards lower addresses) and the stack pointer address for the current fault. We get both from the output of !thread and .trap WinDbg commands:

1: kd> !thread
THREAD ffff9a8e065f7080 Cid 1e7c.1e80 Teb: 000000ce1b0a7000 Win32Thread: ffff9a8e064c9a60 RUNNING on processor 1
[...]
Base ffffce833784d000 Limit ffffce8337847000 Call 0000000000000000
[…]
ffffce83`3784c950 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 fffff801`7e7f5e51 : nt!KiPageFault+0×443 (TrapFrame @ ffffce83`3784c950)

1: kd> .trap ffffce83`3784c950
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000000 rbx=0000000000000000 rcx=fffff8017f831b7f
rdx=fffff8017f830000 rsi=0000000000000000 rdi=0000000000000000
rip=0000000000000000 rsp=ffffce833784cae0 rbp=0000000000000002
r8=0000000000000000 r9=0000000000000000 r10=ffff9a8e060b62c0
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei ng nz na pe nc
00000000`00000000 ?? ???

We see that we have NULL Pointer (Code) here. We now try stack addresses from the top of Execution Residue unless we get a good stack trace:

1: kd> dps ffffce833784cae0 ffffce833784d000
ffffce83`3784cae0 00000000`00000000
ffffce83`3784cae8 00000000`00000000
ffffce83`3784caf0 00000000`00000000
ffffce83`3784caf8 fffff801`7e7f5e51 nt!ObpReferenceObjectByHandleWithTag+0×231
ffffce83`3784cb00 00000000`00000000
ffffce83`3784cb08 ffff868e`00000000
ffffce83`3784cb10 ffff86a6`83360010
ffffce83`3784cb18 ffff9a8e`05e8f990
ffffce83`3784cb20 ffff9a8e`060b62c0
ffffce83`3784cb28 00000000`00000000
ffffce83`3784cb30 ffff9a8e`06794a70
ffffce83`3784cb38 fffff801`7e48f865 nt!IofCallDriver+0×55
ffffce83`3784cb40 ffff9a8e`05e8f960
ffffce83`3784cb48 00000000`00000001
ffffce83`3784cb50 ffffce83`3784cec0
ffffce83`3784cb58 00000000`00000001
ffffce83`3784cb60 ffff9a8e`060b62c0
ffffce83`3784cb68 ffff9a8e`05e8fa78
ffffce83`3784cb70 ffff9a8e`06794a70
ffffce83`3784cb78 fffff801`7e875328 nt!IopSynchronousServiceTail+0×1a8
ffffce83`3784cb80 ffffce83`3784cec0
ffffce83`3784cb88 ffff9a8e`05e8f960
ffffce83`3784cb90 00000000`00000001
[…]

1: kd> k L=ffffce83`3784caf8
# Child-SP RetAddr Call Site
00 ffffce83`3784caf8 fffff801`7e7f5e51 0×0
01 ffffce83`3784cb00 ffff9a8e`05e8f960 nt!ObpReferenceObjectByHandleWithTag+0×231
02 ffffce83`3784cb90 00000000`00000001 0xffff9a8e`05e8f960
03 ffffce83`3784cb98 fffff801`00000000 0×1
04 ffffce83`3784cba0 00000000`00000000 0xfffff801`00000000

1: kd> k L=ffffce83`3784cb38
# Child-SP RetAddr Call Site
00 ffffce83`3784cb38 fffff801`7e48f865 0×0
01 ffffce83`3784cb40 fffff801`7e875328 nt!IofCallDriver+0×55
02 ffffce83`3784cb80 fffff801`7e874bf5 nt!IopSynchronousServiceTail+0×1a8
03 ffffce83`3784cc20 fffff801`7e8745f6 nt!IopXxxControlFile+0×5e5
04 ffffce83`3784cd60 fffff801`7e608bb5 nt!NtDeviceIoControlFile+0×56
05 ffffce83`3784cdd0 00007ffb`8dc6ce54 nt!KiSystemServiceCopyEnd+0×25
06 000000ce`1b2fea68 00000000`00000000 0×00007ffb`8dc6ce54

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -