MIC: Message Integrity Check,中文全称:消息完整性检查
是Windows7新引人的概念,Windows XP、Windows Server 2003上面没有,作用:给Windows的进程做一个安全对象标记,通过该标记来判断进程的安全访问权限。
MIC能够使的应用程序以更低的权限运行,降低了进程修改系统或者损害用户数据的可能性。MIC总共有6级,如下所示:
MIC等级 | 说明 |
---|---|
SECURITY_MANDATORY_UNTRUSTED_RID | 不信任的MIC等级 |
SECURITY_MANDATORY_LOW_RID | 低MIC等级,如IE |
SECURITY_MANDATORY_MEDIUM_RID | 中MIC等级,默认为这个等级,如Explorer |
SECURITY_MANDATORY_HIGH_RID | 高MIC等级,以管理员身份运行的程序 |
SECURITY_MANDATORY_SYSTEM_RID | 系统MIC等级,一般是服务应用程序 |
SECURITY_MANDATORY_PROTECTED_PROCESS_RID | 被保护进程的MIC等级 |
UIPI:User Interface Privilege Isalotion,中文全称:用户界面特权隔离
也是Windows 7引入的新机制,用来规范进程窗口之间窗口消息的传递过程,默认规则为:低权限的进程无法发送窗口消息给高权限的进程,反之可以,同权限的进程可以互通消息。
Explorer.exe
是Windows的资源管理器,MIC等级为SECURITY_MANDATORY_MEDIUM_RID,在资源管理器或者桌面双击一个快捷方式或是程序都会创建一个新的进程,该进程来运行双击的程序。由于Explorer.exe是SECURITY_MANDATORY_MEDIUM_RID,所以他创建的任何进程都是SECURITY_MANDATORY_MEDIUM_RID等级的。
Windows高低权限通信的实现
Windows Xp可以任意通信,Windows Vista引入了接口ChangeWindowMessageFilter(UINT message, UINT dwFlag),flags的标志支持:MSGFLT_ADD,MSGFLT_REMOVE;Windows 7引入了新的接口 ChangeWindowMessageFilterEx(HWND hWnd, UINT message, DWORD action,PCHANGEFILTERSTRUCT pChangeFilterStruct),事件的参数可以是 MSGFLT_ALLOW、MSGFLT_DISALLOW 和 MSGFLT_RESET,将窗口重设成默认筛选器,可选的架构允许操作结果以接收更多的信息。
以下是一位网友的测试结果,摘录如下:
发送方进程权限 | 接收方进程权限 | 进程通信结果 |
---|---|---|
低 | 低 | 成功 |
中 | 中 | 成功 |
高 | 高 | 成功 |
低 | 中 高 | 失败 |
中 | 高 | 失败 |
中 | 低 | 成功 |
高 | 中 低 | 成功 |
低 | 中/高+ChangeWindowMessageFilterEx | 自定义消息成功,窗口消息/WM_SYSCOMMAND/WM_COMMAND成功 |
中 | 高+ChangeWindowMessageFilterEx | 自定义消息成功,窗口消息/WM_SYSCOMMAND/WM_COMMAND成功 |
消息发送的方式:
PostMessage(WM_USER, 0, 0);
PostMessage(WM_KEYDOWN, 0, 0)
PostMessage(WM_SYSCOMMAND,0,0)
PostMessage(WM_COMMAND,IDOK,0)
参考路径:https://blog.csdn.net/whatday/article/details/44278605
实例
在Windows 7实现一个文件拖拽功能时,发现正常双击可以实现文件拖拽,当程序以管理员权限运行时就不支持文件拖拽了,百思不得其解,按道理权限高的时候应该更加容易支持才对。通过查找资料,最终找到了合理的解释及实现方法。
原因:Windows 7 新引入了 MIC和UIPI导致了这个原因,当程序以管理员运行时权限为SECURITY_MANDATORY_HIGH_RID,在资源管理器中间文件拖拽到程序上,相当于【资源管理器Explorer.exe】要发送窗口消息WM_DROPFILES给【我的程序】,由于Explorer.exe权限低于【我的程序】所以被UIPI隔离了,发送的消息被丢弃了。
解决方案:使用ChangeWindowMessageFilter将需要发送的消息做过滤筛选,相当于加入白名单,加入了该名单的消息都不会被丢弃。由于ChangeWindowMessageFilter在 user32.dll 动态库库里面,所以加载该动态库调用函数。另外要使WM_DROPFILES生效需要同时使用 WM_WM_COPYGLOBALDATA(此消息 Windows 未公开) 消息,也就是
ChangeWndMessageFilterOk(WM_DROPFILES, MSGFLT_ADD);
ChangeWndMessageFilterOk(0x0049, MSGFLT_ADD); // 0x0049 == WM_COPYGLOBALDATA
BOOL
CExampleDlg::ChangeWndMessageFilterOk(
UINT
nMessage,
BOOL
bAllow)
{
typedef
BOOL
(WINAPI * ChangeWindowMessageFilterOkFn)(
UINT
,
DWORD
);
HMODULE
hModUser32 = NULL;
hModUser32 = LoadLibrary(_T(
"user32.dll"
));
if
(hModUser32 == NULL) {
return
FALSE;
}
ChangeWindowMessageFilterOkFn pfnChangeWindowMessageFilter = (ChangeWindowMessageFilterOkFn) GetProcAddress(hModUser32,
"ChangeWindowMessageFilter"
);
if
(pfnChangeWindowMessageFilter == NULL)
{
FreeLibrary(hModUser32);
return
FALSE;
}
FreeLibrary(hModUser32);
return
pfnChangeWindowMessageFilter(nMessage, bAllow ? MSGFLT_ADD : MSGFLT_REMOVE);
}
参考路径: