Stack trace, invalid code pointer and hooked functions: pattern cooperation
When looking at a stack trace of one crashed process we noticed an invalid code pointer. It is not a NULL code pointer but has the same stack trace pattern:
0:000> kL
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
0013dfb4 00401791 0×5e388583
0013fdf4 0040189f Application!RequestData+0×3e1
0013fee4 00401d0a Application!main+0×3f
0013ffc0 77e4f23b Application!mainCRTStartup+0×16c
0013fff0 00000000 kernel32!BaseProcessStart+0×23
When we look at raw stack data and examine the backward disassembly of the return address we see that invalid code was called from RequestData function and WinDbg stack trace reconstruction is not suspicious (it is structurally and semantically correct):
0:000> dds esp l10
0013dfb8 00401791 Application!RequestData+0x3e1
0013dfbc 00000140
0013dfc0 0013ee50
0013dfc4 00000fa4
0013dfc8 00000000
0013dfcc 00000000
0013dfd0 00000ece
0013dfd4 0013ffc0
0013dfd8 7ffdc000
0013dfdc 00000140
0013dfe0 0000054c
0013dfe4 50000002
0013dfe8 4b4919ac
0013dfec 00000000
0013dff0 00000000
0013dff4 003f003c
0:000> .asm no_code_bytes
Assembly options: no_code_bytes
0:000> ub 00401791
Application!RequestData+0x3c8:
00401778 Application!RequestData+0x3d0 (00401780)
0040177a lea ebx,[ebx]
00401780 push 0
00401782 push eax
00401783 lea ecx,[esp+esi+0E30h]
0040178a push ecx
0040178b push edi
0040178c call Application!recv (0040e382)
When seeing recv call we might suspect that the crash happened just inside that function because the raw stack data upwards (lower addresses) doesn’t have any execution residue left from nested function calls:
0:000> dds esp-100 esp
0013deb8 00000000
0013debc 00000000
0013dec0 00000000
0013dec4 00000000
0013dec8 00000000
0013decc 00000000
0013ded0 00000000
0013ded4 00000000
0013ded8 00000000
0013dedc 00000000
0013dee0 00000000
0013dee4 00000000
0013dee8 00000000
0013deec 00000000
0013def0 00000000
0013def4 00000000
0013def8 00000000
0013defc 00000000
0013df00 00000000
0013df04 00000000
0013df08 00000000
0013df0c 00000000
0013df10 00000000
0013df14 00000000
0013df18 00000000
0013df1c 00000000
0013df20 00000000
0013df24 00000000
0013df28 00000000
0013df2c 00000000
0013df30 00000000
0013df34 00000000
0013df38 00000000
0013df3c 00000000
0013df40 00000000
0013df44 00000000
0013df48 00000000
0013df4c 00000000
0013df50 00000000
0013df54 00000000
0013df58 00000000
0013df5c 00000000
0013df60 00000000
0013df64 00000000
0013df68 00000000
0013df6c 00000000
0013df70 00000000
0013df74 00000000
0013df78 00000000
0013df7c 00000000
0013df80 00000000
0013df84 00000000
0013df88 00000000
0013df8c 00000000
0013df90 00000000
0013df94 00000000
0013df98 00000000
0013df9c 00000000
0013dfa0 00000000
0013dfa4 00000000
0013dfa8 00000000
0013dfac 00000000
0013dfb0 00000000
0013dfb4 00000000
0013dfb8 00401791 Application!RequestData+0x3e1
So we follow recv call forward disassembly (notice that the first jump is indirect):
0:000> u 0040e382
Application!recv:
0040e382 jmp dword ptr [Application!_imp__recv (00410180)]
Application!closesocket:
0040e388 jmp dword ptr [Application!_imp__closesocket (00410170)]
Application!WSAGetLastError:
0040e38e jmp dword ptr [Application!_imp__WSAGetLastError (00410174)]
Application!send:
0040e394 jmp dword ptr [Application!_imp__send (00410178)]
Application!connect:
0040e39a jmp dword ptr [Application!_imp__connect (0041017c)]
Application!htons:
0040e3a0 jmp dword ptr [Application!_imp__htons (00410198)]
Application!setsockopt:
0040e3a6 jmp dword ptr [Application!_imp__setsockopt (00410184)]
Application!socket:
0040e3ac jmp dword ptr [Application!_imp__socket (00410188)]
0:000> dps 00410180 l10
00410180 71ad2f7f ws2_32!recv
00410184 71ad2d47 ws2_32!setsockopt
00410188 71ad410c ws2_32!socket
0041018c 71ad7ca1 ws2_32!gethostbyname
00410190 71ad4f3b ws2_32!WSAStartup
00410194 71ad7b5b ws2_32!gethostname
00410198 71ad28bc ws2_32!htons
0041019c 71ad3da8 ws2_32!WSACleanup
004101a0 00000000
004101a4 00000000
004101a8 00000000
004101ac 00000000
004101b0 00000000
004101b4 45cd184e
004101b8 00000000
004101bc 00000002
0:000> u 71ad2f7f
ws2_32!recv:
71ad2f7f jmp 7fd60000
71ad2f84 sub esp,10h
71ad2f87 push ebx
71ad2f88 xor ebx,ebx
71ad2f8a cmp dword ptr [ws2_32!PrologPointer (71ae4044)],offset ws2_32!Prolog_v2 (71ad6067)
71ad2f94 push esi
71ad2f95 je ws2_32!recv+0×18 (71ad6207)
71ad2f9b lea eax,[ebp-8]
0:000> u 7fd60000
7fd60000 jmp DllA!recv_patch (612101b6)
7fd60005 mov edi,edi
7fd60007 push ebp
7fd60008 mov ebp,esp
7fd6000a jmp ws2_32!recv+0×5 (71ad2f84)
7fd6000f add byte ptr [eax],al
7fd60011 add byte ptr [eax],al
7fd60013 add byte ptr [eax],al
Finally we see that sockets library functions were patched by a 3rd-party module DllA and we need to contact its vendor.
- Dmitry Vostokov @ DumpAnalysis.org -
May 13th, 2009 at 4:38 pm
Hi Dimitry:
I read your feeds in Google reader and the code snippets you show are not visible clearly. Can you pls.correct this. In order to read your feed i have to open your post in a separate browser window.
-Suren
May 13th, 2009 at 5:01 pm
I use this HTML code for my code snippets:
<p align=”left”><font size=”1″><code>
// code
</code></font>
What do you suggest? I cannot increase the font size because it will not fit in Wordpress-generated window.