技术开发 频道

VS与Win7 共舞:用户界面特权隔离

  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。利用这个函数,我们可以添加或者删除能够通过特权等级隔离的Windows消息。这就像拥有较高特权等级的进程,设置了一个过滤器,允许通过的Windows消息都被添加到这个过滤器的白名单,只有在这个白名单上的消息才允许传递进来。

  如果我们想容许一个消息可以发送给较高特权等级的进程,我们可以在较高特权等级的进程中调用ChangeWindowMessageFilter函数,以MSGFLT_ADD作为参数将消息添加进消息过滤器的白名单。同样的,我们也可以以MSGFLT_REMOVE作为参数将这个消息从白名单中删除。例如:

// 需要的头文件

#include
<windows.h>
#include
<tchar.h>
#include
"resource.h"

// 全局对象
HINSTANCE g_hInstance;
HWND g_hFirstWnd;

// 消息处理函数

INT_PTR CALLBACK PingPongDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow) {
    g_hInstance
= hInstance;
    
// 获得窗口的句柄
       g_hFirstWnd = FindWindow(NULL, _T("用户界面特权等级隔离"));

    TCHAR text[
256];
    LoadString(g_hInstance, g_hFirstWnd
? IDS_PING : IDS_PONG, text, 256);
    
return DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_PINGPONG), NULL, PingPongDlgProc, (LPARAM)text);
}

// 处理对话框消息
INT_PTR CALLBACK PingPongDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    
static LPCTSTR pszPingPong;
    
static HWND hWndSend;
    
static UINT uMsgBall;
    TCHAR sMessageBall[
256];

    
switch (message) {
        
case WM_INITDIALOG:
            pszPingPong
= (LPCTSTR)lParam;
            
if(!LoadString(g_hInstance, IDS_MESSAGE_BALL, sMessageBall, 256))
                
return FALSE;

                      
// 注册新的全局自定义消息,这里的全局,针对此进程而言
            uMsgBall = RegisterWindowMessage(sMessageBall);
            
if(!uMsgBall) return FALSE;

            
// 调用ChangeWindowMessageFilter函数,允许此消息可以传递进来
            ChangeWindowMessageFilter(uMsgBall, MSGFLT_ADD);

            
// 开始发送消息给其他进程,也就是此应用程序的另一个实例
            if (g_hFirstWnd)
                PostMessage(g_hFirstWnd, uMsgBall, (WPARAM)hwndDlg,
0);
            
return TRUE;

        
case WM_TIMER:
            KillTimer(hwndDlg,
1);
            SetDlgItemText(hwndDlg, IDC_TEXT, _T(
""));
            PostMessage(hWndSend, uMsgBall, (WPARAM)hwndDlg,
0); //Send the ball.
            return TRUE;

        
default:
            
if(message == uMsgBall) {        // 如果是我们自定义的消息
                SetDlgItemText(hwndDlg, IDC_TEXT, pszPingPong);
                hWndSend
= (HWND)wParam;
                SetTimer(hwndDlg,
1, 500, 0);    
                
return TRUE;
            }
    }
    
    
return FALSE;
}
0
相关文章