online lostsh.github.io mimikatz-chain | 2026-09-22 rfc 3514: evil bit not set
post 10 2026-09-22 explainer | credential-theft | active-directory 0 of 210 run

The tool that did nothing: how mimikatz turns one local admin into an entire domain

Explainer | Credential theft | Active Directory 15 min read

A file arrived flagged malicious, scored 100 out of 100, tagged with nine threat-actor names. It is mimikatz, and not a modified copy: I pulled the official release from the author's GitHub and diffed the two. Byte identical.

Then I looked at what it did while the sandbox was watching. It printed its banner, printed its prompt, and waited for someone to type. Nobody did.

A genuinely dangerous tool, sitting there completely inert. The danger is real, it is just not in the file: it is in the sequence a person drives it through. That sequence is what this post is about.

TL;DR

One line to take away: the file is not the threat. The privileges of whoever ran it are, and the chain is how those privileges get converted into everything else.

It is not even pretending

The last sample I wrote up went to real trouble to look like a folder. The icon was the exploit, so the icon is now the first thing I look at. Here it is:

The application icon stored inside the analysed binary, shown enlarged: a kiwi fruit sliced in half and viewed face-on, with bright green flesh, a pale cream-coloured centre, a ring of tiny black seeds arranged around that centre, and a thin brown fuzzy skin around the outside edge. The background is transparent. It is drawn in a flat, slightly glossy illustration style and is the personal emblem of the tool's author, whose handle is gentilkiwi.
Figure 1: a kiwi fruit. The author's handle is gentilkiwi and this is the signature. No disguise: no misleading name, no fake publisher, no stolen certificate on the executable

The version information agrees. The publisher field reads gentilkiwi (Benjamin DELPY), the description reads mimikatz for Windows, and there is a field left in the build that just says Build with love for POC only.

Which matters practically: any deception is supplied by the operator, not by the artifact. Rename it, drop it somewhere plausible, or reflectively load it so it never touches disk. Detection built on the filename is worth very little.

What it wants, and why Windows gives it to them

This is the part that explains why it never gets patched.

Single sign-on means lsass.exe has to hold material it can present to a server on your behalf, not a one-way scramble, and hold it for as long as the session lives.

Separately, an administrator can read any process's memory, because debugging requires it.

Put those two together and you have the whole attack. Not a bug. Two features, both working exactly as designed.

Diagram titled Where the secrets actually live, subtitled and which part of the tool reaches into each one. On the left a large red-bordered box represents lsass.exe, the Local Security Authority, described as the Windows process that performs every logon and which must keep usable secrets in memory for as long as you are logged in to provide single sign-on. Inside it are six stacked rows, each an authentication provider: msv holding NTLM hashes for every logged-on user; kerberos holding tickets and AES or RC4 keys; wdigest holding cleartext passwords if re-enabled; tspkg holding Terminal Services credentials; credman holding saved credentials from applications; and cloudap holding the Azure AD Primary Refresh Token. Below the box a label reads read by, followed by a rounded amber chip labelled sekurlsa, twenty commands, and a note that this needs administrator rights plus the debug right. On the right, under the heading And off to one side, six further boxes list other credential stores with the command that reads each: the SAM database holding local account hashes on disk in the registry, read by lsadump colon colon sam; LSA secrets holding service account passwords in cleartext, read by lsadump colon colon secrets; cached domain logons that let you log in when the domain controller is unreachable, read by lsadump colon colon cache; DPAPI master keys, the key to browser and application saved passwords, read by the dpapi module of twenty-two commands; the Credential Manager or Windows vault, read by the vault and crypto modules; and certificate stores containing private keys marked non-exportable, read by crypto colon colon capi and cng. Across the lower part of the diagram a red-bordered panel headed And the one that is not on this machine at all explains that lsadump colon colon dcsync asks a domain controller to replicate an account's password data to you, the same call a second domain controller would make, so no code runs on the domain controller and nothing is written there; it is a legitimate protocol used by an account that should not have the right to use it, which is why hunting only on endpoints misses it and why the detection lives in directory-service auditing instead. A final panel headed The underlying point states that none of this is a vulnerability: Windows keeps these secrets because single sign-on requires it and lets an administrator read any process's memory because debugging requires it, so the fix is never to patch it but to stop the secrets being there with Credential Guard, stop the reading being allowed with LSA Protection, or make what is read worthless through tiering.
Figure 2: the substrate the whole tool operates on. Note the bottom panel: dcsync does not read this machine at all, which is why it gets missed

