Registry Parser
All articles

Proof of Sysinternals use: the EulaAccepted registry trail

8 min read

The first time a Sysinternals tool runs interactively, it pops a EULA dialog. Click through it and the tool writes a EulaAccepted value into the registry so it never asks again. That single value is one of the cleanest per-user execution artifacts you can pull from an NTUSER.DAT hive. The Sysinternals EULA trail does not tell you everything a tool did, but it does tell you, with very little ambiguity, that a specific tool ran under a specific user — and when a name like PsExec shows up, that PsExec evidence is exactly the kind of hands-on-keyboard signal an IR timeline is built around.

The key

The data lives under HKCU\Software\Sysinternals\ in the user's NTUSER.DAT. Each tool the user has accepted the license for gets its own subkey named after the tool, and inside that subkey is a REG_DWORD named EulaAccepted, set to 1:

HKCU\Software\Sysinternals\PsExec
    EulaAccepted    REG_DWORD    0x1
HKCU\Software\Sysinternals\ProcDump
    EulaAccepted    REG_DWORD    0x1
HKCU\Software\Sysinternals\Procmon
    EulaAccepted    REG_DWORD    0x1

The parser logic here is trivial and that is the point: enumerate the subkeys under Software\Sysinternals, and for each one read its EulaAccepted value. The plugin on this site emits exactly two columns — Tool and EulaAccepted — one row per subkey. There is no decoding, no binary structure to unpack, no ROT13. The subkey name is the tool name, and its presence is the finding.

That simplicity is why it survives. Complex artifacts get truncated, rotated, or overwritten. A one-DWORD flag written once and never touched again is durable.

What presence proves

When you find HKCU\Software\Sysinternals\PsExec\EulaAccepted = 1, the defensible reading is: the PsExec executable was run under this user's profile, on (or feeding) this host, at least once. That is a strong statement because it comes from the user's own hive — attribution is not in question the way it is with system-wide artifacts. Whoever owns the NTUSER.DAT is the account that accepted that EULA.

The tools that land in this key are the Sysinternals Suite: PsExec, ProcDump, Procmon (Process Monitor), Procexp (Process Explorer), PsList, PsKill, PsLoggedon, Autoruns, AccessChk, Handle, Streams, SDelete, TCPView, and the rest. Each writes its own subkey under the same parent the first time its EULA is accepted. Treat the subkey name as the canonical tool identifier, but be aware the exact casing and naming follows whatever the binary itself writes, so do not hard-code a whitelist — enumerate what is actually there.

Not all of these tools carry equal weight on a timeline. Some are benign-by-default; a sysadmin runs Procexp and Autoruns constantly. The interesting ones are the tools that show up disproportionately in intrusions:

  • PsExec. Remote command execution. This is the headline. PsExec is a lateral-movement workhorse — it copies a service binary to a target, registers it, and runs commands as SYSTEM or a named account. A PsExec subkey under a user who has no business administering remote hosts is a finding on its own. PsExec evidence in the registry says someone ran the tool from this box; correlate with the service-creation events (System log event ID 7045, PSEXESVC) on the target boxes to draw the line.
  • ProcDump. Process memory dumping. The classic abuse is procdump -ma lsass.exe lsass.dmp to harvest credentials out of LSASS for offline cracking. A ProcDump subkey alongside an LSASS-sized dump file on disk is a credential-theft narrative.
  • SDelete. Secure deletion. Anti-forensics. If SDelete shows up, assume someone tried to destroy evidence and go hunting for what is missing.

The rest — Procmon, Procexp, Handle, TCPView — are recon and analysis tools. They are not proof of malice, but they place a capable operator at the keyboard. An attacker doing live triage on a victim host leaves the same EULA trail a defender would.

The LastWrite is your first-run timestamp

The EulaAccepted value carries no timestamp of its own — it is just a DWORD. The timestamp you want is the LastWrite time of the tool's subkey (HKCU\Software\Sysinternals\PsExec, not the parent Sysinternals key). Because the EULA flag is written once, on first acceptance, and the tool then never rewrites the key on subsequent runs, that key's LastWrite is — in the common case — an approximation of first run for that tool under this user.

