Crash Dump Analysis Patterns (Part 5)
CARE: Crash Analysis Report Environment
DATA (Dump Analysis + Trace Analysis) Facebook group
Please join the community of memory (dump) and trace analysis engineers. This group promotes scientific methods and memory dump-based worldview.
Twitter @ DumpAnalysis You can now follow portal and blog news at DumpAnalysis on Twitter
LinkedIn Group Dr. Watson Enthusiasts All about Dr. Watson errors and more. Get news, excerpts and progress reports about the forthcoming book The Science of Dr. Watson: An Illustrated History of Debugging (ISBN 978-1906717070)
2010 (0x7DA) - The Year of Dump Analysis 2011 (0x7DB) - 2020 (0x7E4) The Debugging Decade
The next pattern I would like to talk about is Optimized Code. If you have such cases you should not trust your crash dump analysis tools like WinDbg. Always suspect that compiler generated code might have been optimized if you see any suspicious or strange behaviour of your tool. Let’s consider this fragment of stack:
Args to Child
77e44c24 000001ac 00000000 ntdll!KiFastSystemCallRet
000001ac 00000000 00000000 ntdll!NtFsControlFile+0xc
00000034 00000bb8 0013e3f4 kernel32!WaitNamedPipeW+0x2c3
0016fc60 00000000 67c14804 MyModule!PipeCreate+0x48
3rd-party function PipeCreate from MyModule opens a named pipe and its first parameter (0016fc60) points to a pipe name L”\\.\pipe\MyPipe”. Inside the source code it calls Win32 API function WaitNamedPipeW (to wait for the pipe to be available for connection) and passes the same pipe name. But we see that the first parameter to WaitNamedPipeW is 00000034 which cannot be the pointer to a valid Unicode string. And the program should have been crashed if 00000034 were a pointer value.
Everything becomes clear if we look at WaitNamedPipeW disassembly (comments are mine):
0:000> uf kernel32!WaitNamedPipeW
mov edi,edi
push ebp
mov ebp,esp
sub esp,50h
push dword ptr [ebp+8] ; Use pipe name
lea eax,[ebp-18h]
push eax
call dword ptr [kernel32!_imp__RtlCreateUnicodeString (77e411c8)]
…
…
…
…
call dword ptr [kernel32!_imp__NtOpenFile (77e41014)]
cmp dword ptr [ebp-4],edi
mov esi,eax
jne kernel32!WaitNamedPipeW+0×1d5 (77e93316)
cmp esi,edi
jl kernel32!WaitNamedPipeW+0×1ef (77e93331)
movzx eax,word ptr [ebp-10h]
mov ecx,dword ptr fs:[18h]
add eax,0Eh
push eax
push dword ptr [kernel32!BaseDllTag (77ecd14c)]
mov dword ptr [ebp+8],eax ; reuse parameter slot
As we know [ebp+8] is the first function parameter in non-FPO calls:
Parameters and Local Variables
And we see it is reused because after we convert LPWSTR to UNICODE_STRING and call NtOpenFile to get a handle we no longer need our parameter slot and the compiler can reuse it to store other information.
There is another compiler optimization we should be aware of and it is called OMAP. It moves the code inside the code section and puts the most frequently accessed code fragments together. In that case if you type in WinDbg, for example,
0:000> uf nt!someFunction
you get different code than if you type (assuming f4794100 is the address of the function you obtained from stack or disassembly)
0:000> uf f4794100
In conclusion the advice is to be alert and conscious during crash dump analysis and inspect any inconsistencies closer.
Happy debugging!
- Dmitry Vostokov @ DumpAnalysis.org -
_1125.png)
Coming Soon:
Debugging Notebook: Essential Concepts, WinDbg Commands and Tools
Crash Dump Analysis for System Administrators and Support Engineers
New Magazines:
Debugged! MZ/PE: MagaZine for/from Practicing Engineers
New Books:
Memory Dump Analysis Anthology, Volume 3
First Fault Software Problem Solving: A Guide for Engineers, Managers and Users
x64 Windows Debugging: Practical Foundations
Also available:
Windows Debugging: Practical Foundations
DLL List Landscape: The Art from Computer Memory Space
Dumps, Bugs and Debugging Forensics: The Adventures of Dr. Debugalov
WinDbg: A Reference Poster and Learning Cards
Memory Dump Analysis Anthology, Volume 2
Memory Dump Analysis Anthology, Volume 1
New Children's Book:
February 15th, 2008 at 3:28 pm
[…] I call this pattern as False Function Parameters where double checks and knowledge of calling conventions are required. Sometimes this pattern is a consequence of another pattern that I previously called Optimized Code. […]
September 17th, 2008 at 9:55 am
[…] http://www.dumpanalysis.org/blog/index.php/2006/12/15/crash-dump-analysis-patterns-part-5/ […]
April 22nd, 2009 at 5:51 pm
[…] safe register association with arguments at the beginning of a function (p. 164) - See my Optimized Code pattern: http://www.dumpanalysis.org/blog/index.php/2006/12/15/crash-dump-analysis-patterns-part-5/ […]
June 2nd, 2009 at 5:49 am
Excellent site. I have found that third party device drivers that have not passed though MS driver testing are culprit even though the stack might not point to them, or the lm command. The driver could have allocated a buffer and made a system call (which caused the crash). It is likely, however, that the driver passed it some erroneous data. As well all know, applications crash when a thread of execution accesses a block of memory it does not own, or it does own but corrupts its state. I saw a big improvement with the introduction of Vista SP1, yet I will still find my system to hang should I fill up with third party downloads. I find a quickened system when I use driver verifier. Oh, and you have an outstanding site.
July 8th, 2009 at 8:53 pm
[…] a pointer to an exception pointers structure is NULL (probably because of optimized code) and we cannot use .exptr command. However we can still use a technique described in Hidden […]