出于安全原因,我的应用程序的UI模块使用high
mandatory integrity level运行。除了一件事,它里面的一切都很棒。为了与旧版本兼容,我需要能够让用户向UI模块发出命令行调用。
目前这种机制是这样的:
Windows资源管理器中的快捷方式调用我的模块,例如:
path-to-module\module.exe -op="a, s, r"
当module.exe
进程解析此命令行时,它会使用FindWindow以其唯一的类名来查找UI模块(或其他自我副本)的运行副本。然后,它使用registered message API发送PostMessage。
然后运行的UI模块(具有high
完整性级别)在收到消息时会相应地处理它。
问题在于,因为UI模块的运行副本具有high
完整性级别,所以它无法从较低的完整性级别接收消息,或者在Windows资源管理器运行时无法接收模块的副本解析一个快捷命令,使其以medium
完整性级别运行。
为了解决这个问题,我找到了这个UIAccess
标记(see here,然后向下滚动到它所说的" UI自动化应用程序的UIAccess "。 )
所以我的假设是,如果我设置这个标志并对我的UI模块进行代码签名:
它将能够绕过我上面描述的UIPI限制。
运行得很好:
但我所看到的是,当我从运行PostMessage
完整性级别的模块中调用ERROR_ACCESS_DENIED时,上面描述的算法中的medium
API仍然失败。
我错过了什么?
答案 0 :(得分:4)
Win32 API文档中介绍了您所描述的内容:
如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。当达到限制时,GetLastError返回
ERROR_NOT_ENOUGH_QUOTA
。当UIPI阻止邮件时,使用GetLastError检索的最后一个错误设置为5(访问被拒绝)。
UIPI为User Interface Privilege Isolation的地方:
什么是用户界面权限隔离(UIPI)
这也称为UI权限级别隔离(UIPI)。
作为Vista中安全启动的一部分,具有UI的应用程序将以三种不同的权限级别运行。应用程序窗口可以与相同或更低级别的其他窗口交互,但不能与更高级别/许可的应用程序交互。
只有较高权限的应用程序明确允许并且调用
ChangeWindowMessageFilter()
的消息时,较低权限模式才能向较高权限的应用程序发送消息。此特权较低的应用程序也只能读取更高权限应用程序所拥有的HWND
。Internet Explorer是一个以最低权限级别运行的示例流程。
参考链接:
http://msdn2.microsoft.com/en-us/library/ms632675.aspx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/AccProtVista.asp
UIPI通过阻止以下行为来阻止较低权限进程访问较高权限进程。
较低的权限流程不能:
- 执行更高进程权限的窗口句柄验证 -
SendMessage
或PostMessage
到更高权限的应用程序窗口。这些应用程序编程接口(API)返回成功但静默地删除窗口消息 - 使用线程挂钩附加到更高权限进程 - 使用Journal钩子监视更高权限的过程 - 执行动态链接库(DLL) - 注入更高权限的进程。启用UIPI后,仍会在不同权限级别的进程之间共享以下共享USER资源。
- 桌面窗口,实际上拥有屏幕表面
- 桌面堆只读共享内存
- 全局原子表
- 剪贴板
正如文档所说,较高权限的应用程序需要使用ChangeWindowMessageFilter()
来允许来自较低权限应用程序的特定窗口消息:
从用户界面权限隔离(UIPI)邮件过滤器添加或删除邮件。
在Windows 7及更高版本中,请改用ChangeWindowMessageFilterEx()
:
修改指定窗口的用户界面权限隔离(UIPI)邮件过滤器 。
因此,在您的情况下,在您的较高权限进程调用RegisterWindowMessage()
以获取已注册的消息ID之后,它需要将该ID传递给ChangeWindowMessageFilter/Ex()
,以便从较低特权进程接收该消息。