Crash Dump Analysis AntiPatterns (Part 13)

July 9th, 2009

Sometimes we follow the course of established troubleshooting or debugging methods without questioning them or not considering possible exceptions. For example, the usual advice to heap corruption signs in process memory dumps is to ask to enable full page heap. However page heap helps to catch buffer overwrites but not underwrites and heap can also be damaged by other means like double free, passing an invalid address or direct corruption of control structures via a dangling pointer. Therefore in some cases when we enable full page heap we get the same stack trace:

Normal:

0:030> kL 100
ChildEBP RetAddr 
175af77c 7d620ec5 ntdll_7d600000!RtlpCoalesceFreeBlocks+0×231
175af864 7c34218a ntdll_7d600000!RtlFreeHeap+0×38e

175af8ac 67d6153d msvcr71!free+0xc3
175af950 67781d69 Component!OnData+0×504
175af96c 7da4d03d Component!DispatchRequest+0×99

175afc28 7da4d177 rpcrt4!DispatchToStubInCNoAvrf+0×38
175afc7c 7da4d812 rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0×11f
175afca0 7da59a1c rpcrt4!RPC_INTERFACE::DispatchToStub+0xa3
175afcfc 7da4da21 rpcrt4!LRPC_SCALL::DealWithRequestMessage+0×421
175afd20 7da3db14 rpcrt4!LRPC_ADDRESS::DealWithLRPCRequest+0×127
175aff84 7da45eac rpcrt4!LRPC_ADDRESS::ReceiveLotsaCalls+0×430
175aff8c 7da45dd0 rpcrt4!RecvLotsaCallsWrapper+0xd
175affac 7da45e94 rpcrt4!BaseCachedThreadRoutine+0×9d
175affb8 7d4dfe37 rpcrt4!ThreadStartRoutine+0×1b
175affec 00000000 kernel32!BaseThreadStart+0×34

With full page heap enabled:

0:030> kL
ChildEBP RetAddr 
6092f568 7d6822fa ntdll!RtlpDphIsNormalHeapBlock+0×1f
6092f598 7d68256c ntdll!RtlpDphNormalHeapFree+0×21
6092f5f0 7d685443 ntdll!RtlpDebugPageHeapFree+0×146
6092f658 7d65714a ntdll!RtlDebugFreeHeap+0×2c
6092f730 7d62c5c0 ntdll!RtlFreeHeapSlowly+0×37
6092f814 7c34218a ntdll!RtlFreeHeap+0×11a

6092f85c 67d6153d msvcr71!free+0xc3
6092f900 67781d69 Component!OnData+0×504
6092f91c 7da4d03d Component!DispatchRequest+0×99

6092fc10 7da7ec5e rpcrt4!DispatchToStubInCNoAvrf+0×38
6092fc28 7da4d177 rpcrt4!DispatchToStubInCAvrf+0×14
6092fc7c 7da4d812 rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0×11f
6092fca0 7da59a1c rpcrt4!RPC_INTERFACE::DispatchToStub+0xa3
6092fcfc 7da4da21 rpcrt4!LRPC_SCALL::DealWithRequestMessage+0×421
6092fd20 7da3db14 rpcrt4!LRPC_ADDRESS::DealWithLRPCRequest+0×127
6092ff84 7da45eac rpcrt4!LRPC_ADDRESS::ReceiveLotsaCalls+0×430
6092ff8c 7da45dd0 rpcrt4!RecvLotsaCallsWrapper+0xd
6092ffac 7da45e94 rpcrt4!BaseCachedThreadRoutine+0×9d
6092ffb8 7d4dfe37 rpcrt4!ThreadStartRoutine+0×1b
6092ffec 00000000 kernel32!BaseThreadStart+0×34

We see that we get the same Component stack trace before calling free (shown in blue above) so we better search in a database of stack trace signatures before sending Habitual Reply to enable page heap. If there is a match in database then the course of future actions can be completely different: an immediate available hotfix or we find a similar problem that is already under investigation. The sooner we provide a relief to our customer the better.

- Dmitry Vostokov @ DumpAnalysis.org -

Large-scale Structure of Memory Space (Part 1)

July 9th, 2009

There are many books and articles titled “Large-scale Structure of X”, where X can be Space-Time, Cosmos or Universe. Here is the large-scale structure of 12Gb complete memory dump:

The image was generated with the help of ImageMagick. The dump file was interpreted as a raw RGBA image with 8-bits per color:

C:\MemoryDumps>convert -size 56751x56751 -depth 8
-resize 450x450 rgba:complete.dmp dump_12Gb_rgba_8_sq.jpg

The width and height were calculated as sqrt(filesize/4).

Complete memory dumps are physical memory dumps where modularized structure of virtual space of kernel and process memory is not expected but we see some structure nevertheless.

I’ve also created two pages with dump slices. Some viewers do not handle files with more that 32767 pixels in one dimension so I split 450×56751 slice into two:

Complete Memory Dump Slice Part 1 (11Mb JPEG)

Complete Memory Dump Slice Part 2 (10Mb JPEG)  

- Dmitry Vostokov @ DumpAnalysis.org -

Virtualized process, incorrect stack trace, stack trace collection, multiple exceptions, optimized code and C++ exception: pattern cooperation

July 8th, 2009

It happened to me that I accidentally opened a YouTube page and it started playing video so I tried to either stop it or pushed the back browser button. Then immediately WER dialog appeared ruining my intricate multi-tab window. Nevertheless I looked at this event from the positive perspective as an opportunity to analyze a dump file and write a case study. I saved the crash dump using Windows Server 2008 Task Manager for later postmortem analysis.

Today I had a chance to look at it. When we open the dump file we see that it is the dump of a WOW64 process:

0:000> !analyze -v

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 0000000000000000
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 0

STACK_TEXT: 
00000000`0016ed78 00000000`75fcab46 : 00000000`77ddc990 00000000`0016fd20 00000000`75efa2b1 00000000`0016f760 : wow64cpu!WaitForMultipleObjects32+0×3a
00000000`0016ee20 00000000`75fca14c : 00000000`00000000 00000000`00000000 00000000`75fc3258 00000000`7ffe0030 : wow64!RunCpuSimulation+0xa
00000000`0016ee50 00000000`77d052d3 : 00000000`77cd0000 00000000`00000000 00000000`77de61b0 00000000`77cd0000 : wow64!Wow64LdrpInitialize+0×4b4

00000000`0016f3b0 00000000`77d05363 : 00000000`00000000 00000000`00000000 00000000`7efdf000 00000000`77d07ca7 : ntdll!LdrpInitializeProcess+0×14ac
00000000`0016f660 00000000`77cf85ce : 00000000`0016f760 00000000`00000000 00000000`7efdf000 00000000`00000000 : ntdll! ?? ::FNODOBFM::`string’+0×1ff19
00000000`0016f710 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

