1、Win7UAC的安全、相容及許可權

hopegrace發表於2010-11-24

網上關於這個問題討論較多,但也不外乎幾種方法。總結一下,如附中。順便了解一個UAC。 

UAC,全稱User Account Control(使用者帳戶控制) 

System Safe Monitor(主機入侵防禦系統)

UAC是如何工作的[3]

我們可以簡單的把UAC當作許可權臨時重分配的工具。在預設情況下,所有的非系統核心程式都只擁有標準許可權,這一許可權不能對系統關鍵區域進行修改。對於一個程式,如果它當中含有提權申請,則在執行時會彈出UAC視窗要求提權。如果使用者允許,則程式暫時性的獲得了最高許可權,可以對系統關鍵區域進行更改;如果使用者拒絕,則程式被拒絕執行。而如果程式中沒有提權申請,則系統會讓程式執行於標準許可權下。同時,對於所有程式,都可以用“以管理員身份執行”的方式手動提權。而即便病毒感染了系統,它也處於UAC的監視之下,這使得病毒的反清除行為會受到很大阻礙。正是憑藉這一機制,UAC成為了一道重要的系統防火牆。

在 Windows7(NT6.x系統)中,系統取消了對移動裝置Autorun.inf的支援

使用者介面特權隔離[5]

在早期的Windows作業系統中,在同一使用者下執行的所有程式有著相同的安全等級,擁有相同的許可權。例如,一個程式可以自由地傳送一個Windows訊息到另外一個程式的視窗。從Windows Vista開始,當然也包括Windows 7,對於某些Windows訊息,這一方式再也行不通了。程式(或者其他的物件)開始擁有一個新的屬性——特權等級(Privilege Level)。一個特權等級較低的程式不再可以向一個特權等級較高的程式傳送訊息,雖然他們在相同的使用者許可權下執行。這就是所謂的使用者介面特權隔離 (User Interface Privilege Isolation,UIPI)。

UIPI的引入,最大的目的是防止惡意程式碼傳送訊息給那些擁有較高許可權的視窗以對其進行攻擊,從而獲取較高的許可權等等。

UIPI的執行機制

在Windows 7中,當UAC(User Account Control)啟用的時候,UIPI的執行可以得到最明顯的體現。在UAC中,當一個管理員使用者登入系統後,作業系統會建立兩個令牌物件(Token Object):第一個是管理員令牌,擁有大多數特權(類似於Windows Vista之前的System中的使用者),而第二個是一個經過過濾後的簡化版本,只擁有普通使用者的許可權。

預設情況下,以普通使用者許可權啟動的程式擁有普通特權等級(UIPI的等級劃分為低等級(low),普通(normal),高等級(high),系統 (system))。同樣的,以管理員許可權執行的程式,例如,使用者右鍵單擊選擇“以管理員身份執行”或者是通過新增“runas”引數呼叫 ShellExecute執行的程式,這樣的程式就相應地擁有一個較高(high)的特權等級。

這將導致系統會執行兩種不同型別,不同特權等級的程式(當然,從技術上講這兩個程式都是在同一使用者下)。我們可以使用Windows Sysinternals工具集中的程式瀏覽器(Process Explorer)檢視各個程式的特權等級。[6]

所以,當你發現你的程式之間Windows訊息通訊發生問題時,不妨使用程式瀏覽器檢視一下兩個程式之間是否有合適的特權等級。

UIPI所帶來的限制

正如我們前文所說,等級的劃分,是為了防止以下犯上。所以,有了使用者介面特權隔離,一個執行在較低特權等級的應用程式的行為就受到了諸多限制,它不可以:

驗證由較高特權等級程式建立的視窗控制程式碼

通過呼叫SendMessage和PostMessage向由較高特權等級程式建立的視窗傳送Windows訊息

使用執行緒鉤子處理較高特權等級程式

使用普通鉤子(SetWindowsHookEx)監視較高特權等級程式

向一個較高特權等級程式執行DLL注入

但是,一些特殊Windows訊息是容許的。因為這些訊息對程式的安全性沒有太大影響。這些Windows訊息包括:

0x000 – WM_NULL

0x003 – WM_MOVE

0x005 – WM_SIZE

0x00D – WM_GETTEXT

0x00E – WM_GETTEXTLENGTH

0x033 – WM_GETHOTKEY

0x07F – WM_GETICON

0x305 – WM_RENDERFORMAT

0x308 – WM_DRAWCLIPBOARD

0x30D – WM_CHANGECBCHAIN

0x31A – WM_THEMECHANGED

0x313, 0x31B (WM_???)

修復UIPI問題

