从csrss弹出的ASSERT对话框谈起
昨天遇到一件怪事,在进行远程线程注入的时候从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对话框谈起相关推荐
- 调用API弹出打印机属性对话框
调用api弹出打印机属性对话框 Author:vitoriatang From:Internet .NET Framework封装了很多关于打印的对话框,比如说PrintDialog, PageSe ...
- Delphi中点击网页弹出的Alert对话框的确定按钮
实现的方法有很多,一般都是使用Windows API函数遍历窗口,查找指定标题的窗口,然后从该窗口查找确定按钮,向该按钮发送鼠标消息进行模拟点击.由于IE8由Alert弹出的网页对话框的标题是&quo ...
- C#调用API弹出打印机属性对话框
调用api弹出打印机属性对话框 Author:vitoriatang From:Internet .NET Framework封装了很多关于打印的对话框,比如说PrintDialog, PageSe ...
- php js对话框,JavaScript_js弹出框、对话框、提示框、弹窗实现方法总结(推荐),一、JS的三种最常见的对话框- phpStudy...
js弹出框.对话框.提示框.弹窗实现方法总结(推荐) 一.JS的三种最常见的对话框 //====================== JS最常用三种弹出对话框 ==================== ...
- html弹出保存文件对话框_初步了解CAD的模板文件
样板文件作为一个模板和标准,通常只保留同类图纸共有的一些参数和图形.用好模板可以夫规范作图,可以达到事半功倍的效果!样板文件的扩展名是dwt. 1.在CAD早期版本中,样板文件很好找,因为在CAD的安 ...
- JavaScript弹出框、对话框、提示框、弹窗总结
JavaScript弹出框.对话框.提示框.弹窗总结. 1.JS的三种最常见的对话框 //====================== JS最常用三种弹出对话框 =================== ...
- JavaScript实现弹出“确定/取消”对话框的方法
在网页中经常会让用户提交一些事件,然后在事件处理之前会弹出"确定/取消"对话框,待用户确定后再利用程序处理事件,今天就教大家如何利用JavaScript实现弹出"确定/取 ...
- VB.net MessageBox弹出的确认对话框点击确定按钮
VB.net MessageBox弹出的确认对话框点击vb.net教程确定按钮 Dim dr As DialogResult = MessageBox.Show("XX", &qu ...
- 打印系统开发(30)——调用API弹出打印机属性对话框
调用api弹出打印机属性对话框 一.printerProperties 二.documentProperties 三.openPrinter 四.closePrinter 五.samplecodes: ...
- Windows程序奔溃后,禁止弹出“停止工作”对话框
在Win7及以后的系统中,如果一个程序发生了奔溃,系统会弹出一个"XX已停止工作"的对话框,如果不去这个窗口上点击"关闭程序",那么这个窗口会一直存在,最为关键 ...
最新文章
- 堆排序算法实现思想个人理解
- 【BLE MIDI】MIDI 文件格式分析 ( FF 58 04 拍号 | 音符开指令 | 音符关指令 | 音轨结束标志 )
- 加载场景不销毁的实现
- 计算机操作系统的新技术新知识,计算机操作系统教程:核心与设计原理
- 257. 二叉树的所有路径 golang
- 触手直播停服,游戏主播们涌入快手
- k-center 聚类
- python 深度学习超参优化
- Leetcode-496-下一个更大元素 I
- android studio 2.2 preview 3,Android Studio 2.2 Preview 3 发布,优化图片支持
- 新手抖音直播需要什么设备;看完让你少花冤枉钱。
- maven命令打jar包
- 浏览器htmlcss面试题
- java replaceall 问号_java中替换问号 | 学步园
- 虚拟机无法ping通物理机解决方案
- 前端学习规划xmind
- 高考之后,“学”并未止步 :Juphoon Class (菊风云课堂)上线,助力构建实时互动课堂
- [晓说]程序员的十层楼
- Redis灵魂百问(入门详细基础教程)
- hadoop经验调优
热门文章
- html 好看表格样式,简单但是好看的表格样式
- 车辆动力学模型在仿真测试中的应用实践
- 我在b站上大学:计算机类优秀网课汇总【持续更新】
- 熟悉VB 6.0界面
- C#代码整洁之道:代码重构与性能提升
- 代码整洁之道-程序员的职业素养
- 基于区块链的医疗供应链数据隐私保护分布式信息隐藏框架
- el-table 树形表格 自定义展开图标_目前比较满意的安卓桌面启动器:非线性动画 + 精美图标包...
- mysql正则mybatis中用法_SQL正则表达式及mybatis中使用正则表达式
- 数据挖掘—网格搜索2