如何让应用不受 Windows UIPI 机制影响

前言

关于 UIPI (User Interface Privilege Isolation) ,官方文档 已经给出了详细的描述,该机制阻止某些行为来防止较低权限的进程访问较高权限的进程,以下是官方文档中列出的被阻止的行为

A lower privilege process cannot:

  • Perform a window handle validation of higher process privilege.
  • SendMessage or PostMessage to higher privilege application windows. These Application Programming Interfaces (APIs) return success but silently drop the window message.
  • Use thread hooks to attach to a higher privilege process.
  • Use Journal hooks to monitor a higher privilege process.
  • Perform DLL injection to a higher privilege process.

解决方案

那我们该如何允许被阻止的行为?

方式一 : UIAccess

做法 : 在应用程序清单文件 app.manifest 中,将 uiAccess 设置为 true (默认值是 false)。同时你还需要给应用程序进行数字签名。

<requestedExecutionLevel level="asInvoker" uiAccess="true" />

影响 :

  • 如果你设置了 UIAccess 的应用程序可能会被其它应用启动,那么需要注意其它应用启动该应用时,请明确设置 UseShellExecute = true, 不然将因为权限问题导致启动失败。
using (Process process = Process.Start(new ProcessStartInfo()
{
    UseShellExecute = true,
    Arguments = string.Empty,
    FileName = "D:\\test.exe",
}))
  • 如果你的应用的窗口已经设置了 Topmost = true,那么 UIAccess 的加入将会使你的窗口层级更高。

方式二 : 更改注册表,Windows 重启后生效(慎重)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 下增加 EnableUIPI 以达到禁用 UIPI 机制的效果,需要注意,一旦这样设置,意味着 Windows UIPI 的约束将不再起作用。

EnableUIPI 注册表示例

方式三 : 提高进程的完整性级别
从官方文档中,可以看到 Windows 定义了四种完整性级别:low, medium, high, system。那么可以尽量提高进程的完整性级别。(比如,以管理员的方式启动应用)

方式四 : ChangeWindowMessageFilterEx
该 API 能修改指定窗口的 UIPI 消息过滤。比如在如下示例中,进程 A 采用管理员方式启动,考虑到对接的应用完整性级别参差不齐,那么就可以通过 ChangeWindowMessageFilterEx 指定消息过滤,让低完整性级别的进程也能发送消息给到高完整性级别的进程。

public partial class MainWindow : Window //进程 A 代码示例
{
    private const int WM_APP = 0x8000;
    private const int WM_CUSTOM_MESSAGE = WM_APP + 1;

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool ChangeWindowMessageFilterEx(IntPtr hwnd, uint msg, uint action, IntPtr pChangeFilterStruct);

    private enum MessageFilterAction
    {
        MSGFLT_ALLOW = 1,
        MSGFLT_DISALLOW = 2,
        MSGFLT_RESET = 0
    }

    public MainWindow()
    {
        InitializeComponent();
        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
        hwndSource.AddHook(WndProc);
        ChangeWindowMessageFilterEx(hwndSource.Handle, WM_CUSTOM_MESSAGE, (uint)MessageFilterAction.MSGFLT_ALLOW, IntPtr.Zero);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_CUSTOM_MESSAGE)
        {
            MessageBox.Show($"Message received.");
            handled = true;
        }

        return IntPtr.Zero;
    }
}
posted @   学,然后知不足  阅读(119)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示