从csrss弹出的ASSERT对话框谈起

本文详细描述了一次在Win XP多用户环境中,远程线程注入csrss进程时遇到的断言问题。通过分析,发现断言错误源于MFC的AUX_DATA::UpdateSysMetrics函数,由于csrss进程没有关联桌面导致GetDC()返回NULL。断言对话框通过LPC从session 1的csrss进程传递到session 0的csrss进程中显示。进一步研究发现,csrss进程的ExceptionPort为NULL,导致不同session下的行为差异。文章探讨了加载DLL时的断言失败,以及系统中ExceptionPort的工作机制。
摘要由CSDN通过智能技术生成

 

昨天遇到一件怪事,在进行远程线程注入的时候从csrss进程中竟然弹出了vc的ASSERT对话框。根据对话框提示信息找到了断言的位置在mfc的auxdata.cpp的第95行代码:
void AUX_DATA::UpdateSysMetrics()
{
 // System metrics
 cxIcon = GetSystemMetrics(SM_CXICON);
 cyIcon = GetSystemMetrics(SM_CYICON);

 // System metrics which depend on subsystem version
 afxData.cxVScroll = GetSystemMetrics(SM_CXVSCROLL) + CX_BORDER;
 afxData.cyHScroll = GetSystemMetrics(SM_CYHSCROLL) + CY_BORDER;

 // Device metrics for screen
 HDC hDCScreen = GetDC(NULL);
 ASSERT(hDCScreen != NULL); <------------------就是这个断言
 cxPixelsPerInch = GetDeviceCaps(hDCScreen, LOGPIXELSX);
 cyPixelsPerInch = GetDeviceCaps(hDCScreen, LOGPIXELSY);
 ReleaseDC(NULL, hDCScreen);
}
具体的环境就是win xp进行多用户登陆:首先登陆一个windows帐号user1, session id = 0, 对csrss进程成功进行了远程线程注入。接着在保持user1登陆的情况下切换用户登陆到user2,进去之后同样的对新的session(session id = 1)的csrss进程进行远程线程注入,没什么问题。但是切回到user1后发现界面上有一个断言对话框,显示了上面代码位置的断言失败。查看这个对话框所在的进程确实是session 0的csrss进程。因为是一个稳定的重现的问题,使用windbg远程附加到session 0的csrss进程,查看弹出对话框的线程调用栈如下:
 ChildEBP RetAddr 
        0071f8d8 77d193f5 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
        0071f910 77d2688a USER32!NtUserWaitMessage+0xc
        0071f938 77d3b7c5 USER32!InternalDialogBox+0xd0 (FPO: [6,1,4])
        0071fbf8 77d3b12b USER32!SoftModalMessageBox+0x938 (FPO: [1,165,4])
        0071fd48 77d65fdf USER32!MessageBoxWorker+0x2ba (FPO: [1,78,4])
        0071fda0 764f9b1b USER32!MessageBoxTimeoutW+0x7a (FPO: [6,19,0])
        0071fe7c 764f9d5b winsrv!HardErrorHandler+0x2e8 (FPO: [0,44,4])
        0071fe9c 764fb0f1 winsrv!ProcessHardErrorRequest+0x9b (FPO: [1,3,4])
        0071febc 764fb173 winsrv!UserHardErrorEx+0x234 (FPO: [3,2,4])
        0071fed0 75aa47a0 winsrv!UserHardError+0x12 (FPO: [2,0,0])
        0071fff4 00000000 CSRSRV!CsrApiRequestThread+0x18a (FPO: [Non-Fpo])
这里很奇怪,断言的调用链里面应该会出现__crtMessageBoxA,除非是符号不对,但是调用栈里面所有的返回地址都有符号。
难道是调用栈不完整,于是结合汇编代码对调用栈进行核实---没问题。一个偶然的原因在ReactOS上面看了一下CsrApiRequestThread函数的源代码才意识到这个对话框是通过LPC端口投递过来的消息显示。winsrv!UserHardError是最后一个出错处理回调例程。
用户态调试查不出这个LPC是哪里投递过来的,转而使用内核态调试。
根据从运程线程注入的结果,对session 1的csrss进程进行的远程线程一直没有收到注入成功的回复,很自然想到看一下session 1的csrss进程的情况。

kd> !process 81a81468 
PROCESS 81a81468  SessionId: 1  Cid: 0238    Peb: 7ffd5000  ParentCid: 0240
    DirBase: 084003e0  ObjectTable: e178ca80  HandleCount: 128.
    Image: csrss.exe
    VadRoot 81711920 Vads 100 Clone 0 Private 702. Modified 2674. Locked 0.
    DeviceMap e10000b8
    Token                             e1474138
    ElapsedTime                       00:01:01.984
    UserTime                          00:00:01.500
    KernelTime                        00:00:01.921
    QuotaPoolUs

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值