Wednesday, November 18, 2020

The 2020 Volatility Plugin Contest results are in!

We would like to begin by thanking the participants for their hard work and contributions to Volatility. It’s always exciting to see continued innovation in the field of memory forensics from research teams across the globe! Despite the challenges of this unprecedented year, we had 8 submissions, including a number of new plugins, an output renderer, and a new graphical user interface. This year’s participants also had the additional challenge of learning all the new paradigms and interfaces of Volatility 3.

Independent open source projects and communities only remain viable because of contributors who are willing to sacrifice their time and resources. Please show your appreciation for the contestants’ contributions by following them on Twitter/GitHub/LinkedIn, providing feedback on their ideas, and helping to improve their code with testing, documentation, or contributing patches. 

We would like to thank Volexity for being a sustaining sponsor of the Volatility Foundation and, in particular, for contributing to this year’s contest. We would also like to thank Paessler AG for their donation toward the contest prizes!

Placements and Prizes for the 2020 Volatility Plugin Contest:

1st place and $2000 USD cash or One Free Seat at Malware and Memory Forensics Training by the Volatility Team goes to:

Gustavo Moreira for Netfilter  

2nd place and $1000 USD cash goes to:

Jelle Vergeer for SSHKeys 

3rd place and $750 USD cash goes to:

Aviel Zohar for Volatility Explorer, StructAnalyzer, WinObjGUI, FileScanGUI, P2V, PFNInfo, RAMMap, Winobj

Below is a detailed summary of all submissions, ordered alphabetically by first name. If you have feedback for the participants, we're sure they'd love to hear your thoughts! As previously mentioned, these developers deserve huge props. We look forward to seeing future work by these authors! 

Aviel Zohar: Volatility Explorer, StructAnalyzer, WinObjGUI, FileScanGUI, P2V, PFNInfo, RAMMap, Winobj

This contest submission includes a number of components intended to make Volatility more approachable and user-friendly to investigators. Volatility Explorer is a graphical user interface that provides a user experience similar to Sysinternal’s Process Explorer but only leveraging the information extracted from volatile memory. The Struct Analyzer plugin allows an analyst to parse memory resident data structures in a graphical hierarchy. WinObjGUI provides a capability to view kernel objects with a similar user experience provided by Sysinternal’s WinObj tool. FileScanGui allows an analyst to view files by providing a Window’s Explorer user interface experience. The submission also includes tools for mapping physical to virtual addresses, extracting the provenance of memory regions, and exploring forensics artifacts in physical memory: P2V and PFNInfo. The submission leverages these capabilities to create a tool that provides a similar user experience to Sysinternal’s RAMMap. Finally, the submission also includes an updated version of WinObj.

Related References:

Bjorn Stelte:  EvtxLogs Plugin

This submission provides the capability to extract evtx entries from physical memory of Windows systems. The EvtxLogs plugin leverages the work done by Willi Ballenthin's python-evtx/evtxtract libraries. By focusing on memory samples, it allows a forensics analyst to get insights into events that were happening at the time of acquisition, and events that happened in the past on the suspected system. In particular, this can augment the data used for temporal reconstruction of system events. 

Related References: 

Bjorn Stelte:  Syslog Renderer

This submission involved a Volatility 3 renderer for sending Volatility output to a syslog server. The syslog output renderer is intended for situations where a forensics analyst is attempting to analyze a large number of memory samples. An analyst could integrate Volatility into an automated pipeline and send the results to a unified syslog server. Then, the analyst could access the server to triage, using strings and other analysis methods which systems need deeper forensic analysis.

Related References:

Gustavo Moreira: MountInfo Plugin 

The use of containers has seen significant growth in production Linux environments. Previous Volatility file system analysis capabilities did not fully enumerate information related to containers, which left much work on part of the analyst. This plugin closes that gap by replicating the per-process mount information as exported in the /proc/<pid>/mountinfo file on live systems.