FOLLOWUP_IP:
wow64cpu!WaitForMultipleObjects32+3a
00000000`75ec374f 418bbda0000000  mov     edi,dword ptr [r13+0A0h]

MODULE_NAME: wow64cpu 

Then we load a WOW64 extension that allows us to analyze 32-bit parts of saved 64-bit dumps and we retry the default analysis:

0:000> .load wow64exts; .effmach x86
Effective machine: x86 compatible (x86)

0:000:x86> !analyze -v

IP_ON_HEAP:  ffffffffc0d84c02
The fault address in not in any loaded module, please check your build's rebase
log at <releasedir>\bin\build_logs\timebuild\ntrebase.log for module which may
contain the address if it were loaded.

STACK_TEXT: 
00000000`003b0068 iexplore!__dyn_tls_init_callback <PERF> +0×0
ffffffff`c0d84c02 unknown+0×0
ffffffff`aacf27dc unknown+0×0
ffffffff`c1d84c02 unknown+0×0
ffffffff`b3cf38dc unknown+0×0
ffffffff`c2d84c02 unknown+0×0
00000000`3ecf38dc unknown+0×0
[…]
00000000`7aca19dd unknown+0×0
ffffffff`e0d84c02 unknown+0×0
ffffffff`a7ca19dd unknown+0×0
ffffffff`

FOLLOWUP_IP:
iexplore!__dyn_tls_init_callback <PERF> (iexplore+0x80068)+0
003b0068 70f7            jo      iexplore!__dyn_tls_init_callback <PERF> (iexplore+0x80061) (003b0061)

Clearly the shown above stack trace is incorrect but at the same time the first thread stack looks consistent:

0:000:x86> k 100
ChildEBP RetAddr 
0051d930 7756e91a ntdll_77e70000!NtWaitForMultipleObjects+0x15
0051d9cc 77888f76 kernel32!WaitForMultipleObjectsEx+0x11d
0051da20 7617ab28 user32!RealMsgWaitForMultipleObjectsEx+0x14d
0051da48 7617ac88 ole32!CCliModalLoop::BlockFn+0x97
0051da70 7617ad74 ole32!ModalLoop+0x5b
0051da80 76287c28 ole32!SwitchSTA+0x21
0051daac 762889d4 ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x127
0051db8c 7617ad2e ole32!CRpcChannelBuffer::SendReceive2+0xef
0051dba8 7617ace0 ole32!CCliModalLoop::SendReceive+0x1e
0051dc20 7619e688 ole32!CAptRpcChnl::SendReceive+0x73
0051dc74 779f1074 ole32!CCtxComChnl::SendReceive+0x1c5
0051dc90 779f102b rpcrt4!NdrProxySendReceive+0x49
0051dc9c 779f0146 rpcrt4!NdrpProxySendReceive+0xb
0051e0a4 779f11ee rpcrt4!NdrClientCall2+0x18f
0051e0c8 779649c2 rpcrt4!ObjectStublessClient+0x90
0051e0d8 74bc86e3 rpcrt4!ObjectStubless+0xf
WARNING: Frame IP not in any known module. Following frames may be wrong.
0051e0e4 74bda9bb ieframe+0x1986e3
0051e0f0 74b020d9 ieframe+0x1aa9bb
0051e164 74adbb6a ieframe+0xd20d9
0051e18c 77888807 ieframe+0xabb6a
0051e1b8 77888962 user32!InternalCallWinProc+0x23
0051e230 7788c4b6 user32!UserCallWinProcCheckWow+0x109
0051e274 7788c517 user32!SendMessageWorker+0x55b
0051e298 75b3f74a user32!SendMessageW+0x7f
0051e2c0 75b3f63b comctl32!CToolbar::TBOnLButtonUp+0x12f
0051e368 75b37020 comctl32!CToolbar::ToolbarWndProc+0xaa9
0051e388 77888807 comctl32!CToolbar::s_ToolbarWndProc+0x9b
0051e3b4 77888962 user32!InternalCallWinProc+0x23
0051e42c 77888aad user32!UserCallWinProcCheckWow+0x109
0051e490 77888b00 user32!DispatchMessageWorker+0x380
0051e4a0 74ae07ce user32!DispatchMessageW+0xf
0051e4d4 74a7ffce ieframe+0xb07ce
0051e4e0 74a6f579 ieframe+0x4ffce
0051e504 74a6f4c7 ieframe+0x3f579
0051f574 74a5d1ba ieframe+0x3f4c7
0051f7a4 003333c3 sxs!_hmod__RPCRT4_dll <PERF> (sxs+0x8d1ba)
0051fbe8 0033325a iexplore!wWinMain+0x27b
0051fc7c 775de4a5 iexplore!_initterm_e+0x1b1
0051fc88 77eecfed kernel32!BaseThreadInitThunk+0xe
0051fcc8 77eed1ff ntdll_77e70000!__RtlUserThreadStart+0x23
0051fce0 00000000 ntdll_77e70000!_RtlUserThreadStart+0x1b

We look at the stack trace collection to find another exception and we see it indeed on 7th stack trace:

0:000:x86> ~*k 100

[...]

   7  Id: b44.b1c Suspend: 0 Teb: 7efad000 Unfrozen
ChildEBP RetAddr 
05baee9c 7756e91a ntdll_77e70000!NtWaitForMultipleObjects+0x15
05baef38 775649d9 kernel32!WaitForMultipleObjectsEx+0x11d
05baef54 7761573d kernel32!WaitForMultipleObjects+0x18
05baefc0 77615969 kernel32!WerpReportFaultInternal+0x16d
05baefd4 775ec66f kernel32!WerpReportFault+0×70
05baf060 77eed03e kernel32!UnhandledExceptionFilter+0×1b5
05baf068 77ebf2d0 ntdll_77e70000!__RtlUserThreadStart+0×6f
05baf07c 77f229b3 ntdll_77e70000!_EH4_CallFilterFunc+0×12
05baf0a4 77e93099 ntdll_77e70000!_except_handler4+0×8e
05baf0c8 77e9306b ntdll_77e70000!ExecuteHandler2+0×26
05baf178 77e92eff ntdll_77e70000!ExecuteHandler+0×24
05baf198 7757f328 ntdll_77e70000!KiUserExceptionDispatcher+0xf
05baf4fc 7155dead kernel32!RaiseException+0×58

WARNING: Stack unwind information not available. Following frames may be wrong.
05baf534 7155a59d Flash10b!DllUnregisterServer+0×1adbe0
05baf550 7150ca25 Flash10b!DllUnregisterServer+0×1aa2d0
05baf564 7150b5b5 Flash10b!DllUnregisterServer+0×15c758
05baf588 7150b90a Flash10b!DllUnregisterServer+0×15b2e8
00000000 00000000 Flash10b!DllUnregisterServer+0×15b63d

