Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
转储分析
明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
qiliu3
2014-02-14, 15:39 下午
windbg分析结果为SOFTWARE_NX_FAULT,我知道这是堆栈越界,执行到数据区的代码导致的
堆栈如下:
15b2f03c 559a568f 2ea4344c 2ebb1e80 00000000 0x33c9256c
15b2f078 76b5b57d 2ebb1eb0 15b2f0b0 15b2f0ac XXXXXXXXXX!std::_Tree<std::_Tmap_traits<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,_LoadwayInfo,std::less<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >,std::allocator<std::pair<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > const ,_LoadwayInfo> >,0> >::erase+0x20
//XXXXXXXXXXXX是我们自己的模块,也是这个堆栈中唯一存在与我们相关的一项
15b2f0a4 76b5b4a9 2ebb1e80 2e9c7248 76c77430 ole32!CStdMarshal::ConnectSrvIPIDEntry+0x26 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1989]
15b2f0e4 76b52a18 17f24a5c 00000005 00000000 ole32!CStdMarshal::MarshalServerIPID+0x78 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1146]
15b2f154 753c592c 08e610b0 17f24a40 00000005 ole32!CRemoteUnknown::RemQueryInterface+0x17c [d:\w7rtm\com\ole32\com\dcomrem\remoteu.cxx @ 421]
15b2f180 754405f1 76b528f0 15b2f368 00000006 rpcrt4!Invoke+0x2a
15b2f584 76c6d7e6 08eec8f0 08eee810 17ee6158 rpcrt4!NdrStubCall2+0x2ea
15b2f5cc 76c6d876 08eec8f0 17ee6158 08eee810 ole32!CStdStubBuffer_Invoke+0xb6 [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1590]
15b2f614 76c6ddd0 17ee6158 08e40390 00000000 ole32!SyncStubInvoke+0x3c [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
15b2f660 76b88a43 17ee6158 08e94d88 08eec8f0 ole32!StubInvoke+0xb9 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
15b2f73c 76b88938 08eee810 00000000 08eec8f0 ole32!CCtxComChnl::ContextInvoke+0xfa [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
15b2f758 76c6a44c 17ee6158 00000001 08eec8f0 ole32!MTAInvoke+0x1a [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 2105]
15b2f788 76c6db41 d0908070 08eee810 08eec8f0 ole32!AppInvoke+0xab [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086]
15b2f868 76c6a45c 17ee6100 08eeec20 08e40378 ole32!ComInvokeWithLockAndIPID+0x372 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1724]
15b2f8b4 753c5eba 25b14120 559afb5c 08e40378 ole32!ThreadInvoke+0x302 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751]
15b2f8ec 753c624c 76c6df76 25b14120 15b2f9d0 rpcrt4!DispatchToStubInCNoAvrf+0x46
15b2f944 753c67f5 00000000 00000000 00000000 rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0x141
15b2f968 753c6796 25b14120 00000000 00000000 rpcrt4!RPC_INTERFACE::DispatchToStub+0x90
15b2f9a4 753c66b1 25b14120 25b14184 00000000 rpcrt4!RPC_INTERFACE::DispatchToStubWithObject+0xbc
15b2f9f0 753c65c3 15b2fa08 00000000 17f249b0 rpcrt4!LRPC_SCALL::DispatchRequest+0x214
15b2fa10 753c6581 25b14068 17f249d8 1800d538 rpcrt4!LRPC_SCALL::QueueOrDispatchCall+0xc7
15b2fa2c 753c6425 17f249b0 08e40378 00000000 rpcrt4!LRPC_SCALL::HandleRequest+0x305
15b2fa5c 753c6398 17f249b0 08626d18 00000000 rpcrt4!LRPC_SASSOCIATION::HandleRequest+0x153
15b2fa90 753c4abf 17f249b0 15b2fad0 08626d18 rpcrt4!LRPC_ADDRESS::HandleRequest+0xc4
15b2fb18 753c49ac 00000000 15b2fb34 753c480f rpcrt4!LRPC_ADDRESS::ProcessIO+0x44c
15b2fb24 753c480f 006cd49c 00000000 15b2fb5c rpcrt4!LrpcServerIoHandler+0x16
15b2fb34 77cb47a6 15b2fba0 006cd49c 085744c0 rpcrt4!LrpcIoComplete+0x16
15b2fb5c 77ca345f 15b2fba0 00000000 00000000 ntdll!TppAlpcpExecuteCallback+0x1c5
15b2fcc4 76d4336a 0069d0b0 15b2fd10 77c89f72 ntdll!TppWorkerThread+0x5a4
15b2fcd0 77c89f72 0069d0b0 5c1fa653 00000000 kernel32!BaseThreadInitThunk+0xe
15b2fd10 77c89f45 77ca3e85 0069d0b0 00000000 ntdll!__RtlUserThreadStart+0x70
15b2fd28 00000000 77ca3e85 0069d0b0 00000000 ntdll!_RtlUserThreadStart+0x1b
其中
XXXXXXXXXX!std::_Tree<std::_Tmap_traits<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,_LoadwayInfo,std::less<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >,std::allocator<std::pair<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > const ,_LoadwayInfo> >,0> >::erase+0x20,这个是我们自己的模块,但是后面的方法,某一个map的erase方法,根本没有地方调用过
我反编译XXXXXXX::erase这一行的返回地址
76b5b57d所在的函数,如下:
0:082> u 76b5b57d-0x26 L30
ole32!CStdMarshal::ConnectSrvIPIDEntry [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1978]:
76b5b557 8bff mov edi,edi
76b5b559 55 push ebp
76b5b55a 8bec mov ebp,esp
76b5b55c 51 push ecx
76b5b55d 53 push ebx
76b5b55e 56 push esi
76b5b55f 8b7508 mov esi,dword ptr [ebp+8]
76b5b562 57 push edi
76b5b563 ff750c push dword ptr [ebp+0Ch]
76b5b566 8d45fc lea eax,[ebp-4]
76b5b569 50 push eax
76b5b56a 8d4508 lea eax,[ebp+8]
76b5b56d 50 push eax
76b5b56e 8d450c lea eax,[ebp+0Ch]
76b5b571 50 push eax
76b5b572 8d4630 lea eax,[esi+30h]
76b5b575 50 push eax
76b5b576 8bf9 mov edi,ecx
76b5b578 e818000000 call ole32!CStdMarshal::CreateStub (76b5b595)
//反汇编代码来看,明明掉的是这个,怎么会跑到我们的XXXXXXXX模块的某一个map的erase呢?
76b5b57d 8bd8 mov ebx,eax
76b5b57f 85db test ebx,ebx
76b5b581 0f8d6e020000 jge ole32!CStdMarshal::ConnectSrvIPIDEntry+0x2c (76b5b7f5)
76b5b587 5f pop edi
76b5b588 5e pop esi
76b5b589 8bc3 mov eax,ebx
76b5b58b 5b pop ebx
76b5b58c c9 leave
76b5b58d c20800 ret 8
Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
qiliu3
2014-02-14, 15:40 下午
15b2f03c 559a568f 2ea4344c 2ebb1e80 00000000 0x33c9256c
15b2f078 76b5b57d 2ebb1eb0 15b2f0b0 15b2f0ac XXXXXXXXXX!std::_Tree<std::_Tmap_traits<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,_LoadwayInfo,std::less<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >,std::allocator<std::pair<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > const ,_LoadwayInfo> >,0> >::erase+0x20
15b2f0a4 76b5b4a9 2ebb1e80 2e9c7248 76c77430 ole32!CStdMarshal::ConnectSrvIPIDEntry+0x26 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1989]
15b2f0e4 76b52a18 17f24a5c 00000005 00000000 ole32!CStdMarshal::MarshalServerIPID+0x78 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1146]
15b2f154 753c592c 08e610b0 17f24a40 00000005 ole32!CRemoteUnknown::RemQueryInterface+0x17c [d:\w7rtm\com\ole32\com\dcomrem\remoteu.cxx @ 421]
15b2f180 754405f1 76b528f0 15b2f368 00000006 rpcrt4!Invoke+0x2a
15b2f584 76c6d7e6 08eec8f0 08eee810 17ee6158 rpcrt4!NdrStubCall2+0x2ea
15b2f5cc 76c6d876 08eec8f0 17ee6158 08eee810 ole32!CStdStubBuffer_Invoke+0xb6 [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1590]
15b2f614 76c6ddd0 17ee6158 08e40390 00000000 ole32!SyncStubInvoke+0x3c [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
15b2f660 76b88a43 17ee6158 08e94d88 08eec8f0 ole32!StubInvoke+0xb9 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
15b2f73c 76b88938 08eee810 00000000 08eec8f0 ole32!CCtxComChnl::ContextInvoke+0xfa [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
15b2f758 76c6a44c 17ee6158 00000001 08eec8f0 ole32!MTAInvoke+0x1a [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 2105]
15b2f788 76c6db41 d0908070 08eee810 08eec8f0 ole32!AppInvoke+0xab [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086]
15b2f868 76c6a45c 17ee6100 08eeec20 08e40378 ole32!ComInvokeWithLockAndIPID+0x372 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1724]
15b2f8b4 753c5eba 25b14120 559afb5c 08e40378 ole32!ThreadInvoke+0x302 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751]
15b2f8ec 753c624c 76c6df76 25b14120 15b2f9d0 rpcrt4!DispatchToStubInCNoAvrf+0x46
15b2f944 753c67f5 00000000 00000000 00000000 rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0x141
15b2f968 753c6796 25b14120 00000000 00000000 rpcrt4!RPC_INTERFACE::DispatchToStub+0x90
15b2f9a4 753c66b1 25b14120 25b14184 00000000 rpcrt4!RPC_INTERFACE::DispatchToStubWithObject+0xbc
15b2f9f0 753c65c3 15b2fa08 00000000 17f249b0 rpcrt4!LRPC_SCALL::DispatchRequest+0x214
15b2fa10 753c6581 25b14068 17f249d8 1800d538 rpcrt4!LRPC_SCALL::QueueOrDispatchCall+0xc7
15b2fa2c 753c6425 17f249b0 08e40378 00000000 rpcrt4!LRPC_SCALL::HandleRequest+0x305
15b2fa5c 753c6398 17f249b0 08626d18 00000000 rpcrt4!LRPC_SASSOCIATION::HandleRequest+0x153
15b2fa90 753c4abf 17f249b0 15b2fad0 08626d18 rpcrt4!LRPC_ADDRESS::HandleRequest+0xc4
15b2fb18 753c49ac 00000000 15b2fb34 753c480f rpcrt4!LRPC_ADDRESS::ProcessIO+0x44c
15b2fb24 753c480f 006cd49c 00000000 15b2fb5c rpcrt4!LrpcServerIoHandler+0x16
15b2fb34 77cb47a6 15b2fba0 006cd49c 085744c0 rpcrt4!LrpcIoComplete+0x16
15b2fb5c 77ca345f 15b2fba0 00000000 00000000 ntdll!TppAlpcpExecuteCallback+0x1c5
15b2fcc4 76d4336a 0069d0b0 15b2fd10 77c89f72 ntdll!TppWorkerThread+0x5a4
15b2fcd0 77c89f72 0069d0b0 5c1fa653 00000000 kernel32!BaseThreadInitThunk+0xe
15b2fd10 77c89f45 77ca3e85 0069d0b0 00000000 ntdll!__RtlUserThreadStart+0x70
15b2fd28 00000000 77ca3e85 0069d0b0 00000000 ntdll!_RtlUserThreadStart+0x1b
0:082> u 76b5b57d-0x26 L30
ole32!CStdMarshal::ConnectSrvIPIDEntry [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1978]:
76b5b557 8bff mov edi,edi
76b5b559 55 push ebp
76b5b55a 8bec mov ebp,esp
76b5b55c 51 push ecx
76b5b55d 53 push ebx
76b5b55e 56 push esi
76b5b55f 8b7508 mov esi,dword ptr [ebp+8]
76b5b562 57 push edi
76b5b563 ff750c push dword ptr [ebp+0Ch]
76b5b566 8d45fc lea eax,[ebp-4]
76b5b569 50 push eax
76b5b56a 8d4508 lea eax,[ebp+8]
76b5b56d 50 push eax
76b5b56e 8d450c lea eax,[ebp+0Ch]
76b5b571 50 push eax
76b5b572 8d4630 lea eax,[esi+30h]
76b5b575 50 push eax
76b5b576 8bf9 mov edi,ecx
76b5b578 e818000000 call ole32!CStdMarshal::CreateStub (76b5b595)
76b5b57d 8bd8 mov ebx,eax
76b5b57f 85db test ebx,ebx
76b5b581 0f8d6e020000 jge ole32!CStdMarshal::ConnectSrvIPIDEntry+0x2c (76b5b7f5)
76b5b587 5f pop edi
76b5b588 5e pop esi
76b5b589 8bc3 mov eax,ebx
76b5b58b 5b pop ebx
76b5b58c c9 leave
76b5b58d c20800 ret 8
Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
格蠹老雷
2014-02-14, 17:02 下午
ole32!CStdMarshal::CreateStub 是很复杂的一个函数,是可能调用到COM对象的实现模块的
因为栈溢出,所以自动的回溯可能遗漏栈帧,用dds esp或者在RPC那个阶段找被调用的对象和方法
Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
qiliu3
2014-02-14, 17:35 下午
谢谢张老师回复!
通过dds esp来观察,是这样:
我一直怀疑是因为接口不匹配的原因引起的,因为我们的动态库依赖别人的,以前也经常出现因为接口不匹配导致的crash
只是这个crash不是100%出现的,又没有模拟出来
如果怀疑是接口不匹配引起的,想拿出证据的话,怎么拿呢?
15b2f040 559a568f XXXXXXXXXXXXX!std::_Tree<std::_Tmap_traits<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,_LoadwayInfo,std::less<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >,std::allocator<std::pair<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > const ,_LoadwayInfo> >,0> >::erase+0x20
15b2f044 2ea4344c
15b2f048 2ebb1e80
15b2f04c 00000000
15b2f050 c0000005
15b2f054 2ea4344c
15b2f058 00000000
15b2f05c 095a1f00
15b2f060 15b2f040
15b2f064 15b2ea68
15b2f068 15b2f574
15b2f06c 76b96751 ole32!_except_handler4 [d:\winmain\minkernel\crts\crtw32\misc\i386\chandler4gs.c @ 83]
15b2f070 369d10d7
15b2f074 00000000
15b2f078 15b2f0a4
15b2f07c 76b5b57d ole32!CStdMarshal::ConnectSrvIPIDEntry+0x26 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1989]
Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
qiliu3
2014-02-14, 17:38 下午
查看堆栈上这行:
15b2f03c 559a568f 2ea4344c 2ebb1e80 00000000 0x33c9256c
反汇编返回地址的汇编,发现是一条 call指令
ff15d4609c55 call dword ptr [XXXXXXXXXX!_imp_??0?$basic_stringDU?$char_traitsDstdV?$allocatorD (559c60d4)]
这个就有问题了,正常情况下应该是call的下一条,这个可以作为接口不匹配的证据么?
Re: 明明调的不是我们的函数,怎么会跑到我们的模块里面了呢?
格蠹老雷
2014-02-15, 10:16 上午
dds的结果暗示,曾经发生过非法访问异常的
如果怀疑接口不匹配,那么在宏观层面找线索,比如双方模块的版本号,时间等