Related References:

Gustavo Moreira: Netfilter Plugin

This plugin provides full support for the enumeration of Netfilter hooks for all modern versions of the Linux kernel. The Netfilter subsystem is routinely abused by kernel rootkits to control the network stack, such as the recently disclosed Drovorub and Cloud Snooper malware samples. Abusing Netfilter hooks provides a rootkit with the ability to monitor for 'magic packets' containing command-and-control data; sniff outgoing and incoming network connections; and even silently modify packet data. Properly implemented rootkits will also abuse Netfilter to hide malicious traffic from userland network monitors, such as tcpdump and Wireshark, running on the local system.

Related References: 

Jelle Vergeer: SSHKeys Plugin

This submission implemented a Volatility 3 plugin to extract SSH session keys, which are used to encrypt and decrypt network traffic between an SSH client and server. The plugin can extract keys from Linux OpenSSH ssh (client) and sshd (server) processes by locating and parsing a structure that holds the symmetric key cipher name, the keys used for encryption/decryption, and the initialization vectors (IVs) used for encryption/decryption. For each SSH session, two key/IV pairs are recovered, client to server and server to client.  Given the output of the author's Volatility plugin (a JSON containing key and IV) and a PCAP of the network traffic between SSH client and server, users can decrypt and parse the network traffic using another tool the author developed, The result is complete transparency into the entire SSH network session.

Related References:

Or Chechik and Inon Weber: check_parent_spoof Plugin

This submission provides a practical method to detect stealth techniques used by malware in the wild and post-exploitation toolkits, such as Cobalt Strike. Although there are ways to identify parent process spoofing on live machines using ETW and via dead disk forensics by parsing event logs, the check_parent_spoof plugin for Volatility 3 adds this capability to memory analysis. In many cases, after creating a child process with a spoofed parent, code is injected into the child, which warrants analyzing memory anyway. The ability to triage all of these aspects with a single source of evidence provides a powerful capability.

Related References:

Or Chechik and Inon Weber: check_peb_spoof Plugin

In addition to parent process spoofing, another common obfuscation technique is PEB-Spoofing or PEB-Masquerading, which provides a mechanism for bypassing UAC. This plugin provides the ability to detect spoofed process names and detect malware using this technique. This is accomplished by comparing the name in the PEB with the name from the EPROCESS kernel structure. 

Related References:
Here are a few additional resources for previous contests and community-driven plugins:

Volatility Foundation Contest Home Page:

Volatility 2019 Plugin Contest Results:
Volatility 2018 Plugin Contest Results:
Volatility 2017 Plugin Contest Results:
Volatility 2016 Plugin Contest Results: 
Volatility 2015 Plugin Contest Results:
Volatility 2014 Plugin Contest Results:
Volatility 2013 Plugin Contest Results:

Volatility Community GitHub Repository: 


Wednesday, May 27, 2020

When Anti-Virus Engines Look Like Kernel Rootkits

While analyzing real-world systems, memory analysts will often encounter anti-virus (AV) engines, EDRs, and similar products that, at first glance, look suspiciously like malware. This occurs because these security products leverage the same techniques commonly employed by malware—such as API hooking, system call hooking, and registering callbacks—in order to gain the insight they need to detect and analyze threats.

A recent journal publication by members of our team examined this issue for userland API hooks. In this blog post we will show an example of what AV kernel hooks often look like. The sample investigated in this post was sent by a friend who wanted clarification of the behavior, as it was part of a real investigation. In particular, Volatility's ssdt plugin was showing many system call table entries as being hooked, and our friend wanted to know if the hooks were malicious or benign.

System Calls Background