[...]

  97  Id: b44.ff4 Suspend: 1 Teb: 7ee9f000 Unfrozen
ChildEBP RetAddr 
7387facc 77561270 ntdll_77e70000!ZwWaitForSingleObject+0x15
7387fb3c 775611d8 kernel32!WaitForSingleObjectEx+0xbe
7387fb50 713e0a11 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
7387fb74 713e0d34 Flash10b!DllUnregisterServer+0x30744
7387fb78 775de4a5 Flash10b!DllUnregisterServer+0x30a67
7387fb84 77eecfed kernel32!BaseThreadInitThunk+0xe
7387fbc4 77eed1ff ntdll_77e70000!__RtlUserThreadStart+0x23
7387fbdc 00000000 ntdll_77e70000!_RtlUserThreadStart+0x1b

Then we switch to this thread and try to find and set the new exception context:

0:000:x86> ~7s
ntdll_77e70000!NtWaitForMultipleObjects+0x15:
77e90bc5 c21400          ret     14h

0:007:x86> kv
ChildEBP RetAddr  Args to Child             
05baee9c 7756e91a 00000002 05baeeec 00000001 ntdll_77e70000!NtWaitForMultipleObjects+0x15
05baef38 775649d9 05baeeec 05baef88 00000000 kernel32!WaitForMultipleObjectsEx+0x11d
05baef54 7761573d 00000002 05baef88 00000000 kernel32!WaitForMultipleObjects+0x18
05baefc0 77615969 05baf090 00000001 00000001 kernel32!WerpReportFaultInternal+0x16d
05baefd4 775ec66f 05baf090 00000001 19e00de6 kernel32!WerpReportFault+0x70
05baf060 77eed03e 00000000 77ebf2d0 00000000 kernel32!UnhandledExceptionFilter+0×1b5
05baf068 77ebf2d0 00000000 05bafacc 77e9da38 ntdll_77e70000!__RtlUserThreadStart+0×6f
05baf07c 77f229b3 00000000 00000000 00000000 ntdll_77e70000!_EH4_CallFilterFunc+0×12
05baf0a4 77e93099 fffffffe 05bafabc 05baf1e0 ntdll_77e70000!_except_handler4+0×8e
05baf0c8 77e9306b 05baf190 05bafabc 05baf1e0 ntdll_77e70000!ExecuteHandler2+0×26
05baf178 77e92eff 01baf190 05baf1e0 05baf190 ntdll_77e70000!ExecuteHandler+0×24
05baf198 7757f328 00000003 19930520 05baf544 ntdll_77e70000!KiUserExceptionDispatcher+0xf
05baf4fc 7155dead e06d7363 00000001 00000003 kernel32!RaiseException+0×58
WARNING: Stack unwind information not available. Following frames may be wrong.
05baf534 7155a59d 05baf544 715e7954 715e5ac0 Flash10b!DllUnregisterServer+0×1adbe0
05baf550 7150ca25 002c1f7c 4237d4f8 4237c598 Flash10b!DllUnregisterServer+0×1aa2d0
05baf564 7150b5b5 002c1f60 00000010 423d0b28 Flash10b!DllUnregisterServer+0×15c758
05baf588 7150b90a 4237cb38 7150ba0b 00000000 Flash10b!DllUnregisterServer+0×15b2e8
00000000 00000000 00000000 00000000 00000000 Flash10b!DllUnregisterServer+0×15b63d

Unfortunately 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 Exception pattern using 32-bit raw stack to set the context and display the exception record:

0:007:x86> !wow64exts.info

PEB32: 0x7efde000
PEB64: 0x7efdf000

Wow64 information for current thread:

TEB32: 0x7efaf000
TEB64: 0x7efad000

32 bit, StackBase   : 0×5bb0000
        StackLimit  : 0×5b95000

        Deallocation: 0×5ab0000

64 bit, StackBase   : 0x30ffd20
        StackLimit  : 0x30f8000
        Deallocation: 0x30c0000

0:007:x86> dps 0×5b95000 0×5bb0000
05b95000  00000000
05b95004  00000000
05b95008  00000000
[…]
05baf160  00000009
05baf164  00000000
05baf168  00000000
05baf16c  05bb0000
05baf170  05b95000
05baf174  00000000
05baf178  05baf4fc
05baf17c  77e92eff ntdll_77e70000!KiUserExceptionDispatcher+0xf
05baf180  01baf190
05baf184  05baf1e0 ; .cxr
05baf188  05baf190 ; .exr
05baf18c  05baf1e0
05baf190  e06d7363
[…]

0:007:x86> .cxr 05baf1e0
eax=05baf4ac ebx=002c1f60 ecx=00000003 edx=00000000 esi=716d9c54 edi=00000010
eip=7757f328 esp=05baf4ac ebp=05baf4fc iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
kernel32!RaiseException+0×58:
7757f328 c9              leave

0:007:x86> kv
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr  Args to Child             
05baf4fc 7155dead e06d7363 00000001 00000003 kernel32!RaiseException+0×58
WARNING: Stack unwind information not available. Following frames may be wrong.
05baf534 7155a59d 05baf544 715e7954 715e5ac0 Flash10b!DllUnregisterServer+0×1adbe0
05baf550 7150ca25 002c1f7c 4237d4f8 4237c598 Flash10b!DllUnregisterServer+0×1aa2d0
05baf564 7150b5b5 002c1f60 00000010 423d0b28 Flash10b!DllUnregisterServer+0×15c758
05baf588 7150b90a 4237cb38 7150ba0b 00000000 Flash10b!DllUnregisterServer+0×15b2e8
00000000 00000000 00000000 00000000 00000000 Flash10b!DllUnregisterServer+0×15b63d

0:007:x86> .exr 05baf190
ExceptionAddress: 000000007757f328 (kernel32!RaiseException+0×0000000000000058)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 3
   Parameter[0]: 0000000019930520
   Parameter[1]: 0000000005baf544
   Parameter[2]: 00000000715e7954

We double check that Flash10b code raised the exception indeed:

0:007:x86> .asm no_code_bytes
Assembly options: no_code_bytes

0:007:x86> ub 7155dead
Flash10b!DllUnregisterServer+0×1adbc4:
7155de91 je      Flash10b!DllUnregisterServer+0×1adbcd (7155de9a)
7155de93 mov     dword ptr [ebp-0Ch],1994000h
7155de9a lea     eax,[ebp-0Ch]
7155de9d push    eax
7155de9e push    dword ptr [ebp-10h]
7155dea1 push    dword ptr [ebp-1Ch]
7155dea4 push    dword ptr [ebp-20h]
7155dea7 call    dword ptr [Flash10b!DllUnregisterServer+0×1ba0a3 (7156a370)]
 

