MIC、UIPI、Explorer.exe、Windows訊息傳遞的理解 ,附具體案例說明
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)
例項
在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);
}
參考路徑: