6.8 KiB
GuruScan
Multi-engine malware scan orchestrator for GuruRMM. Runs a sequenced chain of portable security scanners, captures all logs, and writes structured JSON results for downstream processing by the RMM agent.
Deploy Layout
| Path | Purpose |
|---|---|
C:\GuruScan\ |
Base directory — module files, whitelist, state files |
C:\GuruScan\downloads\ |
Scanner EXEs (populated by Download-Scanners.ps1) |
C:\GuruScan\reports\ |
Per-scan zip archives |
C:\ScanLogs\ |
Per-scan log folders (<HOSTNAME>-<YYYYMMDD-HHmmss>\) |
The module files (GuruScan.psm1, GuruScan.psd1, scanners.json) live in the
same directory as the launcher scripts (Invoke-GuruScan.ps1, etc.). This is
typically C:\GuruScan\ or the RMM deployment path — wherever the scripts are placed.
Scanner Chain
Scanners run in this order. Each stage hands off to the next regardless of findings.
| # | Scanner | Category | Notes |
|---|---|---|---|
| 1 | RKill | process-killer | Kills malware-related processes before scanners run. Exit 1 = processes were killed (not a threat indicator). |
| 2 | AdwCleaner | adware | Removes adware, PUPs, and browser hijackers. |
| 3 | Emsisoft Command Line Scanner | antimalware | Two-step: NSIS installer extracts to C:\EmsisoftCmd\, then /update fetches latest definitions, then scans. |
| 4 | HitmanPro | antimalware | Cloud-assisted second-opinion scanner. Trial registry is reset before each run via Invoke-HitmanProTrialReset. |
| 5 | ESET Online Scanner | antimalware | Skipped automatically when running as SYSTEM (requires interactive desktop). |
MSERT (Microsoft Safety Scanner) is excluded from the default chain — it is too slow
for routine remediation runs. Add it back to scanners.json if needed.
Exit Code Semantics
| Scanner | Exit 0 | Exit 1 | Exit 2 | Exit 3 | Other |
|---|---|---|---|---|---|
| RKill | Clean run | Processes killed (not a threat) | — | — | — |
| AdwCleaner | Clean | Cleaned, no reboot needed | Cleaned, reboot required | Found but not cleaned (scan-only) | — |
| Emsisoft | Clean | Threats found/cleaned | Cleaned, reboot required | — | — |
| HitmanPro | Clean | Cleaned | Cleaned, reboot required | — | — |
| ESET | Clean | Threats found | Incomplete removal, reboot may help | — | — |
| MSERT | Clean | Threats found/cleaned | — | — | Non-zero = threats |
| TDSSKiller | Clean | Threats found | — | — | — |
| Stinger | Clean | — | — | — | 13 = threats |
Reboot-required exit codes: AdwCleaner 2, HitmanPro 2, Emsisoft 2, ESET 2.
Autologon / Cleanup Lifecycle
When any scanner exits with a reboot-required code (exit 2), the following sequence runs:
Invoke-RebootCleanupSetupwritescleanup-state.jsonwith the original user, scan ID, and log path.- A hidden
GuruRMM-Tempadministrator account is created with a random password. - One-time autologon (
AutoLogonCount=1) is configured forGuruRMM-Temp. Windows clears the password after the first use. - The account is hidden from the login screen via the
SpecialAccounts\UserListregistry key. - A logon-triggered scheduled task (
GuruRMM-PostRebootCleanup) is registered forGuruRMM-Temp. - The machine reboots after a 15-second warning.
- On next boot, Windows auto-logs in as
GuruRMM-Temp. The WPF splash appears immediately (full-screen, black, cursor hidden). Invoke-PostRebootCleanupruns: verifies pending operations cleared, removes scanner files, writeslogs-ready.json, restores the original user's login name, clears autologon, removes the cleanup task.- A SYSTEM scheduled task (
GuruRMM-TempUserDelete) is registered to delete theGuruRMM-Tempaccount 2 minutes later (cannot delete your own account while logged in). - The splash closes,
logoffis called, and the machine returns to the normal login screen.
Headless / SYSTEM Behavior
-HeadlesspassesNoNewWindowto all scanner launches, suppressing UI windows. Use this when dispatching from an RMM agent that has no interactive desktop.- ESET is automatically skipped when the script detects it is running as the SYSTEM
account (
[System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem). Pass-SkipEsetexplicitly to skip it under other accounts.
Licensing
| Scanner | License for MSP use |
|---|---|
| RKill | Free (BleepingComputer) |
| AdwCleaner | Free for personal and commercial use |
| Emsisoft Command Line Scanner | Free for personal and MSP remediation use |
| HitmanPro | Commercial license required. Each scan uses trial mode; Invoke-HitmanProTrialReset resets the trial window. Verify current licensing terms at https://www.hitmanpro.com before deploying at scale. |
| ESET Online Scanner | Free for personal and commercial use |
Always verify current licensing terms with each vendor before large-scale deployment.
Stand-alone Usage
# Run all scanners in clean mode (default)
.\Invoke-GuruScan.ps1
# Detect only, then auto-remediate if threats found
.\Invoke-GuruScan.ps1 -ScanOnly -AutoRemediate
# Skip ESET (e.g. unattended run)
.\Invoke-GuruScan.ps1 -SkipEset
# Suppress scanner windows (RMM dispatch)
.\Invoke-GuruScan.ps1 -Headless
# View the latest scan results
.\Get-ScanSummary.ps1
# View with AI analysis (requires Ollama)
.\Get-ScanSummary.ps1 -AI
# Re-run clean pass against a prior scan
.\Invoke-Remediation.ps1 -LogRoot "C:\ScanLogs\DESKTOP-20260523-143000"
# Download/refresh scanner EXEs
.\Download-Scanners.ps1
Module Usage
The launcher scripts are thin wrappers. Import the module directly for scripted/pipeline use:
Import-Module .\GuruScan.psd1
# Disk sink (default) — writes results.json + CSV + zip
Invoke-GuruScan
# RMM sink — returns result object to the pipeline, no disk writes
$result = Invoke-GuruScan -OutputSink RMM -Headless
if ($result.total_threats -gt 0) { ... }
# Remediation from a prior scan
Invoke-Remediation -LogRoot "C:\ScanLogs\DESKTOP-20260523-143000"
# Summary report
Get-ScanSummary -AI
# Post-reboot cleanup (called by Invoke-PostRebootCleanup.ps1)
Invoke-PostRebootCleanup -StateFile "C:\GuruScan\cleanup-state.json"
Module Structure
guru-scan\
GuruScan.psm1 # Core module — all helpers + exported cmdlets
GuruScan.psd1 # Module manifest
scanners.json # Scanner definitions (single source of truth)
Invoke-GuruScan.ps1 # Thin launcher -> Invoke-GuruScan
Invoke-Remediation.ps1 # Thin launcher -> Invoke-Remediation
Get-ScanSummary.ps1 # Thin launcher -> Get-ScanSummary
Invoke-PostRebootCleanup.ps1 # WPF splash + logoff; delegates cleanup to module
Download-Scanners.ps1 # Downloads scanner EXEs from scanners.json URLs
downloads\ # Scanner EXEs (gitignored)