0:007:x86> dps 7156a370
7156a370  7757f2cf kernel32!RaiseException
7156a374  77562728 kernel32!WideCharToMultiByte
7156a378  7756c60b kernel32!GlobalFree
7156a37c  77562ddf kernel32!GetCurrentThread
7156a380  775739fe kernel32!SetThreadAffinityMask
7156a384  775654c9 kernel32!VirtualQuery
7156a388  77562e9c kernel32!IsDBCSLeadByte
7156a38c  77561ce5 kernel32!GetACP
7156a390  77565ed6 kernel32!GetCPInfo
7156a394  77561b36 kernel32!MultiByteToWideChar
7156a398  7756eb64 kernel32!ResetEvent
7156a39c  77562c88 kernel32!CreateEventA
7156a3a0  77561a3a kernel32!CloseHandle
7156a3a4  775649c1 kernel32!WaitForMultipleObjects
7156a3a8  77562c64 kernel32!SetEvent
7156a3ac  77560e18 kernel32!InterlockedExchange
7156a3b0  77560e2c kernel32!InterlockedCompareExchange
7156a3b4  77560c79 kernel32!Sleep
7156a3b8  77e935c0 ntdll_77e70000!RtlLeaveCriticalSection
7156a3bc  77e93580 ntdll_77e70000!RtlEnterCriticalSection
7156a3c0  77ea27fe ntdll_77e70000!RtlDeleteCriticalSection
7156a3c4  77ea2512 ntdll_77e70000!RtlInitializeCriticalSection
7156a3c8  77568c28 kernel32!WriteConsoleA
7156a3cc  7757a6dc kernel32!SetStdHandle
7156a3d0  77568c0b kernel32!GetConsoleMode
7156a3d4  77568c75 kernel32!GetConsoleCP
7156a3d8  77564ab7 kernel32!GetStringTypeW
7156a3dc  77576a56 kernel32!GetStringTypeA
7156a3e0  77562d90 kernel32!InitializeCriticalSectionAndSpinCount
7156a3e4  775608d0 kernel32!GetSystemTimeAsFileTime
7156a3e8  77565c3b kernel32!GetEnvironmentStringsW
7156a3ec  77565c13 kernel32!FreeEnvironmentStringsA

I believe the appearance of “dead” in the return address 7155dead was just a coincidence.

So we have found the 3rd-party component that raised e06d7363 C++ exception. Actually Internet search shows that e06d7363 is quite common in many applications.

- Dmitry Vostokov @ DumpAnalysis.org -

Pictures from Memory Space (Part 3)

July 8th, 2009

Recently I discovered Quantum Levels on top of a continuum in one kernel memory dump:

- Dmitry Vostokov @ DumpAnalysis.org -

Full page heap settings on x64 Windows

July 8th, 2009

If we want to use gflags.exe to enable page heap settings (or any other image file execution options) for a 32-bit executable running on x64 Windows we should use 32-bit version of gflags.exe from 32-bit Debugging Tools for Windows (see windbg.org for quick download links) or if we want to set appropriate registry key manually we should use Wow6432Node branch:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<process name with .exe extension>

Name: GlobalFlag
Type: REG_DWORD
Value: 0x02000000

Name: PageHeapFlags
Type: REG_DWORD
Value: 0x00000003

- Dmitry Vostokov @ DumpAnalysis.org -

Raw Stack Dump of WOW64 Process

July 7th, 2009

Sometimes we need to dump raw stack data of the given thread to get correct function arguments or to see execution residue. If the process is WOW64 (32-bit running on x64 Windows) and its memory dump was saved using a 64-bit debugger or a process dumper like userdump.exe we have 2 stacks in it:

64-bit stack:

