Crash Dump Analysis Patterns (Part 49)
Frame Pointer Omission pattern is the most visible compiler optimization technique and you can notice it in verbose stack traces:
0:000> kv
ChildEBP RetAddr
0012ee10 004737a7 application!MemCopy+0x17 (FPO: [3,0,2])
0012ef0c 35878c5b application!ProcessData+0×97 (FPO: [Uses EBP] [3,59,4])
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012ef1c 72a0015b 0×35878c5b
0012ef20 a625e1b0 0×72a0015b
0012ef24 d938bcfe 0xa625e1b0
0012ef28 d4f91bb4 0xd938bcfe
0012ef2c c1c035ce 0xd4f91bb4
…
…
…
To recall FPO is a compiler optimization where ESP register is used to address local variables and parameters instead of EBP. EBP may or may not be used for other purposes. When it is used you will notice
FPO: [Uses EBP]
as in the trace above. For description of other FPO number triplets please see Debugging Tools for Windows help section “k, kb, kd, kp, kP, kv (Display Stack Backtrace)”
Running analysis command points to possible stack corruption:
PRIMARY_PROBLEM_CLASS: STACK_CORRUPTION
BUGCHECK_STR: APPLICATION_FAULT_STACK_CORRUPTION
FAULTING_IP:
application!MemCopy+17
00438637 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
Looking at EBP and ESP shows that they are mismatched:
0:000> r
eax=00000100 ebx=00a027f3 ecx=00000040 edx=0012ee58 esi=d938bcfe edi=0012ee58
eip=00438637 esp=0012ee0c ebp=00a02910 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
application!MemCopy+0×17:
00438637 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:0012ee58=00000010 ds:0023:d938bcfe=????????
We might think about Local Buffer Overflow pattern here but two top stack trace lines are in accordance with each other:
0:000> ub 004737a7
application!ProcessData+0x80:
00473790 cmp eax,edi
00473792 jb application!ProcessData+0x72 (00473782)
00473794 mov ecx,dword ptr [esp+104h]
0047379b push esi
0047379c lea edx,[esp+38h]
004737a0 push ecx
004737a1 push edx
004737a2 call application!MemCopy (00438620)
So perhaps EBP value differs greatly from ESP due to its usage as general purpose register and in fact there was no any stack corruption. Despite using public symbols we have the instance of Incorrect Stack Trace pattern and we might want to reconstruct it manually. Let’s search for EBP value on raw stack below the crash point:
0:000> !teb
TEB at 7ffdf000
ExceptionList: 0012ffb0
StackBase: 00130000
StackLimit: 00126000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7ffdf000
EnvironmentPointer: 00000000
ClientId: 0000660c . 00005890
RpcHandle: 00000000
Tls Storage: 00000000
PEB Address: 7ffd9000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
0:000> dds 00126000 00130000
00126000 00000000
00126004 00000000
00126008 00000000
...
...
...
0012eb0c 00a02910
0012eb10 7c90e25e ntdll!NtRaiseException+0xc
0012eb14 7c90eb15 ntdll!KiUserExceptionDispatcher+0x29
0012eb18 0012eb24
0012eb1c 0012eb40
0012eb20 00000000
0012eb24 c0000005
0012eb28 00000000
0012eb2c 00000000
0012eb30 00438637 application!MemCopy+0x17
0012eb34 00000002
0012eb38 00000000
0012eb3c d938bcfe
...
...
...
0012ebf4 00a02910
0012ebf8 00438637 application!MemCopy+0×17
0012ebfc 0000001b
…
…
…
0012f134 00436323 application!ConstructInfo+0×113
0012f138 00a02910
0012f13c 0000011c
…
…
…
Let’s see what functions ConstructInfo calls:
0:000> ub 00436323
application!ConstructInfo+0x103
00436313 lea edx,[esp+10h]
00436317 push edx
00436318 push eax
00436319 push 30h
0043631b push ecx
0043631c push ebx
0043631d push ebp
0043631e call application!EnvelopeData (00438bf0)
We notice EBP was pushed prior to calling EnvelopeData. If we disassemble this function we would see that it calls ProcessData from our partial stack trace:
0:000> uf 00438bf0
application!EnvelopeData:
00438bf0 sub esp,1F4h
00438bf6 push ebx
00438bf7 mov ebx,dword ptr [esp+20Ch]
00438bfe test ebx,ebx
00438c00 push ebp
...
...
...
00438c76 rep stos byte ptr es:[edi]
00438c78 lea eax,[esp+14h]
00438c7c push eax
00438c7d push ebp
00438c7e call application!ProcessData (00473710)
00438c83 pop edi
00438c84 pop esi
Let’s try elaborate form of k command and supply it with custom ESP and EBP values pointing to
0012f134 00436323 application!ConstructInfo+0×113
and also EIP of the fault:
0:000> k L=0012f134 0012f134 00438637
ChildEBP RetAddr
0012f1cc 00435a65 application!MemCopy+0×17
0012f28c 0043532e application!ClientHandleServerRequest+0×395
0012f344 00434fcd application!Accept+0×23
0012f374 0042e4f3 application!DataArrival+0×17d
0012f43c 0041aea9 application!ProcessInput+0×98
0012ff0c 0045b278 application!AppMain+0xda
0012ff24 0041900e application!WinMain+0×78
0012ffc0 7c816fd7 application!WinMainCRTStartup+0×134
0012fff0 00000000 kernel32!BaseProcessStart+0×23
We see that although it misses some initial frames after MemCopy we aided WinDbg to walk to the bottom of the stack and reconstruct the plausible stack trace for us.
- Dmitry Vostokov @ DumpAnalysis.org -
October 18th, 2010 at 10:01 am
[…] Debugging Experts Magazine Online Today we introduce an icon for Frame Pointer Omission pattern: […]