Crash Dump Analysis Patterns (Part 234)
Monday, November 30th, 2015Sometimes we identify a function parameter that caused abnormal behavior, for example, Invalid Pointer access violation and want to see from which module or function it was probably originated:
0:009> kvL
# ChildEBP RetAddr Args to Child
00 0381f048 74e715e9 00000002 0381f098 00000001 ntdll!NtWaitForMultipleObjects+0x15
01 0381f0e4 76ce19fc 0381f098 0381f10c 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
02 0381f12c 76ce41d8 00000002 7efde000 00000000 kernel32!WaitForMultipleObjectsExImplementation+0xe0
03 0381f148 76d08074 00000002 0381f17c 00000000 kernel32!WaitForMultipleObjects+0x18
04 0381f1b4 76d07f33 0381f294 00000001 00000001 kernel32!WerpReportFaultInternal+0x186
05 0381f1c8 76d07828 0381f294 00000001 0381f264 kernel32!WerpReportFault+0x70
06 0381f1d8 76d077a7 0381f294 00000001 9a131a15 kernel32!BasepReportFault+0x20
07 0381f264 772574ff 00000000 772573dc 00000000 kernel32!UnhandledExceptionFilter+0x1af
08 0381f26c 772573dc 00000000 0381ffd4 7720c550 ntdll!__RtlUserThreadStart+0x62
09 0381f280 77257281 00000000 00000000 00000000 ntdll!_EH4_CallFilterFunc+0x12
0a 0381f2a8 7723b499 fffffffe 0381ffc4 0381f3e4 ntdll!_except_handler4+0x8e
0b 0381f2cc 7723b46b 0381f394 0381ffc4 0381f3e4 ntdll!ExecuteHandler2+0x26
0c 0381f2f0 7723b40e 0381f394 0381ffc4 0381f3e4 ntdll!ExecuteHandler+0x24
0d 0381f37c 771f0133 0181f394 0381f3e4 0381f394 ntdll!RtlDispatchException+0x127
0e 0381f37c 00010101 0181f394 0381f3e4 0381f394 ntdll!KiUserExceptionDispatcher+0xf (CONTEXT @ 0381f3e4)
WARNING: Frame IP not in any known module. Following frames may be wrong.
0f 0381f844 00df3d1e 064bf018 0b925970 06501dd8 0×10101
10 0381f860 00ca0a15 064bf018 0b925970 0c86a949 ModuleA!Bar+0×3e
11 0381f888 00ca07d4 064bf018 0b925970 09584580 ModuleB!Foo2+0×75
12 0381f8e4 00ca0ae3 0b925970 00000000 09584008 ModuleB!Foo1+0xb4
[…]
Here we backtrack the invalid function call pointer to a function argument parameter:
0:009> .cxr 0381f3e4
eax=06501dd8 ebx=0381f8c4 ecx=0b925970 edx=0b925527 esi=064bf018 edi=0381f898
eip=00010101 esp=0381f848 ebp=0c86a949 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
00010101 1f pop ds
0:009> k 1
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0381f844 00df3d1e 0×10101
0:009> ub 00df3d1e
ModuleA!Bar+0x2e:
00df3d0a mov ecx,dword ptr [esp+10h]
00df3d0e mov edi,dword ptr [esp+18h]
00df3d12 push edi
00df3d13 push eax
00df3d14 mov edx,dword ptr [ecx]
00df3d16 push ecx
00df3d17 push esi
00df3d18 mov edx,dword ptr [edx+4]
00df3d1b call dword ptr [edx+10h]
The value of EDX comes from EDX+4 which comes from ECX pointer value which was probably one of function parameters:
0:009> dp ecx L1
0b925970 0b925978
0:009> dp poi(ecx)+4 L1
0b92597c 0b925527
0:009> dc 0b925527
0b925527 20202020 80202020 01010101 01010101 ………
0b925537 00010101 01010101 01010000 01000101 …………….
[…]
Since the data came from ModuleA function parameter it was passed from the previous call:
0:009> kL 4
# ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0381f844 00df3d1e 0x10101
01 0381f860 00ca0a15 ModuleA!Bar+0×3e
02 0381f888 00ca07d4 ModuleB!Foo2+0×75
03 0381f8e4 00ca0ae3 ModuleB!Foo1+0xb4
0:009> ub 00ca0a15
ModuleB!Foo2+0×61:
00ca0a01 add esp,10h
00ca0a04 and edi,0FFFFFFF8h
00ca0a07 lea edx,[esp+20h]
00ca0a0b push edx
00ca0a0c push ebp
00ca0a0d push edi
00ca0a0e push esi
00ca0a0f call dword ptr [ModuleA!_imp__Bar (00cc32c0)]
The passed parameter looks like the second argument of Bar and ModuleB!Foo2, and the first argument of ModuleB!Foo1:
0:009> dps 0381f860
0381f860 064bf018
0381f864 00ca0a15 ModuleB!Foo2+0x75 ; return address when calling ModuleA!Bar
0381f868 064bf018
0381f86c 0b925970
0381f870 0c86a949
0381f874 0381f898
0381f878 0b925970
0381f87c 09584580
0381f880 064bf018
0381f884 0381f8c4
0381f888 0b925970
0381f88c 00ca07d4 ModuleB!Foo1+0xb4 ; return address when calling ModuleB!Foo2
0381f890 064bf018
0381f894 0b925970
0381f898 09584580
0381f89c 064bf018
0381f8a0 00ccd7d0
0381f8a4 0381f954
0381f8a8 00000000
0381f8ac 00000001
0381f8b0 00000000
0381f8b4 0b926d18
0381f8b8 00000000
0381f8bc 00000005
0381f8c0 00000000
0381f8c4 0b925970
0381f8c8 00000000
0381f8cc 00000000
0381f8d0 00000000
0381f8d4 00000000
0381f8d8 00000000
0381f8dc 00000000
0381f8e0 00000000
0381f8e4 00000000
0381f8e8 00ca0ae3 ModuleB!iFoo0+0×13 ; return address when calling ModuleB!Foo1
0381f8ec 0b925970
0381f8f0 00000000
We see Parameter Flow analysis pattern:
0:009> kvL 4
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0381f844 00df3d1e 064bf018 0b925970 06501dd8 0×10101
01 0381f860 00ca0a15 064bf018 0b925970 0c86a949 ModuleA!Bar+0×3e
02 0381f888 00ca07d4 064bf018 0b925970 09584580 ModuleB!Foo2+0×75
03 0381f8e4 00ca0ae3 0b925970 00000000 09584008 ModuleB!Foo1+0xb4
The example is from x86 Windows where parameters are passed through stack, and, therefore, are seen in the verbose stack trace output (kv). For x64 Windows systems such parameters may be Hidden and what we see in verbose output can be False Function Parameters. However, we can still track in some cases certain values found in Execution Residue and associate them with particular stack trace frames (including Past Stack Traces).
Parameter Flow memory analysis pattern is similar to trace analysis Data Flow pattern.
- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -