Article logo

User Account Control

bypassing UAC to get full privileges

Introduction


Since my last article was about Windows Access Tokens, I thought it would be interesting to write about the User Account Control security feature in Windows.


Today, we'll go over what UAC is and how it works at a high level, building on the concepts from my previous article. We'll also look at some common bypass techniques and how it has historically been shown to be a not very effective security feature.


Before continuing, if you’re not familiar with Windows access tokens, I recommend checking out my previous article on the topic, where I dive into what they are and the crucial role they play in the Windows operating system.


Note


There are many articles out there describing this security feature and how to bypass it. In this article, I'll explain how it works and walk through some techniques to get around it. I’m not introducing any novel bypass techniques here, so full credit goes to the original authors of each technique shown.


User Account Control


I'm pretty sure that at some point you've come across this dialog when running something as administrator:



Well, that's the UAC consent prompt. Basically, it shows up when an application needs to perform a privileged action or when you run something as administrator. When you click "Yes", the application requesting those administrator privileges switches to a higher-privilege context, which allows it to perform more sensitive actions.


But why does this even exist?


User Account Control (UAC) is a built-in Windows security feature meant to help prevent unauthorized changes to the system. Whenever something tries to make changes that require administrator-level permissions, UAC steps in and asks the user to either approve or deny the action.


The idea behind this is to reduce the chances of malicious code running with full administrative privileges. Instead of everything having full control by default, UAC forces a checkpoint where the user has to explicitly allow sensitive actions.


Unless UAC is turned off, it's also designed to make it harder for malware to tamper with its settings or disable it altogether. It's enabled by default on Windows systems, but it can be configured if you have administrative privileges.


How it works


Let's look at an example of UAC in action. I'll run cmd.exe (without using "Run as administrator") and check my user privileges:



