Crash Dump Analysis Patterns (Part 56)

The case when a function pointer or a return address becomes a Wild Pointer and EIP or RIP value lies in a valid region of memory the execution path may continue through a region called Wild Code. This might loop on itself or eventually reach non-executable or invalid pages and produce an exception. Local Buffer Overflow might lead to this behavior and also data corruption that overwrites function pointers with valid memory addresses.

My favorite example is when a function pointer points to zeroed pages with EXECUTE page attribute. What will happen next when we dereference it? All zeroes are perfect x86/x64 code:

0:001> dd 0000000`771afdf0
00000000`771afdf0  00000000 00000000 00000000 00000000
00000000`771afe00  00000000 00000000 00000000 00000000
00000000`771afe10  00000000 00000000 00000000 00000000
00000000`771afe20  00000000 00000000 00000000 00000000
00000000`771afe30  00000000 00000000 00000000 00000000
00000000`771afe40  00000000 00000000 00000000 00000000
00000000`771afe50  00000000 00000000 00000000 00000000
00000000`771afe60  00000000 00000000 00000000 00000000

0:001> u
ntdll!DbgUserBreakPoint:
00000000`771afe00 0000    add     byte ptr [rax],al
00000000`771afe02 0000    add     byte ptr [rax],al
00000000`771afe04 0000    add     byte ptr [rax],al
00000000`771afe06 0000    add     byte ptr [rax],al
00000000`771afe08 0000    add     byte ptr [rax],al
00000000`771afe0a 0000    add     byte ptr [rax],al
00000000`771afe0c 0000    add     byte ptr [rax],al
00000000`771afe0e 0000    add     byte ptr [rax],al

Now if RAX points to a valid memory page with WRITE attribute the code will modify the first byte at that address:

0:001> dq @rax
000007ff`fffdc000 00000000`00000000 00000000`035a0000
000007ff`fffdc010 00000000`0359c000 00000000`00000000
000007ff`fffdc020 00000000`00001e00 00000000`00000000
000007ff`fffdc030 000007ff`fffdc000 00000000`00000000
000007ff`fffdc040 00000000`0000142c 00000000`00001504
000007ff`fffdc050 00000000`00000000 00000000`00000000
000007ff`fffdc060 000007ff`fffd8000 00000000`00000000
000007ff`fffdc070 00000000`00000000 00000000`00000000

Therefore the code will be perfectly executed:

0:001> t
ntdll!DbgBreakPoint+0x2:
00000000`771afdf2 0000    add     byte ptr [rax],al ds:000007ff`fffdc000=00

0:001> t
ntdll!DbgBreakPoint+0x4:
00000000`771afdf4 0000    add     byte ptr [rax],al ds:000007ff`fffdc000=00

0:001> t
ntdll!DbgBreakPoint+0x6:
00000000`771afdf6 0000    add     byte ptr [rax],al ds:000007ff`fffdc000=00

0:001> t
ntdll!DbgBreakPoint+0x8:
00000000`771afdf8 0000    add     byte ptr [rax],al ds:000007ff`fffdc000=00

0:001> t
ntdll!DbgBreakPoint+0xa:
00000000`771afdfa 0000    add     byte ptr [rax],al ds:000007ff`fffdc000=00

- Dmitry Vostokov @ DumpAnalysis.org -

4 Responses to “Crash Dump Analysis Patterns (Part 56)”

  1. Crash Dump Analysis » Blog Archive » Crash Dump Analysis Patterns (Part 66) Says:

    […] provided specific recommendation hints. When looking at the crash point we see an instance of Wild Code […]

  2. Crash Dump Analysis » Blog Archive » Crash Dump Analysis Patterns (Part 84) Says:

    […] the assembly code looks almost wild (not like generated by your favourite compiler). For example (that also shows .NET runtime native […]

  3. Crash Dump Analysis » Blog Archive » Wild code and partial stack reconstruction Says:

    […] recently got a chance to see an instance of Wild Code pattern in kernel […]

  4. Dmitry Vostokov Says:

    Sometimes

    0:000> k
    ChildEBP RetAddr
    03ced1b0 771d6aec ntdll!KiFastSystemCallRet
    03ced1b4 75406a8e ntdll!NtWaitForMultipleObjects+0xc
    03ced250 7734be76 KERNELBASE!WaitForMultipleObjectsEx+0x100
    03ced298 7734bee4 kernel32!WaitForMultipleObjectsExImplementation+0xe0
    03ced2b4 7736072f kernel32!WaitForMultipleObjects+0x18
    03ced320 773609ca kernel32!WerpReportFaultInternal+0x186
    03ced334 77360978 kernel32!WerpReportFault+0x70
    03ced344 773608f3 kernel32!BasepReportFault+0x20
    03ced3d0 7720820a kernel32!UnhandledExceptionFilter+0x1af
    03ced3d8 771ae364 ntdll!__RtlUserThreadStart+0x62
    03ced3ec 771ae1fc ntdll!_EH4_CallFilterFunc+0x12
    03ced414 771d72b9 ntdll!_except_handler4+0x8e
    03ced438 771d728b ntdll!ExecuteHandler2+0x26
    03ced45c 771af9d7 ntdll!ExecuteHandler+0x24
    03ced4e8 771d7117 ntdll!RtlDispatchException+0x127
    03ced4e8 63050001 ntdll!KiUserExceptionDispatcher+0xf
    03ceda64 771e73e2 ModuleA!FunctionA+0xc1
    03ceda84 0141b848 ntdll!_SEH_epilog4_GS+0xa
    03cedcb4 767cbbf4 ModuleB!FunctionB+0x188
    03cedcc8 767cbcb5 gdi32!NtGdiOpenDCW+0xc
    03cedf70 013bc7df gdi32!hdcCreateDCW+0x517
    03cee0c8 7734c413 ModuleB!FunctionC+0xff
    03cee0e0 7734c3c2 kernel32!WaitForSingleObjectExImplementation+0x75
    03cee0f4 65e66c9c kernel32!WaitForSingleObject+0x12
    WARNING: Frame IP not in any known module. Following frames may be wrong.
    00000000 00000000 0x65e66c9c

    We see Incorrect Stack Trace pattern since it doesn’t make sense that waiting functions call GDI and other modules. Also the return address for ModuleA!FunctionA looks coincidental: 63050001. Although we are able to see code we are not able to disassemble it backwards:

    0:000> u 63050001
    ModuleA!FunctionA+0xc1:
    63050001 a1056383c4 mov eax,dword ptr ds:[C4836305h]
    63050006 108d4c241051 adc byte ptr [ebp+5110244Ch],cl
    6305000c ff15b4a00563 call dword ptr [ModuleA!_imp__OutputDebugStringA (6305a0b4)]
    63050012 8b4e14 mov ecx,dword ptr [esi+14h]
    63050015 85c9 test ecx,ecx
    63050017 740e je ModuleA!FunctionA+0xe7 (63050027)
    63050019 8b11 mov edx,dword ptr [ecx]
    6305001b 8b4204 mov eax,dword ptr [edx+4]

    0:000> ub 63050001
    ^ Unable to find valid previous instruction for 'ub 63050001'

    0:000> ub 63050001-1
    ^ Unable to find valid previous instruction for 'ub 63050001-1'

    0:000> ub 63050001-2
    ^ Unable to find valid previous instruction for 'ub 63050001-2'

    0:000> ub 63050001-3
    ModuleA!FunctionA+0xa4:
    6304ffe4 ffd2 call edx
    6304ffe6 84c0 test al,al
    6304ffe8 7541 jne ModuleA!FunctionA+0xeb (6305002b)
    6304ffea 6818c20563 push offset ModuleA!`string' (6305c218)
    6304ffef 68bcc10563 push offset ModuleA!`string' (6305c1bc)
    6304fff4 8d442418 lea eax,[esp+18h]
    6304fff8 6800010000 push 100h
    6304fffd 50 push eax

Leave a Reply

You must be logged in to post a comment.