System calls are the common mechanism by which unprivileged code in userland (process) memory requests services through the kernel to access privileged resources, such as the hard drive to create/read/write/delete files, the network stack to send/receive packets, the monitor to display information to the user, and numerous other resources. System calls are also used to enumerate the active system state, such as the list of running processes, active network connections, loaded kernel modules, and nearly everything else that live forensic tools and endpoint agents gather for analysis. This obviously makes the system call table an attractive target for malware to tamper with, as well as a high-value location for security agents to monitor.

To check for signs of rootkits, Volatility's ssdt plugin locates each system call table present in a memory sample and then enumerates each system call table entry. For each entry, it prints either the containing module, if found, or UNKNOWN if the entry points to a memory location not associated with the kernel itself or a module contained within the kernel module list. Several common kernel rootkit methods of hiding code will trigger the classification as UNKNOWN, such as unlinking the malicious module from the module list, or allocating a RWX memory region and then using it to host code after the malicious module is unloaded (see this blog post on analyzing a detached kernel thread).

Unfortunately, the use of system call hooking by AV and EDR engines frequently triggers UNKNOWN entries in ssdt output, as security agents' attempts to "hide" on a system often leverage the same tactics used by malware.

Initial Analysis

To start the analysis, the ssdt plugin was run against the sample:

$ python -f sample.raw --profile=Win7SP1x86  ssdt > ssdt-output.txt 
Volatility Foundation Volatility Framework 2.6
$ grep -c UNKNOWN ssdt-output.txt 
$ grep UNKNOWN ssdt-output.txt | head -20
  Entry 0x000d: 0x886ea580 (NtAlertResumeThread) owned by UNKNOWN
  Entry 0x000e: 0x881f70b0 (NtAlertThread) owned by UNKNOWN
  Entry 0x0013: 0x886e4d88 (NtAllocateVirtualMemory) owned by UNKNOWN
  Entry 0x0016: 0x88217ca0 (NtAlpcConnectPort) owned by UNKNOWN
  Entry 0x002b: 0x886e9e80 (NtAssignProcessToJobObject) owned by UNKNOWN
  Entry 0x004a: 0x886ea390 (NtCreateMutant) owned by UNKNOWN
  Entry 0x0056: 0x886e9c48 (NtCreateSymbolicLinkObject) owned by UNKNOWN
  Entry 0x0057: 0x88438858 (NtCreateThread) owned by UNKNOWN
  Entry 0x0058: 0x886e9d00 (NtCreateThreadEx) owned by UNKNOWN
  Entry 0x0060: 0x886e9f30 (NtDebugActiveProcess) owned by UNKNOWN
  Entry 0x006f: 0x886e4910 (NtDuplicateObject) owned by UNKNOWN
  Entry 0x0083: 0x886eaba8 (NtFreeVirtualMemory) owned by UNKNOWN
  Entry 0x0091: 0x88436198 (NtImpersonateAnonymousToken) owned by UNKNOWN
  Entry 0x0093: 0x886ea4d0 (NtImpersonateThread) owned by UNKNOWN
  Entry 0x009b: 0x880d3478 (NtLoadDriver) owned by UNKNOWN
  Entry 0x00a8: 0x886eaae0 (NtMapViewOfSection) owned by UNKNOWN
  Entry 0x00b1: 0x886ea2e0 (NtOpenEvent) owned by UNKNOWN
  Entry 0x00be: 0x886e4de0 (NtOpenProcess) owned by UNKNOWN
  Entry 0x00bf: 0x886e4db8 (NtOpenProcessToken) owned by UNKNOWN
  Entry 0x00c2: 0x886ea1a8 (NtOpenSection) owned by UNKNOWN

Looking at the output, it appears that 45 entries are hooked by UNKNOWN module(s). Furthermore, the hooked functions are commonly targeted by both malware and security agents.

Classifying One Hook

To begin the process of determining if the hooks are benign or malicious, volshell was used to examine the code of a few hooks. volshell is a Volatility plugin that allows you to interactively explore a memory sample, including viewing, searching, and disassembling arbitrary addresses in any context (the kernel or a particular process).