As shown in the output, my user is a local administrator (since it's a member of the Administrators group). However, when running whoami /priv, we can see that no special privileges are enabled, we're effectively in a limited context.


And that's exactly what's going on. UAC restricts the user access token to prevent every application from running with full privileges by default.


Now, let's see what happens when we run cmd.exe as administrator:



This time, we have all the privileges of a local administrator. In other words, our token is no longer limited.


Limited Access Token and Full Access Token


Previously, I mentioned some important concepts like the “limited token”, but what does that actually mean?


As I explained in my last article, an access token represents the security context of a process or thread and defines what privileges it has. In simple terms, it's what Windows uses to decide what a process is allowed to do and what it isn’t.


An access token includes things like the user identity, the groups the user belongs to (like Administrators), and a set of privileges (such as the ability to debug processes or modify system settings). Every time a process is created, it gets a copy of a token, and from that point on, all access checks are based on it.


Now, tying this back to UAC, not all tokens are created equal. Even if you're part of the Administrators group, Windows can give your processes a filtered (or limited) token, where certain privileges are removed or disabled. This is what prevents everything from running with full administrative rights by default.


Logon process


When you log in to the system, the LSA verifies your credentials and creates your access token, which defines your security context.


If you're a member of the Administrators group, things get a bit more interesting. Instead of giving you full privileges right away, Windows actually creates two separate access tokens: a standard (limited) token and a full administrator token. The last one is linked to the initial one.


The standard token is the one used by default. It contains your user information, but most administrative privileges are removed or disabled, and the Administrators group SID is marked as deny-only. In practice, this means your processes behave like those of a regular user, even though you're technically an administrator.


This limited token is used to start the desktop (via explorer.exe) and, from there, all child processes inherit it. That’s why everything you launch normally runs in a restricted context.


The full administrator token, on the other hand, is only used when you explicitly approve an elevation prompt (the UAC prompt). Once you click "Yes", the process is started again, but this time using the unrestricted token, with all administrative privileges enabled.


This is exactly what we saw when running whoami /priv without elevation, the cmd process was created using the standard (limited) user token.


On the other hand, when we ran cmd as administrator, the process was started with the full access token instead, which is why all privileges were available.


Secure Desktop


When running something as administrator, Windows switches to a different environment called the Secure Desktop.


This is an extra security layer used during the elevation process. When an application requests administrative privileges, the normal desktop (the one you're interacting with) is temporarily dimmed, and the UAC prompt is shown in this isolated environment instead.


The key thing here is isolation. Only trusted Windows processes can interact with the Secure Desktop, which means other applications, especially potentially malicious ones, can't interfere with the prompt, simulate clicks, or try to trick the user into approving something, thereby preventing attacks like UI spoofing or shatter attacks, where a malicious process might try to send input or manipulate another window to gain elevated privileges.


Once the user responds to the prompt (either "Yes" or "No"), Windows switches back to the normal desktop, and the process either continues with elevated privileges or is denied.


Standard user vs Local Administrator


UAC also applies to standard users, but it behaves differently compared to local administrators. Standard users are those who are not members of the "Administrators" group, which means they don’t have sensitive privileges, even if they had a full token.


However, sometimes these users still need to perform sensitive actions, like installing a program. In those cases, another UAC prompt is shown to the user, but this time it’s a Credential Prompt:



This time, instead of just clicking Yes or No, users must provide local administrator credentials to run with elevated privileges, since they don’t have a full token with high privileges.


I make this distinction because a UAC bypass typically involves having local administrator access with a limited token, and then trying to obtain a full token without triggering a prompt for the user.


In this article, we’ll assume we’ve gained access as a local administrator, but without elevation (with a limited token), and we’ll try to bypass that restriction without triggering a UAC prompt for the user.


Is UAC secure?


Now, the question is: Is UAC really secure?


Let’s say a local administrator (running with a limited token) executes a malicious program without elevation. This program will only have limited access to the system unless the user explicitly approves administrative actions by clicking 'Yes' on the UAC prompt. On its own, the program can’t really abuse token privileges, since it’s running with standard user permissions, which aren’t an escalation vector.


So, is there a way to bypass this limited token and gain full privileged access without even showing a UAC prompt to the user?


Historically, it’s been shown that UAC isn’t really effective at preventing elevated actions. In fact, there are multiple techniques that can bypass these token restrictions and obtain full token privileges.


Many of these techniques abuse the fact that, when something runs as administrator, parts of the environment context are shared. This opens the door to modifying certain environment variables used by elevated processes that don’t trigger a UAC prompt, such as Scheduled Tasks.


SilentCleanup Scheduled Task UAC Bypass


One of the simplest well-known UAC bypass techniques is abusing the SilentCleanup Scheduled Task. This method was first discovered by the legendary James Forshaw in 2017, and still works today.


Conceptually, this technique abuses how certain Scheduled Tasks are configured in Windows.


The SilentCleanup task is interesting for two key reasons:


  • It can be triggered by a regular user (or a split-token administrator running without elevation)
  • It is configured to run with highest privileges, meaning it will auto-elevate without showing a UAC prompt

So far, that already sounds like a perfect candidate for a UAC bypass.


Now, here’s where things get interesting.


When the task runs, it launches cleanmgr.exe using a path that includes the %windir% environment variable (normally C:\Windows):



The problem is that this variable is not hardcoded, and can be influenced by the user through the HKCU\Environment registry key


This basically means:


  • The task runs with high privileges (auto-elevated)
  • But part of what it executes depends on a user-controlled environment variable

In other words, you get a privileged process partially controlled by an unprivileged context.


By overriding %windir% to point to something attacker-controlled (or even injecting commands), when the task executes, it will run our payload instead of the expected binary, but now with elevated privileges. And since the task is auto-elevated, this happens completely silently, without triggering any UAC prompt.


You can easily abuse this technique using the following commands:


# Modify environment variable to cmd.exe
reg add "HKCU\Environment" /v "windir" /d "C:\Windows\System32\cmd.exe\" /f

# run scheduled task
schtasks /run /tn \Microsoft\Windows\DiskCleanup\SilentCleanup /I


As observed, it worked and and we ended up with a cmd.exe running with full privileges.


There are many other techniques that rely on abusing the shared environment between the limited token and the full access token. Of course, most of these techniques are now flagged by AV solutions, but with a bit of creativity, you can still experiment and try to bypass those restrictions.


So, how can this be patched? The core issue here is the shared environment between low-privileged and high-privileged tokens. This happens because both tokens belong to the same principal.


Ideally, the solution would be to isolate the environments between the low-privileged context and the high-privileged one, something we’ll come back to at the end of the article.


Bypassing UAC with SSPI Datagram Contexts


Another cool technique to bypass UAC is playing with NTLM authentication with Datagram contexts. This technique was discovered by antonioCoco.


I won't enter in detail on how this technique works because the original article already explains it really well.


At a high level, this technique abuses how UAC restrictions are applied differently depending on the type of authentication.


When a user logs in interactively, UAC enforces a filtered token (the limited token we’ve been discussing). However, this restriction does not apply in the same way to network authentication. When authentication happens over the network (e.g., NTLM), the system may generate tokens that are not filtered by UAC (this does not always happen, but won't enter in detail here).


So the question is: what if we could perform a network authentication locally?


This is where SSPI comes into play. By using APIs like AcquireCredentialsHandle and InitializeSecurityContext with the ISC_REQ_DATAGRAM flag, it’s possible to force NTLM into a datagram-based flow. This changes how the authentication is handled and prevents LSASS from recognizing it as a local authentication.


As a result, the system treats it as a network logon, even though everything is happening on the same machine.


During this process, LSASS creates a new logon session and generates both a filtered token and an elevated one. Once created, we impersonate the new security context, which is unfortunately associated with the filtered token. However, because of how tokens are later referenced internally, some operations may end up using the elevated token, even if the caller appears to be running with a limited one.


This happens because the AcquireCredentialsHandle API, when used in network redirectors and receives the logon session of the caller, resolves it using the base token associated with that session. In our case, that ends up being the elevated token.


The reason for this behavior is the order in which the tokens are created. When using ISC_REQ_DATAGRAM to simulate a network authentication, the system first creates the elevated token and associates it with the new logon session. After that, the filtered (UAC-restricted) token is derived from it.


So even if we are impersonating the filtered token, when we authenticate to a local service that calls AcquireCredentialsHandle in network redirectors and passes the caller’s logon ID (this has to be a local service, since providing a logon ID directly requires kernel-level privileges), LSASS ends up referencing the first token created for that logon session, which is the elevated one.


In practice, this allows us to authenticate against local services (for example over \\127.0.0.1) and perform actions with elevated privileges, all without triggering a UAC prompt.


This combined with CreateSvcRpc it's possible to achieve command execution with system privileges. The exploit was created by antonioCoco.



As observed, we achieved command execution as system.


Other techniques


So far, we've looked at two different techniques to bypass UAC. However, there are many more that I won't cover here. That said, you can check out the UACME project, which contains a large collection of UAC bypass techniques implemented in a practical way. It's a great resource if you want to discover more techniques, since it not only shows different approaches, but also how they behave across Windows versions. It contains patched and unpatched techniques.


Administrator Protection


Previously, when describing the SilentCleanup scheduled task UAC bypass technique, I mentioned that the issue was that the high-privileged context and the low-privileged context share the same environment, such as environment variables and so on. This happens because when you run something as administrator, even though you switch to a more privileged context, the full access token still belongs to the same principal, which ends up having the exact same environment.


As explained earlier, many of the bypass techniques in the wild rely on abusing this behavior. So, what did Microsoft do about this? Well, as described in the documentation, UAC is a security feature, not a security boundary, which means that most bypass techniques are not treated as security issues—especially those related to environment-based abuse.


However, something new is being cooked in the preview builds in the Windows Insider Program. A new security feature (which was introduced and then removed from Windows 11 25H2 due to compatibility/security issues lol) is expected to come back in future releases of Windows 11.


What is Administrator Protection


Administrator protection is a new security feature in Windows 11 that aims to rethink how elevation works under the hood.


At its core, it follows the principle of least privilege: users run in a deprivileged state by default and only receive administrative rights when they’re actually needed, and only after explicitly approving the action. So far, this sounds similar to how UAC already behaves, but the implementation is quite different.


When a user signs in, instead of having both a filtered token and a full admin token tied to the same account, they only get a deprivileged token. Then, when an operation requires admin privileges, Windows prompts the user for authorization as usual.


The key difference is what happens next.


Instead of reusing the same user context with a more privileged token, Windows creates a completely separate, system-generated (and hidden) account. This account is used to generate an isolated admin token, which is then assigned only to the process requesting elevation.


Once that process finishes, the token is destroyed to prevent malicious programs from reusing it.


Because the elevated process runs under a different account, there is also a clear separation between the user environment and the elevated environment. In other words, the elevated context no longer shares things like environment variables or other user-controlled state with the original user.


This feature integrates with Windows Hello, allowing users to approve elevation requests using secure and user-friendly authentication methods.


This time, Administrator Protection actually sounds like a much stronger security boundary compared to plain UAC. However, as said earlier, it hasn’t been implemented in official releases yet.


Before wrapping up, I’d like to recommend two articles by James Forshaw, who has done some great research on Administrator Protection in Windows Insider preview builds. I think they’re definitely worth a read, super interesting and very informative.



Conclusion


In this article, we explored what User Account Control (UAC) is and how, over time, it has been shown to be far from a robust security feature. As we’ve seen, it comes with several caveats that make it possible to completely bypass it under certain conditions.


We also introduced Administrator Protection, which appears to be a much stronger approach, as it actually enforces a clearer security boundary between user and administrator actions.


None of the techniques discussed in this article are mine, I’m just sharing them because I think they’re great, and the original authors did an excellent job discovering and documenting them. All credit goes to them.


That's all folks, hope you enjoyed it. See you next time 👋


References


https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/
https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/how-it-works
https://splintercod3.blogspot.com/p/bypassing-uac-with-sspi-datagram.html
https://www.tiraniddo.dev/2017/05/exploiting-environment-variables-in.html
https://github.com/antonioCoco/SspiUacBypass
https://projectzero.google/2026/26/windows-administrator-protection.html
https://projectzero.google/2026/02/windows-administrator-protection.html
https://learn.microsoft.com/en-us/windows/security/application-security/application-control/administrator-protection/?tabs=intune
https://github.com/hfiref0x/UACME