On Self Dumps of Secure String API
Sometimes we get crashes with the following stack trace pattern:
0:000> kv 100
ChildEBP RetAddr Args to Child
0012cecc 7c91df4a 7c8094fe 00000002 0012cef8 ntdll!KiFastSystemCallRet
0012ced0 7c8094fe 00000002 0012cef8 00000001 ntdll!ZwWaitForMultipleObjects+0xc
0012cf6c 7c80a085 00000002 0012d09c 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
0012cf88 6990763c 00000002 0012d09c 00000000 kernel32!WaitForMultipleObjects+0x18
0012d91c 699082b1 0012f090 00000001 00198312 faultrep!StartDWException+0×5df
0012e990 7c8635d1 0012f090 00000001 00000000 faultrep!ReportFault+0×533
0012f030 78138a09 0012f090 00000022 c000000d kernel32!UnhandledExceptionFilter+0×587
0012f368 781443d1 00000000 00000000 00000000 msvcr80!_invoke_watson+0xc4
0012f38c 0040b02f 0012f538 00000104 004f80a0 msvcr80!strcat_s+0×29
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f39c 0012f538 00000104 00430848 0012f538 Application+0xb020
0:000> .exptr 0012f090
----- Exception record at 0012f040:
ExceptionAddress: 781443d1 (msvcr80!strcat_s+0x00000029)
ExceptionCode: c000000d
ExceptionFlags: 00000000
NumberParameters: 0
----- Context record at 0012f098:
eax=f2c4dacf ebx=00000000 ecx=00000002 edx=7c91e514 esi=00000022 edi=00000000
eip=781443d1 esp=0012f36c ebp=004f7658 iopl=0 nv up ei ng nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000286
msvcr80!strcat_s+0x29:
781443d1 83c414 add esp,14h
0:000> !error c000000d
Error code: (NTSTATUS) 0xc000000d (3221225485) - An invalid parameter was passed to a service or function.
We clearly see that the crash involved strcat_s but we don’t see any invalid instruction or access violation call. The ADD instruction is perfectly valid above. However, if we disassemble EIP backwards we would see the call to _invalid_parameter function and it looks like it has a name association with Dr. Watson:
0:000> ub 781443d1
msvcr80!strcat_s+0×1c:
781443c4 5e pop esi
781443c5 8930 mov dword ptr [eax],esi
781443c7 53 push ebx
781443c8 53 push ebx
781443c9 53 push ebx
781443ca 53 push ebx
781443cb 53 push ebx
781443cc e89f46ffff call msvcr80!_invalid_parameter (78138a70)
0:000> uf 78138a70
Flow analysis was incomplete, some code may be missing
msvcr80!_invoke_watson:
78138945 55 push ebp
78138946 8dac2458fdffff lea ebp,[esp-2A8h]
7813894d 81ec28030000 sub esp,328h
[...]
msvcr80!_invalid_parameter:
78138a70 55 push ebp
78138a71 8bec mov ebp,esp
78138a73 ff3528401c78 push dword ptr [msvcr80!__pInvalidArgHandler (781c4028)]
78138a79 e85ba1ffff call msvcr80!_decode_pointer (78132bd9)
78138a7e 85c0 test eax,eax
78138a80 59 pop ecx
78138a81 7403 je msvcr80!_invalid_parameter+0×16 (78138a86)
msvcr80!_invalid_parameter+0x13:
78138a83 5d pop ebp
78138a84 ffe0 jmp eax
msvcr80!_invalid_parameter+0x16:
78138a86 6a02 push 2
78138a88 e806330000 call msvcr80!_crt_debugger_hook (7813bd93)
78138a8d 59 pop ecx
78138a8e 5d pop ebp
78138a8f e9b1feffff jmp msvcr80!_invoke_watson (78138945)
According to MSDN documentation, _s secure functions by default use a postmortem debugger mechanism:
Secure-enhanced CRT parameter validation
So we have something that is similar to Self-Dump pattern here. The same parameter checking is seen in the case of C++ STL exceptions. In case of custom unhandled exception filters not resorting to WER faulrep.dll other stacks can show process termination, for example, with wcscpy_s:
0:000> kL 100
ChildEBP RetAddr
0111cb64 7c947c39 ntdll!KiFastSystemCallRet
0111cb68 7c80202b ntdll!ZwTerminateProcess+0xc
0111cb78 78138a2b kernel32!TerminateProcess+0×20
0111ceb4 78144ba1 MSVCR80!_invoke_watson+0xe6
0111ced8 67dbb47d MSVCR80!wcscpy_s+0×29
0111cf00 67dbc93b Application!CopyName+0×5d
[…]
Here the specified size of the destination buffer was smaller than the size of source NULL-terminated strings, which was a good thing anyway: old strcpy or strcat function would definitely caused buffer overflow effects. Now we have a nice side effect too, the dump is saved, ready for a postmortem analysis and subsequent code improvement.
- Dmitry Vostokov @ DumpAnalysis.org -