MishmarמִשְׁמָרMEESH-marHebrew for a guard post — the watch, and the people who keep it.

WorkVulnerability and endpoint security

From a one-off compromise assessment to a repeatable Windows audit

An agentless, read-only PowerShell audit that re-runs the checks of a Windows compromise assessment, diffs each run against a known-good baseline and keeps remediation behind tiers.

The problem

A compromise assessment of a Windows workstation is usually a one-time effort: persistence, running state, accounts and logs are examined once, and the questions stop when the report is delivered. They stay worth asking.

A current-state check for remote-management software can report none present on a host where a remote-control product was installed and later removed. A sweep that looks only at what is installed now cannot see what ran and left.

The goal: an examination that runs on demand, without an agent, only reads, records what it ruled out as well as what it found, and reports what changed since a known-good state.

What was built

A PowerShell module of 13 checks: endpoint protection state, persistence, remote access, processes, services and kernel drivers, scheduled tasks, network, firewall, filesystem staging directories, accounts and credential-theft posture, browser extensions and developer toolchain, execution history, and logging posture.

The remote-access check has a historical half. It reads per-user execution and recent-file artifacts and leftover configuration directories to find products that ran and were removed. When it finds a trace, it parses the product’s own logs to separate “ran, but no session occurred” from “the logs are gone and this cannot be determined”.

Each finding carries a severity, evidence, a rationale and, where one exists, a benign explanation. Reports render as HTML, JSON and CSV. A baseline is a JSON report from a clean run; later runs are diffed against it by stable key as New, Changed, Resolved or Unchanged.

Remediation is a separate subsystem that no check can reach:

Tier Rule Unattended
Safe Only increases observability; one documented command reverses it Yes, the only eligible tier
Guarded Reversible, but can remove access or stop something starting No: exported as a script for review, or applied only with an explicit tier and force
Manual Destructive, irreversible or a matter of judgement Never; documented steps only

Design decisions

  • Read-only at runtime. It can run on a production host without a change window, and during an incident without destroying evidence.
  • Pass findings are first class. A report of problems alone cannot show what was checked and cleared, and a Pass that disappears between runs is a signal.
  • Diff only stable values. Process IDs, timestamps, counts and ephemeral ports stay out of the compared data. Volatile inventory is reported but never diffed.
  • Degrade, never fail. Without administrator rights some sources are unreadable, and one returns an empty exclusion list rather than an error. Each gap is reported as an explicit limitation, never as an all-clear.
  • Severity discipline. Nothing reaches Medium without a concrete indicator on a specific artifact. Suppressions are data, each documented as a deliberate blind spot.
  • The tool is attack surface. Findings are attacker-influenced, so HTML encoding is a tested control and a report makes no network requests when opened. An elevated run from a user-writable path is a privilege-escalation route, so the engine refuses to apply changes from one, checks its own module ACLs, and refuses plans whose actions arrive as text rather than live code.
  • Recoverable changes. Dry run is the default. Each action is verified before and after, backed up first (a failed backup cancels it), added to a reverse-order rollback script, and logged append-only, refusals included.

Two lessons changed the code. First, a read can destroy data. Listing the Windows credential store from a scheduled logon that could not unlock the user’s DPAPI keys reported an empty store, and stored credentials were lost. Now anything that makes Windows decrypt user DPAPI data first checks token and session metadata. A single function may list the store, and it re-checks before doing so. A skipped inventory reports as Info, not Pass. A follow-up fix covered machine accounts, which have working keys but reach their own empty store.

Second, a scriptblock-closure pattern once left 34 of 42 remediation blocks unable to run. They parsed and registered, and failed only when executed. The constructor now rejects closures, and tests assert every catalog block is reachable.

Evidence and limits

  • 408 Pester tests pass under Windows PowerShell 5.1 and PowerShell 7.
  • The credential-safety suite (147 tests) runs syntax-tree rules over the whole source tree. One function alone may invoke the credential-listing commands, under any spelling. No other API that decrypts user DPAPI data may appear. Every file-content read needs a guard in the same function, on the same path wherever the read names one. Each rule is first proven on synthetic code that must and must not trip it.
  • 36 deliberate regressions were introduced; each makes the suite fail.

Limits:

  • Not an EDR or antivirus: a point-in-time snapshot, blind to fileless implants and activity between runs.
  • It reads through the ordinary Windows API, which a kernel implant can subvert. A clean report is evidence, not proof.
  • A baseline captured on a compromised host treats the compromise as normal; no technical defence exists.
  • No CIS or STIG mapping, and no score.
  • The file-read rule matches exact command names, so an alias or a .NET stream reader would slip past it; none is used in the source.

Where it applies

For a payer or CMS contractor preparing an authorization package, the pattern yields recurring configuration-monitoring evidence: a known-good baseline, dated diffs, Pass findings that document coverage, and remediation records with backups, rollback and an append-only log.

For semiconductor and advanced-manufacturing suppliers, the same constraints suit Windows engineering workstations, where agents are often unwelcome and change windows scarce: read-only, agentless, no runtime dependencies, no default network calls. Customer security questionnaires ask about remote-access tooling, and historical traces can show whether it was present in the past, not only whether it is installed today.

For fractional security leadership, the method transfers: turn a one-off investigation into a repeatable control, and let automation act alone only where a false positive is harmless.

Independent work by Wade Blackwell. Each write-up is written from scratch for this site, without client, employer or personal data. Names, hostnames, addresses and configuration detail are left out on purpose.