基於Windows Vista之前的作業系統行為所設計的應用程式,可能希望Windows訊息能夠在程式之間自由的傳遞,以完成一些特殊的工作。當這些應用程式在 Windows 7上執行時,因為UIPI機制,這種訊息傳遞被阻斷了,應用程式就會遇到相容性問題。為了解決這個問題,Windows Vista引入了一個新的API函式ChangeWindowMessageFilter[7]。利用這個函式,我們可以新增或者刪除能夠通過特權等級隔離的 Windows訊息。這就像擁有較高特權等級的程式,設定了一個過濾器,允許通過的Windows訊息都被新增到這個過濾器的白名單,只有在這個白名單上的訊息才允許傳遞進來。

如果我們想容許一個訊息可以傳送給較高特權等級的程式,我們可以在較高特權等級的程式中呼叫ChangeWindowMessageFilter函式,以 MSGFLT_ADD作為引數將訊息新增進訊息過濾器的白名單。同樣的,我們也可以以MSGFLT_REMOVE作為引數將這個訊息從白名單中刪除。

一個示例

對於系統訊息的處理,接受訊息的程式需要將該訊息加入到白名單中,可以通過下面的程式碼實現:

需要在高許可權程式開始的地方加入以下程式碼,指定什麼訊息可以接受

 

程式碼

1 typedef BOOL (WINAPI *_ChangeWindowMessageFilter)( UINT , DWORD);
2
3 BOOL CVistaMsgRecvApp::AllowMeesageForVista(UINT uMessageID, BOOL bAllow)//註冊Vista全域性訊息
4  {
5 BOOL bResult = FALSE;
6 HMODULE hUserMod = NULL;
7  //vista and later
8 hUserMod = LoadLibrary( Luser32.dll );
9 if( NULL == hUserMod )
10 {
11 return FALSE;
12 }
13 _ChangeWindowMessageFilter pChangeWindowMessageFilter = (_ChangeWindowMessageFilter)GetProcAddress( hUserMod, ChangeWindowMessageFilter );
14 if( NULL == pChangeWindowMessageFilter )
15 {
16 AfxMessageBox(_T(create windowmessage filter failed));
17 return FALSE;
18 }
19 bResult = pChangeWindowMessageFilter( uMessageID, bAllow ? 1 : 2 );//MSGFLT_ADD: 1, MSGFLT_REMOVE: 2
20 if( NULL != hUserMod )
21 {
22 FreeLibrary( hUserMod );
23 }
24 return bResult;
25 }

對於自定義訊息,通常是指大於WM_USER的訊息,我們首先必須在系統中註冊該訊息,然後在呼叫上面的程式碼:

 


#define WM_MYNEWMESSAGE (WM_USER + 999)
UINT uMsgBall=::RegisterWindowMessage (WM_MYNEWMESSAGE )
if(!uMsgBall)
return FALSE;

註冊訊息通過RegisterWindowMessage實現,函式的引數就是你需要註冊的訊息值。

此時,低等級的程式就可以像高等級的程式傳送訊息了。

附 Win7下如何讓應用程式以管理員身份進行安裝執行

1、法一:

runas /profile /env /user:mydomainadmin “mmc %windir%system32dsa.msc”

我感覺這種方法不靠譜。

2、法二:

通過manifest檔案使VC應用程式獲得管理員許可權

這種方法還不錯[1]。

<security>

<requestedPrivileges>

<requestedExecutionLevel level=”requireAdministrator” uiAccess=”false”/>

</requestedPrivileges>

</security>

3、法三:

起名為setup,win7會自己提升許可權,增加manifest檔案。還有一種方法是改登錄檔。HKEY_CURRENT_USERSoftware MicrosoftWindows NTCurrentVersionAppCompatFlagsLayers

新增一個字串值 名稱就是你的程式的路徑和名字,值為RUNASADMIN。

也可以做成服務。

4、其它方法:

還有的網友說:有個開源的專案叫做RunAs,就是用來以指定使用者來執行程式的專案,可以參考

參考網址和更多閱讀

[1] http://hi.baidu.com/crowreturns/blog/item/f5e7cefd7546a284b801a07e.html

[2] http://www.cnblogs.com/sun8134/archive/2009/10/30/1593025.html

[3] 360 論壇

[4] http://topic.csdn.net/u/20100203/14/d98d8310-4971-47d1-94b1-9cdfbf159b4f.html

[5] http://blog.csdn.net/jinhill/archive/2010/07/21/5752870.aspx

[6] Sysinternals Utilities Index

http://technet.microsoft.com/en-us/sysinternals/bb545027.aspx

[7] ChangeWindowMessageFilter

http://msdn.microsoft.com/en-us/library/ms632675%28VS.85%29.aspx

[ Using the ChangeWindowMessageFilter function is not recommended, as it has process-wide scope. Instead, use the ChangeWindowMessageFilterEx function to control access to specific windows as needed. ChangeWindowMessageFilter may not be supported in future versions of Windows.]

[8]http://it.chinawin.net/softwaredev/article-b6f9.html


相關文章