Quick Tip: Using PowerShell to generate a GPO report

Someone asked me today how to easily export a readable report of all GPOs applied to a system (they were performing a security audit and needed an easy to way to script this).  Of course, I immediately thought of PowerShell!  So, here’s how you can export a readable report of all GPOs applied to a system in question in PowerShell:

> Import-Module GroupPolicy
> Get-GPOReport -All -ReportType Html -Path AllGPOsReport.htm

Of course, you can also use Get-GPOReport to generate a report for a specific GPO and/or export as XML, if you prefer.

Monitoring file system changes with PowerShell

I recently returned from facilitating Lenny Zeltser‘s excellent Reverse Engineering Malware course at SANS Security West.  One of the utilities covered in the course is called CaptureBAT, which is a useful utility for monitoring a system for changes while performing malware analysis.  Of course, given my ongoing interest in PowerShell, I decided to see if I could emulate some of CaptureBAT’s file system monitoring functionality natively in a PS script.

There are several strategies that you can use to monitor the file system in PowerShell and I decided to use the .Net framework to help accomplish this task.  Here’s how I did it:

  1. Create a new System.IO.FileSystemWatcher object, and set appropriate settings:
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = $searchPath
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true

    .Path is the path that will be monitored, .IncludeSubdirectories tells the FileSystemWatcher to monitor all subdirectories of .Path

  2. Now we need to define some events that will fire when $watcher detects a filesystem change, I’m going to define an event for Changed, Created, Deleted, and Renamed:
    $changed = Register-ObjectEvent $watcher "Changed" -Action {
       write-host "Changed: $($eventArgs.FullPath)"
    $created = Register-ObjectEvent $watcher "Created" -Action {
       write-host "Created: $($eventArgs.FullPath)"
    $deleted = Register-ObjectEvent $watcher "Deleted" -Action {
       write-host "Deleted: $($eventArgs.FullPath)"
    $renamed = Register-ObjectEvent $watcher "Renamed" -Action {
       write-host "Renamed: $($eventArgs.FullPath)"

    Within each event you can define code for what you want to happen when the event fires.  In this example I’m just directly outputting the type of action and the full path of the changed object on the filesystem.

  3. That’s pretty much it.  These events will hang around until you close your current PowerShell session or manually unregister the events.  You can unregister the events using the Unregister-Event command:
    Unregister-Event $changed.Id
    Unregister-Event $created.Id
    Unregister-Event $deleted.Id
    Unregister-Event $renamed.Id

As you can see – monitoring file system changes is actually quite easy with PowerShell.  You could easily take the output of this script and write it to a file (either using output redirection, or specifying output directly in the script) and with a little more code you could read in a CSV/structured file containing a list of exclusions (i.e. what CaptureBat does) and within each event filter out unwanted “noise.”

The great thing about this method is that it just *works* in Windows systems that have PowerShell.  No need to install any applications or run any third-party utilities – which the malware that you’re looking at may be looking for (i.e. anti-analysis measures built into some malware).  My goal is to build a complete replacement for CaptureBat within PowerShell in my spare time over the next few weeks.  Once done, I’ll post the complete script with explanations on my blog…

But for now, time to spend some quality time with the family.  Have a great weekend.

Quick Tip: PowerShell Grep Equivalent

I’ve used searching in my previous PowerShell posts, but I thought that it deserves a dedicated “Quick Tip” posting.  I know that folks coming from a *nix background will be very familiar with using grep to search for pretty much anything and seemingly not having access to this tool can be disappointing for those trying to use Windows as their primary OS (for the one or two of you out there that have decided to come to the “dark side” 😎 ).  But…do not fret!  There are a number of ways to run equivalent searches within Windows out of the box.  Since I’ve been on a PowerShell kick lately, let me introduce you to a decent grep alternative that is built into PowerShell: select-string.

Select-String is a built-in cmdlet in PowerShell that will allow you to search files, piped input, objects, etc for a pattern (which is, by default, a regular expression).  Select-String can take in a number of options, but can be quite simple to use.  For example, if you want to search for the text “evildoer” within all files in the current directory, you can use the following command:

select-string .\*.* -pattern "evildoer"

It is important to note that by default, select-string is case-insensitive; so, if you need a case sensitive search, add in the -CaseSensitive parameter.

Ok, now let’s do something a bit more complex.  I want to look for anything that looks like an email address in all txt files recursively under C:\.  So, to make that happen we need to do a little more work:

get-childitem c:\ -include *.txt -rec | select-string -pattern "\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6}"

First, I need to use get-childitem (think DIR) to recursively go through the drive and return only files matching *.txt.  Then I pipe these returned objects to select-string and search their contents by using a basic regex that will match on things that look like email addresses.

Of course, there are a number of other ways to use select-string but since this is a “quick tip” I’ll keep things brief.  If you’d like more details, you can find additional information in the PowerShell documentation on TechNet.

Searching the Registry using PowerShell

On a cold and rainy Thursday morning, I thought that it would be a good time to write a post on searching the Windows registry using PowerShell.  In an Incident Response scenario you may want or need to do some live analysis on a compromised system, and part of this analysis may be to search the registry for some sort of artifact that is appropriate.  Using PowerShell can help you do this in a relatively efficient manner and is, of course, built in on new version of Windows (i.e. Windows 7, 2008, etc).

For example, let’s say that you know (or have guessed) that you’re dealing with some sort of malware that is probably going to be calling home at some time and you are wanting to look through the registry to see if the malware author decided to store any IPs/URLs in the clear.  In PowerShell you are able to easily browse and search through the registry, just like you were dealing with a filesystem.  There are a number of ways to accomplish this (for example, using -match rather than select-string), so feel free to use whatever method you’re comfortable with.  But, let me show you how I mangled my way through it this morning…

  1. Open up a PowerShell window.
  2. Let’s look for things that appear to be IP addresses under HKEY_CURRENT_USER, so first I need to recursively iterate through everything under that hive.  I do this by using the Get-ChildItem method:
    Get-ChildItem HKCU:\ -rec -ea SilentlyContinue

    This method returns a complete list of all keys (as objects of course) under the HKCU hive.

  3. From there, we’re going to need to dig into each of these returned objects and do our search.  So I’m going to pipe the output of the previous command into a foreach loop and then retrieve the data for each key:
    Get-ChildItem HKCU:\ -rec -ea SilentlyContinue | foreach {
       $CurrentKey = Get-ItemProperty -Path $_.PsPath
  4. Now that we have the contents that we want to search, let’s search for something that looks like an IP address and then print out any matches:
       select-string "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" -input $CurrentKey -AllMatches | foreach {($_.matches)|select-object Value}

    You’ll notice the use of a simple regular expression that will match on things that “look” like IP addresses.  If, for example, you’d prefer to look for URLs, a simple regex that you can use that’ll match most URLs would be: “\b(ht|f)tp(s?)[^ ]*\.[^ ]*(\/[^ ]*)*\b”.

  5. So putting it all together, to perform a simple string search of the registry for possible IP addresses and URLs using a regular expression you can use the following script:
    write-host "Possible IP addresses:`n"
    Get-ChildItem HKCU:\ -rec -ea SilentlyContinue | foreach {
       $CurrentKey = (Get-ItemProperty -Path $_.PsPath)
       select-string "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" -input $CurrentKey -AllMatches | foreach {($_.matches)|select-object Value}
    write-host "`nPossible URLs:`n"
    Get-ChildItem HKCU:\ -rec -ea SilentlyContinue | foreach {
       $CurrentKey = (Get-ItemProperty -Path $_.PsPath)
       select-string "\b(ht|f)tp(s?)[^ ]*\.[^ ]*(\/[^ ]*)*\b" -input $CurrentKey -AllMatches | foreach {($_.matches)|select-object Value}

This code will return any hits on the specified regular expressions, but doesn’t actually give you context as to where it was found within the registry.  If you’re just looking for odd URLs/IP addresses, it may be useful for you to just see a simple list of both to run through; but, if you want more context you may want to use a conditional with -match rather than select-string and then just output $CurrentKey:

write-host "Possible IP addresses:`n"
Get-ChildItem HKCU:\ -rec -ea SilentlyContinue | foreach {
   $CurrentKey = (Get-ItemProperty -Path $_.PsPath)
   if ($CurrentKey -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b") {
write-host "Possible URLs:`n"
Get-ChildItem HKCU:\ -rec -ea SilentlyContinue | foreach {
   $CurrentKey = (Get-ItemProperty -Path $_.PsPath)
   if ($CurrentKey -match "\b(ht|f)tp(s?)[^ ]*\.[^ ]*(\/[^ ]*)*\b") {

PowerShell can be a really powerful tool for easily searching the registry and is a good, albeit slightly slower, alternative to using another method that would require an interpreter, etc (i.e. Perl).  Have fun!

Finding an Active Directory User's SID using PowerShell

I sometimes need a quick and easy way of determining a user’s Active Directory SID (for example, when performing forensics on the Recycle Bin). Yes, there are ways to find out a SID in ADUC (check out how here) – but I think that utilizing PowerShell is more efficient in this case.

To find a user’s SID, within PowerShell run the following (replacing <domain> and <user> with the appropriate information for your query):

$objUser = New-Object System.Security.Principal.NTAccount(<domain>,<user>)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])

To further enhance efficiency, I’ve actually wrapped this into a parametrized PowerShell script, which you can feel free to download here.  Remember, that in order to get the script to run, you need to set your execution policy to “RemoteSigned” by running the following command:

Set-ExecutionPolicy RemoteSigned