網上關于這個問題讨論較多,但也不外乎幾種方法。總結一下,如附中。順便了解一個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( L"user32.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的消息,我們首先必須在系統中注冊該消息,然後在調用上面的代碼:
注冊消息通過RegisterWindowMessage實作,函數的參數就是你需要注冊的消息值。
此時,低等級的程序就可以像高等級的程序發送消息了。
附 Win7下如何讓應用程式以管理者身份進行安裝執行
1、法一:
runas /profile /env /user:mydomain\admin "mmc %windir%\system32\dsa.msc"
我感覺這種方法不靠譜。
2、法二:
通過manifest檔案使VC應用程式獲得管理者權限
這種方法還不錯[1]。
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
3、法三:
起名為setup,win7會自己提升權限,增加manifest檔案。還有一種方法是改系統資料庫。HKEY_CURRENT_USER\Software \Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
添加一個字元串值 名稱就是你的程式的路徑和名字,值為RUNASADMIN。
也可以做成服務。
4、其它方法:
還有的網友說:有個開源的項目叫做RunAs,就是用來以指定使用者來運作程式的項目,可以參考
參考網址和更多閱讀
[3] 360 論壇
[6] Sysinternals Utilities Index
<a href="http://technet.microsoft.com/en-us/sysinternals/bb545027.aspx">http://technet.microsoft.com/en-us/sysinternals/bb545027.aspx</a>
[7] ChangeWindowMessageFilter
<a href="http://msdn.microsoft.com/en-us/library/ms632675%28VS.85%29.aspx">http://msdn.microsoft.com/en-us/library/ms632675%28VS.85%29.aspx</a>
[ 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