Hedge this. Key LastWrite reflects the last modification to any value or metadata in the key, so if anything else ever writes into that subkey, the timestamp moves and your "first run" reading breaks. In practice these subkeys usually hold nothing but EulaAccepted, so the LastWrite tends to stick at first-acceptance time — but verify the key really does contain only that one value before you put "first executed at" on a slide. If there are other values, treat the LastWrite as "last touched," not "first run."

What this artifact does not give you is a run count or a last-run time. Unlike UserAssist, there is no per-launch counter here. EulaAccepted is binary: accepted or not. For execution frequency and recency you pivot to other artifacts.

The two caveats that will burn you

It persists. The EulaAccepted value is written once and never cleared by the tool. Uninstalling the tool — Sysinternals tools are standalone executables, so there is rarely a real uninstall — does not remove the key. Deleting the binary does not remove the key. The flag can therefore reflect activity from months or years ago. It proves the tool ran at some point; without the LastWrite caveats above, it says nothing about when, and nothing about how many times. Do not let a stale EULA key inflate your read of recent activity.

Absence is not proof of non-use. This is the one that matters most. Every modern Sysinternals tool accepts an -accepteula command-line flag that suppresses the dialog and the registry write:

psexec -accepteula \\target cmd.exe

Any attacker scripting PsExec — which is to say, essentially all of them — will pass -accepteula precisely so the tool runs unattended. That means the registry key is never written. The same applies to tools run from contexts that cannot accept the EULA (a different user profile, a service account, a non-interactive session). So an empty HKCU\Software\Sysinternals does not mean Sysinternals tools were never used on the host. It means they were never interactively accepted under this profile. Treat presence as high-confidence proof of use; treat absence as no information at all.

The practical consequence: the EulaAccepted trail catches the operator who ran a tool by hand and clicked through the dialog — the analyst, the curious admin, the attacker doing manual triage — and misses the automated, scripted, -accepteula-flagged invocation. That is a feature, not a bug, for IR. When the key is present, you are looking at hands-on-keyboard interaction, not a scheduled job.

Where this sits in a timeline

A PsExec EulaAccepted key is a starting point, not a conclusion. Pivot outward:

  • The subkey LastWrite gives you an approximate first-run anchor. Drop it on the timeline.
  • Look for the binary itself — psexec.exe, psexec64.exe — via Prefetch, AmCache, and the MFT. Those give you execution recency and the path the binary ran from.
  • On the targets, hunt the PSEXESVC service-install events and the artifacts of whatever PsExec delivered. The EULA key tells you the source host; the target host tells you the impact.
  • Cross-reference other registry artifacts of lateral movement — mapped drives, ShellBags, and RDP MRU entries — to corroborate that this user was operating across hosts.

Tools

  • RegRipper's sysinternals plugin walks Software\Sysinternals and reports each tool subkey with its EulaAccepted value and the key's LastWrite. See the RegRipper plugins reference for the full artifact catalog.
  • Eric Zimmerman's Registry Explorer / RECmd will surface the same key; point a batch file at Software\Sysinternals and pull the subkey LastWrites into CSV.
  • The parser on this site enumerates the Sysinternals subkeys and shows the Tool and EulaAccepted columns directly. You can analyze NTUSER.DAT in your browser with nothing uploaded to a server.

Frequently asked questions

Where does Sysinternals store the EulaAccepted value? Under HKCU\Software\Sysinternals\<ToolName>\EulaAccepted, a REG_DWORD set to 1, in the user's NTUSER.DAT hive. There is one subkey per tool whose license the user has accepted.

What does a PsExec EulaAccepted key prove? That the PsExec executable was run interactively under this user's profile at least once, and the license dialog was accepted. It does not prove what PsExec did, or against which targets — but it places PsExec, a lateral-movement tool, in this user's hands.

Can I tell when the tool first ran? Approximately. The LastWrite time of the tool's subkey is usually the first-acceptance (first-run) time, because the EULA flag is written once and not rewritten — but only if nothing else ever modifies that subkey. Verify the key holds only EulaAccepted before treating it as a firm first-run timestamp.

If the key is missing, does that mean the tool was never used? No. The -accepteula command-line flag suppresses both the dialog and the registry write, and scripted attacker use almost always passes it. Absence is not evidence of non-use; presence is strong evidence of use.

Does deleting the tool remove the key? No. The value persists indefinitely. It can reflect activity from long before the period you are investigating, so anchor it with the subkey LastWrite rather than assuming it is recent.