How the program itself works

The mechanics first, because they explain why our copy sat there doing nothing.

mimikatz is a REPL. You type module::command; it splits on the double colon, looks the module up in a table, the command up in that module's own table, and calls the handler recorded there.

Because the dispatch is table-driven, the whole command surface sits in the file as data: handler addresses, names, help text. Read the table and you know everything the tool can be asked to do without executing an instruction. That is where the 25 modules and 210 commands come from, and how I confirmed nothing had been added to this build.

Diagram titled What the program itself does, subtitled from double-click to prompt and where the sandbox run stopped. On the left, six stacked boxes connected by downward arrows trace the program's startup. First, wmain, the entry point, where nothing has happened yet. Second, mimikatz begin, which sets the console title and installs a Control-C handler. Third, print the banner, six lines giving version, build date and both authors, annotated as the point the sandbox reached, with a note that 383 wide characters are written to the stdout buffer. Fourth, mimikatz initOrClean with argument TRUE, which walks all twenty-five modules and calls each one's init function, annotated with the observation that this is why DLLs such as vaultcli.dll get loaded before any command runs, a trap for analysts. Fifth, a loop over each command-line argument, running it as a command and echoing it, annotated that the argument count was one so this loop never ran once. Sixth, a while loop that prints the mimikatz hash prompt and then blocks reading standard input, annotated in red that the sandbox run ended here because standard input was empty, giving end-of-file and exit. On the right, three panels. The first, headed How a typed command is resolved, shows the example sekurlsa colon colon logonpasswords being split on the double colon into module sekurlsa and command logonpasswords, then the module looked up in a table of twenty-five, the command looked up in that module's own table of twenty, and the handler pointer stored there being called. The second, headed That table is the capability list, explains that because the lookup is table-driven the whole command surface sits in the file as data, twenty-five modules and two hundred and ten commands each with its handler address and help text, so reading the table reveals everything the tool can be asked to do without running any of it. The third, headed The consequence, states that mimikatz has no autonomous behaviour at all, no timer, no beacon, no auto-run and no fallback action if there is no input; it is a library of two hundred and ten steps with a prompt in front of it, the operator is the control flow, and left alone it does precisely nothing, which is exactly what was observed.
Figure 3: the startup path, and the exact line where our detonation stopped. Note the fourth step: every module's initialiser runs before the first prompt, pulling in credential-related DLLs and fooling people into reporting credential access that never happened

No timer, no beacon, no auto-run, no fallback if nobody types. It is a library of 210 steps with a prompt in front of it. The operator is the control flow.

The proof that ours ran nothing

An empty command line in a sandbox report proves nothing on its own: a blank field can just as easily mean the capture failed. So here is something better.

Console output lands in a CRT heap buffer, written from offset zero every time, with a live character count alongside it. That buffer survives into the memory dumps. Here is everything the process ever put in it:

stdout buffer, recovered from the dump
  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mimikatz.com  ***/

mimikatz # 

383 characters for the banner, then 12 for the prompt, written over the top of it from offset zero. Nothing after that.

Diagram titled The proof that nothing ran, subtitled twelve characters of arithmetic in a heap buffer. An opening panel explains that Windows programs do not print straight to the screen: they hand text to the C runtime, which copies it into a four-thousand-and-ninety-six-byte block on the heap, always starting at the beginning of that block, and remembers how many characters are live; that block survives in the memory dumps, and in the examples below position zero is a newline in both strings so the visible text starts at position one. Step one, framed in amber and headed The banner is printed, 383 characters written from position zero, shows a line of monospaced text beginning with two spaces, then a short row of hash characters forming ASCII art, then three spaces, then mimikatz 2.2.0 x64 build 19041 dated September 19 2022 at 17:44:08, trailing off into a closing comment marker. The first eleven characters are underlined in amber and labelled positions one to eleven: two spaces, the ASCII art, two spaces. Step two, framed in blue and headed The prompt is printed, 12 characters, also from position zero, shows the same line except that the ASCII art has been replaced by the text mimikatz followed by a hash symbol and spaces, with the remainder of the line identical. The first eleven characters are underlined in blue and labelled positions one to eleven overwritten, everything from position twelve on is still the banner. Below, two panels. The left, green-bordered and headed What we measured in the dump, lists that buffer positions zero to twelve equal the prompt string, true; buffer positions twelve to three hundred and eighty-three equal the banner string, true; buffer position three hundred and eighty-three is zero fill and was never written; and that the buffer is byte-identical across two snapshots taken nine point three seconds apart. The right, red-bordered and headed Why that settles it, explains that every print starts at position zero, so any command output of any length would have overwritten the leftover banner text, that text is still sitting there untouched, and therefore no command ever printed anything.
Figure 4: the banner was printed, the prompt overwrote its first twelve characters, and then nothing. Every write starts at offset zero, so command output of any length would have destroyed the banner tail. It is still sitting there

