Files
claudetools/projects/msp-tools/guru-scan/README.md
Howard Enos f844054847 sync: auto-sync from HOWARD-HOME at 2026-05-26 21:58:00
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-05-26 21:58:00
2026-05-26 21:58:09 -07:00

170 lines
6.8 KiB
Markdown

# 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:
1. `Invoke-RebootCleanupSetup` writes `cleanup-state.json` with the original user, scan ID, and log path.
2. A hidden `GuruRMM-Temp` administrator account is created with a random password.
3. One-time autologon (`AutoLogonCount=1`) is configured for `GuruRMM-Temp`. Windows clears the password after the first use.
4. The account is hidden from the login screen via the `SpecialAccounts\UserList` registry key.
5. A logon-triggered scheduled task (`GuruRMM-PostRebootCleanup`) is registered for `GuruRMM-Temp`.
6. The machine reboots after a 15-second warning.
7. On next boot, Windows auto-logs in as `GuruRMM-Temp`. The WPF splash appears immediately (full-screen, black, cursor hidden).
8. `Invoke-PostRebootCleanup` runs: verifies pending operations cleared, removes scanner files, writes `logs-ready.json`, restores the original user's login name, clears autologon, removes the cleanup task.
9. A SYSTEM scheduled task (`GuruRMM-TempUserDelete`) is registered to delete the `GuruRMM-Temp` account 2 minutes later (cannot delete your own account while logged in).
10. The splash closes, `logoff` is called, and the machine returns to the normal login screen.
---
## Headless / SYSTEM Behavior
- `-Headless` passes `NoNewWindow` to 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 `-SkipEset` explicitly 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
```powershell
# 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:
```powershell
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)
```