Windows 小记 8 -- EndTask 结束任务的安全问题

EndTask 函数用于结束任务,它会强制终止目标窗口的进程,因此不建议用于常规操作。

这种终止方式属于暴力手段,不会允许进程资源的释放。某些软件可能会使用此方法来强制结束顽固的 GUI 进程。此功能在 taskmgr.exe(任务管理器)中的实现形式是进程列表中的“结束任务”功能。在最新的 Windows 11 中,用户可以通过开发者选项启用它,这会在任务栏右键菜单中添加“结束任务”选项。

通过我的测试发现,EndTask 函数没有进行任何安全边界检查,允许低权限用户终止受保护的进程和系统关键进程。终止这些关键进程会导致系统蓝屏。

例如,GetDesktopWindow() 函数可以获取桌面顶级窗口的句柄(#32769),这在我之前的动态壁纸制作研究文章中有提到。这个窗口属于 CSRSS 进程,而 CSRSS 是一个系统关键进程。终止该进程会导致系统立即蓝屏。

以下代码会导致 CSRSS 进程停止工作:

EndTask(GetDesktopWindow(), FALSE, TRUE);

通过分析 EndTask 函数的实现细节,我发现该函数最终通过与 CSRSS 进程通信,请求调用 CSR 中的服务接口来终止目标窗口(进程)。换句话说,以上代码会导致 CSRSS 自己终止自己,由于它是系统关键进程,这会导致系统蓝屏。

那么是否除了 GetDesktopWindow() 外,我们就没有其他跟特权进程 CSRSS 进程有关的窗口了?答案是否定的,我们可以轻松通过多种方式胁迫 CSRSS 生成交互式窗口。

比如 MessageBox 函数,我们知道它可以生成消息框,用于显示一些需要立即通知的错误消息。但你是否知道它有一些文档中从未提及的特性?

MessageBox 函数的定义为:

int MessageBox(
  HWND    hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT    uType
);

当调用者(仅需普通权限的进程)尝试在 uType 中指定:MB_DEFAULT_DESKTOP_ONLY 或者 MB_SERVICE_NOTIFICATION 时,将生成交互式消息框。此类消息框由 CSRSS 进程的线程创建,提供给非交互式进程(主要为服务)快捷地向交互式用户显示重要信息。

使 CSRSS 生成消息框

注意:在包括 Windows NT 4.0 在内的早期版本系统中,只有在 SYSTEM 特权进程中设置 MB_DEFAULT_DESKTOP_ONLY、MB_SERVICE_NOTIFICATION、MB_TOPMOST 或 MB_SERVICE_NOTIFICATION_NT3X 中的任意一个标志位,才会出现此现象。而在 Windows Vista 及更高版本中,MB_TOPMOST 和 MB_SERVICE_NOTIFICATION_NT3X 标志位则不会导致消息框由 CSRSS 进程生成,无论是特权还是非特权。

调用 MessageBox 消息框的底层有两个分支:一个是 SoftModalMessageBox 另一个就是 ServiceMessageBox。ServiceMessageBox 是服务消息框, SoftModalMessageBox 是普通消息框。

ServiceMessageBox 内检测当前调用线程的会话是否是活动的交互式用户会话,如果是,则直接调用 NtRaiseHardError (ExpRaiseHardError)。而这个函数内部其实是通信 CSRSS。

  • Windows 2000 (NT 5.0) 至 Windows Server 2003 (NT 5.1) ExpRaiseHardError 调用 LPC 函数 LpcRequestWaitReplyPortEx 通知 CSRSS,并传入 HARDERROR_MSG 结构。目标LPC 端口是本进程的 EPROCESS.ExceptionPort。

  • Windows Vista (NT 6.0) 以后 Vista 的内核是一次史诗级更新,换成了 ALPC。为了保持兼容性,内核导出的 LPC API 依然存在,但它们仅简单地调用 ALPC 的相关函数。 ExpRaiseHardError 调用的是 LpcSendWaitReceivePort 函数,这个函数只是进入临界区之后调用 ALPC 组件的 AlpcpProcessSynchronousRequest 函数而已,目标端口保持不变。

如果会话不同,则通过 WinStationSendMessage 将消息先发送至目标会话的 CSRSS。然后由目标活动会话的 CSRSS 拉起窗口。

总结(不一定最正确):

(1)尽量不要在应用中使用 assert() 等断言,减少 CRT 的使用;

(2)MessageBox 函数不要使用 MB_SERVICE_NOTIFICATION / MB_DEFAULT_DESKTOP_ONLY;

(3)不要使用 WinStationSendMessage 和 WTSSendMessage 等函数;

(4)主进程由启动器进程启动,在启动器进程中关闭硬件错误消息弹窗;

(5)通过 Hook 挂钩 NtRaiseHardError,拦截程序运行过程中可能由内部代码错误引起的任何弹窗,修改成自己的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涟幽516

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值