user32!setwindowpos 为什么消失了?
>> 今天shichang说他在debugsogouexplorer的时候突然发现user32!setwindowpos的断点无法设置了,而前几天可以设置的。 这个我观察了一下我的windbg(注,我的os和shichang一样 win7 旗舰版).
>> 这个问题实际上是我的win7下我没有设置微软的符号库,因此windbg加载的是user32自带的export symbol,而这个symbol显示的和dependency显示一致,而shichang发现无法找到setwindowpos时候加载的符号库是pdb symbol,而这个符号库显示的是ntsetwindowpos.
aliim 中出现:
这个问题目前由于dump中只能看到如此代码,而看不到app的代码,因此推论:
1. auto_ptr的使用,基本上定位到queue_timerex_task 因为queue_timer_task并不使用auto_ptr
2. 从auto_ptr被呼叫的call stack来看,不像是一个正常的过程即并不来自于
rvcore_timerex_func/rvcore_cleanup_fuc 而是NLG_Return 因此比较怀疑是发生了异常导致了回滚。
推断到了这儿基本上就搞不下去了。。。。
|
文件: |
dumpscx.rar |
大小: |
294KB |
下载: |
下载 | |
然后我将dump和symbol复制到自己的电脑,重现!analyze -v
通过这个观察发现实际上timerex访问了一个imtribe已经卸载的地址空间中的。
windbg为何不识别我设置的localpath.
问题是这样的.
1. srv*d:\symbols*
2. srv*d:\symbols*localpth*
.reload /f aliim.exe
I find symbol can't be loaded ..
why ??
我发现是这样的, 所有mpath中SYMSVR后属于符号svr的本次cache,它有特定的加载格式.
path//xxx.pdb
而symsvr后的为本地路径,则没有这个限制,而我将本地路径错误的添加到svrcache路径就出问题了.
然后我修改
3. srv*d:\symbols*;localpth
.reload /f aliim.exe
错误依然,why?
原来windbg在每个svrcache path下建立一个标记文件 pingme.txt ,只要存在,就认为这个目录是svrcache,删除重新热load ok
uacagent 的一个crash,当时我从王俊那儿拿到了一个dump,
从vc中看到的情况如下:
从vc来看,显示m_spUACMgr == NULL.
不过从多年来的经验,vc的这类报告基本不靠谱, 那么继续往下分析.
找出windbg
从windbg的分析来看 , 确实存在了一个读取空指针的问题, 但是从严谨的角度出发, 得问who 是null.
我们看看windbg报告错误的代码,
这一行显示了,uacagent.cpp@582行报告错误,而这行就是第一张图得的那一行显示的...
还是得说从严谨的角度我们还得分析, 一般大家或许都知道 release 编译后的this指针 往往表现为ecx, 因此
vc显示this指针为空往往是没有意义的,那么我们来看看这个案例:
0:000> uf uacclient!CUACAgent::ReportAction
uacclient!CUACAgent::ReportAction [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 547]:
547 64608c60 56 push esi
548 64608c61 8b742408 mov esi,dword ptr [esp+8]
548 64608c65 807e0900 cmp byte ptr [esi+9],0
548 64608c69 751d jne uacclient!CUACAgent::ReportAction+0x28 (64608c88)
uacclient!CUACAgent::ReportAction+0xb [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 550]:
550 64608c6b 68484c6164 push offset uacclient!`string' (64614c48)
550 64608c70 6a00 push 0
550 64608c72 683cb96164 push offset uacclient!g_uaclog (6461b93c)
550 64608c77 e83497ffff call uacclient!CLogShell::Log (646023b0)
550 64608c7c 83c40c add esp,0Ch
551 64608c7f b801000000 mov eax,1
551 64608c84 5e pop esi
583 64608c85 c20c00 ret 0Ch
uacclient!CUACAgent::ReportAction+0x28 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 554]:
554 64608c88 837e1400 cmp dword ptr [esi+14h],0
554 64608c8c 751d jne uacclient!CUACAgent::ReportAction+0x4b (64608cab)
uacclient!CUACAgent::ReportAction+0x2e [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 556]:
556 64608c8e 68f04b6164 push offset uacclient!`string' (64614bf0)
556 64608c93 6a00 push 0
556 64608c95 683cb96164 push offset uacclient!g_uaclog (6461b93c)
556 64608c9a e81197ffff call uacclient!CLogShell::Log (646023b0)
556 64608c9f 83c40c add esp,0Ch
557 64608ca2 b801000000 mov eax,1
557 64608ca7 5e pop esi
583 64608ca8 c20c00 ret 0Ch
uacclient!CUACAgent::ReportAction+0x4b [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 560]:
560 64608cab 837e1002 cmp dword ptr [esi+10h],2
560 64608caf 751d jne uacclient!CUACAgent::ReportAction+0x6e (64608cce)
uacclient!CUACAgent::ReportAction+0x51 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 562]:
562 64608cb1 68904b6164 push offset uacclient!`string' (64614b90)
562 64608cb6 6a00 push 0
562 64608cb8 683cb96164 push offset uacclient!g_uaclog (6461b93c)
562 64608cbd e8ee96ffff call uacclient!CLogShell::Log (646023b0)
562 64608cc2 83c40c add esp,0Ch
563 64608cc5 b801000000 mov eax,1
563 64608cca 5e pop esi
583 64608ccb c20c00 ret 0Ch
uacclient!CUACAgent::ReportAction+0x6e [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 583]:
583 64608cce 57 push edi
567 64608ccf 8b7c2410 mov edi,dword ptr [esp+10h]
567 64608cd3 85ff test edi,edi
567 64608cd5 751e jne uacclient!CUACAgent::ReportAction+0x95 (64608cf5)
uacclient!CUACAgent::ReportAction+0x77 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 569]:
569 64608cd7 68484b6164 push offset uacclient!`string' (64614b48)
569 64608cdc 6a04 push 4
569 64608cde 683cb96164 push offset uacclient!g_uaclog (6461b93c)
569 64608ce3 e8c896ffff call uacclient!CLogShell::Log (646023b0)
569 64608ce8 83c40c add esp,0Ch
uacclient!CUACAgent::ReportAction+0x8b [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 569]:
569 64608ceb 5f pop edi
570 64608cec b801000000 mov eax,1
570 64608cf1 5e pop esi
583 64608cf2 c20c00 ret 0Ch
uacclient!CUACAgent::ReportAction+0x95 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 575]:
575 64608cf5 8b06 mov eax,dword ptr [esi]
575 64608cf7 8b503c mov edx,dword ptr [eax+3Ch]
575 64608cfa 8d4c240c lea ecx,[esp+0Ch]
575 64608cfe 51 push ecx
575 64608cff 57 push edi
575 64608d00 56 push esi
575 64608d01 c7442418ffffffff mov dword ptr [esp+18h],0FFFFFFFFh
575 64608d09 ffd2 call edx
577 64608d0b 66837c240c00 cmp word ptr [esp+0Ch],0
579 64608d11 74d8 je uacclient!CUACAgent::ReportAction+0x8b (64608ceb)
uacclient!CUACAgent::ReportAction+0xb3 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 582]:
582 64608d13 8b4c2414 mov ecx,dword ptr [esp+14h]
582 64608d17 8b7614 mov esi,dword ptr [esi+14h]
582 64608d1a 8b06 mov eax,dword ptr [esi]
582 64608d1c 8b502c mov edx,dword ptr [eax+2Ch]
582 64608d1f 51 push ecx
582 64608d20 57 push edi
582 64608d21 56 push esi
582 64608d22 ffd2 call edx
582 64608d24 5f pop edi
582 64608d25 5e pop esi
583 64608d26 c20c00 ret 0Ch
上面的代码片断中,结合源代码可以准确的发现这个编译版本CUACAgent 的this指针采用esi指针来描述的.
其中的第二个加下划线行,对应source code:
if(!m_spUACMgr)
{
g_uaclog.Log(lp_debug, _T(__FUNCTION__)_T(" m_spUACMgr is null"));
return S_FALSE;
}
也就是说它访问了this->m_spUACMgr
而汇编代码
554 64608c88 837e1400 cmp dword ptr [esi+14h],0
也就是说esi+14h访问到了这个成员变量,那么我们继续验证:
赫赫,看到了+14h的地方果然是m_spUACMgr,到了这儿我们100%的确定esi是this,那么再来看看, crash前后的代码;;;
uacclient!CUACAgent::ReportAction+0xb3 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\uacpackage\uacclient\uacagent.cpp @ 582]:
582 64608d13 8b4c2414 mov ecx,dword ptr [esp+14h]
582 64608d17 8b7614 mov esi,dword ptr [esi+14h]
582 64608d1a 8b06 mov eax,dword ptr [esi] (出问题行)
582 64608d1c 8b502c mov edx,dword ptr [eax+2Ch]
582 64608d1f 51 push ecx
582 64608d20 57 push edi
582 64608d21 56 push esi
582 64608d22 ffd2 call edx
582 64608d24 5f pop edi
582 64608d25 5e pop esi
583 64608d26 c20c00 ret 0Ch
从出问题行的上一行,我们看到esi+14h,赫赫,不就是this->m_spUACMgr吗?
然后再取这个指针的值,+2c偏移量,我用脚猜一下是 IUACMgr::ReportAction这个函数,
赫赫,到了这儿基本上就确定了, 这个m_spUAcMgr在这个函数执行过程中被修改掉了,
由于本函数确定在main thread 被调用,因此思路是寻找m_spUAcMgr = NULL;
结果找到了,
王俊反馈,说sdk出问题了,...
拿到dump后我做了以下分析...
从windbg的分析来看,内存被改写了.
通过将一分完好的wwsdkcom.dll 和出问题时候的对比,如下...
0:016> !address 506a23a0
ProcessParametrs 002716d8 in range 00270000 00370000
Environment 002ec548 in range 00270000 00370000
50500000 : 50501000 - 001f4000
Type 01000000 MEM_IMAGE
Protect 00000020 PAGE_EXECUTE_READ
State 00001000 MEM_COMMIT
Usage RegionUsageImage
FullPath C:\Users\bufan\Desktop\dump2\6.30.25M\wwsdkcom.dll
通过分析正常情况的内存页属性是E|R, 异常请款下!address 无法拿到,因该是非fulldump引起的.
PAGE_EXECUTE_READ 通过msdn观察
- PAGE_EXECUTE_READ
- 0x20
|
Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation. |
因此基本推断由于程序正常情况的执行导致的违规写入将直接导致访问违规,崩溃....
0:015> lm v m wwsdkcom*
start end module name
50500000 507ec000 wwsdkcom (deferred)
Image path: C:\Users\bufan\Desktop\dump2\6.30.25M\wwsdkcom.dll
Image name: wwsdkcom.dll
Timestamp: Wed Jul 21 16:35:21 2010 (4C46B149)
CheckSum: 002EABF1
ImageSize: 002EC000
File version: 1.0.0.1
Product version: 1.0.0.1
File flags: 0 (Mask 3F)
File OS: 4 Unknown Win32
File type: 2.0 Dll
同时也可以看到windbg显示的timestamp 和checksun是写在 文件中的,因此可以大胆推断:
1. 用户直接修改了文件,因为修改wwsdkcom.dll 意图破解之前也发生过
2. 用户在程序运行后修改,根据sl的意见,程序运行时候修改page protection 也是可能的.
另外 据同时反映...
下面是一个相似的问题:
FOLLOWUP_IP:
protocol!CScHead::PackData+75 [e:\aliwwautopackage\trunk\sourcecode\imclient-rv\source\protocol\sc_head.cpp @ 23]
64227094 d08bcee82853 ror byte ptr [ebx+5328E8CEh],1
NTGLOBALFLAG: 0
CHKIMG_EXTENSION: !chkimg -lo 50 -d !protocol
64227094 - protocol!CScHead::PackData+75
[ 50:d0 ]
1 error : !protocol (64227094)
FAULTING_THREAD: 000008f8
BUGCHECK_STR: APPLICATION_FAULT_MEMORY_CORRUPTION_INVALID_POINTER_WRITE_ONE_BIT
PRIMARY_PROBLEM_CLASS: MEMORY_CORRUPTION_ONE_BIT
DEFAULT_BUCKET_ID: MEMORY_CORRUPTION_ONE_BIT
LAST_CONTROL_TRANSFER: from 642042f0 to 64227094
windbg显示的很正确
从地址64227094 开始的protocol.dll 被修改了
修改后的代码,即出问题的第一行就直接导致了一个对非法地址的写入
2010-12-29 日发现一个crash
1。 现象,测试同事那儿发现,点击某个html页面时候,如果频率比价多,必然crash
2。 在其他同事机器上此问题,不太容易出现
3。 dump 的call stack 显示信息不够多,且提示heap
corruption
4。 出现了其他操作的crash,原因也是heap corruption
在通过反复比对dump后 采用:
开启appverify,但是仅仅打开heap选项;
启动程序,结果发现了好几个错误;
*bstr = CComBSTR(xxx);
之类的代码,显然将返回参数用一个local var来填充了,那么确实是否crash只有天知道了;
进过此修改后,崩溃没有再次出现,继续观察中。。。。
这个方法有点土,但是也算是一种方案
2011-01-17 晚,发现一个问题,即用户启动社区版im后,点击免费注册即可crash;
而且,只有打包机器才会出现这个问题,其他开发同事编译出来的代码均没有此现象!
需要说明的是:
打包机器和开发机器均安装了vs2005 chn+sp1;
编译环境一致; 包括使用的lib 和headers;
第二个现象:
发现同模块即imbiz.dll 内和crash点完全无关的一处代码提交后,才有这个现象的;
只要删除那初提交此现象消失;
需要说明的是,这个提交在crash发生时候根本没有被运行过,这个添加仅仅是增加了一个成员函数,没有用到任何静态,全局变量;仅仅是一个字符串处理函数;
经过反复排查比较,比如一开始以为打包程序有问题,因为打包程序是通过命令行来执行vs2005 编译的;
又比如,回滚代码;
最后查看编译器生成的代码(必然崩溃的反汇编):
rv::HRESULT_EX hr; // source code
1836 0c45e0d3 8d4de8 lea ecx,[ebp-18h]
1836 0c45e0d6 e8e5c0f3ff call imbiz!_S_MAGIC_EMOTION_DOWNLOAD::_S_MAGIC_EMOTION_DOWNLOAD (0c39a1c0)
1837 0c45e0db 68acb34b0c push offset imbiz!`string' (0c4bb3ac)
1837 0c45e0e0 8d4de4 lea ecx,[ebp-1Ch]
... hr = xxx
1837 0c45e0fc 8d4de8 lea ecx,[ebp-18h]
1837 0c45e0ff e85cf9e3ff call imbiz!rv::HRESULT_EX::operator= (0c29da60)
工程师机器上编译出来的反汇编:
1836 0217c3a3 8d4de8 lea ecx,[ebp-18h]
1836 0217c3a6 e8b552e4ff call imbiz!rv::HRESULT_EX::HRESULT_EX (01fc1660)
1837 0c45e0db 68acb34b0c push offset imbiz!`string' (0c4bb3ac)
1837 0c45e0e0 8d4de4 lea ecx,[ebp-1Ch]
... hr = xxx
1837 0c45e0fc 8d4de8 lea ecx,[ebp-18h]
1837 0c45e0ff e85cf9e3ff call imbiz!rv::HRESULT_EX::operator= (0c29da60)
最后在打包机器上关闭 /GL选项
1836 0ce191d3 8d4de8 lea ecx,[ebp-18h]
1836 0ce191d6 e8e584feff call imbiz!rv::HRESULT_EX::HRESULT_EX (0ce016c0)
1837 0c45e0db 68acb34b0c push offset imbiz!`string' (0c4bb3ac)
1837 0c45e0e0 8d4de4 lea ecx,[ebp-1Ch]
... hr = xxx
1837 0c45e0fc 8d4de8 lea ecx,[ebp-18h]
1837 0c45e0ff e85cf9e3ff call imbiz!rv::HRESULT_EX::operator= (0c29da60)
也就是说在打包机器上,在开启 /GL后,
rv::HRESULT_EX hr; 这句source code竟然被编译成了
_S_MAGIC_EMOTION_DOWNLOAD hr; 类似于这个代码
这样我们就看到,实际上程序竟然构造了一个这个对象。。。。。。
但是后面的汇编又显示在执行hr=xxx 的时候,又执行了
... hr = xxx
1837 0c45e0fc 8d4de8 lea ecx,[ebp-18h]
1837 0c45e0ff e85cf9e3ff call imbiz!rv::HRESULT_EX::operator= (0c29da60)
呵呵