Two other things agree: the process's own recorded command line is a single item with no arguments, so the argument loop never had anything to iterate over; and the string the tool would have printed when running a command-line argument appears nowhere in any of the 146 memory dumps.

0 of 210 commands. Staged, not used, at least not in the window we were shown.

The chain, in order

Three rows per step: what it needs, the command, what it gives you. The third row of each step is the first row of the next. That is the whole structure.

A wide five-column flow diagram titled The chain, subtitled each step exists only because the previous one produced the key it needs, with a second line noting that mimikatz supplies the steps and the operator supplies the control flow. Each of the five columns is a step and contains three stacked boxes: what it needs, the command, and what it gives you, with a curved arrow labelled unlocks connecting each column to the next. Step one, get the right to read memory, needs local administrator on this box, uses the commands privilege colon colon debug and token colon colon elevate, and gives you SeDebugPrivilege enabled or a SYSTEM token. Step two, read every secret in LSASS, needs SeDebugPrivilege from step one, uses sekurlsa colon colon logonpasswords, sekurlsa colon colon ekeys and sekurlsa colon colon msv, and gives you NTLM hashes, AES keys, Kerberos tickets and sometimes cleartext passwords. Step three, reuse a secret without cracking it, needs an NTLM hash or AES key from step two, uses sekurlsa colon colon pth and kerberos colon colon ptt, and gives you a logon session as another user with no password needed. Step four, ask a domain controller for everyone else, needs a replication-capable account from step three, uses lsadump colon colon dcsync, and gives you the hash of any account including krbtgt. Step five, mint your own tickets forever, needs the krbtgt hash from step four, uses kerberos colon colon golden and misc colon colon skeleton, and gives you tickets for any user in any group valid for years. Across the bottom an amber panel headed Why the order is fixed explains that you cannot read LSASS without the debug right so step one comes first, you cannot pass a hash you have not read so step two precedes step three, DCSync needs an account holding replication rights which is what step three gets you, and a golden ticket needs the krbtgt hash which only DCSync hands over; each arrow is a dependency rather than a preference, and removing any single step makes everything to its right unreachable, which is also where the defences go. A final panel headed And in the sample we analysed reads, in green: none of it, zero of the two hundred and ten available commands ran, the tool printed its banner, printed its prompt and waited for someone to type, and nobody did.
Figure 5: the whole attack. Read the bottom row of each column, then the top row of the next: same thing. That is what makes it a chain and not a menu

Why that order, and not some other order

It reads like a list of options. It is not. Each step is blocked until the previous one completes, and the reasons are mechanical:

A dependency graph, not a preference. Every link is somewhere to put a control, and early links are worth more than late ones.

The one step that breaks the pattern

One exception, and it is the detection gap people fall into. Step 2 has an offline variant, sekurlsa::minidump, which parses a dump file of lsass.exe instead of reading the live process.

That dump comes from a signed Microsoft binary. Task Manager will produce one from a right-click menu. Dump on the victim, copy the file off, parse it somewhere else entirely: mimikatz never touches the victim machine.

If your detection strategy is "find mimikatz", this costs you the whole case.

The surface it draws from

Five commands make the chain. The file contains 210. Here is the rest of it, grouped by what it is for:

