From the FireEye blog post (authored by Matt Dunwoody):
Script block logging records blocks of code as they are executed by the PowerShell engine, thereby capturing the full contents of code executed by an attacker, including scripts and commands. Due to the nature of script block logging, it also records de-obfuscated code as it is executed. For example, in addition to recording the original obfuscated code, script block logging records the decoded commands passed with PowerShell’s -EncodedCommand argument, as well as those obfuscated with XOR, Base64, ROT13, encryption, etc., in addition to the original obfuscated code. Script block logging will not record output from the executed code. Script block logging events are recorded in EID 4104. Script blocks exceeding the maximum length of an event log message are fragmented into multiple entries. A script is available to parse script block logs and reassemble fragmented blocks (see reference 5).
While not available in PowerShell 4.0, PowerShell 5.0 will automatically log code blocks if the block’s contents match on a list of suspicious commands or scripting techniques, even if script block logging is not enabled. These suspicious blocks are logged at the “warning” level in EID 4104, unless script block logging is explicitly disabled. This feature ensures that some forensic data is logged for known-suspicious activity, even if logging is not enabled, but it is not considered to be a security feature by Microsoft. Enabling script block logging will capture all activity, not just blocks considered suspicious by the PowerShell process. This allows investigators to identify the full scope of attacker activity. The blocks that are not considered suspicious will also be logged to EID 4104, but with “verbose” or “information” levels.
While the blog post does not specify what constitutes 'suspicious', this was a pretty good description of what I was seeing. This Windows Powershell blog post contains information similar to Matt's post, but doesn't use the term "suspicious", instead stating that "PowerShell automatically logs script blocks when they have content often used by malicious scripts." So, pretty interesting stuff.
After updating my Python installation with the appropriate dependencies (thinks to Jamie for pointing me to an install binary I needed, as well as some further assistance with the script), I ran the following command:
That's right...you run the script directly against a .evtx file; hence, the need to ensure that you have the right dependencies in place in your Python installation (most of which can be installed easily using 'pip'). The output file "blocks.txt" contains the decoded script blocks, which turned out to be very revealing. Rather than looking at long strings of clear and encoded text, broken up across multiple events, I could now point to a single, unified file containing the script blocks that had been run at a particular time, really adding context and clarity to my timeline and helping me build a picture of the attacker activity, providing excellent program execution artifacts. The decoded script blocks contained some 'normal', non-malicious stuff, but also contained code that performed credential theft, and in one case, privilege escalation code, both of which could be found online, verbatim.
It turns out that "Microsoft-Windows-Powershell/4100" events are also very interesting, particularly when they follow an identified 4104 event, as these events can contain error messages indicating that the Powershell script didn't run properly. This can be critical in determining such things as process execution (the script executed, but did it do so successfully?), as well as the window of compromise of a system.
Again, all of this work was done across what's now up to half a dozen Windows 10 Professional systems. Many thanks to Kevin for the nudge in the right direction, and to Jamie for her help with the script.
Matt's DerbyCon 2016 Presentation