昨天遇到一件怪事,在进行远程线程注入的时候从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
    QuotaPoolUsage[PagedPool]         123956
    QuotaPoolUsage[NonPagedPool]      4160
    Working Set Sizes (now,min,max)  (125, 50, 345) (500KB, 200KB, 1380KB)
    PeakWorkingSetSize                2818
    VirtualSize                       59 Mb
    PeakVirtualSize                   76 Mb
    PageFaultCount                    3524
    MemoryPriority                    BACKGROUND
    BasePriority                      13
    CommitCharge                      874

/略去一些无关线程信息

THREAD 8170eda8  Cid 0238.096c  Teb: 7ffd3000 Win32Thread: e24c1ba0 WAIT: (WrLpcReply) UserMode Non-Alertable
            8170ef9c  Semaphore Limit 0x1
        Waiting for reply to LPC MessageId 0000209e:
        Current LPC port e1353840
        Not impersonating
        DeviceMap                 e10000b8
        Owning Process            81a81468       Image:         csrss.exe
        Wait Start TickCount      13207          Ticks: 2483 (0:00:00:38.796)
        Context Switch Count      17                 LargeStack
        UserTime                  00:00:00.140
        KernelTime                00:00:00.015
        Win32 Start Address 0x7ff90000
        Start Address KERNEL32!BaseThreadStartThunk (0x7c810856)
        Stack Init f72f1000 Current f72f0a94 Base f72f1000 Limit f72ee000 Call 0
        Priority 13 BasePriority 13 PriorityDecrement 0 DecrementCount 0
        ChildEBP RetAddr 
        f72f0aac 8050117a nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
        f72f0ab8 804fa9be nt!KiSwapThread+0x46 (FPO: [0,0,0])
        f72f0ae0 805989d5 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])
        f72f0b18 80598b21 nt!LpcpRequestWaitReplyPort+0x43d (FPO: [Non-Fpo])
        f72f0b30 8060a467 nt!LpcRequestWaitReplyPortEx+0x21 (FPO: [Non-Fpo])
        f72f0cd4 8060a8c5 nt!ExpRaiseHardError+0x1bd (FPO: [Non-Fpo])
        f72f0d44 8053d808 nt!NtRaiseHardError+0x16b (FPO: [Non-Fpo])
        f72f0d44 7c92eb94 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f72f0d64)
        0350b348 7c92e273 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
        0350b34c 77d65d43 ntdll!NtRaiseHardError+0xc (FPO: [6,0,0])
        0350b3a8 77d48ffe USER32!ServiceMessageBox+0x145 (FPO: [Non-Fpo])
        0350b504 77d65fdf USER32!MessageBoxWorker+0x13e (FPO: [Non-Fpo])
        0350b55c 77d66084 USER32!MessageBoxTimeoutW+0x7a (FPO: [Non-Fpo])
        0350b590 77d50598 USER32!MessageBoxTimeoutA+0x9c (FPO: [Non-Fpo])
        0350b5b0 77d50550 USER32!MessageBoxExA+0x1b (FPO: [Non-Fpo])
        0350b5cc 1020c2aa USER32!MessageBoxA+0x45 (FPO: [Non-Fpo])
        0350b604 1020cd3e MSVCR71D!__crtMessageBoxA+0x16a (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/crtmbox.c @ 119]
        0350c75c 1020ca2a MSVCR71D!CrtMessageWindow+0x2be (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/dbgrpt.c @ 617]
        0350f7d8 03666b3f MSVCR71D!_CrtDbgReport+0x41a (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/dbgrpt.c @ 516]
        0350f818 0361bad2 MFC71UD!AfxAssertFailedLine+0x2f (FPO: [Non-Fpo]) (CONV: stdcall) [f:/vs70builds/3077/vc/mfcatl/ship/atlmfc/src/mfc/afxasert.cpp @

28]
        0350f830 0368cc9e MFC71UD!AUX_DATA::UpdateSysMetrics+0x62 (FPO: [Non-Fpo]) (CONV: thiscall) [f:/vs70builds/3077

/vc/mfcatl/ship/atlmfc/src/mfc/auxdata.cpp @ 95]
        0350f840 0368cd5d MFC71UD!AUX_DATA::AUX_DATA+0x2e (FPO: [Non-Fpo]) (CONV: thiscall) [f:/vs70builds/3077/vc/mfcatl/ship/atlmfc/src/mfc/auxdata.cpp @

35]
        0350f848 10201d48 MFC71UD!$E5+0xd (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/mfcatl/ship/atlmfc/src/mfc/auxdata.cpp @ 22]
        0350f850 035da943 MSVCR71D!_initterm+0x18 (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/crt0dat.c @ 600]
        0350f860 035daa5a MFC71UD!_CRT_INIT+0xa3 (FPO: [Non-Fpo]) (CONV: stdcall) [f:/vs70builds/3077/vc/crtbld/crt/src/crtdll.c @ 184]
        0350f8ac 7c9211a7 MFC71UD!_DllMainCRTStartup+0x9a (FPO: [Non-Fpo]) (CONV: stdcall) [f:/vs70builds/3077/vc/crtbld/crt/src/crtdll.c @ 266]
        0350f8cc 7c93cbab ntdll!LdrpCallInitRoutine+0x14
        0350f9d4 7c936178 ntdll!LdrpRunInitializeRoutines+0x344 (FPO: [Non-Fpo])
        0350fc80 7c9362da ntdll!LdrpLoadDll+0x3e5 (FPO: [Non-Fpo])
        0350ff28 7c801bb9 ntdll!LdrLoadDll+0x230 (FPO: [Non-Fpo])
        0350ff90 7c80ace4 KERNEL32!LoadLibraryExW+0x18e (FPO: [Non-Fpo])
        0350ffa4 7ff90010 KERNEL32!LoadLibraryW+0x11 (FPO: [Non-Fpo])
