Thursday, April 28, 2016

PowerForensics and Remote Machines

One of the biggest issues I have with PowerForensics is that it can only be executed on the local system.  This is great if you have something like F-Response which allows you to locally mount the hard drive of a remote system, after which you can execute PowerForensics commandlets against the remote system's hard drive.  But what if I don't have F-Response?

A few months ago I spoke with Jared Atkinson, the developer of PowerForensics, about this topic.  He mentioned the idea of reading the contents of the PowerForensics DLL into a byte array, establishing a remote PowerShell session and using reflection to load the byte array.  This doesn't actually import the commandlets into the session, but you do gain access to the various classes and their methods.

I tested this process, and was trying out PowerForensics in general but came across some issues.  While executing processing such as this in a PowerShell session on a remote system you end up using a large amount of processing and memory (the latter of which makes me cringe).  I saw spikes up to 1.5 GB of memory utilization depending on which methods you call.  I abandoned the idea, but eventually came up with an idea:

The idea

With F-Response, the client is reading the raw bytes of the hard drive and transmitting that to the examiner's machine where the data structures are then processed.  This means the processing and memory utilization is mostly on the examiner side.

So why not emulate this process in PowerForensics?

From what I can tell, it will take a bit of work to add this functionality to PowerForensics. For the time being I will supplement with some scripts I have already written, and work on the C# code as I can (or as Jared can).

Proof of Concept Process

Step 1: Establish a session with a remote system (easy enough)

PS> $Session = New-PSSession -ComputerName DeathStar

Step 2: Inject a function to get a read handle on local drives or volumes

In order to read the raw bytes directly from disk you have to utilize the CreateFile or CreateFileW Windows API (there is no way around this for a live system, or at least none known to me).  Rather than P/Invoke the C# code for this method, we want to use .NET Reflection to avoid runtime compilation.  Luckily I already wrote a function for this in PowerShell (you can find it here).  It creates a new function Get-FileStream, and accepts a parameter -DriverNumber or -VolumeLetter, acquires a read handle to the drive or volume, and returns a .NET FileStream object using that handle.

The following command executes the Get-FileStream PowerShell script in the Session we've already established:
PS> Invoke-Command -Session $Session -FilePath .\Get-FileStream.ps1
Then we can execute the Get-FileStream function and get a read handle and file stream on Drive 0:
PS> Invoke-Command -Session $Session -ScriptBlock { $FileStream = Get-FileStream -DriveNumber 0 } 

 Step 3: Inject a function to read chunks of disk and return a byte array

This is also pretty simple, it just needs to accept a FileStream, a Byte Offset, and a Length of bytes to return.  I also already have a function for this in PowerShell (you can find it here).

First we inject the function into the session:
PS> Invoke-Command -Session $Session -FilePath .\Get-BytesFromStream.ps1
Then we can execute the function to return the first 512 bytes of the hard drive as a byte array:
PS> $ByteArray = Invoke-Command -Session $Session -ScriptBlock { Get-BytesFromStream -Stream $FileStream -Offset 0 -Length 512 }

Step 4: Parse the Byte Array with PowerForensics