Diagram titled The whole command surface, subtitled twenty-five modules, two hundred and ten commands, read straight out of the file as data. Six horizontal bands group the modules by purpose, each band listing its modules as rounded chips with a command count. The first band, Credential theft in red, contains sekurlsa with twenty commands, lsadump with sixteen, dpapi with twenty-two, vault with two, and ngc with five. The second band, Identity forgery in amber, contains kerberos with nine, crypto with fourteen, and sid with six. The third band, Local control in blue, contains privilege with nine, token with five, process with nine, service with eleven, and misc with twenty-three. The fourth band, Reach and recon in teal, contains net with twelve, ts with five, rpc with four, iis with one, and sysenv with four. The fifth band, Anti-forensics in purple, contains event with two and standard with eleven. The sixth band, Hardware and oddities in grey, contains sr98 with eight, rdm with two, acr with four, busylight with five, and minesweeper with one. Below, two panels. The left, green-bordered and headed What we checked, states that nothing has been added to this build: two independent scans of the file agree on twenty-five modules and two hundred and ten commands, and so do the public source code, the README and the process memory. The right, amber-bordered and headed And the number that matters, states that you do not need many of them, the five-step chain is all you need, and everything else is convenience, coverage of odd cases, or a joke.
Figure 6: 210 commands, and the attack needs five. The long tail is coverage for awkward cases, plus, in the case of the one-command minesweeper module, a long-standing joke

Two worth a second look. dpapi (22 commands) is the underrated one: the route to everything the browser and the applications saved for you. misc (23) is where the nasty one-liners live, including a skeleton key that makes one password work for every account in the domain, an in-memory credential logger, and working implementations of several named vulnerabilities.

The same file, four different outcomes

The tool escalates nothing by itself, so impact is set entirely by who ran it. This is the most useful frame for triage:

Diagram titled The same file, four different outcomes, subtitled the tool escalates nothing, it cashes in what you already hold. Four stacked rungs, connected by downward arrows with the note that the rung above is what gets you here and none of it is automatic. The first rung, Standard user, is tagged nearly useless in green: it can show you your own tickets and your own token, it cannot read LSASS and cannot touch the SAM, and the one real capability at this level is offline, namely that handing it a memory dump obtained some other way will let it parse that dump. The second rung, Local administrator, is tagged the pivotal rung in amber: everything changes here because an administrator can enable the debug right and the debug right means reading LSASS, so every credential of every user logged into this machine becomes readable, including any administrator who has visited it. The third rung, SYSTEM, is tagged a formality in amber: reached with token colon colon elevate once you already have administrator rights, needed for the SAM, LSA secrets and cached domain logons, and not a separate conquest but a step on the way. The fourth rung, Domain admin or DC, is tagged the whole estate in red: DCSync hands over any account's hash including krbtgt, with krbtgt you forge tickets for anyone for years, skeleton key makes one password work for every account, and at this point the domain is not compromised but owned. A closing blue panel headed The sentence to remember states that finding this file on a machine tells you very little on its own, that what matters is who was logged into that machine because that is the exact list of credentials the operator now holds, and that you should scope the incident to the sessions rather than to the binary.
Figure 7: the second rung is where the whole thing turns. Everything above it is consequence; everything below it is noise

Finding this file tells you very little. Knowing who was logged into that machine tells you the blast radius, because that is exactly the set of credentials now in someone else's hands.

What it is all for

Step 5 answers "to what end", and it is where most remediation goes wrong.

Servers do not verify you. They verify a ticket signed with a key only domain controllers hold, and that key belongs to krbtgt. One key, whole domain.

So the question is never "can they guess a password". It is "do they have the signing key".