WARNING: Frame IP not in any known module. Following frames may be wrong.
        0350ffb4 7c80b50b 0x7ff90010
        0350ffec 00000000 KERNEL32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

看到这一个线程的信息之后,原因终于找到了,是在对session 1的csrss进行注入之后,加载dll,初始化mfc动态链接库的时候导致断言失败,对话框通过LPC的方式重定向到session 0的csrss进程去显示了。到这里还是有很多疑问,主要是两个问题:
1.为什么auxdata.cpp第94行HDC hDCScreen = GetDC(NULL);获取屏幕DC的时候会得到NULL句柄。
2.为什么在对session 0的csrss进程注入的时候没有出现这个问题。

写了如下的测试dll:
#include "stdafx.h"
#include <crtdbg.h>

#define ASSERT(expr, msg) /
 do { if (!(expr) && /
 (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, NULL, msg))) /
 _CrtDbgBreak(); } while (0)

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 if (DLL_PROCESS_ATTACH == ul_reason_for_call){
  _asm int 3    ;这里的断点,是为了跟踪调试GetDC
  ASSERT(NULL != GetDC(0), NULL);
 }
    return TRUE;
}

同时写一个简单的注入程序将上面的dll注入到csrss进程中。内核调试在int 3断点中断,nop掉int 3指令。单步跟踪GetDC(注意跟踪的时候对)同时结合windows nt的源代码,发现之所以返回NULL,是因为csrss进程没有关联桌面,获取不到屏幕DC(具体参考nt源代码)。
同时发现session 0确实也拿不到屏幕DC,继续跟踪断言消息框显示流程。发现__crtMessageBoxA函数(VC有源代码)在uType参数加上了MB_SERVICE_NOTIFICATION标志,导致MessageBoxWorker函数(win2k源代码)最终调用ServiceMessageBox,而不是SoftModalMessageBox。

kd> !process 8150b5c0 
PROCESS 8150b5c0  SessionId: 1  Cid: 0dc0    Peb: 7ffdd000  ParentCid: 023c
    DirBase: 02b403e0  ObjectTable: e11a0e48  HandleCount: 136.
    Image: csrss.exe
    VadRoot 816ca8d0 Vads 86 Clone 0 Private 199. Modified 2530. Locked 0.
    DeviceMap e1000110
    Token                             e1157930
    ElapsedTime                       01:41:39.406
    UserTime                          00:00:02.906
    KernelTime                        00:00:04.250
    QuotaPoolUsage[PagedPool]         127108
    QuotaPoolUsage[NonPagedPool]      3600
    Working Set Sizes (now,min,max)  (96, 50, 345) (384KB, 200KB, 1380KB)
    PeakWorkingSetSize                2097
    VirtualSize                       59 Mb
    PeakVirtualSize                   64 Mb
    PageFaultCount                    4342
    MemoryPriority                    BACKGROUND
    BasePriority                      13
    CommitCharge                      304

//略去无关线程

