Execution
PowerShell logs and history
PowerShell forensics: 4103/4104 script block logs, 400/403/800 engine events, PSReadLine ConsoleHost_history.txt, transcripts and logging policy keys.
- Location
- C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx
- Proves
- Which PowerShell code ran, under which account, and when; typed commands per user
- Timestamps
- Event TimeCreated as FILETIME, UTC; PSReadLine lines undated (file $SI only); transcript names and headers in local time, no zone
- Retention
- Verbose logging off by default; EVTX rolls over at max size (days on busy hosts); PSReadLine keeps the last 4,096 commands
- Access
- Administrator for EVTX (locked live, export with wevtutil epl); PSReadLine history is a plain text file in each user profile
- Evidence of
- Execution
- Type
- Event log
- Windows
- Vista / 78 / 8.11011
- KAPE target
- EventLogsPowerShellConsolePowerShellTranscripts
- Velociraptor
- Windows.Triage.Targets:EventLogsPowerShellConsolePowerShellTranscripts
Tools
Compare all toolsWhat it is
PowerShell is the attacker's favourite LOLBin: it downloads payloads, runs code in memory and drives lateral movement without dropping a binary. Windows keeps several independent traces of it. Two event logs record the engine and the code itself, the PSReadLine module saves what users typed at the console, and optional transcription writes whole sessions to text files. Each source has different defaults, so knowing what is logged out of the box is as important as knowing where to look.
Location
| Source | Location | Availability |
|---|---|---|
| Operational log (Windows PowerShell 5.x) | Microsoft-Windows-PowerShell/Operational → C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx | Script block logging needs PowerShell 5 (native on Windows 10/11, WMF 5.1 on 7/8.1) |
| Classic log | Windows PowerShell → C:\Windows\System32\winevt\Logs\Windows PowerShell.evtx | All versions |
| PowerShell 7 log | PowerShellCore/Operational → PowerShellCore%4Operational.evtx | Only if PowerShell 7 is installed and its event provider is registered |
| PSReadLine history | C:\Users\<user>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt | PowerShell 5.1+ (PSReadLine ships with Windows 10 and later) |
| Transcripts | PowerShell_transcript.<COMPUTER>.<random>.<yyyyMMddHHmmss>.txt, in the user's Documents folder by default or in a policy OutputDirectory (per-day yyyyMMdd subfolders) | Only when transcription is enabled |
| Logging policy | HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ (ScriptBlockLogging, ModuleLogging, Transcription); PowerShell 7: HKLM\SOFTWARE\Policies\Microsoft\PowerShellCore\ | SOFTWARE hive (User Configuration policies land in NTUSER.DAT) |
The history file name follows the host: ConsoleHost_history.txt for the console, Visual Studio Code Host_history.txt for the VS Code extension. Accounts such as SYSTEM keep theirs under C:\Windows\System32\config\systemprofile\AppData\Roaming\....
What it proves
- Code executed: event 4104 stores the text of each script block PowerShell compiled, including decoded
-EncodedCommandcontent and code fromInvoke-Expression, under the account that ran it. - Engine start and command line: 400 (engine state None → Available) and 403 (Available → Stopped) in
Windows PowerShell.evtx, with aHostApplicationfield holding the full launch command line. - Commands and parameters: 4103 (module logging) in the Operational log and 800 (pipeline execution details) in the classic log record cmdlets and their bound parameters.
- What a user typed:
ConsoleHost_history.txtlists interactive console commands, including those from sessions whose logs were cleared. - It does not prove success: a logged block may have failed. PSReadLine does not capture scripts run with
-File, non-interactive-Commandlaunches or remoting sessions.
Key fields
| Event / file | Useful fields | Notes |
|---|---|---|
| 4104 Operational | MessageNumber, MessageTotal, ScriptBlockText, ScriptBlockId, Path | Large scripts are split across several events sharing one ScriptBlockId |
| 4103 Operational | ContextInfo (host, user, command name), Payload (parameter bindings) | Only with module logging enabled |
| 4105 / 4106 Operational | ScriptBlockId, RunspaceId | Invocation start/stop; only with invocation logging |
| 400 / 403 classic | HostApplication, EngineVersion, HostName | EngineVersion 2.0 suggests a downgrade to bypass logging |
| 800 classic | UserId, HostApplication, command details | Written when module logging is on |
ConsoleHost_history.txt | One command per line (multi-line commands kept) | Plain text, no timestamps |
| Transcript | Header (user, machine, host application, start time), then input and output | Per-command headers with EnableInvocationHeader |
Timestamps
| Timestamp | Set when | Format | Pitfalls |
|---|---|---|---|
Event TimeCreated | Script block compiled, engine started/stopped, pipeline ran | FILETIME, UTC | Event Viewer shows local time; convert before correlating (UTC and local time) |
| History file $SI modification | Last command appended | NTFS, UTC | Only dates the last line; individual commands are undated |
| History file $SI creation | First command saved for that host | NTFS, UTC | Resets if the file was deleted and recreated |
| Transcript file name and header | Session start | Local time, yyyyMMddHHmmss | Carries no time zone indicator |
Retention and clearing
- Nothing verbose is on by default. Script block, module and invocation logging must be enabled by policy (
EnableScriptBlockLogging,EnableModuleLoggingplus aModuleNameslist,EnableScriptBlockInvocationLogging). Without them, PowerShell still writes a warning-level 4104 for blocks containing content it considers suspicious. - Event logs roll over when they reach their maximum size; on a busy host with script block logging, the Operational log can cover only days.
- PSReadLine keeps the last 4,096 commands by default (
MaximumHistoryCount), saves after each command, and drops lines matching sensitive strings such aspassword,asplaintext,token,apikeyorsecret. - Anti-forensics:
Set-PSReadLineOption -HistorySaveStyle SaveNothing, deleting or editing the history file,wevtutil cl, runningpowershell -Version 2, or deleting the policy keys. Clearing a log leaves event 104 in System (1102 for Security); see Windows event logs.
Collection
- KAPE targets:
EventLogs(all.evtx),PowerShellConsole(PSReadLine history and ISE autosave files),PowerShellTranscripts(default and common transcript folders). - Velociraptor (
Windows.Triage.Targets):EventLogs,PowerShellConsole,PowerShellTranscripts. - Built-in: the policy keys live in the SOFTWARE hive (
RegistryHivesSystem); export them or read them live.
wevtutil epl Microsoft-Windows-PowerShell/Operational E:\case\PS-Operational.evtx
wevtutil epl "Windows PowerShell" E:\case\WindowsPowerShell.evtx
Get-ChildItem C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\*_history.txt -Force |
Copy-Item -Destination E:\case\PSReadLine\ -PassThru
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell /s
A transcript in a custom OutputDirectory is not covered by the default targets: read the Transcription policy key first and collect that folder separately.
Parsing tools
- EvtxECmd (Eric Zimmerman): ships maps for 4103, 4104, 400, 403, 600 and 800, plus 4104 in
PowerShellCore/Operational. - Chainsaw and Hayabusa (open source): Sigma-based hunting over 4104 and the classic log.
- Velociraptor:
Windows.EventLogs.PowershellScriptblock(4104, defaults to warning-level blocks),Windows.EventLogs.PowershellModule(4103) andWindows.System.Powershell.PSReadline. - Get-WinEvent: filter by ID and join
ScriptBlockTextsegments byScriptBlockIdto rebuild long scripts. - Any text editor for
ConsoleHost_history.txtand transcripts.
Investigation tips
- Start with warning-level 4104 events: they exist even where nobody enabled logging, and they flag exactly the blocks PowerShell itself found suspicious.
- Rebuild split scripts by
ScriptBlockIdbefore decoding; the payload is often a Base64 or compressed blob in a later segment. - Compare
HostApplicationin 400 with 4104:powershell.exe -nop -w hidden -enc ...launched bywmiprvse.exe,mshta.exeor an Office process points to WMI or macro execution. - Check every user's
ConsoleHost_history.txt, including service and admin accounts: attackers on an interactive session often typeInvoke-WebRequest,Add-MpPreference -ExclusionPathor credential-dumping commands. - Correlate
powershell.exeruns in Prefetch with 4104 time ranges, and look for AMSI detections in Microsoft Defender logs for the same scripts. - Review the logging policy keys and their last write time: logging switched off shortly before the incident is itself anti-forensics.
Related artifacts
- Windows event logs (EVTX)Windows event log cheat sheet: EVTX locations, must-know event IDs for logons, processes, services and log clearing, retention, audit policy and parsing tools.
- Prefetch Files (.pf)Windows Prefetch cheat sheet: .pf location per version, run count, the last eight run times, referenced files, retention limits and how to parse.
- Amcache.hveAmcache.hve cheat sheet: file and program inventory keys, SHA-1 hashes, PE metadata, timestamps and why an entry alone does not prove execution.
- Microsoft Defender logs and quarantineMicrosoft Defender forensics: Operational events 1116/1117/5001/5007, MPLog files, DetectionHistory, encrypted quarantine, exclusion keys and tampering traces.
- Scheduled TasksScheduled tasks cheat sheet: task XML and .job files, TaskCache registry keys, DynamicInfo times, hidden tasks, TaskScheduler and 4698 events.
- WMI repository and SCCM RecentlyUsedAppsWMI repository cheat sheet: OBJECTS.DATA, event filters, consumers and bindings, WMI-Activity 5857–5861, MOF files and SCCM CCM_RecentlyUsedApps.
- Sysmon Event LogSysmon cheat sheet: Operational log location, key event IDs, ProcessGuid and hash correlation, config in the registry, tampering signs and parsing tools.
- IIS Web Server LogsIIS logs cheat sheet: W3C log location per site, UTC timestamps, default fields, HTTPERR, applicationHost.config and how to hunt webshells on Windows servers.
- Windows Subsystem for Linux (WSL)WSL cheat sheet: Lxss registry key, WSL1 rootfs vs WSL2 ext4.vhdx, bash_history inside distros, wsl.exe execution traces, wsl$ share access and evasion.
Glossary terms
- Windows event IDThe number identifying an event type within a given provider; it only has meaning when paired with its provider and log channel.
- LOLBin (living-off-the-land binary)A legitimate, signed Windows binary that attackers abuse to download, execute or hide payloads without dropping their own tools.
- Evidence of executionArtifacts that show a program actually ran on a Windows system, as opposed to merely existing on disk, and how strongly each one supports that claim.
- Anti-forensicsTechniques used to destroy, hide or falsify evidence, such as log clearing, timestomping, wiping and deleting shadow copies or the USN journal.
- UTC vs local time in Windows artifactsWhy some Windows artifacts record UTC and others local time, and how the TimeZoneInformation registry key helps normalize a forensic timeline.