diff --git a/.claude/scripts/guruscan-agent-test.sh b/.claude/scripts/guruscan-agent-test.sh index a6d2f998..0fec25d2 100644 --- a/.claude/scripts/guruscan-agent-test.sh +++ b/.claude/scripts/guruscan-agent-test.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # guruscan-agent-test.sh - Deploy GuruScan to a Windows GuruRMM agent and run an -# end-to-end smoke test (full 3-engine chain, EICAR-seeded, clean mode), pulling -# every log back for review. +# end-to-end smoke test (full 3-engine chain, clean mode), pulling every log back +# for review. # # Phases: -# prep - upload module to C:\GuruScan, Defender-exclude tool/test dirs, -# download RKill+Emsisoft, fetch HitmanPro, seed EICAR, verify ready +# prep - upload module to C:\GuruScan, Defender-exclude tool dirs, +# download RKill+Emsisoft, fetch HitmanPro, verify ready # scan - dispatch Invoke-GuruScan.ps1 -Headless (clean mode) and poll # collect - pull results.json + per-scanner logs into the repo # all - prep then scan then collect @@ -14,10 +14,9 @@ # bash guruscan-agent-test.sh # # Mirrors the RMM plumbing in run-onboarding-diagnostic.sh (vault auth -> JWT -> -# chunked base64 upload -> dispatch -> poll). EICAR is the standard harmless AV -# test file; it is assembled on the endpoint (never written to this host) and -# dropped only into a Defender-excluded folder so GuruScan's own engines are what -# detect it. +# chunked base64 upload -> dispatch -> poll). Detection testing uses the real +# malware-samples set via the scan-one / verify-each phases. Prep's EICAR seed is +# DISABLED by default (kept for future scanners) -- enable with SEED_EICAR=1. set -u @@ -25,6 +24,11 @@ TARGET="${1:-}" PHASE="${2:-all}" SCANNER_ARG="${3:-}" +# EICAR test-file seeding in the prep phase. DISABLED by default -- kept (not +# deleted) so it can be switched back on to smoke-test detection as new scanners +# are added to the chain. Enable per-run with: SEED_EICAR=1 bash guruscan-agent-test.sh ... +SEED_EICAR="${SEED_EICAR:-0}" + if [ -z "$TARGET" ]; then echo "[ERROR] Usage: bash guruscan-agent-test.sh " >&2 exit 1 @@ -273,12 +277,12 @@ phase_prep() { upload_file "$GS_DIR/$f" "C:\\GuruScan\\$f" || { _logerr "upload failed" --context "file=$f host=$AGENT_HOST"; return 1; } done - # 2) Defender exclusions for tool + downloads + test dirs (so Defender does not - # nuke the scanner EXEs or grab EICAR before GuruScan's engines run). + # 2) Defender exclusions for tool + downloads dirs (so Defender does not nuke + # the scanner EXEs before GuruScan's engines run). local sf="$WORK_DIR/defender.ps1" cat > "$sf" <<'PS' $ErrorActionPreference='Continue' -foreach($p in @('C:\GuruScan','C:\GuruScan\downloads','C:\GuruScanTest','C:\EmsisoftCmd')){ +foreach($p in @('C:\GuruScan','C:\GuruScan\downloads','C:\EmsisoftCmd')){ try { Add-MpPreference -ExclusionPath $p -ErrorAction Stop; Write-Output "EXCLUDED $p" } catch { Write-Output ("EXCLUDE-SKIP " + $p + " : " + $_.Exception.Message) } } @@ -310,12 +314,16 @@ try { PS run_ps "$sf3" 300 70 "download-hitmanpro" || echo "[WARN] HitmanPro download dispatch issue" - # 5) seed EICAR into the Defender-excluded test folder (assembled on endpoint) - local sf4="$WORK_DIR/eicar.ps1" - cat > "$sf4" <<'PS' + # 5) [OPTIONAL] seed EICAR into a Defender-excluded test folder (assembled on + # the endpoint). DISABLED unless SEED_EICAR=1 -- retained so detection can be + # smoke-tested as new scanners are added to the chain. + if [ "$SEED_EICAR" = "1" ]; then + local sfe="$WORK_DIR/eicar.ps1" + cat > "$sfe" <<'PS' $ErrorActionPreference='Continue' $dir='C:\GuruScanTest' if(-not (Test-Path $dir)){New-Item -ItemType Directory -Path $dir -Force|Out-Null} +try { Add-MpPreference -ExclusionPath $dir -ErrorAction Stop } catch {} # Standard EICAR test signature, assembled from fragments so it is never stored # contiguously anywhere except the on-disk test file. $e = 'X5O!P%@AP[4\PZX54(P^)7CC)7}' + '$EICAR' + '-STANDARD-ANTIVIRUS-' + 'TEST-FILE!$H+H*' @@ -329,9 +337,12 @@ if(Test-Path $f){ Write-Output "EICAR MISSING after write - Defender (or other AV) grabbed it despite exclusion" } PS - run_ps "$sf4" 60 24 "seed-eicar" || { _logerr "EICAR seed failed" --context "host=$AGENT_HOST"; return 1; } + run_ps "$sfe" 60 24 "seed-eicar" || { _logerr "EICAR seed failed" --context "host=$AGENT_HOST"; return 1; } + else + echo "[INFO] EICAR seeding disabled (set SEED_EICAR=1 to enable)" + fi - # 6) readiness check - confirm all three scanner binaries present + EICAR present + # 6) readiness check - confirm all three scanner binaries + module present local sf5="$WORK_DIR/ready.ps1" cat > "$sf5" <<'PS' $ErrorActionPreference='Continue' @@ -339,8 +350,7 @@ $need=@{ 'RKill' ='C:\GuruScan\downloads\rkill.exe'; 'Emsisoft' ='C:\GuruScan\downloads\EmsisoftCommandlineScanner64.exe'; 'HitmanPro' ='C:\GuruScan\downloads\HitmanPro_x64.exe'; - 'Module' ='C:\GuruScan\GuruScan.psm1'; - 'EICAR' ='C:\GuruScanTest\eicar_test.com' + 'Module' ='C:\GuruScan\GuruScan.psm1' } $ok=$true foreach($k in $need.Keys){ @@ -353,7 +363,7 @@ PS if grep -q 'ALL-READY' "$WORK_DIR/last_result.json" 2>/dev/null || \ echo "$(jq -r '.stdout' "$WORK_DIR/last_result.json" 2>/dev/null)" | grep -q 'ALL-READY'; then echo "[OK] prep complete - endpoint is READY for scan" - post_alert "[RMM] GuruScan test: prepped $AGENT_HOST (module+3 scanners+EICAR staged)" + post_alert "[RMM] GuruScan test: prepped $AGENT_HOST (module+3 scanners staged)" else echo "[WARN] prep finished but not all components READY - review output above before scanning" fi diff --git a/.consoles.tsv b/.consoles.tsv new file mode 100644 index 00000000..b2162060 --- /dev/null +++ b/.consoles.tsv @@ -0,0 +1,38 @@ +E43883325A01000000000728377B00000000077EA56D0000000063AA61F7:2109856759 Brooklyn/Skybar +0CEA1435AAF500000000086B8A0E0000000008DE4A2A0000000067127DFB:407050433 CGU-Curves +0CEA1456463900000000087729C50000000008EAA14D0000000067282B45:989250246 CGU-Goldstein Dallas +0CEA146890BF000000000885E5160000000008FA3AD6000000006741FA51:285001334 CGU-Goldstein Tucson +0CEA1435051D00000000086D735B0000000008E04F13000000006715B430:1815899630 CGU-VWP-TUS +1C6A1B1BC2470000000008B8D1B50000000009302B160000000067A67E3A:1341833834 Cloud Gateway Ultra +6C63F8E9CD9800000000094CFFCA0000000009CD3A8800000000687D9005:1084531562 CuttingEdge UDMPro +D8B3708AE5F60000000007A651B900000000080875E00000000064CFE6BD:939536870 DM-Pavon +70A741E5251100000000068DAE250000000006DC7A5D0000000062D9B71F:1222483871 JT Auto +0CEA14686F770000000008802B2D0000000008F436E80000000067384AE9:2084984694 KhaldaCamdenUGC +0CEA1434EF9100000000086D12120000000008DFE9B300000000671508C7:670109092 Khalsa - River +28704E50EF0C000000000836684F0000000008A5F6870000000066A67F43:686916544 Longhouse1 +70A741E4C69900000000068F8F5D0000000006DE792D0000000062DCCE57:666594072 PST Cloud Key NW +D021F9DDC1D900000000066960E50000000006B6173A00000000627C2548:11007881 Quantum +AC8BA96E7C3F000000000713F14D000000000769454D000000006395CE06:70122304 Reliant +7845588752630000000006025234000000000648E4B6000000006131C3CC:1815508705 Tedards UDM +58D61F818A150000000009CD55A0000000000A58E46400000000696D3CBA:437346010 UCG - Glabman +0CEA14D50CD30000000008969B8D00000000090BEDCE00000000675EB9B7:155421411 UCG - Stoltz +0CEA1460EE4000000000087F808E0000000008F383C100000000673721CE:1645583723 UCG-Barry +58D61F68767B0000000009AFA222000000000A3888580000000069357CA3:1690549690 UCG-Coin and Autograph +0CEA14D4C0CD00000000089DE1D90000000009139BAD00000000676A4F4F:1758362784 UCG-CurvesHouse +28704E8E4E01000000000851C88B0000000008C2F92F0000000066E5C860:782809919 UCG-LaHC +0CEA1460F4F400000000087F719F0000000008F374480000000067370AD3:1901426120 UCG-Lonestar +1C6A1B18C1570000000008B644D900000000092D77E90000000067A2C4AC:638116470 UCG-PST-CC +1C6A1B18B9710000000008B66FAD00000000092DA4AD0000000067A2FE82:2127817160 UCG-PST-NW +0CEA14DDCEED00000000089EE6FB000000000914B0AD00000000676BD633:300091274 UCG-Ridgetop +1C6A1B4B14DD0000000008CE3561000000000946A4750000000067C563E4:1543906151 UCG-Scileppi +0CEA14D4C14B00000000089DE5100000000009139F4000000000676A52E5:1443984829 UCG-Shelly +E438832F425500000000072165880000000007777EC60000000063A3D2AA:266756141 UDM - Stamback +D021F96C10F9000000000646421B000000000690DCFE0000000061F0BB7D:1721816512 UDM-Dataforth +28704E7141BF00000000084707E60000000008B793950000000066CC83AC:1219071989 UDM-IMC-L1 +6C63F81897ED0000000008E5804C00000000095F09450000000067E023DD:1515952861 UDM-IMC-MOO +6C63F81896F10000000008E58C4600000000095F15D20000000067E03555:254136650 UDM-Valley Wide Plastering (56th) +28704E831A4D00000000085404440000000008C551D10000000066EA49C0:1825669966 UDM_SE-Cutting Edge +28704E60E7FB00000000083E6C5B0000000008AE7A6F0000000066BA2D00:2029099918 UDR-LensAuto +8478489CADB50000000008D2116D00000000094AB6200000000067C9F881:242820913 UDR-Patriot Sonoita +1C0B8B4894530000000008E9D6A0000000000963A87B0000000067E5F8A5:878948159 UDR7-Lozano_Johns +2d6b654d-9b79-4eaa-b2e1-52062a5690ef UOS Server diff --git a/errorlog.md b/errorlog.md index f8b6f05d..905f47ee 100644 --- a/errorlog.md +++ b/errorlog.md @@ -23,6 +23,8 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · 2026-07-10 | GURU-5070 | packetdial | HTTP 404 GET https://pbx.packetdial.com/ns-api/v2/domains/vwp.91912.service/users/100: {"code":404,"message":"Resource not found."} [ctx: cmd=user] (x2) +2026-07-10 | Howard-Home | unifi-wifi | [correction] hand-rolled raw curl against the Site Manager connector (reads AND a production write: disabled Teleport on Goldstein Tucson UCG) instead of using the unifi-wifi skill; correct approach = gw-sitemanager.sh for reads, and for VPN-server config the skill has no command (WIP) so flag it and use the UI / extend the skill rather than free-hand writes [ctx: skill=unifi-wifi gateway=CGU-Goldstein-Tucson] + 2026-07-10 | Mikes-MacBook-Air | packetdial | HTTP 404 DELETE https://pbx.packetdial.com/ns-api/v2/domains/vwp.91912.service/users/105/devices/sip%3A105a%40vwp.91912.service: {"code":404,"message":"Device not found."} [ctx: cmd=raw] 2026-07-10 | Mikes-MacBook-Air | packetdial | HTTP 404 DELETE https://pbx.packetdial.com/ns-api/v2/domains/vwp.91912.service/users/105/devices: {"code":404,"message":"Device not found."} [ctx: cmd=raw] diff --git a/session-logs/2026-07/2026-07-10-howard-guruscan-rkill-whitelist.md b/session-logs/2026-07/2026-07-10-howard-guruscan-rkill-whitelist.md new file mode 100644 index 00000000..a5e18e39 --- /dev/null +++ b/session-logs/2026-07/2026-07-10-howard-guruscan-rkill-whitelist.md @@ -0,0 +1,145 @@ +# GuruScan — RKill Process Whitelist + Scan-Log Protection — 2026-07-10 + +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech + +## Session Summary + +Resumed the paused GuruScan verification effort (multi-engine malware scanner, +`projects/msp-tools/guru-scan`) to fix a real defect: RKill, which runs first in +the chain as a process killer, could terminate the PowerShell host running the +scan itself, aborting the whole chain before HitmanPro and Emsisoft ever launch. +A parallel commit pushed from another machine this same day +(`7a5a657 test-results: TPM-PC production scan ... RKill-kills-parent bug found`) +independently confirmed the bug against a live production scan, so the fix lands +on an observed real-world failure. + +The clean fix uses RKill's own `-w ` switch, which takes a whitelist of full +EXE paths (one per line, no quotes — quotes break RKill's path matching) that it +must not terminate. The module now writes `C:\GuruScan\rkill-whitelist.txt` before +the scanner loop, containing the live host path (`(Get-Process -Id $PID).Path`) +plus the standard 64/32-bit `powershell.exe` locations, written ASCII (no BOM) so +the first line matches cleanly. `scanners.json` passes `-w C:\GuruScan\rkill-whitelist.txt` +on RKill's scan and clean args. RKill was already scanner #1 in the array order, so +no reordering was needed. + +Two follow-up changes came from user direction. First, the EICAR prep-phase seed in +the RMM test harness (`.claude/scripts/guruscan-agent-test.sh`) was **disabled, not +deleted** — gated behind a `SEED_EICAR` flag (default off) with its own self-contained +Defender exclusion, so it can be switched back on (`SEED_EICAR=1`) to smoke-test +detection as new scanners are added. Detection testing otherwise uses the real +malware-samples set via the `scan-one`/`verify-each` phases. Second, the post-reboot +cleanup was hardened so scan logs are never removed: `Invoke-ScannerCleanup.ps1` already +only deleted scanner install dirs + `C:\GuruScan\downloads` (never `C:\ScanLogs`), but +it now documents that invariant and adds a runtime guard that skips any path under +`C:\ScanLogs` or `C:\GuruScan\reports`, so a future edit can't accidentally delete the +logs or archives that must survive the remediate → reboot → cleanup lifecycle. + +All three guru-scan files parse clean and the harness passes `bash -n`. The guru-scan +submodule was committed and pushed (rebased onto the other machine's concurrent commits); +the superproject gitlink bump + harness change + this log sync via `/save`. + +## Key Decisions + +- **RKill `-w` whitelist over any process-renaming or ordering hack** — RKill natively + supports a whitelist file of full EXE paths; using it is the simplest correct fix and + needs no change to how the orchestrator launches. +- **Whitelist written ASCII (no BOM)** — RKill reads the whitelist line-by-line; a UTF-8 + BOM would corrupt the first path match. The existing `whitelist.txt` (Emsisoft/HitmanPro) + stays UTF-8 because those engines tolerate it; the RKill file is deliberately ASCII. +- **EICAR disabled, not removed** — user wants it retained for future scanner smoke-tests. + Gated behind `SEED_EICAR` (default 0) rather than deleted. +- **Cleanup guard scoped to `C:\ScanLogs` + `C:\GuruScan\reports`** — belt-and-suspenders: + logs were already safe, but an explicit runtime guard + doc comment prevents a future + edit from ever adding a log path to the removal list. +- **RKill fix in module + scanners.json (not harness-only)** — so it applies to production + runs, not just the test harness (the harness just deploys the same module/JSON). + +## Problems Encountered + +- **guru-scan push rejected (non-fast-forward)** — remote had newer commits from another + machine (including the TPM-PC RKill-kills-parent finding). Resolved by + `git fetch` + `git rebase origin/main`, then push (`7a5a657..087c73c`). + +## Configuration Changes + +Modified (guru-scan submodule, committed `087c73c` + pushed): +- `GuruScan.psm1` — write `C:\GuruScan\rkill-whitelist.txt` (ASCII) before the scanner + loop; live host path via `Get-Process -Id $PID` + standard PowerShell paths, de-duped. +- `scanners.json` — RKill `scan_args`/`clean_args` add `-w C:\GuruScan\rkill-whitelist.txt`. +- `Invoke-ScannerCleanup.ps1` — doc that scan logs/archives are never removed; runtime + guard skips any path under `C:\ScanLogs` or `C:\GuruScan\reports`. + +Modified (main repo): +- `.claude/scripts/guruscan-agent-test.sh` — EICAR prep seed gated behind `SEED_EICAR` + (default off, self-contained Defender exclusion); readiness check no longer requires + EICAR; header/alert comments updated. + +## Credentials & Secrets + +- None created or discovered this session. + +## Infrastructure & Servers + +- **DESKTOP-MS42HNC** — GuruScan test VM (agent id `0de89b88-b21d-4647-ab64-96157ba87cc5`, + AZ Computer Guru / Howard-VM). Not touched this session; RKill-whitelist verification + (re-run `prep`) pending its next online window. +- **TPM-PC** — production endpoint where the RKill-kills-parent bug was observed (see the + concurrent commit `7a5a657` / `test-results/` in guru-scan). +- **GuruRMM API** — `http://172.16.3.30:3001`; creds vault `infrastructure/gururmm-server.sops.yaml`. +- GuruScan deploy paths: `C:\GuruScan\` (module + `rkill-whitelist.txt`), `C:\GuruScan\downloads\` + (scanner EXEs), `C:\EmsisoftCmd\` (Emsisoft), `C:\ScanLogs\\` (logs, preserved), + `C:\GuruScan\reports\.zip` (log archive, preserved). + +## Commands & Outputs + +- RKill whitelist switch: `rkill -w C:\path\wl.txt` — full EXE paths, one per line, no quotes, + ANSI/UTF-8 (no BOM). RKill lists whitelisted-and-ignored processes at run. +- Validation: `bash -n .claude/scripts/guruscan-agent-test.sh` → OK; PowerShell AST + `ParseFile` on `GuruScan.psm1` + `Invoke-ScannerCleanup.ps1` → clean. +- Enable EICAR smoke-test: `SEED_EICAR=1 bash .claude/scripts/guruscan-agent-test.sh prep`. +- guru-scan submodule push: `7a5a657..087c73c main -> main`. + +## Pending / Incomplete Tasks + +- **Verify the RKill whitelist live** — re-run `bash .claude/scripts/guruscan-agent-test.sh + DESKTOP-MS42HNC prep` (or `scan`) when the VM is online; confirm `rkill-whitelist.txt` is + written and RKill logs the PowerShell host as an ignored/whitelisted process. +- **Emsisoft vs HitmanPro detection comparison** — still open from the prior session + (`scan-one Emsisoft` on DESKTOP-MS42HNC). See `project_guruscan_in_test_paused`. +- **Clean up DESKTOP-MS42HNC** — remove samples/zip/EICAR/test artifacts; re-enable Defender + RTP + Tamper Protection (disabled at the console for malware testing). + +## Reference Information + +- guru-scan commit: `087c73c` (pushed to `https://git.azcomputerguru.com/azcomputerguru/guru-scan.git` main). +- Prior related logs: `session-logs/2026-06/2026-06-22-howard-guruscan-hardening.md`, + `.../2026-06-22-howard-gururmm-dispatch-hang-fix-guruscan-paused.md`. +- Memory: `project_guruscan_in_test_paused`. +- RKill command-line reference (BleepingComputer): `-d` debug, `-h` help, `-l `, `-w `. +- HitmanPro exit-code bitmask: bit0(1)=threats, bit2(4)=reboot → 5 = threats+reboot. + +## Update: guru-scan `3ca5ba7` — whitelist Syncro/Datto EDR/GuruRMM from RKill + HitmanPro + +Per follow-up: ensure RKill **and** HitmanPro (and Emsisoft) never touch Syncro, Datto +EDR, or GuruRMM files/folders. + +- **HitmanPro/Emsisoft (folder exclusion via `whitelist.txt`)** — GuruRMM + (`C:\Program Files\GuruRMM`, `C:\ProgramData\GuruRMM`) and Syncro + (`C:\Program Files\RepairTech`, `(x86)`, `C:\ProgramData\Syncro`) were already listed. + Added **Datto EDR / Datto AV** (Infocyte lineage): `C:\Program Files\Infocyte`, + `C:\Program Files\Datto`, `C:\Program Files (x86)\Datto`, `C:\ProgramData\Datto`, + `C:\ProgramData\CentraStage\AEMAgent\RMM.AdvancedThreatDetection`. Datto EDR agent is + `agent.exe` (service `HUNTAgent`); standard install is the Infocyte tree, CentraStage + path covers a Datto-RMM-bundled EDR deployment. +- **RKill (process killer, not a file scanner)** — folder exclusions don't apply, so the + module now enumerates every RUNNING process whose EXE lives under a whitelisted tool + folder and adds it to the `-w` RKill whitelist by full path (folder-membership → no + hardcoded exe names). Spares GuruRMM, Syncro, Datto EDR, ScreenConnect, Bitdefender, + MSP360, Splashtop agents live at scan time. + +Datto EDR paths confirmed from Datto's own allowlisting guide +(`edr.datto.com/.../allowlisting-agent.htm`). `GuruScan.psm1` parses clean. +guru-scan HEAD now `3ca5ba7` (pushed).