Diagram titled Why resetting passwords does not undo it, subtitled the golden ticket and the double reset nobody does. An opening panel explains that in a Windows domain you do not prove who you are to each server; you get a ticket from the domain controller and servers trust the ticket because it is signed with a key that only the domain controller knows, and that key belongs to a hidden account called krbtgt: one key for the whole domain. It concludes that the question is therefore not whether an attacker can guess a password but whether the attacker has the signing key. Two boxes sit side by side. The left, green-bordered and headed Normally, lists three steps: you log in with a password; the domain controller checks it and issues a ticket signed with the krbtgt key; servers accept the ticket. It notes that changing the password makes step one fail, so access is revoked. The right, red-bordered and headed With the krbtgt key stolen, lists: skip logging in entirely; write your own ticket with any username, any group and any lifetime, signing it yourself with the stolen key; servers accept it because the signature is valid so there is nothing to check. It notes that changing the password does nothing. A curved red arrow between them is captioned: step one is where password resets work, and the forgery does not use step one. An amber panel headed So what actually revokes it explains that resetting the krbtgt account twice with a wait in between is required; twice because the domain controller deliberately keeps the previous key valid so that tickets issued moments before the reset do not all break at once, meaning a single reset leaves the attacker's forged tickets still honoured by that previous key, and the wait must cover one full replication cycle plus the longest ticket lifetime, ten hours by default. It adds that a single krbtgt reset is one of the most common incomplete remediations there is. A final line reads: this is the to-what-end of the whole chain, not stealing passwords but acquiring the ability to issue identity itself.
Figure 8: the forgery skips the step that password resets protect. And the reset that does work has to be done twice, which is the part that gets missed

That is the destination of the whole chain. Not stealing passwords, acquiring the ability to issue identity. Once someone writes their own tickets they are not a user with stolen credentials any more, they are a second authority.

Where the defences actually cut

Because the chain is a dependency graph, the useful question is not "which products should I buy" but "which link am I cutting, and how early".

Diagram titled Where each defence cuts the chain, subtitled the five-step chain again, with the control that breaks each link and what it costs the attacker. Across the top, the five steps from the earlier chain diagram appear as small boxes connected by arrows: get the debug right, read LSASS, reuse the secret, ask the domain controller, and forge tickets. Dashed lines drop from each step to the control that breaks it. Under step one, Tiered administration and privileged access workstations, in green: never let a privileged account log into an ordinary machine, because if administrator credentials never land here then step one never happens at all, tagged strongest and slowest. Under step two, two controls. LSA Protection or RunAsPPL, in green: runs LSASS as a protected process so user-mode reads are refused outright whatever privilege you hold, tagged best value per hour spent. And below it Credential Guard, in amber: moves hashes and tickets out of LSASS entirely but does not cover the SAM, DPAPI, the vault or cached logons, tagged partial by design. Under step three, the Protected Users group, in amber: blocks NTLM and RC4 for members and stops credential caching so there is less worth replaying, tagged watch your service accounts. Under step four, least privilege plus event 4662 auditing, in amber: replication rights held by a non-domain-controller account is the anomaly, so remove the rights and alert on directory-access event 4662, tagged detection not prevention. Under step five, the double krbtgt reset, in red: the only thing that revokes an already-forged ticket, twice with a wait in between, tagged cleanup after the fact. A red-bordered panel headed The door that re-opens warns that the same download ships a signed kernel driver whose entire job is to clear that protected flag again, that its certificate is revoked, and that RunAsPPL should therefore be paired with HVCI and Microsoft's vulnerable-driver blocklist or the control is one driver load from gone. A final panel headed And read it right to left too explains that cutting a late link limits the damage while cutting an early link prevents it, so the controls are not equivalent: stopping step one costs the attacker the whole chain whereas resetting krbtgt only tidies up after they have finished using it, and most places invest heavily on the right-hand side because that side can be bought while the left-hand side is organisational, unglamorous, and the one that actually ends the attack.
Figure 9: the same five steps, with the control that breaks each one. The left-hand side is worth more than the right-hand side, and costs more to implement, which is why most estates are defended from the wrong end

The one to single out is LSA Protection. lsass.exe runs as a protected process and user-mode reads are refused regardless of privilege. It cuts step 2, which everything downstream depends on, and it is one RunAsPPL value under HKLM\SYSTEM\CurrentControlSet\Control\Lsa.

One caveat, and it is why the rest of the download matters. The same archive ships a kernel driver whose whole purpose is to switch that protection back off. It is signed by the author on a certificate the issuer revoked for "privilege withdrawn", expired, with no countersignature, so it should not validate anywhere. A revoked certificate only protects you as well as your revocation checking does. Pair LSA Protection with HVCI and Microsoft's vulnerable-driver blocklist, or the control is one driver load from gone.

What the automated tooling made of all this

A short detour, because the gap between the report and the artifact was wide.

The sandbox produced 324 signatures and mapped 127 ATT&CK techniques. That mapping contains none of the techniques this tool exists to perform. No LSASS credential dumping, no DCSync, no rogue domain controller, no golden ticket, no skeleton key.

