Background
I'm trying to understand more about the Mandatory Integrity Control system in Windows, and have been looking through the background processes that are running at High
integrity on my laptop.
I've read through all the documentation that I can find on the integrity system, and my understanding is this: The integrity level of a newly started process should be (at most) the lower of the integrity level of the parent process and that of the executable file. If the process wants to elevate above that level, there should be a UAC prompt (assuming UAC is set to Always notify
).
System Info
- Windows 10 Pro 21H2 (build
19044.17066
) - Secure Boot enabled
- UAC set to
Always notify
(highest level on the slider). - PC is domain-joined. (Not sure if that would make any difference.)
- My user account is in the local
Administrators
group. - Group policy settings (under
Windows Settings > Security Settings > Local Policies > Security Options
) are:User Account Control: Admin Approval Mode for the built-in Administrator account
- Value:
Not Defined
- Value:
User Account Control: Allow UIAccess applications to prompt for elevation without using the secure desktop
- Value:
Disabled
- Value:
User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode
- Value:
Prompt for consent on the secure desktop
- Value:
User Account Control: Behavior of the elevation prompt for standard users
- Value:
Prompt for credentials
- Value:
User Account Control: Detect application installations and prompt for elevation
- Value:
Enabled
- Value:
User Account Control: Only elevate executables that are signed and validated
- Value:
Enabled
- Value:
User Account Control: Only elevate UIAccess applications that are installed in secure locations
- Value:
Enabled
- Value:
User Account Control: Run all administrators in Admin Approval Mode
- Value:
Enabled
- Value:
User Account Control: Switch to the secure desktop when prompting for elevation
- Value:
Enabled
- Value:
User Account Control: Virtualize file and registry write failures to per-user locations
- Value:
Enabled
- Value:
Observation
I've found an example of an executable that seems to always run at High
integrity (as reported by Process Explorer). It's an executable called SnagPriv.exe
which is part of TechSmith Snagit 2019. This is normally started by the main Snagit process (Snagit32.exe
, which itself runs at Medium
integrity), and it runs as a background process. However, if I manually start SnagPriv.exe
from a non-elevated (Medium
integrity) command prompt, I get the same behavior - SnagPriv.exe
runs at High
integrity.
Executable info
icacls
output:
icacls 'C:\Program Files\TechSmith\Snagit 2019\SnagPriv.exe'
C:\Program Files\TechSmith\Snagit 2019\SnagPriv.exe NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
BUILTIN\Users:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX)
Successfully processed 1 files; Failed processing 0 files.
All of these ACEs are inherited from C:\Program Files
. They are also all the same on Snagit32.exe
, the executable that calls the one in question.
sigcheck
output:
sigcheck64.exe -m 'C:\Program Files\TechSmith\Snagit 2019\SnagPriv.exe'
Sigcheck v2.82 - File version and signature viewer
Copyright (C) 2004-2021 Mark Russinovich
Sysinternals - www.sysinternals.com
c:\program files\techsmith\snagit 2019\SnagPriv.exe:
Verified: Signed
Signing date: 8:17 AM 27/10/2018
Publisher: TechSmith Corporation
Company: TechSmith Corporation
Description: Snagit RPC Helper
Product: SnagPriv
Prod version: 19.0.1.2448
File version: 19.0.1.2448
MachineType: 64-bit
Manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"><requestedExecutionLevel level="asInvoker" uiAccess="true"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"><asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"><ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</ms_windowsSettings:dpiAware></asmv3:windowsSettings></asmv3:application><ms_compatibility:compatibility xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" xmlns="urn:schemas-microsoft-com:compatibility.v1"><ms_compatibility:application xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1"><ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></ms_compatibility:supportedOS><ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></ms_compatibility:supportedOS><ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></ms_compatibility:supportedOS></ms_compatibility:application></ms_compatibility:compatibility></asmv1:assembly>
Here's the manifest pretty-printed:
<asmv1:assembly manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<trustInfo
xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges
xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="true"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<ms_windowsSettings:dpiAware
xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM
</ms_windowsSettings:dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<ms_compatibility:compatibility
xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1"
xmlns="urn:schemas-microsoft-com:compatibility.v1">
<ms_compatibility:application
xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1">
<ms_compatibility:supportedOS
xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}">
</ms_compatibility:supportedOS>
<ms_compatibility:supportedOS
xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}">
</ms_compatibility:supportedOS>
<ms_compatibility:supportedOS
xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}">
</ms_compatibility:supportedOS>
</ms_compatibility:application>
</ms_compatibility:compatibility>
</asmv1:assembly>
My understanding of the above is:
- The
SnagPriv.exe
executable has no integrity label, which means it should default toMedium
. Note that if I add an integrity label ofLow
to the executable then it doesn't change the end result. - The executable is signed, but this should not cause the UAC prompt to be bypassed. (Even if it were signed by Microsoft, which it is not.)
- The manifest does not request elevation. (And even if it did, the UAC prompt should not be bypassed.)
Observed Behavior
If I use Process Monitor to observe what happens when I manually start SnagPriv.exe
from a Medium
command prompt, I can see that it actually runs three times in succession. The first two times, it runs at Medium
integrity (or Low
if I add the explicit label to the executable). Then, a consent.exe
process starts, and finishes straight away (without showing me a UAC prompt). Finally, SnagPriv.exe
runs for a third time, now at High
integrity. All three runs of SnagPriv.exe
have my Medium
command prompt as their parent process.
Possible explanations
Here are the possible explanations I can think of:
SnagPriv.exe
is requesting elevation from some other "colluding" process that is already running atHigh
integrity. (However I have checked and this behavior occurs even when there are no other processes running that are part of this application.)- The application has stored some sort of persistent access token that allows it to elevate. (Not sure if this is possible.)
- Some sort of UAC bypass exploit is being done. (Seems highly unlikely, as this is a reputable application.)
- My UAC settings are being ignored, or I have misunderstood what they mean. This would explain why
consent.exe
runs but doesn't show the prompt. (Note though that UAC seems to be working as expected other than this case.) - There is some mechanism that I'm not aware of for an executable (or signer) to be registered as not requiring a UAC prompt (e.g. in the registry somewhere). Obviously I would expect such a setting to be only modifiable from
High
integrity, but this could have been done at install time. (I would have run the installer elevated.)
Just to be clear, my question isn't about why this particular application needs to have a process running at High
integrity. (I'm fairly sure this is legitimate, as it's a screen-capture app.) I'd just like to understand how it is able to do this, so that I can be on the lookout for malicious code that might use the same mechanism. I'm sure I'm just missing something obvious, but I have no idea what it is.
Does anyone know what I might be missing? Or are there any tools that I could use to better understand what's going on? I've tried Process Monitor and API Monitor, but they both return tons of output for the relevant processes, and I'm not sure what types of API calls I should be looking at to narrow it down.