A one-shot, read-only audit of what is running on a Windows PC and what starts itself automatically.
It is not an antivirus and it does not replace one. It answers a different question: what is on this machine, where did it come from, and what launches it without being asked? Antivirus asks "do I recognise this as bad?" — this asks "can everything here account for itself?"
It finds things that hide by looking legitimate:
- Programs running from odd places — Temp, AppData, Downloads — instead of where software normally installs
- Files impersonating Windows components: right name, wrong folder, or a lookalike spelling like
svch0st.exe - Anything unsigned, tampered with, or signed by a company that makes no sense for what it claims to be
- A malicious DLL loaded into an otherwise genuine, correctly-signed program
- Everything that starts itself automatically — including the hiding places most tools skip: the
\Microsoft\scheduled-task branch, svchost-hosted services, WMI subscriptions, AppInit_DLLs, IFEO hijacks, per-user COM hijacks, accessibility-key backdoors - Programs talking to the internet, or quietly listening for incoming connections
- Browser extensions (listed for you to recognise — those can't be verified automatically)
It cannot find:
- Malicious code injected into a running legitimate program. The file on disk is genuine and every check here passes. Catching this needs a kernel driver watching continuously — that is what EDR products are, and no script can substitute.
- Rootkits. Anything that has taken over the kernel can lie to every check here. If you suspect one, run Microsoft Defender Offline Scan, which boots outside Windows.
- Bad behaviour inside a signed file. It verifies who signed something, never what it does. Signed software can still be malicious.
- Anything not present when you ran it. It's a snapshot, not a monitor. Something that ran and exited leaves nothing for it to see.
So use it alongside Defender, not instead of it. They answer different questions, and neither one covers the other's blind spots.
Everything above is explained in detail further down — see What it checks, Reading the output, and Coverage and limits.
Discord: discord.gg/mR4Ee5PQ9x — ask in
#github-posts. Good for "is this thing on my machine normal?" and for reading
a scan report together.
GitHub Issues: open an issue for bugs, false positives, or anything you'd rather keep public and searchable.
False positives are genuinely useful to report — if this tool flags something legitimate on your machine, that's a bug worth fixing, not your problem to work around.
Or from this page: green Code button → Download ZIP.
Then extract the ZIP somewhere — Desktop or Downloads is fine. This step
matters: double-clicking a .bat while you're still browsing inside the zip
will not work properly, because Windows opens zip contents from a temporary
location.
Prefer the command line? git clone https://github.com/HatefulJb/process-audit.git
Double-click Run-Scan.bat and approve the UAC prompt. Results appear in a
new window (the one you launched from will look like nothing happened —
that's expected).
Takes about a minute. A timestamped copy of the output is written to reports\.
| Double-click | Time | Checks DLLs? | |
|---|---|---|---|
| Full (recommended) | Run-Scan.bat |
~50s | Yes — all ~1,700 loaded modules |
| Quick | Run-Scan-Quick.bat |
~15s | No |
Roughly two thirds of the full runtime is the DLL check, which verifies every module loaded into every running process. Quick mode skips only that; every other check still runs, and the output states plainly that DLLs were not checked, so a quick run can never be mistaken for a full one.
The first run of the day can take two to three minutes. Nothing is wrong. Every file has to be read from disk and hashed, Defender scans each one as it is touched, and Windows may fetch certificate revocation lists over the network for signers it has not seen recently. Run it a second time and it drops to the times above, because all three of those are now cached. If you are impatient, use quick mode — it does not touch anywhere near as many files.
Those timings are measured elevated, which is how Run-Scan.bat runs.
Unelevated is faster, but only because it can see less: 1,095 modules instead of
1,685, since it cannot read the modules loaded into service and system
processes. Faster for the wrong reason.
What you give up in quick mode: detection of DLL sideloading — a legitimate
signed .exe with a malicious DLL dropped beside it. Every other check in this
tool passes that scenario, so the DLL check is the only thing that would catch
it. Use quick mode for a fast look; use the full scan when it matters.
From a terminal, the same switch works directly:
powershell -NoProfile -ExecutionPolicy Bypass -File .\Scan-Processes.ps1 -Quick- SmartScreen warns about the
.bat→ More info → Run anyway. It says this about every unsigned batch file from the internet, not just this one. - "running scripts is disabled on this system" → that's PowerShell's default
Restrictedpolicy.Run-Scan.batalready works around it for this one run only, without changing any setting on your machine. - File is "blocked" because it came from the internet → right-click
Scan-Processes.ps1→ Properties → tick Unblock → OK. (Windows adds that mark to anything extracted from a downloaded zip.)
Perfectly reasonable if you'd rather not run a .bat you didn't write. Open
PowerShell as Administrator in the extracted folder and run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\Scan-Processes.ps1Drop the as Administrator part if you want — it still works, it just can't see protected processes, and the report tells you exactly how many it missed.
There is deliberately no
irm ... | iexone-line installer here. Piping a script straight from the internet into your shell means running code you never read. That's the exact habit this tool exists to help you catch, and it would be absurd to ask you to do it in order to run it. Download it, read it, then run it.
You do have to download it — but nothing installs. There is no setup
program, no service, no scheduled task, no background process, no registry
changes, and no network calls. It runs when you run it and it's gone when it
exits. Afterwards the only things on your disk are the files you downloaded and
a text report in reports\. Delete the folder and it's completely gone.
If someone sent you this, your instinct to distrust it is correct. This tool does four things that a careful person should refuse on sight. All four are explained below, and all four are verifiable in about a minute. "A friend vouched for it" is not verification.
1. Run-Scan.bat launches an elevated PowerShell with -ExecutionPolicy Bypass.
That is genuinely the shape of a malicious dropper. It's used here because the
scan needs administrator rights to read protected process paths and service
keys, and because most machines block unsigned .ps1 files by default. You do
not have to use it — run Scan-Processes.ps1 directly instead and skip the
batch file entirely.
2. It compiles C# at runtime (Add-Type) and calls into kernel32.dll.
Also a real malware pattern. Here it is one function, ProcPath, that calls
OpenProcess + QueryFullProcessImageName to ask Windows "what file is this
process running from?" for processes that WMI won't answer for. It requests
PROCESS_QUERY_LIMITED_INFORMATION (0x1000) — the most restricted access
right that exists for this. It cannot read process memory, write to a
process, or inject anything. Read the block; it's about 20 lines.
3. Your antivirus or EDR may flag the script itself. PowerShell that calls
Add-Type and OpenProcess trips behavioural heuristics on several products.
That is the heuristic doing its job — the pattern is legitimately worth flagging
in general. It doesn't mean this script is malicious, and it doesn't mean your
AV is broken.
4. It reads a lot about your machine — running processes, autostart entries, services, scheduled tasks, network connections. That's the job. It matters that none of it goes anywhere (see below).
The whole tool is one plain-text PowerShell file. Open it in Notepad. Then, to check the claims rather than trust them, search it for every command that could change or transmit anything:
Select-String -Path .\Scan-Processes.ps1 -Pattern 'Remove-Item|Set-ItemProperty|New-ItemProperty|Remove-ItemProperty|Stop-Process|Stop-Service|Start-Process|sc\.exe|reg\.exe|Invoke-WebRequest|Invoke-RestMethod|WebClient|DownloadString|Net\.Sockets|Invoke-Expression|New-Item|Set-Content|Add-Type'You should get exactly three results, and nothing else:
| What it is | Why it's there |
|---|---|
Add-Type ... TypeDefinition |
The ProcPath helper described above. |
New-Item -ItemType Directory -Path $ReportDir |
Creates the reports\ folder. |
Set-Content -LiteralPath $reportPath |
Writes the report text file. |
(If you widen the search to include tool names like certutil or rundll32
you'll also hit the $LolBins line. That one is a string — a list of
program names the scan looks for in your scheduled tasks. It is pattern data,
not a command being run.)
That's the complete list of everything this script does beyond reading. There
is no registry write, no file deletion, no process or service manipulation,
and no network call of any kind — no Invoke-WebRequest, no WebClient, no
sockets, no VirusTotal lookup, nothing. Your data cannot leave your machine
because there is no code capable of sending it.
The only thing it writes is a text report, into its own folder.
The tool rests on one idea: a process's name means nothing. Anyone can name
a program svchost.exe and give it the Windows gear icon. Real identity is
path + signature + parent. Every check below gets at one of those three.
| # | Check | Question it answers |
|---|---|---|
| 1 | Path | Is this running from a normal install location, or from Temp/AppData/Downloads? |
| 2 | Signature | Is it cryptographically signed, and by a company that makes sense? |
| 2b | Loaded modules | Is every DLL loaded into every running process signed? Catches DLL sideloading — where a signed .exe is left alone and a malicious DLL is dropped beside it. |
| 3 | Impersonation | Is a core Windows process name running from the wrong folder, or a near-miss spelling (svch0st, scvhost, lsas)? |
| 4 | Ancestry | Did svchost come from services.exe as it must? Did a script host get spawned by Word or a browser? |
| 5a | Run keys | What launches at login via HKLM/HKCU Run and RunOnce? |
| 5b | Services | What runs at boot, including svchost-hosted services resolved via their ServiceDll? |
| 5c | Scheduled Tasks | What runs on a schedule, and with what arguments? |
| 5d | Startup folders | What's in Startup, and where do those shortcuts actually point? |
| 5e | WMI subscriptions | Any fileless persistence — event consumers that run commands? |
| 5f | The less obvious hooks | AppInit_DLLs, Winlogon Shell/Userinit, IFEO debugger hijacks, SilentProcessExit monitors, LSA packages, per-user COM hijacks, Active Setup, print monitors, netsh helpers, accessibility-binary swaps, screensaver. |
| 5g | Browser extensions | What's installed in Chrome/Edge/Brave — listed for you to recognise. |
| 6 | Network | Which processes hold connections to the outside world? |
| 7 | Defender | Real-time protection on? Definitions current? |
Section 5f is where the techniques live that most people never check. A few worth understanding:
- AppInit_DLLs — a DLL listed here is loaded into nearly every GUI process on the machine. It should be empty.
- IFEO debugger — setting a "debugger" for
notepad.exemeans launching Notepad silently runs something else instead. - Winlogon
Shell/Userinit— these run at logon before anything else. Defaults areexplorer.exeandC:\Windows\system32\userinit.exe,. - Per-user COM hijack — an
HKCUCLSID overrides the matchingHKLMone, so a component the system loads gets silently replaced. Only flagged when it actually shadows a system entry. - Accessibility swaps — replacing
sethc.exeorutilman.exegives a SYSTEM shell from the logon screen without signing in.
These are checked against what a stock Windows install looks like, so the question is "does this differ from default", not "does this look scary".
Browser extensions are listed, not judged. Extensions can't be signature-verified the way a binary can, and adware lives there more than anywhere else. The tool shows you names and IDs; recognising them is your job.
Four levels. Only one of them means "something is wrong."
| Level | Meaning |
|---|---|
OK |
The check passed, nothing found. |
INFO |
Present and accounted for. Signed, normal location. No action. |
REVIEW |
Not an accusation. Something the tool cannot clear on its own — an unsigned binary, a script it can't read for you, a vendor it doesn't recognise. You decide. |
FLAG |
Reserved for things with no benign explanation: a core Windows name in the wrong folder, a broken signature, a command-running WMI consumer. |
A clean machine still produces REVIEW items. Expect a handful. Different PCs will produce completely different lists depending on installed games, vendor utilities, and drivers.
Run it once now, while things are working, and keep that report. Its real value is comparison. "Six review items" on its own means very little. "Six review items last month, nine today, and I don't recognise the three new ones" is a genuine signal.
powershell.exe -ExecutionPolicy Bypass -WindowStyle Hiddenin a scheduled task. Textbook malware shape — and also how plenty of legitimate self-written automation is set up.powershell.exeis signed by Microsoft, so the executable tells you nothing. Judge it by its arguments and by reading the script it points to.- A running program whose file is "not on disk." Self-deleting malware does this. So does every auto-updating app — Discord, Spotify, VS Code and others run from version-numbered folders and delete the old one on update while the old process keeps running. Check for a sibling version folder first.
- Apps running from
AppData. Electron apps install per-user by design. Suspicious in combination with unsigned, not on its own. - Unsigned
.bat/.vbs/.ps1files. Scripts cannot carry an Authenticode signature at all. "Unsigned" is not a finding for them — read the file instead. - Names containing a scary word. A service called
WarpJITSvcis Microsoft's Direct3D software renderer, not a VPN leftover. Check the publisher, not the string.
Being honest about what it doesn't see matters more than the list of what it does.
It does not check every running process, even elevated. Every report opens with its own coverage line, so you never have to guess:
Processes: 285 total | 104 path from WMI | 12 recovered via Win32 API | 5 kernel (no file) | 164 unresolved
Read that as: 104 processes gave up their image path directly, 12 more were recovered by asking Windows a second way, 5 have no file to check at all, and 164 could not be resolved in this run.
That last number is almost entirely an elevation problem. Measured on the same machine, minutes apart:
| Unelevated | Elevated | |
|---|---|---|
| Processes total | 285 | 294 |
| Path from WMI | 104 | 275 |
| Recovered via Win32 API | 12 | 14 |
| Kernel, no file to check | 5 | 5 |
| Unresolved | 164 | 0 |
| Unique executables verified | 56 | 115 |
| Service keys it could not read | 2 | 0 |
Run it as administrator and every process that has a file on disk gets checked.
The unresolved count and the service key(s) could not be read warning
disappear because there is genuinely nothing left unchecked. If you see either
message, you ran it unelevated.
The only permanent gap is the 5 processes with no file on disk at all —
System, Registry, Secure System, System Idle Process and
Memory Compression are kernel-space constructs, not programs. There is no
.exe to hash and no signature to read.
Protected processes like Defender's MsMpEng.exe are not a gap. You cannot
read their memory, but their image path and signature verify normally, because
that only needs PROCESS_QUERY_LIMITED_INFORMATION — the most restricted access
right there is, which Windows grants for exactly this purpose.
Also note that unique files checked is smaller than process count, correctly:
88 running copies of svchost.exe are 88 processes but one file, and checking
that file once is the right thing to do.
Almost all of it is signature verification, and that cost scales with file size, because Authenticode hashes the entire file. Measured on one desktop:
| File | Size | Signature check |
|---|---|---|
claude.exe |
266 MB | 1043 ms |
Discord.exe |
211 MB | 801 ms |
| median file | — | 17 ms |
Three large Electron apps accounted for 70% of the executable-checking total.
The bigger cost is the DLL check — ~1,685 unique modules loaded across ~290
processes, about 34 seconds, or two thirds of the run. That's the price of
catching sideloading, and -Quick skips it if you'd rather have a 15-second
scan. Measured end to end, elevated:
| Mode | Modules checked | Scan time |
|---|---|---|
| Full, elevated | 1,683 | 51.7s |
| Quick, elevated | none | ~15s |
| Full, unelevated | 1,095 | ~36s |
Unelevated is faster only because it sees less — it cannot read the modules inside service and system processes, so 590 of them go unchecked.
Worth knowing why that check produces so little noise: of ~1,685 modules on a
stock machine, the vast majority are
unsigned on a stock machine, and all 75 fall into two categories that are
filtered by name, not by guesswork — Store/MSIX packages (signed at the package
level, not per file) and .NET native images under Windows\assembly\NativeImages
(compiled locally by ngen from already-signed assemblies, so they never carry a
signature). Excluding those two leaves zero. An unsigned DLL that isn't one of
those is worth your attention.
Where a check genuinely could not run, the tool says so and counts it —
e.g. 2 service key(s) could not be read - NOT checked. A scanner that hides
its blind spots is worse than one with fewer checks, because it converts
"I couldn't look" into "nothing there."
-
No network calls, no VirusTotal lookups. Nothing about your machine leaves it. The trade-off: no reputation data, so judgement is yours.
-
No file-content malware detection. It never inspects what a binary actually does. Use Defender or another AV for that — they are complementary.
-
No rootkit detection. Anything that has already subverted the kernel can lie to every API this tool uses. If you suspect that, run Microsoft Defender Offline Scan (Windows Security → Virus & threat protection → Scan options), which boots outside Windows.
-
No process-injection detection — and this is deliberate. Injection means malicious code running inside a legitimate signed process: the file on disk is genuine, the signature is valid, the ancestry is correct, and every check in this tool passes. Catching it means scanning each process's memory for executable regions not backed by any file. Two things make that a bad idea here. Protected processes refuse memory reads outright, so the highest-value targets are exactly the ones you cannot inspect. And every JIT compiler on the machine — .NET, Chrome's JavaScript engine, Java, node — allocates unbacked executable memory constantly and by design, so the check would produce hundreds of hits on a completely clean PC with no path-based rule able to separate a compiler from a payload. That is the same false-positive problem the DLL check had, except unsolvable. Reliable detection needs a kernel driver and continuous monitoring, which is what EDR products are. A 35-second PowerShell script cannot do it, and one that claimed to would just be lying to you.
-
It never changes anything. No fixes, no quarantine, no deletion. It reports; you act.
For deeper work, both free from Microsoft (Sysinternals) — you download a zip and
run the .exe, there is no setup program:
- Autoruns — every persistence location and many more, with a VirusTotal detection-ratio column. Enable Options → Hide Microsoft entries and Options → Scan Options → Check VirusTotal.
- Process Explorer — Task Manager with the answers filled in. Enable Options → Verify Image Signatures and add the VirusTotal column. Shows processes as a tree, so ancestry is visible at a glance.
Windows 8 or newer. It relies only on PowerShell 5.1, which is already part of Windows — so once you've downloaded this folder there are no other dependencies to fetch. Runs on Windows 10 and 11 as-is.
| File | Purpose |
|---|---|
Run-Scan.bat |
Double-click launcher for the full scan, requests elevation |
Run-Scan-Quick.bat |
Same, but skips the DLL check (~15s instead of ~50s) |
Scan-Processes.ps1 |
The scan itself — read it before running |
reports\ |
Timestamped output, created on first run |
reports\ contains your machine's process list, file paths and network
connections. Don't share those files without reading them first.
This is free, and always will be — every check is in the box, nothing is held back for a paid version.
Most of the work wasn't writing the checks, it was hunting down the false positives so it doesn't cry wolf at your antivirus, your game launchers, or a Windows component that happens to have a scary name. If it found something on your machine, or just told you nothing was wrong and you slept better, and you want to throw a couple of dollars at it, that's genuinely appreciated:
Starring the repo and passing it to someone who needs it helps just as much, and costs nothing. So does reporting a false positive — that one actually makes the tool better for everyone.