sync: auto-sync from HOWARD-HOME at 2026-06-21 20:56:44

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-21 20:56:44
This commit is contained in:
2026-06-21 20:57:10 -07:00
parent 924fa39b34
commit 8fde10c743
2 changed files with 191 additions and 1 deletions

View File

@@ -23,6 +23,7 @@ set -u
TARGET="${1:-}"
PHASE="${2:-all}"
SCANNER_ARG="${3:-}"
if [ -z "$TARGET" ]; then
echo "[ERROR] Usage: bash guruscan-agent-test.sh <hostname|uuid> <prep|scan|collect|all>" >&2
@@ -530,11 +531,63 @@ PS
post_alert "[RMM] GuruScan verify-each on $AGENT_HOST complete - see per-engine detect/remove matrix"
}
# ===========================================================================
# scan-one <Scanner>: fully automated single-scanner test. ONE command does it
# all, hands-off: restore the malware-lab samples, clear stale cleanup state,
# run the scanner DETACHED + NO-CAP via the same path production uses, then
# collect and report (detections, removal, results.json, reboot-cleanup task).
# Mirrors how we proved Emsisoft -- no manual stitching.
# ===========================================================================
phase_scan_one() {
local scanner="${SCANNER_ARG:-HitmanPro}"
echo ""; echo "=== PHASE: scan-one ($scanner) - automated, detached, no-cap ==="
# Setup: free the mutex (kill any prior GuruScan run + scanner procs), clear
# stale cleanup task/state, and restore the malware lab samples.
local sf="$WORK_DIR/one_setup.ps1"
cat > "$sf" <<'PS'
$ErrorActionPreference='Continue'
Get-ScheduledTask -EA SilentlyContinue | Where-Object { $_.TaskName -like 'GuruScan-*' } | ForEach-Object { try{ Stop-ScheduledTask -TaskName $_.TaskName -EA SilentlyContinue }catch{}; try{ Unregister-ScheduledTask -TaskName $_.TaskName -Confirm:$false -EA SilentlyContinue }catch{} }
foreach($n in @('a2cmd','HitmanPro_x64','rkill','EmsisoftCommandlineScanner64')){ Get-Process -Name $n -EA SilentlyContinue | Stop-Process -Force -EA SilentlyContinue }
Start-Sleep 3
Get-ScheduledTask -TaskName 'GuruRMM-ScannerCleanup' -EA SilentlyContinue | Unregister-ScheduledTask -Confirm:$false -EA SilentlyContinue
Remove-Item 'C:\GuruScan\cleanup-state.json' -Force -EA SilentlyContinue
$zip = Get-ChildItem 'C:\Users\Owner\Downloads' -Filter '*.zip' -EA SilentlyContinue | Where-Object { $_.Name -match 'malware' } | Select-Object -First 1
if($zip){ Expand-Archive -Path $zip.FullName -DestinationPath 'C:\Users\Owner\Desktop' -Force -EA SilentlyContinue }
$n=(Get-ChildItem 'C:\Users\Owner\Desktop\malware-samples-master' -Recurse -File -EA SilentlyContinue).Count
Set-Content 'C:\GuruScan\_one_before.txt' $n
Write-Output ("setup done - malware samples present: $n")
PS
run_ps "$sf" 240 70 "setup" || { echo "[ERROR] setup failed"; return 1; }
# Run the scanner the production way: detached scheduled task, unlimited time.
gs_launch_detached "-Scanners $scanner -Headless" "one" || { echo "[ERROR] launch failed"; return 1; }
gs_wait_detached "one" "$scanner" || true
# Report the outcome (parsed from what GuruScan actually wrote).
local rf="$WORK_DIR/one_report.ps1"
cat > "$rf" <<'PS'
$ErrorActionPreference='Continue'
$before=Get-Content 'C:\GuruScan\_one_before.txt' -EA SilentlyContinue
$after=(Get-ChildItem 'C:\Users\Owner\Desktop\malware-samples-master' -Recurse -File -EA SilentlyContinue).Count
Write-Output ("samples: before=$before after=$after REMOVED=" + ([int]$before-[int]$after))
$d=Get-ChildItem 'C:\ScanLogs' -Directory -EA SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if($d -and (Test-Path (Join-Path $d.FullName 'results.json'))){ $r=Get-Content (Join-Path $d.FullName 'results.json') -Raw|ConvertFrom-Json
Write-Output ('results.json -> total_threats=' + $r.total_threats + ' reboot_required=' + $r.reboot_required)
$r.scanners|ForEach-Object{ Write-Output (' ' + $_.name + ': exit=' + $_.exit_code + ' threats=' + $_.threats_found) } }
$ct=Get-ScheduledTask -TaskName 'GuruRMM-ScannerCleanup' -EA SilentlyContinue
if($ct){ Write-Output ('reboot-cleanup task -> REGISTERED (state=' + $ct.State + ', logon-delay=' + $ct.Triggers[0].Delay + ')') } else { Write-Output 'reboot-cleanup task -> NOT registered' }
PS
run_ps "$rf" 60 24 "report" || true
post_alert "[RMM] GuruScan automated scan-one ($scanner) complete on $AGENT_HOST"
}
case "$PHASE" in
prep) phase_prep ;;
scan) phase_scan ;;
scan-one) phase_scan_one ;;
collect) phase_collect ;;
verify-each) phase_verify_each ;;
all) phase_prep && phase_scan && phase_collect ;;
*) echo "[ERROR] Unknown phase '$PHASE' (prep|scan|collect|verify-each|all)" >&2; exit 1 ;;
*) echo "[ERROR] Unknown phase '$PHASE' (prep|scan|scan-one <Scanner>|collect|verify-each|all)" >&2; exit 1 ;;
esac