THREAD 8141c278  Cid 0dc0.01b0  Teb: 7ffd3000 Win32Thread: e1dd6938 WAIT: (WrLpcReply) UserMode Non-Alertable
            8141c46c  Semaphore Limit 0x1
        Waiting for reply to LPC MessageId 00003e93:
        Current LPC port e13cb988
        Not impersonating
        DeviceMap                 e1000110
        Owning Process            0       Image:         <Unknown>
        Attached Process          8150b5c0       Image:         csrss.exe
        Wait Start TickCount      23986          Ticks: 4438 (0:00:01:09.343)
        Context Switch Count      17                 LargeStack
        UserTime                  00:00:00.093
        KernelTime                00:00:00.031
        Win32 Start Address 0x02b60000
        Start Address KERNEL32!BaseThreadStartThunk (0x7c810669)
        Stack Init f72f6000 Current f72f5a94 Base f72f6000 Limit f72f3000 Call 0
        Priority 13 BasePriority 13 PriorityDecrement 0 DecrementCount 0
        Kernel stack not resident.
        ChildEBP RetAddr 
        f72f5aac 80501366 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
        f72f5ab8 804fabd0 nt!KiSwapThread+0x46 (FPO: [0,0,0])
        f72f5ae0 80598d01 nt!KeWaitForSingleObject+0x1c2 (FPO: [5,5,4])
        f72f5b18 80598e4d nt!LpcpRequestWaitReplyPort+0x43d (FPO: [4,4,0])
        f72f5b30 8060a799 nt!LpcRequestWaitReplyPortEx+0x21 (FPO: [3,0,0])
        f72f5cd4 8060abf7 nt!ExpRaiseHardError+0x1bd (FPO: [Non-Fpo])
        f72f5d44 8053da48 nt!NtRaiseHardError+0x16b (FPO: [Non-Fpo])
        f72f5d44 7c92eb94 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f72f5d64)
        02c6b2d8 7c92e273 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
        02c6b2dc 77d65d43 ntdll!NtRaiseHardError+0xc (FPO: [6,0,0])
        02c6b338 77d48ffe USER32!ServiceMessageBox+0x145 (FPO: [4,13,0])
        02c6b494 77d65fdf USER32!MessageBoxWorker+0x13e (FPO: [1,78,4])
        02c6b4ec 77d66084 USER32!MessageBoxTimeoutW+0x7a (FPO: [6,19,0])
        02c6b520 77d50598 USER32!MessageBoxTimeoutA+0x9c (FPO: [6,2,4])
        02c6b540 77d50550 USER32!MessageBoxExA+0x1b (FPO: [5,0,0])
        02c6b55c 1001811a USER32!MessageBoxA+0x45 (FPO: [4,0,0])
        02c6b594 10012c5e ApiHook!__crtMessageBoxA+0x16a (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/crtmbox.c @ 119]
        02c6c6ec 1001283a ApiHook!CrtMessageWindow+0x2be (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/dbgrpt.c @ 617]
        02c6f768 10011fa3 ApiHook!_CrtDbgReport+0x41a (FPO: [Non-Fpo]) (CONV: cdecl) [f:/vs70builds/3077/vc/crtbld/crt/src/dbgrpt.c @ 516]
        02c6f850 1001320b ApiHook!DllMain+0x53 (FPO: [Non-Fpo]) (CONV: stdcall) [e:/lzz/vc proj/apihook/apihook.cpp @ 20]
        02c6f898 7c9211a7 ApiHook!_DllMainCRTStartup+0xbb (FPO: [Non-Fpo]) (CONV: stdcall) [f:/vs70builds/3077/vc/crtbld/crt/src/dllcrt0.c @ 297]
        02c6f8b8 7c93cbab ntdll!LdrpCallInitRoutine+0x14
        02c6f9c0 7c936178 ntdll!LdrpRunInitializeRoutines+0x344 (FPO: [Non-Fpo])
        02c6fc6c 7c9362da ntdll!LdrpLoadDll+0x3e5 (FPO: [Non-Fpo])
        02c6ff14 7c801bb9 ntdll!LdrLoadDll+0x230 (FPO: [Non-Fpo])
        02c6ff7c 7c801d6e KERNEL32!LoadLibraryExW+0x18e (FPO: [Non-Fpo])
        02c6ff90 7c801da4 KERNEL32!LoadLibraryExA+0x1f (FPO: [3,0,0])
        02c6ffac 02b6000a KERNEL32!LoadLibraryA+0x94 (FPO: [1,0,0])
WARNING: Frame IP not in any known module. Following frames may be wrong.
        02c6ffec 00000000 0x2b6000a
内核函数ExpRaiseHardError根据当前进程的ExceptionPort发送这个消息框调用。这时候刚好csrss的ExceptionPort为NULL,系统使用默认的ExpDefaultErrorPort,但csrss(session 0)是默认的ExpDefaultErrorPortProcess, 操作系统对这个进程的消息不进行LPC投递,直接返回. 这就是为什么第一个csrss被注入没有弹出断言消息框的原因。这之后的第二个csrss进程的ExceptionPort也是NULL,LPC被发送到了ExpDefaultErrorPort,第一个csrss对该消息进行了处理显示了断言消息框。

进一步发现系统中只有system,smss,csrss进程没有ExceptionPort,其它的进程都有ExceptionPort。这个Port的名字就是"ApiPort",每一个session都有一个这样的Port,csrss进程负责监听,而没有ExceptionPort的进程则通过ExpDefaultErrorPort发送,默认由session 0的csrss进程处理。

