Open-source project
itm4n/PrivescCheck avatar
itm4n/PrivescCheck

PrivescCheck: a single PowerShell file that enumerates Windows privilege escalation paths

Privilege Escalation Enumeration Script for Windows

3,980 stars509 forksPowerShellBSD-3-Clause

At a glance

What is it?
One script, three tiers of checks, four report formats, and an unusually honest warning that running it as administrator makes it less useful.
Who is it for?
PrivescCheck is a good example of a security tool whose most important behaviour is a refusal. Running it with administrator privileges makes it skip the access control checks it exists to perform, so the tool that finds privilege escalation paths is least useful when you are already privileged, and the README says so in a callout before the first command.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly PowerShell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Run it unprivileged, and the README tells you why twice

The description is a privilege escalation enumeration script for Windows, and the README frames the scope as identifying common Windows vulnerabilities and configuration issues that are not necessarily covered by public security standards, then collecting information useful for exploitation and post-exploitation tasks.

Before any command appears, there is an IMPORTANT callout that changes how you should use the tool. All access control checks are done in the context of the current user, so if the script is run with administrator privileges a lot of vulnerability checks are skipped to avoid generating incorrect findings.

That is a design decision, not a bug, and it is the right one. A check that asks whether a file or registry key is writable by unprivileged users is meaningless when the process already holds full control of everything. The tool stops rather than emitting findings it knows are wrong, and by default it refuses to run elevated at all. The `-Force` option exists to override that warning, and the flag documentation is explicit that it is for people who understand why the default behaviour is what it is.

This makes PrivescCheck a tool you run as the user you are investigating, not as an administrator auditing a machine you already own. That distinction is worth internalising before the first scan.

Three tiers of checks behind three switches

The command surface is small, and the README documents it as a compact syntax block.

txt
Invoke-PrivescCheck [-Extended] [-Audit] [-Risky] [-Report <FORMAT>[,...]]
    [-FilePath <PREFIX>]  [-Silent] [-Force]

The switches map to three defined check types. Base checks always execute, unless the script is run as an administrator, and they are mainly intended for identifying privilege escalation vulnerabilities or other important issues. Extended checks run only when `-Extended` is given, and exist mainly to provide additional information useful for exploit development or post-exploitation. Audit checks run only with `-Audit` and provide information relevant to the context of a configuration audit.

That separation matters because the value of the output changes with the tier. A base check finding is a privilege escalation vector. An extended check finding is a fact that helps someone who already has a foothold decide what to do next. An audit check finding is a hardening observation. Mixing them produces a report where you cannot tell which kind of thing you are looking at.

There is a fourth switch that is not a check type at all. `-Risky` includes checks that are likely to trigger active EDR counter measures because of their behaviour. That is an explicit warning that some enumeration is itself detectable, which is a decision the operator has to make rather than one the tool should make silently.

Three ways to run it, from a look to a full sweep

The README gives three use cases, and the progression is the point. The first is a quick assessment, the second adds extended checks, the third adds audit checks and asks for every report format.

bat
powershell -ep bypass -c ". .\PrivescCheck.ps1; Invoke-PrivescCheck -Report TXT,HTML"

The extensive version adds `-Extended` before the report option, and the comprehensive version adds `-Audit` and passes `ALL` as the format list.

The `-ep bypass` flag is worth pausing on, because it disables PowerShell execution policy for the process, which is normally `Restricted` on clients and `RemoteSigned` on servers. The README explains the policies and gives a cleaner way to achieve the same thing inside a session:

powershell
Set-ExecutionPolicy Bypass -Scope Process -Force
. .\PrivescCheck.ps1

Scope Process rather than Machine is the detail that matters, since it changes nothing outside the current session. The README is also honest that this trick fails when execution policy is enforced through a group policy object, and gives the alternative of reading the file and piping it through `Invoke-Expression` after starting a new session.

For download, the README links a stable release asset URL for PrivescCheck.ps1 and notes the link can be pasted into a PowerShell terminal as a DownloadString call. The script ships as a single file, which is the whole distribution model: there is no installer and no module to register.

Four report formats and who each one is for

The report system separates human reading from machine parsing, which is more thought than most enumeration scripts invest here.

The TXT report is described as a raw text report similar to the terminal output, except that it contains only ASCII characters for better compatibility with text editors. The HTML report opens in a web browser, needs no internet connection because it has no external dependencies, and offers sorting and filtering. That combination makes it the report you actually want when a finding list is long, because scanning a wall of terminal output for the one item that matters is slow.

CSV and XML are for consumption by automated reporting tools. The README adds a note that the output structure is not documented yet but can be inferred by analysing a generated file, and suggests using the `Id` value of each check as a unique identifier. That is a reasonable stability anchor to build on and also a small gap: an undocumented schema you reverse engineer is still an undocumented schema.