This part was a little tricky (only since I'm not great with C#).  Since the MasterBootRecord class is not exposed when you import the module, and there is no ByteArray input to Get-ForensicMasterBootRecord, we need to make some changes to the module.
I installed Visual Studio and downloaded the latest release's source code (from here).
After loading up the C# Project in Visual Studio, I opened MasterBootRecord.cs and made the MasterBootRecord class public:
public class MasterBootRecord
Examining the methods we see a Get method which takes a drivePath input.  We need to create a new Get method that accepts a Byte Array as input, which is easy enough:
public static MasterBootRecord Get(byte[] byteArray)
{
    // Read Master Boot Record (first 512 bytes) from disk
    return new MasterBootRecord(byteArray);
}
NOTE: Upon trying to build I get a weird error saying the PartionEntry class is less accessible than MasterBootRecord.PartitionEntry, so I modified the PartitionEntry class to also be public.

After building my project I import my new modified PowerForensics DLL into PowerShell:
PS> Import-Module .\PowerForensics.dll
Then I take a look at the now Public MasterBootRecord class, and its Get method:
PS> [PowerForensics.MasterBootRecord]::Get
OverloadDefinitions
-------------------
static PowerForensics.MasterBootRecord Get(string drivePath)
static PowerForensics.MasterBootRecord Get(byte[] byteArray)
Success!  Now we can see the Get method accepting a byte array as input.  Lets test it against our $ByteArray variable from earlier:
PS> [PowerForensics.MasterBootRecord]::Get([byte[]]$ByteArray) | Format-List
MbrSignature   :
DiskSignature  : 2A255ADF
CodeSection    : {51, 192, 142, 208...}
PartitionTable : {NTFS, NTFS, NTFS}
Success again.  We have just parsed the Master Boot Record of a remote system with minimal impact to the target system all using tools built into the Windows OS [since Windows 7].

Next Steps?

So now that the proof of concept is complete there are a few roads I can take.

Enhancement within PowerForensics

In order to include this process within PowerForensics itself there are some complex topics that need to be addressed. For example, if we want to have a -ComputerName switch on the commandlets, PowerForensics will need a helper function to generate a RemoteRunspace object, then create PowerShell instances within the Runspace and inject commands.

If we want to be minimally invasive in this process we need to find a way to reduce the amount of times these steps are performed, meaning creating this runspace and maintaining it, rather than creating it, executing the command, and disposing of it each time you run a commandlet.  In all honesty it will be easier (at least for me) to utilize the built in New-PSSession command to establish the session, then add a -Session switch to each commandlet and appropriate processing for a session.

This will be my ultimate goal, but since I am not great with C# it will likely take me a while to implement, which leads me to the other option:

Light Modification to PowerForensics, and an external "wrapper" script temporarily

This just means insuring the appropriate classes are public and have a public method that accepts a Byte Array as input.  Then I can create a PowerShell script that utilizes the Get-FileStream and Get-BytesFromStream functions I've already created to perform the actions outlined above.


I will likely work on the latter since it is quick, and hope to dedicate time to the former solution in the future.  If you have any questions, don't hesitate to ask!


UPDATE:
As I make changes to the PowerForensics project, I'll publish my changes to GitHub in my fork here:
https://github.com/davidhowell-tx/PowerForensics
Once it's established and working I'll talk to Jared about incorporating the changes into his main project.

Monday, December 28, 2015

(1) Invoke-LiveResponse - PowerShell Incident Response Tool

A few days ago I published the version 1.1 release of Invoke-LiveResponse to my github.  You can find the release here: https://github.com/davidhowell-tx/Invoke-LiveResponse/releases or you can view the repo here: https://github.com/davidhowell-tx/Invoke-LiveResponse

I really wanted to  publish this blog entry about the tool, but  I already have big changes coming for version 1.2.  This will end up being an introduction to the tool, and a discussion of features soon to come.

Invoke-LiveResponse

This tool is basically an offshoot of Dave Hull's Kansa repo. I liked the idea, but I had some issues with the tool so I took it on as a side project to write my own tool along the same lines.  The idea behind Invoke-LiveResponse is to provide a framework to perform remote live response on Windows systems in your enterprise using PowerShell scripts.

PowerShell is a very powerful scripting language that can be used to retrieve valuable information from a Windows system.  From past information through the parsing of forensic artifacts, present information by showing active connections, processes, and files, or future information by listing scheduled tasks or WMI event consumers.

In the background, Invoke-LiveResponse is utilizing Windows Remote Management or WinRM, which allows for the remote execution of commands or scripts. For more information regarding WinRM, see this article. While WinRM is a requirement, if WinRM isn't enabled on the target systems Invoke-LiveResponse will attempt to enable WinRM automatically.  This involves creating/modifying a few registry keys and starting the WinRM service.  After execution, Invoke-LiveResponse will then attempt to revert any modified settings to their original state.
Note: Currently there isn't any support for modifying Windows Firewall rules remotely to allow WinRM to work properly. This may need to be configured manually to work.

Collection Modules (in Version 1.1, just called Modules)

Collection modules are standalone PowerShell scripts that return information about a system.  These are the core of the tool.  I've attempted to develop modules that are relatively narrow in scope, rather than create a script that returns a large amount of information about an array of areas. For example, rather than a script that returns all forensic information regarding processes that have executed in the past, I prefer to have individual scripts with one parsing prefetch, another parsing the Application Compatibility Cache, etc.

Collection Groups (in Version 1.1 called Module Sets)

Collection groups are logical groups of collection modules that you can configure for common tasks. My thoughts are to have things like, MalwareTriage1stPass, MalwareTriage2ndPass, TriageIISServer, etc.

Collection groups are configured through the CollectionGroups.conf file in the .\CollectionModules directory.  The format is in XML, and I've included one of my own for an example.

Here is a quick look at how to define a Collection Group:

<ExampleCollectionGroup Description="This is an example">
    <CollectionModule Name="Get-ArpCache.ps1" InputValues="" /> 
    <CollectionModule Name="Get-DNSCache.ps1" InputValues="" />
    <CollectionModule Name="Get-ProcessMemory.ps1" InputValues="conhost.exe null" /></ExampleCollectionGroup>

The 3rd collection module entry is to show how to pass variables to modules that require a variable.  Currently the Get-ProcessMemory module isn't released as I'm still testing the impact to target systems when it is run.

Analysis Modules (not available in version 1.1)

Analysis modules are PowerShell scripts that are run against the results of collection modules. The idea is to automate as much analysis as possible, and we can do this through the analysis modules.

My initial idea for an analysis module was to create a timeline of all events collected.  This has proven to be a little more difficult than I anticipated, so this particular script will be a while in the making.

Some of my additional ideas that are in the works are a Virus Total checker that takes hashes of processes or files and returns the score on Virus Total and the date of the VT report, or flags it as "unseen".  Another is to create a "rootkit revealer" which requires the normal Get-Processes API query, and the Rekall pslist or psscan, and compares the results of the two to find any hiding processes.

Plugins

There are a couple of things that I realized would differ in different environments, so I've included a "plugins" directory for a few options that can be customized further.

Credentials

I have a friend that uses a privileged account manager for accounts used during incident response, so the major plugin functionality is with the -Credential switch.  By default, using -Credential will just execute the Get-Credential commandlet build into PowerShell to prompt for alternate credentials.

In cases where credentials are stored elsewhere, such as a Privileged Account Manager, you can write a script that interacts with the PAM's API, or whatever else you use, and return a PSCredential object. Name this script Invoke-LiveResponseCredentials.ps1 and place it in the .\Plugins directory.
NOTE: In version 1.2 this is changing to just Credentials.ps1.

Soon I will be adding a Credentials plugin script that queries the Thycotic API and returns a credential object.  All you will need to do with it is replace the URL to your Thycotic instance, if this is the product you use.  If anyone develops other Credentials plugins, I would be happy to add them to the repo.

GUI

Another plugin that is currently possible is the GUI.  I've created my own GUI to interact with the Invoke-LiveResponse command-line script for those that prefer it.  If you want, you can write your own and replace it in the .\Plugins directory.

Command Line Screenshots

The first thing you'll want to do is tweak the save path and concurrent jobs settings.

If you want to change these back to the default settings (2 Concurrent Jobs, and a "Results" folder where Invoke-LiveResponse is located) you can do the following:




Next, take a look at the available modules.
Note, this parameter has changed to ShowCollectionModules in version 1.2






Then, take a look at the Module Sets.
Note: These are called Collection Groups in version 1.2, and the parameter changed to ShowCollectionGroups.










Finally, take a test run on your local system.

GUI Screenshots

Launch the GUI:




The GUI's main window displays collection modules on the left, and you can add and remove targets on the right using the textbox and the add or remove button.



















You can change the save path and concurrent jobs settings by using the File menu and selecting options.












You can check specific modules that you want to run, or you can select a Module Set (Collection Group in version 1.2) from the drop down list which will check the appropriate modules for you.

Wiki

I've attempted to summarize the ideas contained within Invoke-LiveResponse.  I am working to put this content, and more, into the GitHub Wiki for the project.  I plan to document each module, and maintain a roadmap for enhancements to the framework and the modules.