从csrss弹出的ASSERT对话框谈起相关推荐

  1. 调用API弹出打印机属性对话框

    调用api弹出打印机属性对话框  Author:vitoriatang From:Internet .NET Framework封装了很多关于打印的对话框,比如说PrintDialog, PageSe ...

  2. Delphi中点击网页弹出的Alert对话框的确定按钮

    实现的方法有很多,一般都是使用Windows API函数遍历窗口,查找指定标题的窗口,然后从该窗口查找确定按钮,向该按钮发送鼠标消息进行模拟点击.由于IE8由Alert弹出的网页对话框的标题是&quo ...

  3. C#调用API弹出打印机属性对话框

    调用api弹出打印机属性对话框  Author:vitoriatang From:Internet .NET Framework封装了很多关于打印的对话框,比如说PrintDialog, PageSe ...

  4. php js对话框,JavaScript_js弹出框、对话框、提示框、弹窗实现方法总结(推荐),一、JS的三种最常见的对话框- phpStudy...

    js弹出框.对话框.提示框.弹窗实现方法总结(推荐) 一.JS的三种最常见的对话框 //====================== JS最常用三种弹出对话框 ==================== ...

  5. html弹出保存文件对话框_初步了解CAD的模板文件

    样板文件作为一个模板和标准,通常只保留同类图纸共有的一些参数和图形.用好模板可以夫规范作图,可以达到事半功倍的效果!样板文件的扩展名是dwt. 1.在CAD早期版本中,样板文件很好找,因为在CAD的安 ...

  6. JavaScript弹出框、对话框、提示框、弹窗总结

    JavaScript弹出框.对话框.提示框.弹窗总结. 1.JS的三种最常见的对话框 //====================== JS最常用三种弹出对话框 =================== ...

  7. JavaScript实现弹出“确定/取消”对话框的方法

    在网页中经常会让用户提交一些事件,然后在事件处理之前会弹出"确定/取消"对话框,待用户确定后再利用程序处理事件,今天就教大家如何利用JavaScript实现弹出"确定/取 ...

  8. VB.net MessageBox弹出的确认对话框点击确定按钮

    VB.net MessageBox弹出的确认对话框点击vb.net教程确定按钮 Dim dr As DialogResult = MessageBox.Show("XX", &qu ...

  9. 打印系统开发(30)——调用API弹出打印机属性对话框

    调用api弹出打印机属性对话框 一.printerProperties 二.documentProperties 三.openPrinter 四.closePrinter 五.samplecodes: ...

  10. Windows程序奔溃后,禁止弹出“停止工作”对话框

    在Win7及以后的系统中,如果一个程序发生了奔溃,系统会弹出一个"XX已停止工作"的对话框,如果不去这个窗口上点击"关闭程序",那么这个窗口会一直存在,最为关键 ...

最新文章

  1. 堆排序算法实现思想个人理解
  2. 【BLE MIDI】MIDI 文件格式分析 ( FF 58 04 拍号 | 音符开指令 | 音符关指令 | 音轨结束标志 )
  3. 加载场景不销毁的实现
  4. 计算机操作系统的新技术新知识,计算机操作系统教程:核心与设计原理
  5. 257. 二叉树的所有路径 golang
  6. 触手直播停服,游戏主播们涌入快手
  7. k-center 聚类
  8. python 深度学习超参优化
  9. Leetcode-496-下一个更大元素 I
  10. android studio 2.2 preview 3,Android Studio 2.2 Preview 3 发布,优化图片支持
  11. 新手抖音直播需要什么设备;看完让你少花冤枉钱。
  12. maven命令打jar包
  13. 浏览器htmlcss面试题
  14. java replaceall 问号_java中替换问号 | 学步园
  15. 虚拟机无法ping通物理机解决方案
  16. 前端学习规划xmind
  17. 高考之后,“学”并未止步 :Juphoon Class (菊风云课堂)上线,助力构建实时互动课堂
  18. [晓说]程序员的十层楼
  19. Redis灵魂百问(入门详细基础教程)
  20. hadoop经验调优

热门文章

  1. html 好看表格样式,简单但是好看的表格样式
  2. 车辆动力学模型在仿真测试中的应用实践
  3. 我在b站上大学:计算机类优秀网课汇总【持续更新】
  4. 熟悉VB 6.0界面
  5. C#代码整洁之道:代码重构与性能提升
  6. 代码整洁之道-程序员的职业素养
  7. 基于区块链的医疗供应链数据隐私保护分布式信息隐藏框架
  8. el-table 树形表格 自定义展开图标_目前比较满意的安卓桌面启动器:非线性动画 + 精美图标包...
  9. mysql正则mybatis中用法_SQL正则表达式及mybatis中使用正则表达式
  10. 数据挖掘—网格搜索2