<2020年9月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

文章分类

导航

订阅

调试笔记之GMail挂死

在GMail进入Inbox前,挂死在Loading页面,数分钟后仍纹丝不动。唤WinDBG附身,远程中断方法不能工作:

Break-in sent, waiting 30 seconds...
WARNING: Break-in timed out, suspending.

挂起方法可以开始非入侵式调试会话:
(1374.1134): Wake debugger - code 80000007 (first chance)
eax=00a22d68 ebx=00000000 ecx=0000002a edx=01633062 esi=7dc31cd8 edi=011dd91c
eip=00b0f570 esp=0013caf4 ebp=0013caf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
*** WARNING: Unable to verify checksum for C:\WINDOWS\system32\HidApi.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\WINDOWS\system32\HidApi.dll
HidApi+0xf570:
00b0f570 5d              pop     ebp

上面的程序指针信息显示,当前的线程在执行HidApi模块中的代码。进一步观察栈回溯:

0:000> kn 100
 # ChildEBP RetAddr 
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0013caf4 00b0eb1c HidApi+0xf570
01 0013cb3c 00b03825 HidApi+0xeb1c
02 0013cb50 00a355e5 HidApi+0x3825
03 0013cb64 00a356e5 hidapistub+0x55e5
04 0013cb7c 00a35903 hidapistub+0x56e5
05 0013cbd8 7dd6c39b hidapistub+0x5903
06 0013cbf8 7dea01bd mshtml!CLASSINFO::Init+0x63
07 0013cc28 7ddb27e7 mshtml!CClassTable::AssignWclsid+0x9b
08 0013cc50 75c83e28 mshtml!CDocument::HostProcessUrlAction+0x43
09 0013cc80 75c80f05 JScript!COleScript::CanCreateObject+0x3f
0a 0013cd10 75c99c4f JScript!GetObjectFromProgID+0xf4
0b 0013cd64 75c9cea9 JScript!JsCreateObject+0xc6
0c 0013cd80 75c5f20e JScript!ActiveXObjectFncObj::Construct+0x18
0d 0013ce0c 75c5585e JScript!NameTbl::InvokeInternal+0x1bf
0e 0013ce38 75c5f262 JScript!VAR::InvokeByDispID+0xd4
0f 0013d02c 75c5450a JScript!CScriptRuntime::Run+0x188b
10 0013d0f0 75c610ea JScript!ScrFncObj::Call+0x69
11 0013d184 75c5585e JScript!NameTbl::InvokeInternal+0xd5
12 0013d1b0 75c54d0f JScript!VAR::InvokeByDispID+0xd4
13 0013d3a4 75c5450a JScript!CScriptRuntime::Run+0x18fb
14 0013d468 75c610ea JScript!ScrFncObj::Call+0x69
15 0013d4fc 75c5585e JScript!NameTbl::InvokeInternal+0xd5
16 0013d528 75c54d0f JScript!VAR::InvokeByDispID+0xd4
17 0013d71c 75c5450a JScript!CScriptRuntime::Run+0x18fb
18 0013d7e0 75c60b0d JScript!ScrFncObj::Call+0x69
19 0013d868 75c5f20e JScript!ScrFncObj::Construct+0xd0
1a 0013d8f4 75c5585e JScript!NameTbl::InvokeInternal+0x1bf
1b 0013d920 75c5f262 JScript!VAR::InvokeByDispID+0xd4
1c 0013db14 75c5450a JScript!CScriptRuntime::Run+0x188b
1d 0013dbd8 75c558d1 JScript!ScrFncObj::Call+0x69
1e 0013dc6c 75c5585e JScript!NameTbl::InvokeInternal+0x218
1f 0013dc98 75c61878 JScript!VAR::InvokeByDispID+0xd4
20 0013dcdc 75c61aa9 JScript!VAR::InvokeByName+0x164
21 0013dd50 75c996bd JScript!VAR::InvokeByVar+0xb7
22 0013dd80 75c795ed JScript!VAR::InvokeDispVar+0x2f
23 0013dda4 75c6484b JScript!VAR::InvokeByDispID+0x98
24 0013df98 75c5450a JScript!CScriptRuntime::Run+0x195b
25 0013e05c 75c558d1 JScript!ScrFncObj::Call+0x69
26 0013e0f0 75c5585e JScript!NameTbl::InvokeInternal+0x218
27 0013e11c 75c61878 JScript!VAR::InvokeByDispID+0xd4
28 0013e160 75c61aa9 JScript!VAR::InvokeByName+0x164
29 0013e1d4 75c996bd JScript!VAR::InvokeByVar+0xb7
2a 0013e204 75c795ed JScript!VAR::InvokeDispVar+0x2f
2b 0013e228 75c6484b JScript!VAR::InvokeByDispID+0x98
2c 0013e41c 75c5450a JScript!CScriptRuntime::Run+0x195b
2d 0013e4e0 75c5434f JScript!ScrFncObj::Call+0x69
2e 0013e558 75c5b091 JScript!CSession::Execute+0xb2
2f 0013e5a8 75c5d364 JScript!COleScript::ExecutePendingScripts+0x14f
30 0013e608 75c5d1b6 JScript!COleScript::ParseScriptTextCore+0x221
31 0013e634 7dcd1922 JScript!COleScript::ParseScriptText+0x2b
32 0013e694 7dcd17cb mshtml!CScriptCollection::ParseScriptText+0x1da
33 0013e74c 7dcd18b7 mshtml!CScriptElement::CommitCode+0x1e1
34 0013e784 7dcd06d5 mshtml!CScriptElement::Execute+0xa4
35 0013e7d0 7dc9cf57 mshtml!CHtmParse::Execute+0x41
36 0013e7dc 7dcc4b79 mshtml!CHtmPost::Broadcast+0xd
37 0013e898 7dcd0ffa mshtml!CHtmPost::Exec+0x32f
38 0013e8b0 7dcb4c02 mshtml!CHtmPost::Run+0x55
39 0013e8c0 7dcb503f mshtml!PostManExecute+0x51
3a 0013e8d8 7dcb4fc2 mshtml!PostManResume+0x71
3b 0013e8e4 7dcb401a mshtml!CHtmPost::OnDwnChanCallback+0xc
3c 0013e8f4 7dc9cb42 mshtml!CDwnChan::OnMethodCall+0x19
3d 0013e928 7dc98947 mshtml!GlobalWndOnMethodCall+0x66
3e 0013ea5c 7e418724 mshtml!GlobalWndProc+0x1e2
3f 0013ea88 7e418806 USER32!InternalCallWinProc+0x28
40 0013eaf0 7e4189bd USER32!UserCallWinProcCheckWow+0x150
41 0013eb50 7e418a00 USER32!DispatchMessageWorker+0x306
42 0013eb60 75f9d795 USER32!DispatchMessageW+0xf
43 0013eb78 75fa51b2 BROWSEUI!TimedDispatchMessage+0x33
44 0013edd8 75fa5325 BROWSEUI!BrowserThreadProc+0x336
45 0013ee6c 75fa55ed BROWSEUI!BrowserProtectedThreadProc+0x50
46 0013fef0 7e318e36 BROWSEUI!SHOpenFolderWindow+0x22c
47 0013ff10 00402372 SHDOCVW!IEWinMain+0x129
48 0013ff60 00402444 IEXPLORE!WinMainT+0x2de
49 0013ffc0 7c816ff7 IEXPLORE!_ModuleEntry+0x99
4a 0013fff0 00000000 kernel32!BaseProcessStart+0x23