It does assert data destruction, disk wiping, endpoint denial of service, email collection, screen capture, keylogging, process hollowing, and ten separate command-and-control techniques, one of them over mail protocols, against a program with no network client in its imports that produced, across the whole capture, zero packets that were not Windows talking to Microsoft.

Best of all, some of those signatures fire on strings that are not in the sample. They come from a DLL loaded into the process from the Windows temp directory, VxSSL64.dll. That is the sandbox's own monitoring library. It detected itself and filed the result under the sample's behaviour. Two of the four bullets under its "Evasive" heading are that.

The indicator export was worse. Thirteen of its twenty-two rows are typed as IP addresses and are actually X.509 object identifiers, things like 2.5.29.15, the Key Usage extension, matched by a regex hunting four dot-separated numbers. One row is 02d.cab, typed as a domain: it is the tail of %s_%02d.cab, the format string used to name cabinet files, and .cab is a real TLD. Five more rows are the authors' own websites, lifted straight out of the banner above.

Feeding that list to a blocklist would break Microsoft sign-in, censor a security researcher's blog, and blackhole address space belonging to four national telecoms operators. It would catch nothing, because the tool has no infrastructure to catch.

So what do you actually do about it

In rough order of how much good it does:

  1. Stop privileged accounts logging into ordinary machines. Unglamorous, organisational, expensive, and the only one that ends the attack rather than inconveniencing it. If domain admin credentials never land on a helpdesk laptop, harvesting that laptop yields nothing.
  2. Turn on LSA Protection, paired with HVCI and the vulnerable-driver blocklist so the driver above does not undo it.
  3. Check your EDR is actually recording handle opens against lsass.exe. Plenty of shipped configurations exclude it to cut volume, which quietly removes the best detection you have. Verify, do not assume.
  4. Log command lines, and alert on the :: pattern. Renaming the executable is free; changing the command syntax breaks every cheat sheet and the operator's own habits. Alert on the syntax, not the filename.
  5. Enable directory service auditing on your domain controllers and alert on replication rights being used by anything that is not a domain controller. Without that audit setting, the DCSync step is invisible.
  6. Also hunt for the LSASS dump, not just the tool. Task Manager and comsvcs.dll can produce it, and then the parsing happens on a machine you will never examine.
  7. Write down now how you would do a double krbtgt reset. Not during an incident. The procedure, the wait interval, and who authorises it.

And one thing not to do: do not treat the file hash as your control. This is the stock public release of an open-source tool. A recompile with the banner edited defeats every signature built on its strings, and an in-memory loader never writes a file at all.

Hard lessons

What went well: diffing against upstream early turned an open-ended "is this backdoored" into a closed question and reframed everything after it. The stdout buffer gave a positive proof of inaction rather than an argument from absent evidence, which is the difference between "we saw no commands" and "no command ran". And the detection content was measured against a benign corpus before it shipped, which is the only reason I know the first version of it was useless.

Takeaways

  1. The file is not the threat; the sequence is. No beacon, no persistence, no propagation, no timer. 210 steps and a prompt. The danger is entirely in what a person chains together.
  2. The chain is a dependency graph, so it has weak links. Each step is unreachable until the previous one hands it a key. That is not just a description of an attack, it is a list of places to put a control.
  3. Impact is set by the operator's privilege, not by the binary. At standard user it is nearly inert. At local administrator every credential on the box is readable. Scope your incident to who was logged in, not to what was on disk.
  4. The goal is not passwords, it is the power to issue identity. Which is why a password reset does not evict an attacker who reached step 5, and why the krbtgt reset has to happen twice.
  5. None of it is a vulnerability, so none of it gets patched. Windows keeps usable secrets in memory because single sign-on needs them, and lets administrators read process memory because debugging needs it. The defences remove the secrets, or remove the reading, or make what is read worthless.
  6. "It did nothing" is an observation about one detonation, not a verdict on a file. Ours ran zero of 210 commands, and all 210 were intact and ready. On a real host the safe assumption is the opposite: somebody was there, typing.

The full teardown is in the case report for 61c0810a: how the command table was recovered from the file as data, the certificate work on the driver, the clock reconciliation that fixed a seven-hour error in the timeline, and the detection content with its corpus results.