The `-Report` option took a breaking change in the 2026-09-21 release. The changelog records that the main Report option was refactored to specify output file formats instead of a file path, and that the old `Format` option was marked deprecated. A separate `FilePath` option now specifies the output file name or directory, with the extension appended automatically and, if a directory is given, the filename generated at runtime. The newest release also added a `Stats` switch that produces a CSV of per-check execution times, which is the kind of feature that tells you someone cared about where the slow parts are.

Retro-compatibility and the Metasploit timeout

Two sections of the README are about working around the environment, and both are the kind of detail that separates a tool people use from a tool people read about.

The first is PowerShell 2. A common way to bypass Constrained Language Mode is to use PowerShell v2, because it does not implement that protection, and the README says a significant part of the development effort goes into maintaining that retro-compatibility. There is a struck-through correction in the text here, since the original claim that PowerShell 2 is still enabled by default on recent Windows versions was wrong: it cannot run without the .NET Framework 2.0, which requires a manual install. The strikethrough is left in place, which is a small readable piece of editing history.

The second is Metasploit. Running the script inside a Meterpreter session usually produces a timeout error, because Metasploit's default timeout is 15 seconds and the script needs longer. The README shows the failure:

console
meterpreter > load powershell
Loading extension powershell...Success.
meterpreter > powershell_import /local/path/to/PrivescCheck.ps1
[+] File successfully imported. No result was returned.
meterpreter > powershell_execute "Invoke-PrivescCheck"
[-] Error running command powershell_execute: Rex::TimeoutError Operation timed out.

The fix is to raise the session timeout with the `-t` option of the sessions command, and the README walks through setting it to 120 seconds while noting you may want more. Anyone integrating this into an automated pipeline will hit that timeout before anything else.

What the repository contains beyond the script

The tree shows this is a maintained project rather than a single uploaded file. There is `src/` for the script source, `dist/` for distributed output, `build/` for the packaging pipeline, `data/` for the data the checks read, `info/` for check metadata, `img/` for the report screenshots the README embeds, and `test/` for the test suite.

That `info/` directory is worth pausing on, because it explains something about how the checks are defined. Checks appear to be described as data with an identifier rather than hand-written one at a time, which lines up with the README's advice to use the `Id` value of each check as a unique identifier for parsing, and with a check being added as a discrete unit in the changelog, such as the 2026-09-12 entry adding enumeration of system services that can be restarted by unprivileged users.

The changelog is maintained per release with dates, and the release tags follow a dated version format such as 2026.09.21-1 rather than semver. Two releases published within days of each other, one of which is a bare files-updated note, suggest a workflow that ships whatever is ready rather than batching.

The project is licensed BSD-3-Clause, the detected language is PowerShell, the repository has 3,964 stars, 508 forks and a single open issue, and the last push was on 2026-09-21. A one open issue count for a security script at this scale is a reasonable signal that the check definitions are being maintained rather than left to rot.

Editorial conclusion

PrivescCheck is a good example of a security tool whose most important behaviour is a refusal. Running it with administrator privileges makes it skip the access control checks it exists to perform, so the tool that finds privilege escalation paths is least useful when you are already privileged, and the README says so in a callout before the first command. Everything else follows that pattern: checks are tiered so you pay only for what you need, reports are separated into human and machine formats so results can be parsed without screen scraping, and the odd corners, PowerShell 2 retro-compatibility and Metasploit timeouts, are documented rather than left for you to discover. Start with a plain run and a TXT report, then add -Extended and -Audit once you know the base output.

Frequently asked questions

Why should PrivescCheck not be run as administrator?

Because every access control check runs in the context of the current user, so with administrator privileges many checks are skipped to avoid reporting findings that are simply false. A check asking whether something is writable by unprivileged users tells you nothing when you already hold full control. The script refuses to run elevated by default, and the Force option exists to override that.

What is the difference between the Extended, Audit and Risky switches?

Extended adds checks that help with exploit development and post-exploitation, and Audit adds checks relevant to a configuration audit. Risky is separate from both tiers and includes checks whose behaviour is likely to trip active EDR counter measures, so it is a detection trade-off you opt into rather than a deeper scan.

Which report format should I use?

HTML for reading, since it needs no internet connection and supports sorting and filtering. TXT for a raw text version kept to ASCII characters for text editor compatibility. CSV or XML when an automated reporting tool will consume the results, using the Id value of each check as a unique identifier, since the schema itself is not documented yet.

How do I run PrivescCheck when the execution policy blocks it?

Override it for the current process only with Set-ExecutionPolicy Bypass -Scope Process -Force and then dot-source the script. If execution policy is enforced through a group policy object that trick does not work, and the README gives reading the file and piping it through Invoke-Expression as the alternative.

Why does PrivescCheck time out inside a Meterpreter session?

Metasploit's default session timeout is 15 seconds, which is shorter than a typical full run. Raise it with the -t option of the sessions command; the README walks through setting it to 120 seconds and notes that you may want an even higher value.

Official sources

  1. Issues
  2. itm4n/PrivescCheck on GitHub
  3. License: BSD-3-Clause
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/itm4n-privesccheck.svg)](https://hysenlabs.com/projects/itm4n-privesccheck)