尽管因为没有HidApi和HidApiStub两个模块的符号,WinDBG给出了一个警告,但是展回溯的总体信息来看,这个栈回溯还是很可信的。它显示的是IE的UI线程的执行状况,#48栈帧是IEXPLORE模块的入口函数,#46~#43显示的是BROWSEUI模块创建浏览线程的经过,#42~3f是Windows子系统的用户态模块USER32的窗口消息分发函数,#3e~32是HTML解析模块MSHTML在执行向服务器端的POST动作,因为这个POST动作包含有JavaScript代码,因此MSHTML调用JScript模块中的函数来帮忙,即栈帧#24~#09。从栈帧#0e~09可以看出在JavaScript描述中包含有组件对象,于是开始着手创建这个组件的实例,但是在创建前,JScript模块做如下调用来判断是否可以创建这个对象,这当属于创建前的安全检查:

JScript!COleScript::CanCreateObject

这一检查激发了后来的操作,即栈帧#08~00。至此可以推测,HidApi要么是安全软件植入到IE进程中的模块,要么是病毒程序伪装安全软件来获得执行权。观察一下HidApi的文件属性,原来是某安全软件的模块。

执行ub命令对观察执行点附近的指令,上一条指令居然是INT 2E,也就是调用系统服务的传统方法(参见《软件调试》8.3.2)。看来,IE是挂在内核态了,这也是为什么连WinDBG的远程中断线程也没能工作的原因。

启动一个本地内核调试,找到挂死的IE进程和它的0号线程,然后通过!thread命令显示其详情,可以看到下面这样的栈回溯:

ChildEBP RetAddr  Args to Child             
acebd4f0 8050049e 8a4d4d00 8a4d4c90 804f9cec nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
acebd4fc 804f9cec 00000000 8a4d4c90 e3c5c2e0 nt!KiSwapThread+0x46 (FPO: [0,0,0])
acebd524 805987fc 00000000 00000000 acac8d00 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])
acebd5e0 80598a2a acebd80c acebd730 acebd738 nt!NtSecureConnectPort+0x662 (FPO: [Non-Fpo])
acebd60c acab8ebc acebd80c acebd730 acebd738 nt!NtConnectPort+0x24 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
acebd660 8053cbc8 acebd80c acebd730 acebd738 hidsys+0x12ebc
acebd660 804fd80d acebd80c acebd730 acebd738 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ acebd688)
acebd6f8 ba5e9a05 acebd80c acebd730 acebd738 nt!ZwConnectPort+0x11 (FPO: [8,0,0])
acebd7e8 ba5e3f54 ba5e5da0 00000001 acebd80c KSecDD!CreateConnection+0xe5 (FPO: [Non-Fpo])
acebd81c ba5e38da 00000001 acebd82c 00000000 KSecDD!CreateClient+0x90 (FPO: [Non-Fpo])
acebd830 ba5e9044 acebd93c acebd84c e4df4488 KSecDD!IsOkayToExec+0x2c (FPO: [Non-Fpo])
acebd940 ba5ea4f1 acebdb94 acebd958 acebd968 KSecDD!SecpGetLogonSessionData+0x14 (FPO: [Non-Fpo])
acebd950 acaac168 acebdb94 acebd960 00000000 KSecDD!LsaGetLogonSessionData+0x11 (FPO: [Non-Fpo])
acebd968 acabcd5f acebdb94 acebdbc4 acebdd64 hidsys+0x6168
acebdbe0 acac5393 00b9d6b0 00000004 00000000 hidsys+0x16d5f
acebdbf4 acac5939 00b9d6b0 0000002d acebdc0c hidsys+0x1f393
acebdc14 acacfc96 00b9d6b0 874f609e acebdc30 hidsys+0x1f939
acebdc34 acacfbd4 00b9d6b0 87c10dfc acebdca8 hidsys+0x29c96
acebdc68 acacf2db acebdca8 00b9d6b0 acebdca4 hidsys+0x29bd4
acebdcd8 acacf238 00b9d6b0 874ee004 acebdd18 hidsys+0x292db
acebdcf4 acabd113 00b9e528 acebdd18 874ee004 hidsys+0x29238
acebdd3c acab7637 00b9e528 0013cb10 acebdd64 hidsys+0x17113
acebdd54 8053cbc8 00b9e528 0013cb10 0013caf4 hidsys+0x11637
acebdd54 00b0f570 00b9e528 0013cb10 0013caf4 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ acebdd64)
0013caf4 00000000 00000000 00000000 00000000 0xb0f570

最下面一个栈帧的0013caf4与在用户态观察的最后一个栈帧的刚好一致。接下来的一个栈帧中的KiFastCallEntry是系统分发系统调用的函数。也就是在用户态执行INT 2E后便进入到内核态了,而后调用安全软件自己的驱动模块hidsys,据此可以推测,用户态的HidApi是通过系统调用方式来与内核态的模块Hidsys通信。

内核态栈回溯的顶部是调用NtSecureConnectPort函数,这是连接LPC端口的内核服务,看来挂死的进一步原因是在内核态中调用LPC服务。NtSecureConnectPort的第二个参数是要连接的LPC端口名,其参数类型是UNICODE_STRING,可以使用dS命令观察:

kd> dS acebd730
ba5e98ec  "\LsaAuthenticationPort"

这是LSASS进程对外服务的LPC端口。联系到KSecDD是系统中负责对加密文件进行解密的模块,那么可以推测,HidApi是让自己的驱动帮助它解密某个文件,Hidsys收到调用后,又调用KSecDD来帮忙。

接下来的问题是为什么这个LPC请求没有得到恢复?这可以通过WinDBG!lpc扩展命令来做,ETHREAD结构的LpcReplyMessageId字段记录着当前线程等待回复的LPC消息ID,然后使用!lpc message命令便可以观察这个LPC消息的详情,类似下面这样:

!lpc message 003a41b7
Searching message 3a41b7 in threads ...
Client thread 8a4d4c90 waiting a reply from 3a41b7                         
Searching thread 8a4d4c90 in port rundown queues ...

Server connection port e1bf29c8  Name: LsaAuthenticationPort
    Handles: 1   References: 166
    Server process  : 89b32708 (lsass.exe)
......

终上,可以归纳出,这次因为登录GMail而导致的IE进程挂死的经过是这样的:JavaScript引擎在遇到页面上的组件后,征询是否可以创建这个对象,这引发了安全软件的监视模块HidApi模块被调用,这个模块在工作的过程中需要解密某个信息/文件,于是它通过扩展的系统服务调用请求自己的驱动程序hidsys来帮助,因为hidApi模块本身也是在低权限和不安全的IE进程中,hidsys有调用系统KSecDD来解密,后者向系统中负责安全认证的LSASS进程发送请求,但是因为某种原因没有得到回应,于是就挂死在那里了。

LSASS不回应的原因有很多,其中一种是LSASS的工作代码在服务这个请求时又触发了安全软件的挂钩函数,这个挂钩函数再次调用LSASS的服务,如此死锁。

 

 

posted on 2008年10月19日 9:57 由 Raymond

# re: 调试笔记之GMail挂死 @ 2008年10月20日 8:13

最初以为在讨论脚本问题- -|||
这个问题在Firefox和opera下不会出现

ayarei

Powered by Community Server Powered by CnForums.Net