PowerShell Security: Transcription

You can’t have missed it: PowerShell is not only loved by Admins, DevOps, etc… but also by attackers.
And if there is one thing attackers don’t like, it’s to leave traces.

With PowerShell version 5, some functionality was added to “leave traces” such as “over-the-shoulder” transcription, script block logging and module logging.

CAUTION: Enabling logging is a great thing but may also reveal some sensitive information which might be very useful to attackers as “recon”. Information about your scripts and their location, modules, variables, paths, credentials (I hope not), etc… can be valuable to attackers.

Transcription allows to record all activity in a PowerShell session to a (transcript) log file and allows to quickly find out what happened in that PowerShell session.
Transcription is not new to PowerShell, but starting with PowerShell version 5, the cmdlet Start-Transcript has added more useful information to its transcript header.

For example:

  • ComputerName
  • RunAs User (JEA scenario using impersonation on a constrained endpoint)
  • Host Application (powershell.exe, powershell_ISE.exe, …)
  • Process ID
  • PowerShell version, including Edition (Desktop vs Core)

Also, PowerShell now transcribes console commands that manipulate the console buffer directly and transcription can now be enabled in other hosts such as the PowerShell ISE.

Transcription can be performed in several ways:

  • Manual transcription
  • Semi-automatic transcription
  • Automatic transcription

Manual Transcription

Using the cmdlets ‘Start-Transcription’ and ‘Stop-Transcription’, you decide when to record all activity in a PowerShell session to a transcript.
A useful detail about theses cmdlets is that they return an object when the transcript is started or stopped.
Especially, the property Path is very helpful.


The transcript filename now also includes the computer that generated the transcript and a ‘hash breaker’ to prevent transcript filename collisions.


The parameter -OutputDirectory defines a specific path and folder in which to save the transcript.
Windows PowerShell will automatically assign the transcript name (discussed later).
If you want or need to set the transcript file name, use the parameter -Path.

Semi-Automatic Transcription

PowerShell transcription can also be triggered via PowerShell profiles, as part of the global host profile script (%windir%\system32\WindowsPowerShell\v1.0\profile.ps1) using the cmdlet ‘Start-Transcript’.

A Windows PowerShell profile is a script that runs when Windows PowerShell starts.  The profile can be used as a “startup” script to customize the environment, adding commands, adding aliases, adding variables, loading snap-ins or modules, or… start a transcript. Windows PowerShell supports several profiles for users and PowerShell hosts (powerhell_ISE.exe, powershell.exe, …).
In this way, transcription can be performed for each local PowerShell session.

For more information about PowerShell Profiles, type

Get-Help about_Profiles

NOTE: It’s important to know that PowerShell can also be started without profile (-NoProfile), which makes this semi-automatic transcription approach not bullet-proof for logging and also has some limitations in terms of PS remoting logging.

Automatic Transcription

Automatic transcription provides an “over the shoulder” transcript file of every PowerShell command and script block executed on a system by every user on that system.
It is referred to a system-wide automatic transcription.

Automatic transcription can be enabled via Group Policy using the setting “Turn on PowerShell Transcription” and also allows centralized logging.
By default, a transcript is stored in the users’ Documents folder, with a file name that includes “PowerShell_transcript”.<computerName>.<hash>.<datetime>.txt


This configuration setting can be found in the registry (for manual configuration) under:

Key: HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription
Value: EnableTranscripting (REG_DWORD)

Centralized logging using OutputDirectory

The OutputDirectory setting lets you collect transcripts in a central location (UNC path) for review/parsing/ingestion.
If you implement this policy, ensure that access to the central share is limited to prevent users from reading the previously-written transcripts.
Since the filename includes the computer name (that generated the transcript), it will prevent transcript collisions.

Centralized logging can be configured not only using Group Policy (see above), but also using the PowerShell cmdlet ‘Start-Transcript’ which has a parameter -OutputDirectory.


Hope this helps…
Kurt Roggen [BE]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s