To start, volshell was loaded and the hook for Entry 0x000d: 0x886ea580 (NtAlertResumeThread) was disassembled (numbers, dashes, and arrows added for ease of explanation):

$ python -f sample.raw --profile=Win7SP1x86  volshell
> dis(0x886ea580)
0x886ea580 55                               PUSH EBP                               <----- [1]
0x886ea581 8bec                           MOV EBP, ESP
0x886ea583 ff750c                         PUSH DWORD [EBP+0xc]
0x886ea586 b9fca56e88                MOV ECX, 0x886ea5fc            <-----  [2]
0x886ea58b ff7508                         PUSH DWORD [EBP+0x8]
0x886ea58e 51                               PUSH ECX
0x886ea58f 8b01                            MOV EAX, [ECX]                      <-----  [3]
0x886ea591 ff5004                         CALL DWORD [EAX+0x4]        <-----  [4]
0x886ea594 83c40c                       ADD ESP, 0xc
0x886ea597 5d                               POP EBP
0x886ea598 c20800                       RET 0x8                                    <-----  [5]
0x886ea59b cc                               INT 3
0x886ea59c 0000                           ADD [EAX], AL
0x886ea59e 0000                           ADD [EAX], AL

After reading the disassembly, several things stand out. First, there is a real function prologue with the instructions of "PUSH EBP; MOV EBP, ESP;" [1] and, shortly after, a proper function epilogue [5]. Examining the code in between, a hardcoded address is stored in ECX [2]. That address is dereferenced and stored in EAX [3]. A dereference of EAX + 4 is then used as the target address of a CALL instruction [4].

This code flow can be re-implemented in volshell through the use of its dd (display double word) and dis functions.

> dd(0x886ea5fc, 4)                   
886ea5fc  964c72b4

> dd(0x964c72b4 + 4, 4)          
964c72b8  964ba922

> dis(0x964ba922)
0x964ba922 55                               PUSH EBP
0x964ba923 8bec                           MOV EBP, ESP
0x964ba925 51                               PUSH ECX
0x964ba926 51                               PUSH ECX
0x964ba927 53                               PUSH EBX
0x964ba928 56                               PUSH ESI
0x964ba929 57                               PUSH EDI
0x964ba92a bf010000c0                MOV EDI, 0xc0000001

The first invocation of dd is at the hardcoded address from [2] earlier. As can be seen, the address stored here is 0x964c72b4. The second dd invocation dereferences this address + 4 just as the disassembly in [4] from earlier shows. This gives a CALL target address of 0x964ba922, which the address used in the above dis call.

Looking at the instructions here, there is the beginning of a long function which appears to be the real hook implementation. To determine which, if any, module is hosting the real payload, the drivermodule plugin can be invoked with the address of the function:

$ python -f sample.raw --profile=Win7SP1x86 drivermodule -a 0x964ba922
Volatility Foundation Volatility Framework 2.6
Module                   Driver          Alt. Name    Service Key
--------------------- ------------- ------------- -----------
SYMEVENT.SYS     SymEvent   SymEvent   \Driver\SymEvent

This output shows that the function is inside of the SYMEVENT.SYS driver, which is part of the Symantec AV/Endpoint protection suite installed on the system.

Classifying All Hooks

So far, it has only been shown that 1 of the 45 hooks belongs to Symantec. To ensure that all of them belong to Symantec, the remaining 44 must be checked. Repeating the volshell steps for two more of the system calls showed the same pattern as before: a hardcoded address (different address for each hook) being dereferenced, followed by the value of the first dereference having 4 added then being dereferenced itself. The consistent result between the hooks of this sample was that the final destination was the same: 0x964ba922. With this in mind, it became clear that the process of checking each hook could be automated to see if they all ended at 0x964ba922. 