0:007> k
Child-SP          RetAddr           Call Site
00000000`030fee38 00000000`75fcab46 wow64cpu!WaitForMultipleObjects32+0x3a
00000000`030feee0 00000000`75fca14c wow64!RunCpuSimulation+0xa
00000000`030fef10 00000000`77d373db wow64!Wow64LdrpInitialize+0x4b4
00000000`030ff470 00000000`77cf85ce ntdll! ?? ::FNODOBFM::`string'+0x20061
00000000`030ff520 00000000`00000000 ntdll!LdrInitializeThunk+0xe

0:007> r
rax=0000000000000000 rbx=0000000000000002 rcx=0000000000000400
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=0000000075ec374f rsp=00000000030fee38 rbp=0000000005baef38
 r8=000000000000002b  r9=0000000077e9057a r10=0000000000000000
r11=00000000030fee30 r12=000000007efad000 r13=00000000030ffd20
r14=00000000030fee70 r15=0000000075ec3380
iopl=0 nv up ei pl nz ac pe nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
wow64cpu!WaitForMultipleObjects32+0×3a:
00000000`75ec374f 418bbda0000000  mov     edi,dword ptr [r13+0A0h] ds:00000000`030ffdc0=00000000

0:007> !teb
Wow64 TEB32 at 000000007efaf000

error InitTypeRead( wow64!_TEB32 )...

Wow64 TEB at 000000007efad000
    ExceptionList:        000000007efaf000
    StackBase:            00000000030ffd20
    StackLimit:           00000000030f8000

    SubSystemTib:         0000000000000000
    FiberData:            0000000000001e00
    ArbitraryUserPointer: 0000000000000000
    Self:                 000000007efad000
    EnvironmentPointer:   0000000000000000
    ClientId:             0000000000000b44 . 0000000000000b1c
    RpcHandle:            0000000000000000
    Tls Storage:          0000000000000000
    PEB Address:          000000007efdf000
    LastErrorValue:       0
    LastStatusValue:      c0000034
    Count Owned Locks:    0
    HardErrorMode:        0

32-bit stack:

0:007> .effmach x86
Effective machine: x86 compatible (x86)

0:007:x86> k
ChildEBP RetAddr 
05baee9c 7756e91a ntdll_77e70000!NtWaitForMultipleObjects+0x15
05baef38 775649d9 kernel32!WaitForMultipleObjectsEx+0x11d
05baef54 7761573d kernel32!WaitForMultipleObjects+0x18
05baefc0 77615969 kernel32!WerpReportFaultInternal+0x16d
05baefd4 775ec66f kernel32!WerpReportFault+0x70
05baf060 77eed03e kernel32!UnhandledExceptionFilter+0x1b5
05baf068 77ebf2d0 ntdll_77e70000!__RtlUserThreadStart+0x6f
05baf07c 77f229b3 ntdll_77e70000!_EH4_CallFilterFunc+0x12
05baf0a4 77e93099 ntdll_77e70000!_except_handler4+0x8e
05baf0c8 77e9306b ntdll_77e70000!ExecuteHandler2+0x26
05baf178 77e92eff ntdll_77e70000!ExecuteHandler+0x24
05baf198 7757f328 ntdll_77e70000!KiUserExceptionDispatcher+0xf
05baf4fc 7155dead kernel32!RaiseException+0x58
WARNING: Stack unwind information not available. Following frames may be wrong.
05baf534 7155a59d ComponentA!DllUnregisterServer+0x1adbe0
[...]

0:007:x86> r
eax=00000000 ebx=00000002 ecx=00000003 edx=00000000 esi=00000000 edi=00000000
eip=77e90bc5 esp=05baeea0 ebp=05baef38 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
ntdll_77e70000!NtWaitForMultipleObjects+0×15:
77e90bc5 c21400          ret     14h

Unfortunately there is an error when try to get its TEB (TEB32) using !teb command so we can either use dp command to discover stack base and limit:

0:007:x86> !teb
Wow64 TEB32 at 000000007efaf000

error InitTypeRead( wow64!_TEB32 )…

0:007:x86> dp 000000007efaf000 l3
7efaf000  05baef28 05bb0000 05b95000

or use WOW64 extension for this purpose:

0:007:x86> !wow64exts.info

PEB32: 0x7efde000
PEB64: 0x7efdf000

Wow64 information for current thread:

TEB32: 0×7efaf000
TEB64: 0×7efad000

32 bit, StackBase   : 0×5bb0000
        StackLimit  : 0×5b95000

        Deallocation: 0×5ab0000

64 bit, StackBase   : 0x30ffd20
        StackLimit  : 0x30f8000
        Deallocation: 0x30c0000
Wow64 TLS slots:

WOW64_TLS_STACKPTR64:       0x0000000000000000
WOW64_TLS_CPURESERVED:      0x00000000030ffd20
WOW64_TLS_INCPUSIMULATION:  0x0000000000000000
WOW64_TLS_LOCALTHREADHEAP:  0x0000000000000000
WOW64_TLS_EXCEPTIONADDR:    0x000000007757f328
WOW64_TLS_USERCALLBACKDATA: 0x0000000000000000
WOW64_TLS_EXTENDED_FLOAT:   0x0000000000000000
WOW64_TLS_APCLIST:          0x0000000000000000
WOW64_TLS_FILESYSREDIR:     0x0000000000000000
WOW64_TLS_LASTWOWCALL:      0x0000000000000000
WOW64_TLS_WOW64INFO:        0x000000007efde238

In case these methods don’t work and we want to quickly inspect raw memory around the current ESP value we can still use dps esp-xxx esp+xxx command, where xxx is some offset:

0:007:x86> dps esp-10 esp+10
05baee90  00000000
05baee94  00000000
05baee98  00000000
05baee9c  77e90bc5 ntdll_77e70000!NtWaitForMultipleObjects+0x15
05baeea0  7756e91a kernel32!WaitForMultipleObjectsEx+0x11d
05baeea4  00000002
05baeea8  05baeeec
05baeeac  00000001
05baeeb0  00000000

Remember that dp and dps are better to use here than dd, dds or dq, dqs: they automatically take into account the pointer size, 32-bit in x86 mode and 64-bit in native mode:

0:007:x86> .effmach amd64
Effective machine: x64 (AMD64)

0:007> dps esp-10 esp+10
00000000`030fee28  00000000`006d0008
00000000`030fee30  00000000`030ffd20
00000000`030fee38  00000000`7efad000
00000000`030fee40  00000000`00003da8
00000000`030fee48  00000000`75ec3688 wow64cpu!ServiceNoTurbo+0x28

- Dmitry Vostokov @ DumpAnalysis.org -

Hunting for a Driver

July 6th, 2009

Consider this redirector file system exception while servicing a page fault:

1: kd> k 100
ChildEBP RetAddr 
afa8b2d4 f53442c4 nt!KeBugCheckEx+0x1b
afa8b2fc f533df48 rdbss!RxExceptionFilter+0xf0
afa8b308 8083a93d rdbss!RxFsdCommonDispatch+0×3ca
afa8b330 8083a498 nt!_except_handler3+0×61
afa8b354 8083a46a nt!ExecuteHandler2+0×26
afa8b404 80816479 nt!ExecuteHandler+0×24
afa8b7bc 808346c4 nt!KiDispatchException+0×131
afa8b824 80834678 nt!CommonDispatchException+0×4a

afa8b848 808401e9 nt!KiExceptionExit+0×186
afa8b8ac f5345d44 nt!IopAllocateIrpPrivate+0xa3
afa8b8f8 f534619c rdbss!RxShadowIoHandler+0xac
afa8b924 f534adb3 rdbss!RxShadowLowIo+0×1a1
afa8b94c f5350fa7 rdbss!RxLowIoSubmit+0×182
afa8b970 f5350dbd rdbss!RxLowIoReadShell+0×7d
afa8ba1c f533d8d9 rdbss!RxCommonRead+0×416
afa8baac f534b9a2 rdbss!RxFsdCommonDispatch+0×320
afa8bacc f52c9a63 rdbss!RxFsdDispatch+0xd3
afa8baec 80840153 mrxsmb!MRxSmbFsdDispatch+0×134
afa8bb00 f71dcc45 nt!IofCallDriver+0×45
afa8bb28 80840153 fltmgr!FltpDispatch+0×6f
afa8bb3c f421576a nt!IofCallDriver+0×45
afa8bb4c f4212621 DriverA!Dispatch+0xa4
afa8bb58 80840153 DriverA!Interface_dispatch+0×53

afa8bb6c f5251aef nt!IofCallDriver+0×45
afa8bb9c f5251bd2 DriverB!PassThrough+0×115
afa8bba8 80840153 DriverB!Dispatch+0×78

afa8bbbc f281ac29 nt!IofCallDriver+0×45
WARNING: Stack unwind information not available. Following frames may be wrong.
afa8bbdc 8082784f DriverC+0×5c29
afa8bc14 80840153 nt!MiResolveMappedFileFault+0×640
afa8bc28 f780f42a nt!IofCallDriver+0×45
afa8bc40 80840153 DriverD+0×42a
afa8bc54 80824b6f nt!IofCallDriver+0×45
afa8bc6c 8082645c nt!IoPageRead+0×109
afa8bcf0 80847650 nt!MiDispatchFault+0xd74
afa8bd4c 80836c2a nt!MmAccessFault+0×9c2

afa8bd4c 77df4749 nt!KiTrap0E+0xdc
0012f568 00000000 0×77df4749

We see that DriverA and DriverB are possibly pass-through and have little influence. For DriverC and DriverD we don’t even have symbol files but they are even further down the stack. Default analysis points to the code that tries to call another driver:

1: kd> !analyze -v
[...]
RDR_FILE_SYSTEM (27)
    If you see RxExceptionFilter on the stack then the 2nd and 3rd parameters are the exception record and context record. Do a .cxr on the 3rd parameter and then kb to obtain a more informative stack trace. The high 16 bits of the first parameter is the RDBSS bugcheck code, which is defined as follows:
     RDBSS_BUG_CHECK_CACHESUP  = 0xca550000,
     RDBSS_BUG_CHECK_CLEANUP   = 0xc1ee0000,
     RDBSS_BUG_CHECK_CLOSE     = 0xc10e0000,
     RDBSS_BUG_CHECK_NTEXCEPT  = 0xbaad0000,
Arguments:
Arg1: baad0080
Arg2: afa8b7d8
Arg3: afa8b4d4
Arg4: 8084014f

EXCEPTION_RECORD:  afa8b7d8 -- (.exr 0xffffffffafa8b7d8)
ExceptionAddress: 8084014f (nt!IofCallDriver+0×00000041)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000000
   Parameter[1]: 00000044
Attempt to read from address 00000044

CONTEXT:  afa8b4d4 -- (.cxr 0xffffffffafa8b4d4)
eax=00000003 ebx=00000000 ecx=86a62ed8 edx=861e0468 esi=00000000 edi=87083970
eip=8084014f esp=afa8b8a0 ebp=afa8b8ac iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000  efl=00010286
nt!IofCallDriver+0×41:
8084014f ff548638        call    dword ptr [esi+eax*4+38h] ds:0023:00000044=????????

STACK_TEXT: 
afa8b8ac f5345d44 86997a50 87083970 86863604 nt!IofCallDriver+0×41
afa8b8f8 f534619c 87083970 868634e0 e36c7ad8 rdbss!RxShadowIoHandler+0xac
afa8b924 f534adb3 87083970 868634e0 e36c7ad8 rdbss!RxShadowLowIo+0×1a1
afa8b94c f5350fa7 01083970 868634e0 e36c7ad8 rdbss!RxLowIoSubmit+0×182
afa8b970 f5350dbd 87083970 868634e0 e36c7ad8 rdbss!RxLowIoReadShell+0×7d
afa8ba1c f533d8d9 87083970 868634e0 88b56910 rdbss!RxCommonRead+0×416
afa8baac f534b9a2 f5348028 868634e0 88b56910 rdbss!RxFsdCommonDispatch+0×320
afa8bacc f52c9a63 88964768 868634e0 88d6c020 rdbss!RxFsdDispatch+0xd3
afa8baec 80840153 00000000 018634e0 88f372b8 mrxsmb!MRxSmbFsdDispatch+0×134
afa8bb00 f71dcc45 88f372b8 86863628 8843d418 nt!IofCallDriver+0×45
afa8bb28 80840153 88d6c020 868634e0 868634e0 fltmgr!FltpDispatch+0×6f
afa8bb3c f421576a 00000000 88ad73f0 afa8bb6c nt!IofCallDriver+0×45
afa8bb4c f4212621 88d1ea98 868634e0 80840153 DriverA!Dispatch+0xa4
afa8bb58 80840153 88d1ea98 868634e0 88ada7f8 DriverA!Interface_dispatch+0×53
afa8bb6c f5251aef 86863604 88438a78 00000000 nt!IofCallDriver+0×45
afa8bb9c f5251bd2 88ada7f8 868634e0 80840153 DriverB!PassThrough+0×115
afa8bba8 80840153 88ada7f8 868634e0 88b3a0d8 DriverB!Dispatch+0×78
afa8bbbc f281ac29 00000000 87780ca0 afa8bc14 nt!IofCallDriver+0×45
WARNING: Stack unwind information not available. Following frames may be wrong.
afa8bbdc 8082784f 88b3a0d8 81f2afa4 88ab83d8 DriverC+0×5c29
afa8bc14 80840153 88b3a020 868634e0 88433760 nt!MiResolveMappedFileFault+0×640
afa8bc28 f780f42a 8762cf38 f7811f2f 884336a8 nt!IofCallDriver+0×45
afa8bc40 80840153 884336a8 868634e0 868634e0 DriverD+0×42a
afa8bc54 80824b6f 88ab83e8 86e0e438 88ab83d8 nt!IofCallDriver+0×45
afa8bc6c 8082645c 88b56906 88ab8410 88ab83f0 nt!IoPageRead+0×109
afa8bcf0 80847650 00000000 01fc897c c0007f20 nt!MiDispatchFault+0xd74
afa8bd4c 80836c2a 00000000 01fc897c 00000001 nt!MmAccessFault+0×9c2
afa8bd4c 77df4749 00000000 01fc897c 00000001 nt!KiTrap0E+0xdc
0012f568 00000000 00000000 00000000 00000000 0×77df4749

We assume that IofCallDriver has the same parameters as IoCallDriver but they were not passed on the stack. They are passed via ECX and EDX registers:

1: kd> !devobj 86997a50
86997a50: is not a device object

1: kd> !irp 87083970
IRP signature does not match, probably not an IRP

3: kd> .asm no_code_bytes
Assembly options: no_code_bytes

1: kd> ub f5345d44
rdbss!RxShadowIoHandler+0×8d:
f5345d25 mov     dword ptr [ebp-4],ebx
f5345d28 call    dword ptr [rdbss!_imp__IoGetTopLevelIrp (f534711c)]
f5345d2e mov     dword ptr [ebp-20h],eax
f5345d31 push    ebx
f5345d32 call    dword ptr [rdbss!_imp__IoSetTopLevelIrp (f5347120)]
f5345d38 mov     edx,dword ptr [ebp-24h]
f5345d3b mov     ecx,dword ptr [ebp-28h]

f5345d3e call    dword ptr [rdbss!_imp_IofCallDriver (f5347204)]

We have the value of EBP at the time of the crash at IofCallDriver+0×41 so we need to see how it had changed:

1: kd> uf nt!IofCallDriver
Flow analysis was incomplete, some code may be missing
nt!IofCallDriver:
8084011b mov     edi,edi
8084011d push    ebp
8084011e mov     ebp,esp
80840120 mov     eax,dword ptr [nt!pIofCallDriver (808a5000)]
80840125 test    eax,eax
80840127 jne     nt!IofCallDriver+0xe (80859d6b)

nt!IofCallDriver+0x15:
8084012d dec     byte ptr [edx+23h]
80840130 cmp     byte ptr [edx+23h],0
80840134 jle     nt!IofCallDriver+0x1e (80859d72)

nt!IofCallDriver+0x2c:
8084013a mov     eax,dword ptr [edx+60h]
8084013d sub     eax,24h
80840140 push    esi
80840141 mov     dword ptr [edx+60h],eax
80840144 mov     dword ptr [eax+14h],ecx
80840147 movzx   eax,byte ptr [eax]
8084014a mov     esi,dword ptr [ecx+8]
8084014d push    edx
8084014e push    ecx
8084014f call    dword ptr [esi+eax*4+38h]
80840153 pop     esi
80840154 pop     ebp
80840155 ret

nt!IofCallDriver+0xe:
80859d6b push    dword ptr [ebp+4]
80859d6e call    eax
80859d70 pop     ebp
80859d71 ret

nt!IofCallDriver+0x1e:
80859d72 push    0
80859d74 push    0
80859d76 push    0
80859d78 push    edx
80859d79 push    35h
80859d7b call    nt!KeBugCheckEx (8087c485)
80859d80 int     3
80859d81 pop     ebp
80859d82 jmp     eax

We see the standard prolog and therefore EBP points to the old EBP from RxShadowIoHandler:

1: kd> dp ebp l1
afa8b8ac  afa8b8f8

We have the value of the pointer to a device object, which is invalid:

1: kd> dp afa8b8f8-28 l1
afa8b8d0  86a62ed8

1: kd> !devobj 86a62ed8
86a62ed8: is not a device object

and the value of the pointer to an IRP which is valid:

1: kd> dp afa8b8f8-24 l1
afa8b8d4  861e0468

1: kd> !irp 861e0468
Irp is active with 4 stacks 4 is current (= 0x861e0544)
 Mdl=88ab8410: No System Buffer: Thread 8846e020:  Irp stack trace. 
     cmd  flg cl Device   File     Completion-Context
 [  0, 0]   0  0 00000000 00000000 00000000-00000000   

   Args: 00000000 00000000 00000000 00000000
 [  0, 0]   0  0 00000000 00000000 00000000-00000000   

   Args: 00000000 00000000 00000000 00000000
 [  0, 0]   0  0 00000000 00000000 00000000-00000000   

   Args: 00000000 00000000 00000000 00000000
>[  3, 0]   0 e0 86a62ed8 86ff7028 f5345bdc-87083970 Success Error Cancel
       86a62ed8: is not a device object
 rdbss!RxShadowIrpCompletion
   Args: 00008000 00000000 00008000 00000000

From the full disassembly code of IofCallDriver we see that ECX and EDX values had not been changed so we could get our parameters from them too.

Device object is invalid in IRP too and it points to a NULL driver object:

1: kd> dt _DEVICE_OBJECT 86a62ed8
nt!_DEVICE_OBJECT
   +0×000 Type             : 0
   +0×002 Size             : 0
   +0×004 ReferenceCount   : 0
   +0×008 DriverObject     : (null)
   +0×00c NextDevice       : (null)
   +0×010 AttachedDevice   : (null)
   +0×014 CurrentIrp       : (null)
   +0×018 Timer            : (null)
   +0×01c Flags            : 0
   +0×020 Characteristics  : 0
   +0×024 Vpb              : 0×00040000 _VPB
   +0×028 DeviceExtension  : (null)
   +0×02c DeviceType       : 0×86a62f04
   +0×030 StackSize        : 4 ”
   +0×034 Queue            : __unnamed
   +0×05c AlignmentRequirement : 0
   +0×060 DeviceQueue      : _KDEVICE_QUEUE
   +0×074 Dpc              : _KDPC
   +0×094 ActiveThreadCount : 0
   +0×098 SecurityDescriptor : (null)
   +0×09c DeviceLock       : _KEVENT
   +0×0ac SectorSize       : 0
   +0×0ae Spare1           : 0
   +0×0b0 DeviceObjectExtension : 0×86a62f88 _DEVOBJ_EXTENSION
   +0×0b4 Reserved         : 0×86a62f88

IofCallDriver tried to call a function pointer No.3 from the driver major dispatch table:

1: kd> dt _DRIVER_OBJECT
nt!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void
   +0x010 DriverSize       : Uint4B
   +0x014 DriverSection    : Ptr32 Void
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long
   +0x030 DriverStartIo    : Ptr32     void
   +0x034 DriverUnload     : Ptr32     void
   +0×038 MajorFunction    : [28] Ptr32     long

The resulted effective address is a NULL code pointer (EAX=3, major code and ESI is NULL):

call    dword ptr [esi+eax*4+38h] ds:0023:00000044=????????

Now we come back to our IRP to examine a file object:

     cmd  flg cl Device   File     Completion-Context
>[  3, 0]   0 e0 86a62ed8 86ff7028 f5345bdc-87083970 Success Error Cancel

1: kd> !fileobj 86ff7028

\Userdata\[…]\Application Suite\ApplicationSuite.RUS

Device Object: 0×87300aa8   \Driver\DriverE
Vpb: 0×8843b280
Event signalled
Access: Read SharedRead SharedDelete

Flags:  0x18c0040
 Cache Supported
 Handle Created
 Fast IO Read
 Remote Origin

FsContext: 0xe453fda0 FsContext2: 0xe26904b8
CurrentByteOffset: 0
Cache Data:
  Section Object Pointers: 86b80a9c
  Shared Cache Map: 00000000

Here we see another DriverE and associated drivers from its device stack:

1: kd> !devstack 0×87300aa8
  !DevObj   !DrvObj            !DevExt   ObjectName
  865f9cc8  \Driver\DriverF   865f9d80 
  8737aaf0  \Driver\DriverG    8737aba8 
  87155280  \Driver\DriverH    87155338 
> 87300aa8  \Driver\DriverE       87300b60  BlockVolume1
!DevNode 88b6eac0 :
  DeviceInst is “STORAGE\Volume\{[…]}”
  ServiceName is “volsnap”

- Dmitry Vostokov @ DumpAnalysis.org -

Iterative and Incremental Book Reviewing

July 6th, 2009

Finally I adopted the following process for book reviews:

1. Start reading a book.

2. After sometime put an initial reveiw on this blog.

3. Iteratively and incrementally revise it during read. For example, add additional bits as soon as I discover something good or bad worth mentioning in the book review.

4. When the book is finished put its review blog post into a category: From Cover To Cover.

5. Put the review on Amazon and mark this appropriately by putting its blog post into another category: Reviewed on Amazon.

- Dmitry Vostokov @ LiterateScientist.com -

Memorianic Prophecy 0m7

July 5th, 2009

Discipleship is by working with memories.

Memory as religion

- Dmitry Vostokov @ Memory Religion Portal -

Windows Internals Page Framed

July 5th, 2009

Finally I reused component-like frame previously belonged to an MCSD certificate displayed at Programming Research office where I worked 6-7 years ago (books in a row there are all about C++):

Old Frame

Today I dug it from dusty corners of my apartment and inserted a page 1152 snapshot as promised:

- Dmitry Vostokov @ DumpAnalysis.org -

Memorianic Prophecy 0m6

July 5th, 2009

Life heals Memory.

Memory as religion

- Dmitry Vostokov @ Memory Religion Portal -

Dictionary of Debugging: Memory Dump

July 4th, 2009

Memory Dump

A snapshot of memory. Can be sequential (cell by cell) or selective.

References: Memory Dump - A Mathematical Definition

Synonyms: crash dump, core dump.

Antonyms:

Also: user dump, kernel dump, complete dump, full dump, minidump.

- Dmitry Vostokov @ DumpAnalysis.org -

Blocked LPC thread, coupled processes, stack trace collection and blocked GUI thread: pattern cooperation

July 4th, 2009

This small case study continues where Not using checklists common mistake case study left, after identifying the blocked LPC thread in ServiceA process. We know that ServiceA always asks (coupled with) ServiceB and, indeed, when looking at the latter stack trace collection we see a GUI thread showing a dialog box:

0:000> ~13kc

ntdll!KiFastSystemCallRet
USER32!NtUserWaitMessage
USER32!InternalDialogBox
USER32!DialogBoxIndirectParamAorW
USER32!DialogBoxIndirectParamW
comdlg32!NewGetFileName
comdlg32!NewGetSaveFileName
comdlg32!GetFileName
comdlg32!GetSaveFileNameW
WARNING: Stack unwind information not available. Following frames may be wrong.
DllA!DllEntryPoint
ServiceB!Initialize
[…]
ServiceB!ServiceThread
kernel32!BaseThreadStart

From function names we can infer that the thread was displaying a “Save File As” common dialog box but the service was not allowed to interact with a desktop. This made the service blocked and, in return, made ServiceA blocked too. The suggestion was to enable ServiceB to interact with the desktop and keep an eye on DllA.

- Dmitry Vostokov @ DumpAnalysis.org -

Windows Internals 5th Edition

July 4th, 2009

Got it in the post yesterday shipped via courier from Amazon:

Windows® Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (PRO-Developer)

Buy from Amazon

I originally expected it to be a paperback book but as a publisher myself I welcome the final MS Press decision to make it a hardcover. It is more solid. I plan to read it from cover to cover again, starting from tomorrow. I would like to thank authors for including the reference to www.dumpanalysis.org in the conclusion part of the last chapter 14 dedicated to crash dump analysis. This came as a nice surprise for me and I’m going to install a special plaque in the office and put its picture later on my blog.

- Dmitry Vostokov @ DumpAnalysis.org -

RADII and SDSD

July 4th, 2009

Supportability is similar to serviceability and while working on DebugWare book I realized that writing support tools needs its own buzz word like model-driven software design. Hence SDSD acronym was born a few days ago:

SDSD

Supportability-Driven Software Design

or

Support-Driven Software Design

or

Serviceability-Driven Software Design

Thinking about where to insert requirements, architecture and design led me to another acronym:

RADII

Requirements, Architecture, Design, Implementation and Improvement

The plural form of radius signifies the fact that there is a plurality of ways how SDLC can be implemented. Improvement is similar to Maintenance.

- Dmitry Vostokov @ DumpAnalysis.org -

Naming Infinity

July 3rd, 2009

I read this book from cover to cover while flying on a plane from Dublin to St. Petersburg and back. That was so wonderful reading experience - I couldn’t put the book down during those flights. I recall that I visited the Department of Mathematics a few times when I studied Chemistry in Moscow State University although at that time I knew next to nothing about Russian mathematicians. The book touched me so deeply that I bought the main work of Florensky: The Pillar and Ground of the Truth, the history of Russian philosophy and several books explaining Orthodox Church. This is the best mathematics history book I have ever read, my feelings perhaps comparable to those that I experienced when I finished reading Mathematics: The Loss of Certainty by Morris Kline but that was more than 20 years ago.

Naming Infinity: A True Story of Religious Mysticism and Mathematical Creativity

Buy from Amazon

- Dmitry Vostokov @ LiterateScientist.com -

10 Common Mistakes in Memory Analysis (Part 4)

July 3rd, 2009

One of the common mistakes that I observe is to habitually stick to certain WinDbg commands to recognize patterns. One example is !locks command used to find out any wait chains and deadlock conditions among threads. Recently a service process was reported to be hang and !locks command showed no blocked threads:

0:000> !locks
CritSec +18caf94 at 018CAF94
LockCount          -2
RecursionCount     1
OwningThread       58e8
EntryCount         0
ContentionCount    0
*** Locked

CritSec +18cc7c4 at 018CC7C4
LockCount          -2
RecursionCount     1
OwningThread       58e8
EntryCount         0
ContentionCount    0
*** Locked

The number of threads waiting for the lock is 0 (this calculation is explained in the MSDN article): 

0:000> ? ((-1) - (-2)) >> 2
Evaluate expression: 0 = 00000000

In the past, for that hang sevice memory dumps, !locks command always showed LockCount values corresponding to several waiting threads. Therefore, an engineer assumed that the dump was taken at some random time, not at the time the service was hanging, and asked for a new right dump. The mistake here is that the engineer didn’t look at the corresponding thread stack trace that shows the characteristic pattern of the blocked thread waiting for a reply from an LRPC call:

0:000> ~~[58e8]kc 100

ntdll!KiFastSystemCallRet
ntdll!NtRequestWaitReplyPort
RPCRT4!LRPC_CCALL::SendReceive
RPCRT4!I_RpcSendReceive
RPCRT4!NdrSendReceive
RPCRT4!NdrClientCall2

ServiceA!foo
[…]
ServiceA!bar
RPCRT4!NdrStubCall2
RPCRT4!NdrServerCall2
RPCRT4!DispatchToStubInCNoAvrf
RPCRT4!RPC_INTERFACE::DispatchToStubWorker
RPCRT4!RPC_INTERFACE::DispatchToStub
RPCRT4!RPC_INTERFACE::DispatchToStubWithObject
RPCRT4!LRPC_SCALL::DealWithRequestMessage
RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest
RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls
RPCRT4!RecvLotsaCallsWrapper
RPCRT4!BaseCachedThreadRoutine
RPCRT4!ThreadStartRoutine
kernel32!BaseThreadStart

We don’t see other blocked threads and wait chains because the dump was saved as soon as the freezing condition was detected: the service didn’t allow a user connection to proceed. If more users tried to connect we would have seen critical section wait chains that are absent in this dump.

To prevent such mistakes checklists are indispensable. For one example, see Crash Dump Analysis Checklist. You can also order it in print:

WinDbg: A Reference Poster and Learning Cards

- Dmitry Vostokov @ DumpAnalysis.org -

Overcoming Resistance

July 3rd, 2009

A picture taken during my recent visit to Peterhof (one of the 7 wonders of Russia):

- Dmitry Vostokov @ DumpAnalysis.org -

LiterateScientist update (June, 2009)

June 26th, 2009

Monthly summary of my Literate Scientist blog:

Philosophy: The Basics 

Stalin: The Court of the Red Tsar

A History of Russia

Religion: The Basics

- Dmitry Vostokov @ DumpAnalysis.org -

ManagementBits update (May - June, 2009)

June 25th, 2009

Monthly summary of my Management Bits and Tips blog:

Local Workplace Guides

On Management Amnesia

Hidden Transcripts

Management Bit and Tip 0×8000

Downfloored or Upfloored? 

- Dmitry Vostokov @ DumpAnalysis.org -