A 15-character process name loses its last byte in every view. ps and
netstat both report coreupdater.ex where the real name is coreupdater.exe.
Evidence
Independent oracle — the DFIR Madness Case-001 memory writeup, Volatility on
this same dump:
The other interesting, but now suspect process, 3644 coreupdater.exe had an
active network connection to 203.78.103.109
The answer-key writeups say coreupdater.exe 66 times and never the 14-character
form.
issen (current main, release build) on
tests/data/dfirmadness-szechuan-sauce/DC01-memory.zip:
$ issen memory DC01-memory.zip --command ps
3644 2244 coreupdater.ex Exited
$ issen memory DC01-memory.zip --command netstat --format json
{"Proto":"TCPv4","Local":"10.42.85.10:62613","Remote":"203.78.103.109:443",
"State":"ESTABLISHED","PID":"3644","Process":"coreupdater.ex", ...}
coreupdater.exe is 15 bytes; coreupdater.ex is 14.
Why 15 characters is the sharp edge
_EPROCESS.ImageFileName is UCHAR[15]. A 15-character name fills the array
exactly, leaving no room for a NUL terminator. Anything treating the field as
NUL-terminated, or reserving a byte for one, silently drops the final character —
but only for names of exactly 15 characters. Shorter names are unaffected, which
is why this has gone unnoticed.
memf-windows/src/network.rs::owner_info reads the correct length:
let name_bytes = reader.read_bytes(owner + name_off, 15)?;
let process_name = String::from_utf8_lossy(&name_bytes)
.trim_end_matches('\0')
.to_string();
Since ps and netstat are both affected, the loss is in shared decode rather
than in either command.
Why it matters more than a display nit
It corrupts an IDENTIFIER, silently, with nothing to signal it happened — no
ellipsis, no lossy flag. An examiner grepping for coreupdater.exe gets no
hit; a report cites a filename that does not exist on the volume.
It is also present in the JSON view, which the fleet rule reserves for exact
values: machine views carry the exact serialization token, never humanized or
truncated.
Why the existing test does not catch it
tests/szechuan_netstat.rs:
.find(|r| name_of(r).starts_with("coreupdater"))
A prefix match passes identically for coreupdater.exe and coreupdater.ex. The
assertion is weaker than the property it protects, so the test sits directly
beside the defect and cannot see it.
Suggested fix
- Trace the shared
_EPROCESS.ImageFileName decode and stop reserving/assuming
a terminator; take all 15 bytes and trim only actual NULs.
- Change the test to assert EQUALITY against
coreupdater.exe, not a prefix.
Confirm it FAILS against current main first, or it proves nothing.
- Sweep for the same shape elsewhere — any fixed-width, non-NUL-terminated
field decoded as a C string has this bug for maximum-length values.
A 15-character process name loses its last byte in every view.
psandnetstatboth reportcoreupdater.exwhere the real name iscoreupdater.exe.Evidence
Independent oracle — the DFIR Madness Case-001 memory writeup, Volatility on
this same dump:
The answer-key writeups say
coreupdater.exe66 times and never the 14-characterform.
issen (current main, release build) on
tests/data/dfirmadness-szechuan-sauce/DC01-memory.zip:coreupdater.exeis 15 bytes;coreupdater.exis 14.Why 15 characters is the sharp edge
_EPROCESS.ImageFileNameisUCHAR[15]. A 15-character name fills the arrayexactly, leaving no room for a NUL terminator. Anything treating the field as
NUL-terminated, or reserving a byte for one, silently drops the final character —
but only for names of exactly 15 characters. Shorter names are unaffected, which
is why this has gone unnoticed.
memf-windows/src/network.rs::owner_inforeads the correct length:Since
psandnetstatare both affected, the loss is in shared decode ratherthan in either command.
Why it matters more than a display nit
It corrupts an IDENTIFIER, silently, with nothing to signal it happened — no
ellipsis, no
lossyflag. An examiner grepping forcoreupdater.exegets nohit; a report cites a filename that does not exist on the volume.
It is also present in the JSON view, which the fleet rule reserves for exact
values: machine views carry the exact serialization token, never humanized or
truncated.
Why the existing test does not catch it
tests/szechuan_netstat.rs:A prefix match passes identically for
coreupdater.exeandcoreupdater.ex. Theassertion is weaker than the property it protects, so the test sits directly
beside the defect and cannot see it.
Suggested fix
_EPROCESS.ImageFileNamedecode and stop reserving/assuminga terminator; take all 15 bytes and trim only actual NULs.
coreupdater.exe, not a prefix.Confirm it FAILS against current main first, or it proves nothing.
field decoded as a C string has this bug for maximum-length values.