A junior SOC analyst on duty has reported multiple alerts indicating the presence of PsExec on a workstation. They verified the alerts and escalated the alerts to tier II. As an Incident responder, you triaged the endpoint for artifacts of interest. Now, please answer the questions regarding this security event so you can report it to your incident manager.
An adversary used PsExec to move laterally onto a workstation, and did it repeatedly. Each run dropped the PsExec service binary into the Windows directory, started it as a service, and left a per-run key file and a set of named pipes for the remote console. Prefetch gave the total number of executions of the service binary, and Sysmon file-create and pipe events gave exact times for each one. Picking a single run out of that list and following its key file and pipe tied the activity back to the machine the attacker was working from.
evidence/Tracer/C/Windows/prefetch → PECmd. Run count and the last eight run times per executableMicrosoft-Windows-Sysmon%4Operational.evtx → EvtxECmd to CSV. File create (EID 11) and pipe created (EID 17) eventsTimestamp note: The answer format is
DD/MM/YYYY hh:mm:ss. Sysmon and EvtxECmd print ISO dates, so the day and month must be swapped into the requested order. Sysmon event times are UTC.
On the target, PsExec runs as a service binary, so the prefetch file to read is for the service executable, not the client. List the prefetch folder for psex, then parse it and read the RunCount column for that file. Sysmon agrees: counting the file-create events for the service binary gives the same number of drops.
ls evidence/Tracer/C/Windows/prefetch | grep -i psex
PECmd -d evidence/Tracer/C/Windows/prefetch --csv work/pf -q
Gotcha: A PsExec prefetch file for the client name would only exist on the source machine. The count that matters on this workstation is the service binary’s.
The prefetch file name from Q1 already shows it, and Sysmon confirms where it lands: file-create events (EID 11) write the binary into C:\Windows. Parse the Sysmon log to CSV and filter on the target filename.
EvtxECmd -f Microsoft-Windows-Sysmon%4Operational.evtx --csv work/evtx --csvf sysmon.csv
With nine runs from Q1, the fifth from last is the fifth newest, which is the third entry in the prefetch PreviousRun fields (the last run time is the newest). Cross-check against Sysmon, which lists the nine service binary drops in order, and take the fifth from the bottom. Both sources give the same second. Rewrite the date into the requested day-first order.
python3 -I parse_sysmon.py work/evtx/sysmon.csv
Tip: Raise the CSV field size limit in Python before reading the EvtxECmd output, or the long payload columns will abort the parse.
PsExec names its key file and its pipes after the computer that launched it. Take the key file and stderr pipe from the Q3 run (Q5 and Q7) and read the hostname segment out of them. This was reasoned from that naming convention rather than read from a dedicated field, and the answer fits the format mask.
python3 -I parse_sysmon.py work/evtx/sysmon.csv
Look at Sysmon file-create events (EID 11) with a .key extension, taken from the second right after the Q3 service start. The file is written less than a second after the binary runs.
python3 -I parse_sysmon.py work/evtx/sysmon.csv
Same EID 11 event as Q5. Its UtcTime is one second after the service ran in Q3. Convert to the day-first format.
python3 -I parse_sysmon.py work/evtx/sysmon.csv
Sysmon pipe-created events (EID 17) follow the key file within the same second. PsExec makes stdin, stdout and stderr pipes per run, so filter on the one ending in stderr at the Q3 time. Keep the leading backslash.
python3 -I parse_sysmon.py work/evtx/sysmon.csv
Gotcha: Pipe names include a number that differs on every run. Match on the timestamp, not just the suffix, or you will pick a pipe from another of the nine runs.
| Phase | Action |
|---|---|
| Lateral Movement | Attacker connects from another workstation and copies the PsExec service binary into C:\Windows |
| Execution | Service binary is started as a Windows service; this repeats nine times |
| Lateral Movement | Each run writes a per-run key file named after the source host |
| Execution | Each run opens stdin, stdout and stderr named pipes for the remote console |
| Type | Value |
|---|---|
| File | C:\Windows\PSEXESVC.exe |
| File | PSEXEC-FORELA-WKSTN001-95F03CFE.key |
| Named pipe | \PSEXESVC-FORELA-WKSTN001-3056-stderr |
| Source host | FORELA-WKSTN001 |
| Technique | ID | Description |
|---|---|---|
| System Services: Service Execution | T1569.002 | PsExec starts its service binary on the target |
| Remote Services: SMB/Windows Admin Shares | T1021.002 | PsExec connects through the admin share to deploy the service |
| Lateral Tool Transfer | T1570 | Service binary copied to the workstation |
| Create or Modify System Process: Windows Service | T1543.003 | Temporary service created for each run |
Alert on the PsExec service binary being created in the Windows directory. A file-create of PSEXESVC.exe by the System process is high-signal on a workstation that has no admin tooling reason to host it. Sysmon EID 11 on that path is enough for a rule.
Pipe names give you the source host for free. The key file and the named pipes are labelled with the originating computer name, so a single Sysmon pipe-created event (EID 17) tells you where to pivot next without needing network logs.
Prefetch counts the attacker’s repeats, Sysmon dates them. Prefetch holds a total run count and the last eight times, but only an event log has all nine. Keep Sysmon file and pipe logging enabled on workstations so older runs are not lost when prefetch rolls over.
PsExec ran nine times against this workstation, and every run left the same footprint: a service binary, a key file and a set of pipes, each stamped with the name of the machine it came from. The tool is legitimate, so the detection value is in where the files land and how often they repeat.