View File

@@ -0,0 +1,137 @@
## User
- **User:** Howard Enos (howard)
- **Machine:** Howard-Home
- **Role:** tech
## Session Summary
Finalized and validated the new `screenconnect` skill (ConnectWise Control / ScreenConnect
RESTful API Manager extension), built earlier in the parent session the same way as the
`bitdefender` skill: gather the full API surface, then test until everything works. This
session picked up at the validation/finalization stage.
Ran the `skill-creator` skill against the screenconnect skill to confirm rule compliance.
All checks passed except one: the SKILL.md did not document the errorlog behavior (the
skill-creator mandate wants an explicit line, even though the CLI code already logs genuine
failures and skips expected conditions). Added an "Error logging" section to SKILL.md.
Cleaned up stale "pending unlock" help text in `sc.py` (the control methods are verified
live now, so the text was inaccurate). Re-ran the selftest: 12/12 passing. Committed the
skill finalization to the parent repo (`3a1edb7`).
Captured the RMM-integration vision as **Feature 7** in the GuruRMM `RMM_THOUGHTS.md`:
when a device is flagged for ScreenConnect in the RMM, the RMM builds the correct
parameterized access installer from the device's client/site/tags, pushes it via the agent
so the SC client self-tags into the right Company/Site/Tag, then controls the session and
keeps the SC custom properties in sync. Status: Raw; needs Mike's go before building.
Per Howard's choice, did NOT tear down the SC test on RMM-TEST-MACHINE — kept the
ScreenConnect Client service running and the test session live as a fixture for the
upcoming RMM-integration phase. Only removed the two stray test temp files
(`sc-control-test.txt`, `sc-access.msi`) via an RMM PowerShell command; posted the required
`[RMM]` write-op alert to #dev-alerts.
Fixed two flags raised at the end of the skill work, both in the `guru-rmm` submodule's
`RMM_THOUGHTS.md`: (1) the Feature 7 edit was uncommitted in a detached-HEAD submodule
full of other sessions' in-progress files; (2) the file contained 3 raw NUL bytes that
made it read as binary to grep. Delivered both fixes on an isolated branch off origin/main
(`docs/rmm-thoughts-sc-feature7`, commit `4f10149`, pushed) without disturbing the parent
gitlink or the other 8 dirty files. The NUL bytes turned out to be intentional `^@`
examples inside a jsonb-bug writeup, so they were escaped to readable `\x00` rather than
deleted (meaning preserved).
## Key Decisions
- Ran skill-creator as a validation pass against an existing skill (not to create a new
one) — used its Quality Checklist + mandatory-errorlog rule as the rubric.
- Kept SC installed on RMM-TEST-MACHINE rather than tearing down: the upcoming
GuruRMM<->ScreenConnect integration (Feature 7) needs exactly that fixture. Only removed
test litter (marker file + downloaded msi).
- Delivered the submodule doc change via a branch off origin/main rather than committing in
the detached-HEAD checkout — committing on detached HEAD amid 8 other dirty files risks
orphaning their work. Branch handed off for Mike to merge (the standard submodule
workflow: merge = deploy).
- Reset the redundant uncommitted Feature 7 out of the shared dirty checkout (set the live
file back to origin/main) so it cannot double-merge once the branch lands. The other 8
modified files were left untouched.
- Escaped the NUL bytes to `\x00` instead of stripping them: cat -v revealed they were
deliberate illustrative `^@` characters in a Postgres jsonb-NUL bug writeup; stripping
would have turned "contains a `^@` (NUL)" into empty backticks and lost the point.
## Problems Encountered
- skill-creator validation surfaced one deviation (SKILL.md not documenting errorlog
behavior) -> added an Error-logging section to SKILL.md.
- RMM command dispatch failed twice with "invalid escape" / JSON parse errors because the
PowerShell payload used Windows backslash paths inside the JSON body -> switched to
forward-slash paths (PowerShell accepts them), command then ran clean.
- NUL-byte replacement repeatedly no-op'd: the Bash tool's heredoc was collapsing `\x00`
escapes before Python's string parser saw them, so both the search and replacement
became a bare NUL (replace = no-op). Confirmed via an isolated in-memory test, then fixed
by writing a real script file (`.nulfix.py`) that builds the bytes numerically
(`bytes([0])` and `bytes([0x5C,0x78,0x30,0x30])`) with no backslash escapes in source.
- `git worktree remove` failed with "Permission denied" (Windows file lock) -> force-removed
the directory with PowerShell `Remove-Item -Recurse -Force`, then `git worktree prune`.
Important because the worktree lived under C:\claudetools\ and would have been swept by
/save's `git add -A`.
## Configuration Changes
Modified / committed (parent repo, commit `3a1edb7`):
- `.claude/skills/screenconnect/scripts/sc.py` — removed stale "pending unlock" help text.
Modified earlier in parent session, already committed before this session:
- `.claude/skills/screenconnect/SKILL.md` (incl. the Error-logging section added this
session), `scripts/sc_client.py`, `scripts/selftest.py`, `references/api-reference.md`.
guru-rmm submodule (branch `docs/rmm-thoughts-sc-feature7`, commit `4f10149`, pushed):
- `docs/RMM_THOUGHTS.md` — added Feature 7 (ScreenConnect parameterized deploy + control)
and index line; escaped 3 raw NUL bytes to `\x00`.
Removed (scratch): `C:\claudetools\.nulfix.py`, `C:\claudetools\.nultest.md`,
worktree `C:\claudetools\.gr-wt-feature7`.
## Credentials & Secrets
No new credentials. The screenconnect skill loads its API secret from the SOPS vault
`msp-tools/screenconnect.sops.yaml` field `credentials.api_secret` (never hardcoded);
auth is the `CTRLAuthHeader` (raw secret, no "Basic" prefix) + `Origin` header.
## Infrastructure & Servers
- ScreenConnect instance: `https://computerguru.screenconnect.com`; RESTful API Manager
extension GUID `2d558935-686a-4bd0-9991-07539f5fe749`.
- RMM-TEST-MACHINE active agent id `99d6d692-99e0-4359-9f9c-f43be89f49e5` (a stale
re-enrollment `7d3456f5-...` also exists; last_seen distinguishes them). SC client
service on it: `ScreenConnect Client (1912bf3444b41a08)` = Running (kept as fixture).
- SC test session: `a5d867ab-cbf2-4b00-99a0-80b082ec5ddd` (kept live).
- GuruRMM API `http://172.16.3.30:3001`; Gitea remote
`https://git.azcomputerguru.com/azcomputerguru/gururmm.git`.
## Commands & Outputs
- Selftest: `CLAUDETOOLS_ROOT=C:/claudetools python scripts/selftest.py` -> 12/12 passed.
- RMM cleanup dispatch (forward-slash paths) -> command `d935cd06-...`, completed exit 0:
`REMOVED: C:/Windows/Temp/sc-control-test.txt, C:/Windows/Temp/sc-access.msi` /
`SC SERVICE KEPT: ScreenConnect Client (1912bf3444b41a08) = Running`.
- NUL fix verify: source NULs 3 -> dst NULs 0, 3 literal `\x00` tokens, spans read
"contains a `\x00` (NUL)", "forbids `\x00`", "grep for `\x00`".
## Pending / Incomplete Tasks
- Feature 7 branch `docs/rmm-thoughts-sc-feature7` awaits Mike's merge into gururmm main
(the branch also escapes the 3 NUL bytes; merging fixes them in origin/main).
- GuruRMM<->ScreenConnect integration itself (Feature 7) — needs Mike's go before building.
- SC GetSessions full-fleet inventory gap: the RESTful API Manager extension does not expose
GetSessions/GetAllSessions/GetSessionGroups ("web method does not exist"); needs Mike to
update the extension. Tracked via coord msg 60d9e876. By-name lookup works post-install.
- SC test fixture remains on RMM-TEST-MACHINE intentionally (client service + session live).
## Reference Information
- Parent commit: `3a1edb7` (screenconnect finalize).
- Submodule branch/commit: `docs/rmm-thoughts-sc-feature7` / `4f10149` (off origin/main
`1dce66d`).
- RMM write-op alert message_id `1518461799618449428` (#dev-alerts).
- Skill path: `.claude/skills/screenconnect/` (SKILL.md, scripts/{sc.py,sc_client.py,
selftest.py}, references/api-reference.md).
- ScreenConnect docs: https://docs.connectwise.com/ScreenConnect_Documentation