Cross-process PostMessage, UIPI restrictions and U

2019-07-17 05:59发布

问题:

For security reasons the UI module for my application runs with a high mandatory integrity level. Everything in it works great, except one thing. For compatibility with older versions I need to be able to let users issue command line calls to the UI module.

At the moment this mechanism works as such:

  1. The shortcut from Windows Explorer calls my module, say as such:

    path-to-module\module.exe -op="a, s, r"
    
  2. When module.exe process parses this command line it then locates the running copy of UI module (or another copy of self) using FindWindow by its unique class name. It then sends it a registered message using PostMessage API.

  3. Then the running UI module (with high integrity level), when it receives the message, processes it accordingly.

The problem is that because the running copy of UI module has high integrity level, it cannot receive messages from a lower integrity level, or the copy of the module when it's run by the Windows Explorer to parse a shortcut command, which makes it run with medium integrity level.

To address this I found this UIAccess flag (see here, and scroll down to where it says "UIAccess for UI automation applications".)

So my assumptions were that if I set this flag and code-sign my UI module:

it will be able to bypass the UIPI restriction I described above.

It runs just fine:

But what I see is that PostMessage API in the algorithm I described above still fails with ERROR_ACCESS_DENIED when I call it from the module running with medium integrity level.

What have I missed there?

回答1:

What you describe is covered in the Win32 API documentation:

PostMessage function

If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError returns ERROR_NOT_ENOUGH_QUOTA when the limit is hit.

When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).

Where UIPI is User Interface Privilege Isolation:

What is User Interface Privilege Isolation (UIPI)

This is also known as UI Privilege Level Isolation (UIPI).

As part of the secure initiatuve in Vista, applications with UI will run in three different levels of privilege. Application windows can interact with others windows of the same or lower levels, but cannot interact with applications at higher level/permission.

Lower privilege modes can send messages to higher privileged applications only if explicitly allowed by the higher privilege application with a message calling ChangeWindowMessageFilter(). Also lower privileged applications can only read a HWND owned by a higher privileged application.

Internet Explorer is an example process that runs at the lowest privilege level.

Reference Links:
http://msdn2.microsoft.com/en-us/library/ms632675.aspx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/AccProtVista.asp

UIPI prevents lower privilege processes from accessing higher privilege processes by blocking the following behavior.

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 dynamic link library (DLL)–injection to a higher privilege process.

With UIPI enabled, the following shared USER resources are still shared between processes at different privilege levels.

– Desktop window, which actually owns the screen surface
– Desktop heap read-only shared memory
– Global atom table
– Clipboard

As the documentation says, the higher privilege application needs to use ChangeWindowMessageFilter() to allow specific window messages from lower privilege applications:

Adds or removes a message from the User Interface Privilege Isolation (UIPI)message filter.

On Windows 7 and later, use ChangeWindowMessageFilterEx() instead:

Modifies the User Interface Privilege Isolation (UIPI) message filter for a specified window.

So, in your case, after your higher privileged process calls RegisterWindowMessage() to get a registered message ID, it needs to pass that ID to ChangeWindowMessageFilter/Ex() in order to receive that message from lower privileged processes.