WinDbg : Debugging A Stack Corruption Scenario
The call stack is one of the most important steps to trace a fault in a program. It tells us the sequence of function calls which led to the fault. However, there are times when the call stack itself is corrupted. This makes the debuggers job very difficult, in tracing the fault. Sometimes, it is still possible to reconstruct the stack and hence trace the flow of the program. In this post, we sill try one such instance of tracking the fault by reconstructing the stack.
Commands used:
- kb
- dds (this command is used in this article here). For more details of the d command, please read this.
- uF
At the point of the crash the debugger complains:
(99c.1d48): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=00000000 ecx=00000005 edx=0000002f esi=00000000 edi=00000000
eip=00000100 esp=00b8fd2c ebp=00b8fd4c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
00000100 ?? ???
This gives no hint of a corrupt stack, it rather says Access Violation. The values of the registers is where we get the first clue from. The instruction pointer EIP is set to 0x100. That doesn't seem quite right does it? lets try to see the call stack:
0:002> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00b8fd28 00000000 00000005 0000002f 00000030 0x100
This shows the stack is corrupt. Now we have no clue what sequence of instruction executions lead to this stage. To root cause this problem, we need to start with reconstructing the call stack. the question is, where do we start.
call stack is per thread. A good place to begin would be the thread block. lets see what the TEB for this particular thread can tell us. We will use the !teb debugger extension here.
0:002> !teb
TEB at 7efd7000
ExceptionList: 00b8fdf0
StackBase: 00b90000
StackLimit: 00b8e000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7efd7000
EnvironmentPointer: 00000000
ClientId: 0000099c . 00001d48
RpcHandle: 00000000
Tls Storage: 7efd702c
PEB Address: 7efde000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
The TEB tells us where the stack starts and how big it can grow. On x86 we know that the stack grows from high to low (downwards), thus we have to start at the StackLimit value and go till the StackBase. We will try to see if any of the values in these memory location make any sense to us. A word of caution here : the discarded stack frames are not cleaned up by any one, thus not all legitimate looking values are actually trustable. That is where this might get tricky.
We will use dds, so that the output is dword aligned as well as is any of the dwords map to a symbol which can be resolved then it will.
The output will be long and tedious to go through and requires patience.
0:002> dds b8e000 b90000
00b8e000 00000000
00b8e004 00000000
<Output snipped to save space>
00b8ef48 00000000
00b8ef4c 76ba0000 kernel32!_imp__DebugBreak <PERF> (kernel32+0x0)
00b8ef50 00000000
00b8ef54 00b8ef8c
00b8ef58 00000000
00b8ef5c 00000000
00b8ef60 00002045
00b8ef64 00000000
00b8ef68 00000000
00b8ef6c 00000000
00b8ef70 00000000
00b8ef74 0000000f
00b8ef78 00000000
00b8ef7c 00002045
00b8ef80 00b8ef94
00b8ef84 76bb3418 kernel32!GetConsoleLangId+0x15
00b8ef88 76bb33f4 kernel32!SetTEBLangID+0xf
00b8ef8c 00b8ef90
00b8ef90 00b8efac
00b8ef94 775aec62 ntdll!bsearch+0x70
00b8ef98 00b8efd4
00b8ef9c 00b8efb0
00b8efa0 775aeba1 ntdll!ARRAY_FITS+0x2d
00b8efa4 000007a0
00b8efa8 0000174c
00b8efac 00b8efbc
00b8efb0 00b8efec
00b8efb4 775ae971 ntdll!RtlpLocateActivationContextSection+0x1d9
00b8efb8 0000174c
00b8efbc 00001eec
00b8efc0 000007a0
00b8efc4 0006174c
00b8efc8 00b8f070
00b8efcc 00000000
00b8efd0 536cd652
00b8efd4 00b8f024
00b8efd8 775aedff ntdll!RtlpFindUnicodeStringInSection+0x71
00b8efdc 00b8f104
00b8efe0 74957b88*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\SysWOW64\SYSFER.DLL -
SYSFER!FirstHookFunc+0x21038
00b8efe4 00000001
00b8efe8 00b8f074
00b8efec 0006174c
00b8eff0 c0150008
00b8eff4 00000000
00b8eff8 000007a0
00b8effc 00000002
00b8f000 00b8f078
00b8f004 c0150008
00b8f008 00000000
00b8f00c 7efde000
00b8f010 7efd7000
00b8f014 00b8f034
00b8f018 775aef7b ntdll!RtlFindNextActivationContextSection+0x46
00b8f01c 00b8f058
00b8f020 00b8f07c
00b8f024 00b8f080
00b8f028 00b8f030
00b8f02c 0006174c
00b8f030 00000000
00b8f034 00b8f088
00b8f038 775aed75 ntdll!RtlFindActivationContextSectionString+0xe1
00b8f03c 00b8f058
00b8f040 00b8f07c
00b8f044 00b8f080
00b8f048 00b8f078
00b8f04c 00b8f178
00b8f050 00b8f1a4
00b8f054 00b8f194
00b8f058 00000018
00b8f05c 00000003
00b8f060 00000000
00b8f064 00000002
00b8f068 00000003
00b8f06c 00000002
00b8f070 00000001
00b8f074 536cd652
00b8f078 00000000
00b8f07c 0006174c
00b8f080 000007a0
00b8f084 00b8f094
00b8f088 00b8f144
00b8f08c 775af3df ntdll!AitFireParentUsageEvent+0x772
00b8f090 00000003
00b8f094 00000000
00b8f098 00000002
00b8f09c 00b8f104
00b8f0a0 00b8f0ac
00b8f0a4 775afaa4 ntdll!LdrpDefaultExtension
00b8f0a8 775af442 ntdll!AitFireParentUsageEvent+0x88d
00b8f0ac 00000040
00b8f0b0 00000000
<Output snipped to save space>
00b8f100 00000000
00b8f104 001a0018
00b8f108 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f10c 00000000
00b8f110 00b8f178
00b8f114 00b8f144
00b8f118 00000000
00b8f11c 00020000
00b8f120 00b8f13c
00b8f124 00b8f13c
00b8f128 00b8f13c
00b8f12c 00000002
00b8f130 00000002
00b8f134 00000000
00b8f138 00000005
00b8f13c 00000000
00b8f140 775afaa4 ntdll!LdrpDefaultExtension
00b8f144 775afaa4 ntdll!LdrpDefaultExtension
00b8f148 00b8f2a0
00b8f14c 775af201 ntdll!RtlDosApplyFileIsolationRedirection_Ustr+0x31e
00b8f150 00b8f17c
00b8f154 00b8f330
00b8f158 00b8f4f4
00b8f15c 775af26c ntdll!RtlDosApplyFileIsolationRedirection_Ustr+0x3bc
00b8f160 00000000
00b8f164 00000000
00b8f168 00800000
00b8f16c 00b8f1fc
00b8f170 00000000
00b8f174 775afaa4 ntdll!LdrpDefaultExtension
00b8f178 00000000
00b8f17c 00000000
00b8f180 00000000
00b8f184 00000000
00b8f188 00000000
00b8f18c 00000000
00b8f190 00000000
00b8f194 001a0018
00b8f198 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f19c 00b8f338
00b8f1a0 00000000
<Output snipped to save space>
00b8f1d4 00000000
00b8f1d8 00200000
00b8f1dc 00b8f27c
00b8f1e0 00b8f27c
00b8f1e4 00b8f27c
00b8f1e8 00000020
00b8f1ec 00000020
00b8f1f0 00000000
<Output snipped to save space>
00b8f24c 00000000
00b8f250 00b8f268
00b8f254 004835f0
00b8f258 0048362c
00b8f25c 776848a0 ntdll!LdrpHashTable+0x80
00b8f260 00b8f280
00b8f264 775afa39 ntdll!LdrpFindLoadedDllByName+0x68
00b8f268 74957b88 SYSFER!FirstHookFunc+0x21038
00b8f26c 0048361c
00b8f270 8bb2ba48
00b8f274 00b8f338
00b8f278 776801a0 ntdll!LdrpDefaultPath
00b8f27c 00000000
00b8f280 00b8f2ec
00b8f284 775afeae ntdll!LdrpFindLoadedDll+0xd0
00b8f288 00b8f338
00b8f28c 00000000
00b8f290 00b8f340
00b8f294 775afaa4 ntdll!LdrpDefaultExtension
00b8f298 0000002e
00b8f29c 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f2a0 00b8f2e0
00b8f2a4 775afb16 ntdll!LdrpApplyFileNameRedirection+0x128
00b8f2a8 00000001
00b8f2ac 00b8f4f4
00b8f2b0 775afaa4 ntdll!LdrpDefaultExtension
00b8f2b4 00b8f338
00b8f2b8 00b8f328
00b8f2bc 00b8f344
00b8f2c0 00000000
00b8f2c4 00000000
00b8f2c8 00000000
00b8f2cc 00b8f330
00b8f2d0 00b8f4f4
00b8f2d4 775afaa4 ntdll!LdrpDefaultExtension
00b8f2d8 00000018
00b8f2dc 00000018
00b8f2e0 00b8f468
00b8f2e4 0000002e
00b8f2e8 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f2ec 00b8f468
00b8f2f0 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f2f4 00b8f468
00b8f2f8 775b00b3 ntdll!LdrGetDllHandleEx+0x3cc
00b8f2fc 775ae1b2 ntdll!_SEH_epilog4_GS+0xa
00b8f300 775b0098 ntdll!LdrGetDllHandleEx+0x451
00b8f304 3150d44e
00b8f308 00000001
00b8f30c 775afd37 ntdll!LdrGetDllHandle
00b8f310 00000000
00b8f314 00000000
00b8f318 00000000
00b8f31c 00b8f4bc
00b8f320 00000000
00b8f324 00000000
00b8f328 00000000
00b8f32c 00000000
00b8f330 00000001
00b8f334 776801a0 ntdll!LdrpDefaultPath
00b8f338 001a0018
00b8f33c 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f340 004835f0
00b8f344 00b8f338
00b8f348 01000000
00b8f34c 00000000
<Output snipped to save space>
00b8f444 00000000
00b8f448 00000000
00b8f44c 3150d44e
00b8f450 00b8f304
00b8f454 00000000
00b8f458 00b8f4c8
00b8f45c 775f71f5 ntdll!_except_handler4
00b8f460 46b29a86
00b8f464 fffffffe
00b8f468 775b0098 ntdll!LdrGetDllHandleEx+0x451
00b8f46c 775afd4f ntdll!LdrGetDllHandle+0x18
00b8f470 00000001
00b8f474 00000001
00b8f478 00000000
00b8f47c 00b8f4f4
00b8f480 00b8f4bc
00b8f484 00b8f4d8
00b8f488 77141a43 KERNELBASE!GetModuleHandleForUnicodeString+0x22
00b8f48c 00000001
00b8f490 00000000
00b8f494 00b8f4f4
00b8f498 77141ace KERNELBASE!GetModuleHandleForUnicodeString+0xad
00b8f49c c6fafa63
00b8f4a0 00000000
00b8f4a4 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f4a8 00000002
00b8f4ac 00000000
00b8f4b0 00000000
00b8f4b4 00000000
00b8f4b8 00000000
00b8f4bc 76ba0000 kernel32!_imp__DebugBreak <PERF> (kernel32+0x0)
00b8f4c0 00b8f49c
00b8f4c4 00000000
00b8f4c8 00b8f940
00b8f4cc 77167000 KERNELBASE!_except_handler4
00b8f4d0 b15487b3
00b8f4d4 fffffffe
00b8f4d8 77141ace KERNELBASE!GetModuleHandleForUnicodeString+0xad
00b8f4dc 771673ae KERNELBASE!_SEH_epilog4_GS+0xa
00b8f4e0 77141d09 KERNELBASE!BasepGetModuleHandleExW+0x233
00b8f4e4 c6faf7eb
00b8f4e8 00000000
00b8f4ec 00440bb0
00b8f4f0 74910000 SYSFER
00b8f4f4 001a0018
00b8f4f8 74957b70 SYSFER!FirstHookFunc+0x21020
00b8f4fc 00b8f970
00b8f500 00000000
00b8f504 00000000
00b8f508 00000000
00b8f50c 02080000
00b8f510 00b8f72c
00b8f514 02080000
00b8f518 00b8f524
00b8f51c 00000000
00b8f520 76ba0000 kernel32!_imp__DebugBreak <PERF> (kernel32+0x0)
00b8f524 00000000
<Output snipped to save space>
00b8f5c4 00000000
00b8f5c8 c6fafadb
00b8f5cc 00b8fa20
00b8f5d0 76bb3342 kernel32!_BaseDllInitialize+0x92
00b8f5d4 00000002
00b8f5d8 00000000
00b8f5dc 00b8fab0
00b8f5e0 00b8fa34
00b8f5e4 76bb3357 kernel32!_BaseDllInitialize+0x2cf
00b8f5e8 00000000
00b8f5ec 00000000
00b8f5f0 00481780
00b8f5f4 00000000
00b8f5f8 76ba0000 kernel32!_imp__DebugBreak <PERF> (kernel32+0x0)
00b8f5fc 00000000
00b8f600 00000000
00b8f604 00000000
00b8f608 0048b340
00b8f60c 00000000
00b8f610 00000005
00b8f614 00b8f9d4
00b8f618 74938973 SYSFER!FirstHookFunc+0x1e23
00b8f61c 00000003
00b8f620 00000005
00b8f624 ec3e8105
00b8f628 00000000
00b8f62c 00000002
00b8f630 74938a4c SYSFER!FirstHookFunc+0x1efc
00b8f634 00000000
00b8f638 00000000
00b8f63c 0000007f
00b8f640 00b8f72c
00b8f644 775b3c5a ntdll!RtlpAllocateHeap+0xb5d
00b8f648 0048b340
00b8f64c 775b2caf ntdll!RtlpAllocateHeap+0xc78
00b8f650 0048b128
00b8f654 00000000
00b8f658 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8f65c 3150d70a
00b8f660 00000208
00b8f664 00000000
00b8f668 00480000
00b8f66c 00480150
00b8f670 00440150
00b8f674 00000000
00b8f678 00480150
00b8f67c 00000eb0
00b8f680 00480180
00b8f684 00440180
00b8f688 00000194
00b8f68c 00000004
00b8f690 00480150
00b8f694 0000007f
00b8f698 0048b128
00b8f69c 00590ad8
00b8f6a0 0000007f
00b8f6a4 0000007f
00b8f6a8 00000044
00b8f6ac 00000046
00b8f6b0 00000000
00b8f6b4 00000000
00b8f6b8 0048b338
00b8f6bc 00000000
00b8f6c0 06040002
00b8f6c4 00484338
00b8f6c8 00580048
00b8f6cc 00000000
00b8f6d0 00000000
00b8f6d4 00000208
00b8f6d8 0000007f
00b8f6dc 0000007f
00b8f6e0 dd0401d8
00b8f6e4 00000eb0
00b8f6e8 00000000
00b8f6ec 00000000
00b8f6f0 502c016b
00b8f6f4 00000018
00b8f6f8 0048b128
00b8f6fc 0048b128
00b8f700 0048b123
00b8f704 00000000
00b8f708 00000000
00b8f70c 00480000
00b8f710 03440000
00b8f714 00b8f65c
00b8f718 00b8f660
00b8f71c 00b8f7ec
00b8f720 775f71f5 ntdll!_except_handler4
00b8f724 46b2e8b6
00b8f728 fffffffe
00b8f72c 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8f730 775b3cfe ntdll!RtlAllocateHeap+0x23a
00b8f734 00000208
00b8f738 00000220
00b8f73c 0048b122
00b8f740 0048b120
00b8f744 00000208
00b8f748 00480000
00b8f74c 00000001
00b8f750 00000001
<Output snipped to save space>
00b8f780 00000000
00b8f784 00b8f7b4
00b8f788 77650806 ntdll!RtlpValidateHeap+0x20
00b8f78c 00480000
00b8f790 00000000
00b8f794 00000208
00b8f798 00480000
00b8f79c 00000001
00b8f7a0 00000004
00b8f7a4 00000000
00b8f7a8 0048b120
00b8f7ac 00000000
00b8f7b0 00480000
00b8f7b4 00b8f7fc
00b8f7b8 7765108a ntdll!RtlDebugAllocateHeap+0x31f
00b8f7bc 00480138
00b8f7c0 7765106e ntdll!RtlDebugAllocateHeap+0x308
00b8f7c4 3150d7da
00b8f7c8 00000000
00b8f7cc 00000000
00b8f7d0 00480000
00b8f7d4 00440000
00b8f7d8 00000000
00b8f7dc 0048b128
00b8f7e0 01440bb0
00b8f7e4 00b8f7c4
00b8f7e8 00b8f7c8
00b8f7ec 00b8f8d0
00b8f7f0 775f71f5 ntdll!_except_handler4
00b8f7f4 46b2f046
00b8f7f8 fffffffe
00b8f7fc 7765106e ntdll!RtlDebugAllocateHeap+0x308
00b8f800 7760af0d ntdll!RtlpAllocateHeap+0xc4
00b8f804 00480000
00b8f808 502c016b
00b8f80c 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8f810 3150d8c6
00b8f814 7efd7000
00b8f818 00000000
00b8f81c 00480000
00b8f820 00440000
00b8f824 00000000
<Output snipped to save space>
00b8f8a0 00000000
00b8f8a4 402c006a
00b8f8a8 4000006a
00b8f8ac 00000000
00b8f8b0 00000000
00b8f8b4 00000000
00b8f8b8 00000000
00b8f8bc 00000000
00b8f8c0 00480000
00b8f8c4 00440000
00b8f8c8 00b8f810
00b8f8cc 00b8f814
00b8f8d0 00b8f9c4
00b8f8d4 775f71f5 ntdll!_except_handler4
00b8f8d8 46b2e8b6
00b8f8dc fffffffe
00b8f8e0 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8f8e4 775b3cfe ntdll!RtlAllocateHeap+0x23a
00b8f8e8 00000208
00b8f8ec 00000000
00b8f8f0 00000000
00b8f8f4 00b8f954
00b8f8f8 7efd7000
00b8f8fc 7efd7000
00b8f900 7efde000
00b8f904 74910000 SYSFER
00b8f908 00000000
00b8f90c 00000000
00b8f910 00000000
00b8f914 00000000
00b8f918 00000000
00b8f91c 00000000
00b8f920 7768200c ntdll!RtlpFlsLock
00b8f924 0048b128
00b8f928 00000000
00b8f92c 00000000
00b8f930 00000000
00b8f934 c6faf7eb
00b8f938 00b8f4e4
00b8f93c 00000000
00b8f940 00b8f98c
00b8f944 00000001
00b8f948 74962da0 SYSFER!FirstHookFunc+0x2c250
00b8f94c 00000001
00b8f950 74910000 SYSFER
00b8f954 00440bb0
00b8f958 00b8f964
00b8f95c 74930cb2 SYSFER+0x20cb2
00b8f960 74964c20 SYSFER!org_first_hook_func_addr+0x13fc
00b8f964 00b8f99c
00b8f968 7492d466 SYSFER+0x1d466
00b8f96c 0000000c
00b8f970 7492d44f SYSFER+0x1d44f
00b8f974 ec3e814d
00b8f978 00000000
00b8f97c 00440bb0
00b8f980 74910000 SYSFER
00b8f984 00b8f974
00b8f988 00b8f99c
00b8f98c 00b8f9c4
00b8f990 7492da00 SYSFER+0x1da00
00b8f994 9813bff9
00b8f998 fffffffe
00b8f99c 7492d44f SYSFER+0x1d44f
00b8f9a0 749290bb SYSFER+0x190bb
00b8f9a4 00440bb0
00b8f9a8 749290eb SYSFER+0x190eb
00b8f9ac ec3e8105
00b8f9b0 00000000
00b8f9b4 00000002
00b8f9b8 74910000 SYSFER
00b8f9bc 00b8f9ac
00b8f9c0 ec3e8105
00b8f9c4 00b8f624
00b8f9c8 00b8fa04
00b8f9cc 74953853 SYSFER!FirstHookFunc+0x1cd03
00b8f9d0 ffffffff
00b8f9d4 00b8fa14
00b8f9d8 7492915a SYSFER+0x1915a
00b8f9dc 74910000 SYSFER
00b8f9e0 00000002
00b8f9e4 00000001
00b8f9e8 00b8fab0
00b8f9ec 00484110
00b8f9f0 00b8fa34
00b8f9f4 00000001
00b8f9f8 00000001
00b8f9fc 0048b718
00b8fa00 7760a7a9 ntdll!RtlpCreateSplitBlock+0x4fc
00b8fa04 0048b728
00b8fa08 000008b8
00b8fa0c feeefeee
00b8fa10 0000007b
00b8fa14 0048b340
00b8fa18 00480000
00b8fa1c 0048bfe0
00b8fa20 00b8fa40
00b8fa24 775b99a0 ntdll!LdrpCallInitRoutine+0x14
00b8fa28 74910000 SYSFER
00b8fa2c 00000000
00b8fa30 0000007f
00b8fa34 00b8fb20
00b8fa38 775b3c5a ntdll!RtlpAllocateHeap+0xb5d
00b8fa3c 0048b718
00b8fa40 775b2caf ntdll!RtlpAllocateHeap+0xc78
00b8fa44 0048b348
00b8fa48 00000000
00b8fa4c 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8fa50 3150db06
00b8fa54 000003bc
00b8fa58 00000000
00b8fa5c 00480000
00b8fa60 00480150
00b8fa64 7768206c ntdll!LdrpProcessInitialized
00b8fa68 00000000
00b8fa6c 00480150
00b8fa70 00000c90
00b8fa74 00480180
00b8fa78 00000000
00b8fa7c 00000119
00b8fa80 00000004
00b8fa84 00480150
00b8fa88 0000007f
00b8fa8c 0048b348
00b8fa90 00000001
00b8fa94 0000007f
00b8fa98 0048469c
00b8fa9c 0000007b
00b8faa0 ffffffff
00b8faa4 ffb7b963
00b8faa8 775ba1c0 ntdll!LdrpInitializeThread+0x131
00b8faac 0048b710
00b8fab0 00000000
00b8fab4 06040002
00b8fab8 00484338
00b8fabc 7768206c ntdll!LdrpProcessInitialized
00b8fac0 0000017e
00b8fac4 77680214 ntdll!PebLdr+0x14
00b8fac8 000003bc
00b8facc 0000007f
00b8fad0 00b8fb1c
00b8fad4 91040194
00b8fad8 00000c90
00b8fadc 00000000
00b8fae0 00b8fb2c
00b8fae4 5000016b
00b8fae8 0000001c
00b8faec 0048b348
00b8faf0 0048b348
00b8faf4 0048b343
00b8faf8 00000000
00b8fafc 00b8fb34
00b8fb00 00480000
00b8fb04 03000000
00b8fb08 00b8fa50
00b8fb0c 00000000
00b8fb10 00b8fbe0
00b8fb14 775f71f5 ntdll!_except_handler4
00b8fb18 46b2e8b6
00b8fb1c fffffffe
00b8fb20 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8fb24 775b3cfe ntdll!RtlAllocateHeap+0x23a
00b8fb28 000003bc
00b8fb2c 000003d8
00b8fb30 0048b342
00b8fb34 0048b340
00b8fb38 000003bc
00b8fb3c 00480000
00b8fb40 00000001
00b8fb44 00b8fb50
00b8fb48 77580000 ntdll!`string' <PERF> (ntdll+0x0)
00b8fb4c 00000000
00b8fb50 0001002f
00b8fb54 00000000
00b8fb58 00000000
00b8fb5c 00000000
00b8fb60 00000000
00b8fb64 00000000
00b8fb68 00000000
00b8fb6c 0000027f
00b8fb70 00000000
00b8fb74 0000ffff
00b8fb78 00b8fba8
00b8fb7c 77650806 ntdll!RtlpValidateHeap+0x20
00b8fb80 00480000
00b8fb84 00000000
00b8fb88 000003bc
00b8fb8c 00480000
00b8fb90 00000001
00b8fb94 00000004
00b8fb98 00000000
00b8fb9c 0048b340
00b8fba0 00000000
00b8fba4 00480000
00b8fba8 00b8fbf0
00b8fbac 7765108a ntdll!RtlDebugAllocateHeap+0x31f
00b8fbb0 00480138
00b8fbb4 7765106e ntdll!RtlDebugAllocateHeap+0x308
00b8fbb8 3150dbd6
00b8fbbc 00000000
00b8fbc0 00000000
00b8fbc4 00480000
00b8fbc8 00000000
00b8fbcc 00000000
00b8fbd0 0048b348
00b8fbd4 01000000
00b8fbd8 00b8fbb8
00b8fbdc 0000002b
00b8fbe0 00b8fcc4
00b8fbe4 775f71f5 ntdll!_except_handler4
00b8fbe8 46b2f046
00b8fbec fffffffe
00b8fbf0 7765106e ntdll!RtlDebugAllocateHeap+0x308
00b8fbf4 7760af0d ntdll!RtlpAllocateHeap+0xc4
00b8fbf8 00480000
00b8fbfc 5000016b
00b8fc00 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8fc04 3150dcf2
00b8fc08 00000000
00b8fc0c 00000000
00b8fc10 00480000
00b8fc14 00b8fe1c
00b8fc18 0000002b
00b8fc1c 0000027f
00b8fc20 00000000
00b8fc24 00000000
00b8fc28 00000000
00b8fc2c 00000000
00b8fc30 00000000
00b8fc34 00001f80
00b8fc38 0000ffff
00b8fc3c 00000000
<Output snipped to save space>
00b8fc94 00000000
00b8fc98 4000006a
00b8fc9c 00000000
00b8fca0 00000000
00b8fca4 00000000
00b8fca8 00000000
00b8fcac 00000000
00b8fcb0 00000000
00b8fcb4 00480000
00b8fcb8 00000000
00b8fcbc 00b8fc04
00b8fcc0 00000000
00b8fcc4 00b8fdf0
00b8fcc8 775f71f5 ntdll!_except_handler4
00b8fccc 46b2e8b6
00b8fcd0 fffffffe
00b8fcd4 775b3cd3 ntdll!RtlpAllocateHeap+0xe73
00b8fcd8 775b3cfe ntdll!RtlAllocateHeap+0x23a
00b8fcdc 000003bc
00b8fce0 00000000
00b8fce4 00000000
00b8fce8 00b8fd48
00b8fcec 00000000
00b8fcf0 000003bc
00b8fcf4 00000000
00b8fcf8 00000000
00b8fcfc 00000000
00b8fd00 00b8fd0c
00b8fd04 013a3426*** WARNING: Unable to verify checksum for SimpleApp.exe
SimpleApp!__crtFlsGetValue+0x15 [f:\dd\vctools\crt\crtw32\misc\winapisupp.c @ 428]
00b8fd08 00000003
00b8fd0c 00b8fd4c
00b8fd10 013a169b SimpleApp!_getptd_noexit+0x6a [f:\dd\vctools\crt\crtw32\startup\tidtable.c @ 312]
00b8fd14 00000000
00b8fd18 00000000
00b8fd1c 00000000
00b8fd20 013a161f SimpleApp!_getptd+0x6 [f:\dd\vctools\crt\crtw32\startup\tidtable.c @ 337]
00b8fd24 00b8fd4c
00b8fd28 00000100
00b8fd2c 0000002f
00b8fd30 00000005
00b8fd34 0000002f
00b8fd38 00000030
00b8fd3c 00000031
00b8fd40 00000032
00b8fd44 00000033
00b8fd48 aab7d537
00b8fd4c 00b8fd88
00b8fd50 013a112e SimpleApp!FunctionThree+0x4e
00b8fd54 0000002f
00b8fd58 0000000a
00b8fd5c 0000002b
00b8fd60 0000002c
00b8fd64 0000002d
00b8fd68 0000002e
00b8fd6c 0000002f
00b8fd70 00000030
00b8fd74 00000031
00b8fd78 00000032
00b8fd7c 00000033
00b8fd80 00000034
00b8fd84 aab7d5f3
00b8fd88 00b8fda8
00b8fd8c 013a119e SimpleApp!FunctionTwo+0x4e
00b8fd90 0000002b
00b8fd94 00000003
00b8fd98 00000029
00b8fd9c 0000002a
00b8fda0 0000002b
00b8fda4 aab7d5d3
00b8fda8 00b8fdb4
00b8fdac 013a11dc SimpleApp!FunctionOne+0x1c
00b8fdb0 00000029
00b8fdb4 00b8fdc0
00b8fdb8 76bb338a kernel32!BaseThreadInitThunk+0xe
00b8fdbc 00000000
00b8fdc0 00b8fe00
00b8fdc4 775b9f72 ntdll!__RtlUserThreadStart+0x70
00b8fdc8 00000000
00b8fdcc 3150de26
00b8fdd0 00000000
00b8fdd4 00000000
00b8fdd8 00000000
00b8fddc 00000000
00b8fde0 00000000
00b8fde4 00000000
00b8fde8 00b8fdcc
00b8fdec 00000000
00b8fdf0 00b8fe10
00b8fdf4 775f71f5 ntdll!_except_handler4
00b8fdf8 46b2e576
00b8fdfc 00000000
00b8fe00 00b8fe18
00b8fe04 775b9f45 ntdll!_RtlUserThreadStart+0x1b
00b8fe08 013a1019 SimpleApp!ILT+20(_FunctionOne)
00b8fe0c 00000000
00b8fe10 ffffffff
00b8fe14 77647428 ntdll!FinalExceptionHandler
00b8fe18 00000000
00b8fe1c 00000000
00b8fe20 013a1019 SimpleApp!ILT+20(_FunctionOne)
00b8fe24 00000000
<Output snipped to save space>
00b8fffc 00000000
00b90000 ????????
Since the stack is not cleaned up after usage, we need to find a legitimate starting point inside this memory dump where we can begin. We know that threads usually start with the function RtlUserThreadStart, so we can search for this function's address in the stack. In the above example, RtlUserThreadStart() is highlighted with this color for your help.
So we have located a legitimate point where we can start looking. Now we start walking the frames to see till which point things make sense and where we go awry.
Note: Function pointers in the stack might mean return addresses, though this is not always true but will be, most of the time. from the above output, it appears that things were going well till FunctionThree was called. Things seems to have gone bad somewhere inside FunctionThree. Thus FunctionThree might be a good place to start further digging. Lets start by disassembling the function.
0:002> uF SimpleApp!FunctionThree
SimpleApp!FunctionThree:
013a10e0 55 push ebp
013a10e1 8bec mov ebp,esp
013a10e3 83ec30 sub esp,30h
013a10e6 a100703c01 mov eax,dword ptr [SimpleApp!__security_cookie (013c7000)]
013a10eb 33c5 xor eax,ebp
013a10ed 8945fc mov dword ptr [ebp-4],eax
013a10f0 c745d000000000 mov dword ptr [ebp-30h],0
013a10f7 eb09 jmp SimpleApp!FunctionThree+0x22 (013a1102)
SimpleApp!FunctionThree+0x19:
013a10f9 8b45d0 mov eax,dword ptr [ebp-30h]
013a10fc 83c001 add eax,1
013a10ff 8945d0 mov dword ptr [ebp-30h],eax
SimpleApp!FunctionThree+0x22:
013a1102 837dd00a cmp dword ptr [ebp-30h],0Ah
013a1106 730f jae SimpleApp!FunctionThree+0x37 (013a1117)
SimpleApp!FunctionThree+0x28:
013a1108 8b4d08 mov ecx,dword ptr [ebp+8]
013a110b 034dd0 add ecx,dword ptr [ebp-30h]
013a110e 8b55d0 mov edx,dword ptr [ebp-30h]
013a1111 894c95d4 mov dword ptr [ebp+edx*4-2Ch],ecx
013a1115 ebe2 jmp SimpleApp!FunctionThree+0x19 (013a10f9)
SimpleApp!FunctionThree+0x37:
013a1117 e875010000 call SimpleApp!rand (013a1291)
013a111c 99 cdq
013a111d b90a000000 mov ecx,0Ah
013a1122 f7f9 idiv eax,ecx
013a1124 8b5495d4 mov edx,dword ptr [ebp+edx*4-2Ch]
013a1128 52 push edx
013a1129 e8e6feffff call SimpleApp!ILT+15(_FunctionFour) (013a1014)
013a112e 83c404 add esp,4
013a1131 b801000000 mov eax,1
013a1136 8b4dfc mov ecx,dword ptr [ebp-4]
013a1139 33cd xor ecx,ebp
013a113b e882010000 call SimpleApp!__security_check_cookie (013a12c2)
013a1140 8be5 mov esp,ebp
013a1142 5d pop ebp
013a1143 c3 ret
Looks like there is some kind of a loop inside this function. Look at the following sequence of instructions:
013a111d b90a000000 mov ecx,0Ah
013a1122 f7f9 idiv eax,ecx
013a1124 8b5495d4 mov edx,dword ptr [ebp+edx*4-2Ch]
013a1128 52 push edx
The register ECX is being populated to 16 (0Ah), making the loop iterate 16 times.
013a111d b90a000000 mov ecx,0Ah
This statement below looks like a dereference of a pointer. But what else can we find from this?
013a1124 8b5495d4 mov edx,dword ptr [ebp+edx*4-2Ch]
Assume the following C code:
int i = 10;
int *p = &i;
here we are assigning a pointer to a variable. But since it is a normal variable and not a structure, the pointer can be directly pointed to the location. But in the case of a structure (or class) we would need to move the base pointer to somewhere inside the structure to get the address of the member (very similar to how CONTAINING_RECORD macro works).
struct *pS;
pS->MemberPointer;
In the code we are debugging, it seems to be the case of the later. Hinting that it is a complex data type being used.
Also the multiplication before the dereference hints that it is probably an array whose indices are being populated.
013a1122 f7f9 idiv eax,ecx
We also see that FunctionFour is being called from inside the loop. So lets see what FunctionFour is doing.
0:002> uF SimpleApp!FunctionFour
SimpleApp!FunctionFour:
013a1070 55 push ebp
013a1071 8bec mov ebp,esp
013a1073 83ec1c sub esp,1Ch // Creating stack space for locals
013a1076 a100703c01 mov eax,dword ptr [SimpleApp!__security_cookie (013c7000)]
013a107b 33c5 xor eax,ebp
013a107d 8945fc mov dword ptr [ebp-4],eax
013a1080 c745e400000000 mov dword ptr [ebp-1Ch],0
013a1087 eb09 jmp SimpleApp!FunctionFour+0x22 (013a1092)
SimpleApp!FunctionFour+0x19:
013a1089 8b45e4 mov eax,dword ptr [ebp-1Ch]
013a108c 83c001 add eax,1
013a108f 8945e4 mov dword ptr [ebp-1Ch],eax
SimpleApp!FunctionFour+0x22:
013a1092 837de405 cmp dword ptr [ebp-1Ch],5 // loop exit condition, loop executes 5 times
013a1096 730f jae SimpleApp!FunctionFour+0x37 (013a10a7)
SimpleApp!FunctionFour+0x28:
013a1098 8b4d08 mov ecx,dword ptr [ebp+8] // 8 is pointer size so we are incrementing by pointer size
013a109b 034de4 add ecx,dword ptr [ebp-1Ch]
013a109e 8b55e4 mov edx,dword ptr [ebp-1Ch]
013a10a1 894c95e8 mov dword ptr [ebp+edx*4-18h],ecx // this looks like the operation to index into an array and dereference into the base object.
013a10a5 ebe2 jmp SimpleApp!FunctionFour+0x19 (013a1089) // Unconditional jump to the beginning of loop
SimpleApp!FunctionFour+0x37:
013a10a7 e8e5010000 call SimpleApp!rand (013a1291)
013a10ac 99 cdq
013a10ad b905000000 mov ecx,5
013a10b2 f7f9 idiv eax,ecx
013a10b4 8b5495e8 mov edx,dword ptr [ebp+edx*4-18h]
013a10b8 52 push edx
013a10b9 e851ffffff call SimpleApp!ILT+10(_FunctionFive) (013a100f)
013a10be 83c404 add esp,4
013a10c1 b801000000 mov eax,1
013a10c6 8b4dfc mov ecx,dword ptr [ebp-4]
013a10c9 33cd xor ecx,ebp
013a10cb e8f2010000 call SimpleApp!__security_check_cookie (013a12c2)
013a10d0 8be5 mov esp,ebp
013a10d2 5d pop ebp
013a10d3 c3 ret
This function seems to call FunctionFive inside the loop. Lets see what FunctionFive has to say:
SimpleApp!FunctionFive:
013a1050 55 push ebp
013a1051 8bec mov ebp,esp
013a1053 c7450400010000 mov dword ptr [ebp+4],100h
013a105a b801000000 mov eax,1
013a105f 5d pop ebp
013a1060 c3 ret
Whoa!!! we are putting 100h into EBP + 4. But EBP+4 is the return address. This means that this function will return to an incorrect location. Which is exactly what is happening in our program. If we recall, then code at location 100h was being executed by the CPU (EIP = 100h).
Thus we see that even when the stack is corrupt, it can sometimes be reconstructed from the hints, and then the original fault be located.
No comments:
Post a Comment