To accomplish this, awk was first used to extract just the UNKNOWN addresses from the ssdt output saved earlier:
grep UNKNOWN ssdt-output.txt | awk '{ print $3 }' > unknown-addresses
This placed all of the UNKNOWN addresses in the unknown-addresses file. Next, code was written inside of volshell that repeated the read hardcoded address-> dereference -> dereference+4 pattern. Note: volshell runs inside of the Python shell, so whatever you can do in Python, you can do in volshell as well.  The following shows this code in its entirety, with line numbers added to the beginning of each line.
1.    > for line in open("unknown-addresses", "r").readlines():
2.   ...:    address = int(line.strip(), 16)
3.   ...:    insts = addrspace().zread(address + 6, 5)
4.   ...:    if ord(insts[0]) != 0xb9:
5.   ...:        print "invalid instruction at %x | %x" % (address, ord(insts[0]))
6.   ...:        break
7.   ...:     
8.   ...:    first_addr = struct.unpack("<I", insts[1:])[0]
9.   ...:     
10. ...:   second_addr_str = addrspace().zread(first_addr, 4)
11. ...:   second_addr = struct.unpack("<I", second_addr_str)[0]
12. ...:     
13. ...:   function_addr_str = addrspace().zread(second_addr + 4, 4)
14. ...:   function_addr = struct.unpack("<I", function_addr_str)[0]
15. ...:     
16. ...:   if function_addr != 0x964ba922:
17. ...:        print "incorrect function_address: %x" % function_addr
18. ...:     

This code starts by looping for each line in the file, which contains one line for each UNKNOWN hook address. Next, the address is converted to an integer. On line 3, the hook address plus 6 is read for 5 bytes inside of the kernel address space. This corresponds to reading what should be the MOV ECX, <hardcoded address> instruction at [2] in the first disassembly listing. The first byte of the instruction is verified to be 0xb9, which is the MOV instruction opcode. On line 8, the remaining 4 bytes are then converted to an integer, as they are the hardcoded address in little endian. On lines 10  and 11, the hardcoded address is dereferenced and then converted to an integer. On lines 13 and 14, the dereferenced valued plus 4 is dereferenced and converted to an integer. It is then verified to be the target CALL address of 0x964ba922.

Running this loop over the sample showed that all system call hooks transferred control flow to 0x964ba922, which means that all hooks belonged to the same Symantec driver.

Closing Thoughts

Through a mix of manual reverse engineering and automated comparisons based on knowledge learned, the system call table was automatically verified as clean, and our friend was given a repeatable methodology to apply to other samples in his investigation.

If you like this type of analysis and want to challenge yourself to write plugins that automate memory forensic techniques, then consider a submission to our 2020 Volatility Plugin Contest. This year's contest is based on Volatility 3, and you can learn about the new, exciting features of Volatility 3 in our recently recorded presentation.

If you would like to stay in touch with the Volatility Team and community then consider following us on Twitter, joining our Slack Server, and subscribing to our email list.

Friday, May 15, 2020

The 8th Annual Volatility Plugin Contest!

We are excited to announce that the 8th annual 2020 Volatility Plugin Contest is now accepting submissions until October 1, 2020!

Winners will receive over 3750 USD in cash prizes!

Volatility 3

The 2020 Volatility Plugin Contest encourages research and development in the field of memory analysis. With the announcement of the Volatility 3 Public Beta (blog post and recent presentation), and the current development focus on the Volatility 3 Official Release later this summer, we decided this is an exciting time to shift the Contest to Volatility 3 plugins. As in previous years, the main goal is to encourage innovation in the field of memory analysis.

Submissions provide an opportunity to get industry-wide visibility for your work, put groundbreaking capabilities immediately into the hands of investigators, and contribute back to the open source forensics community. By building on top of Volatility 3, your contributions will help lay the foundation for the next generation of memory forensics! If you are looking for inspiration for the Volatility Plugin Contest, check out the previous results.


We would like to thank Volexity and our other sustaining donors for their continued support.