Flag: Tornado! Hurricane!

Memoryze Memory Forensics Tool

Wednesday, November 26 2008 20:06.40 CST
Author: peter # Views: 43497 Printer Friendly ...

Introduction

The goal of this article is to demonstrate how simple malware analysis can be using Memoryze and some good old fashion common sense. Readers should have some knowledge of how malware works, and be somewhat familiar with Memoryze. A good place to familiarize yourself with Memoryze is the user guide included in the installer.

Memoryze is designed to aid in memory analysis in incident response scenarios. However, it has many useful features that can be utilized when doing malware analysis. Memoryze is special in that it does not rely on API calls. Instead Memoryze parses the operating systems' internal structures to determine for itself what the operating system and its running processes and drivers are doing.

Malware Analysis

The first step in malware analysis differs from analyst to analyst and case to case. Some common first steps are running strings, putting a binary in a disassembler like IDA Pro or doing run time analysis. Using IDA requires that the analyst has enough working knowledge to be able to reverse the binary if needed. It also requires that the binary be unpacked on disk. This article will detail how to do runtime analysis without the help of IDA.

In this case the malware sample came from Offensive Computing, the samples MD5 hash is 117aec6aae1c4d25fc5fa2b9a4f905e5. The analyst will load the malware in a XP SP2 virtual machine (VM). Once the malware is placed in the VM, execute it. The first thing to notice is almost immediately after execution the process has exited. The fact the process exited could indicate a couple of things:
  • The process injected itself somewhere else
  • The process installed a driver which could be hiding a process
  • Malware failed to load due to problems with the environment (i.e. VM aware)
Since the analyst cannot be sure what the malware is doing, the best thing to do now is use Memoryze. The author recommend running a semi-custom audit called AllAudits. Audits are xml documents that Memoryze takes as input and performs actions based on what the xml has enabled. The AllAudits file looks like:
<?xml version="1.0" encoding="utf-8"?>
<script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" chaining="implicit">
  <commands>
    <command xsi:type="ExecuteModuleCommand">
      <module name="w32processes-memory" version="1.0.34.0" />
      <config xsi:type="ParameterListModuleConfig">
        <parameters>
          <param name="pid">
            <value xsi:type="xsd:unsignedInt">4294967295</value>
          </param>
          <param name="handles">
            <value xsi:type="xsd:boolean">true</value>
          </param>
          <param name="sections">
            <value xsi:type="xsd:boolean">true</value>
          </param>
          <param name="ports">
            <value xsi:type="xsd:boolean">true</value>
          </param>
          <param name="strings">
            <value xsi:type="xsd:boolean">false</value>
          </param>          
        </parameters>
      </config>
    </command>
    <command xsi:type="ExecuteModuleCommand">
      <module name="w32drivers-signature" version="1.0.34.0" />
    </command>
    <command xsi:type="ExecuteModuleCommand">
      <module name="w32kernel-rootkitdetection" version="1.0.30.0" />
       <config xsi:type="ParameterListModuleConfig">
        <parameters> 
        <param name="idt">
            <value xsi:type="xsd:boolean">true</value>
        </param>
        <param name="ssdt_index">
            <value xsi:type="xsd:boolean">true</value>
        </param>
        <param name="ssdt_inline">
            <value xsi:type="xsd:boolean">true</value>
        </param>
        <param name="drivers">
            <value xsi:type="xsd:boolean">true</value>
        </param>
        </parameters>
      </config>
    </command>
  </commands>
</script>


This custom audit runs the following four jobs:
  • A full process audit with ports, handles, sections, turned on for every process. Strings is turned off because too much data is generated when scanning all the running processes address spaces.
  • A driver signature scan to enumerate all drivers even those hidden by unlinking the PsLoadedModuleList
  • A hook detection audit that looks for common kernel hooks
To run this audit execute the following command line:
Memoryze.exe -o -script AllAudits.Batch.xml -encoding none
This tells Memoryze to output it to the standard %INSTALLDIR%/Audits/%COMPUTERNAME%/%DateTime%. The next parameter indicates what script to execute and the final parameter tells Memoryze not to compress the output.

If this is malicious software there will be some trace that can be found in one of these audits. It maybe small, but it should be there. To examine the results of a big audit like AllAudits use Audit Viewer available here. Audit Viewer's user guide can be found here. Audit Viewer will render the xml generated by Memoryze in a readable more manageable way.


Figure 1: Processes running after infection

Figure 1, shows all the processes running after the initial infection. There are no real suspicious processes currently running. This process listing does not eliminate the fact the system can still be infected. There are still a plethora of possible infections on the system. Some possibilities are:
  • the malware hijacked another processes image
  • the malware injected itself into another process address space
  • the malware has patched some binary to load itself
  • the malware installed a driver and is now working in the kernel
The next easiest course of action is to look at the loaded drivers and hooks. If the malware installed a driver hopefully it is easily identifiable or is hooking something which will be easy to spot. Clicking the Rootkit tab in Audit Viewer will show the analyst three possible types of rootkits (see Figure 2 for a screen shot).


Figure 2: Hooked SSDT entries

In this case the malware has installed three System Service Descriptor Table (SSDT) hooks. The analyst can determine what driver installed the hooks by looking at the Hooking Module column. The driver in this case is burito24b1-1710.sys. This is a non-standard system driver. At this point the analyst should start to consider the idea that a rootkit has infected their environment. The functions hooked by this driver are:
  • NtEnumerateKey
  • NtEnumerateValueKey
  • NtQueryDirectoryFile
The three hooked functions in question are used to hide registry keys, registry values and files. Memoryze reports the driver should reside at the location c:\windows\system32. When the analyst views that directory the burrito*-*.sys driver does not exist. Further confirmation that the malware installs a driver capable of hiding files on disk.

Clicking on the interrupt descriptor table (IDT) tab reveals nothing useful. Clicking on the interrupt request packet (IRP) tab reveals something else about the driver. It appears the driver is hooking the IRP_MJ_DEVICE_CONTROL function pointer in tcpip.sys. This usually indicates that the driver is hiding some network activity it or a userland process does not want seen.


Figure 3: IRP hooks

A quick note, the operating system commonly hooks itself so there will be a number of driver IRP hooks on a non infected machine.

At this point the level of suspicion should be very high and acquiring this driver for analysis later is going to be important. Acquiring a driver is essentially capturing how it looks in memory and writing that view to disk for analysis. One reason acquisition is important is because the driver is currently hidden on disk. Since the driver is hidden it can't be analyzed at the moment. Acquiring the driver from memory and writing it to disk will allow for it to be analyzed. There are two ways to do acquire the driver. If the analyst is running Audit Viewer on the live system (within the infected environment) check "Running on live memory." Then the analyst can right click on the driver in the DriverAuditSignature, DriverAuditModule, or RootkitAudit tabs and acquire it from memory. If the analyst isn't running on live memory and s/he is running from a memory image. S/he can check "Running on dead memory" and fill in the text box "Path to Image File" with the image path, and then do the right click acquire.


Figure 4: Acquring driver from memory

Figure 4 shows how to acquire the driver from the Rootkit tab view.

From just using Memoryze and viewing the results in Audit Viewer the following has been determined:
  • The executable in question was malicious.
  • The executable file installed a driver with what appears to be a randomly generated name.
  • The driver is a rootkit that hooks three system calls and an IRP routine. With these hooks the rootkit is capable of hiding itself on disk and in the Registry as well as hiding network traffic.


This is a lot of information obtain in a very short period of time without the help of IDA. There is always the potential to go further. In this case, the question becomes what else is the driver doing or has it done? It is common for rootkits to want to have some userland presence. This is usually due to the fact that it takes less knowledge, is safer, and easier to have a userland component than do everything in the kernel (even though it is possible).

Continuing further, the analyst may want to try and see if it's possible to identify a userland component. Any userland component would have to be injected into another process since a quick, top level examination of processes did not reveal anything.

Further Analaysis

Analysts can use a number of methods to determine what process has been compromised. This article will discuss two. The first is to look at a complete listing of all open ports on the system. The reason the analyst is going to want to look at ports is that the tcpip.sys hook indicates that the driver is trying to hide some network activity. Identifying the process that has suspicious ports open, may quickly identify which process has been compromised. To get the complete listing of all ports double click on the process tree root. Double clicking on the process tree root will also give the analyst a complete listing of all files, mutants, processes, registry keys, event handles, as well as DLLs, and strings. This will take all the process handles and sort them by least frequency of occurrence. This means, for example, the file handles that occur least frequently across all processes are at the top of the list and file handles that occur frequently across all processes (and are less likely to be malicious) are at the bottom of the list. This makes it so the analyst doesn't have to sift through all the results and can focus only on files or other handles that have a low occurrence across all processes. See Figure 5.


Figure 5: Port listing of all processes
In this case all the ports are listed for all processes. Since Memoryze identifies listening ports in memory and does not rely on API calls the tcpip.sys hook the rootkit install is useless. The analyst will see two suspicious ports 19769 and 16196.

The fact that services.exe is listening on a non default windows port is one indication the process might have been compromised. Running tcpview on the machine will reveal that port 16196 is hidden. This indicates that services.exe was the process that was injected. The next step from here would be to acquire the process, examine its memory sections, and identify injected DLLs.

The second method for identifying compromised processes has two parts. The first part of this method is to use a feature built into the Audit Viewer. When the analyst right clicks on the root of the process tree they will get an option "Scan process for executable memory" this operation will scan all the processes for sections marked EXECUTE_READWRITE. The EXECUTE_READWRITE memory section permission, is something Jamie Butler spoke about at Hack In The Box Dubai (slides). This specific permission is commonly related to maliciously injected code - either shellcode or inject dlls/threads. When the analyst scans the processes, they get a report back that four processes out of twenty-three processes have the potential indicator that the process has been injected.


Figure 6: Result of scan for executable code

The second part of the approach will tell the analyst if any of these processes actually has an injected DLL in memory. Use the process acquisition techniques discussed by Peter Silberman at Hack In the Box Kuala Lumpur (slides). First acquire all four processes in question. Acquisition is easy to do if the analyst is running Audit Viewer on the infected machine. If the analyst isn't running Audit Viewer on the live machine they can acquire an image of the machine and give Audit Viewer the path to the image. Once Audit Viewer is setup right click on each process in the tree view and acquire the process. Once the processes have been acquired (the author recommends renaming the directories to something that indicates what it contains) run find_injected_dll.py on each acquired process.
Output from running find_injected_dll.py script:
find_injected_dll.py acquired_explorer_exe/
Found 0 injected dll(s)

find_injected_dll.py acquired_csrss_exe/
Found 0 injected dll(s)

find_injected_dll.py acquired_winlogon_exe/
Found 0 injected dll(s)

find_injected_dll.py acquired_services_exe/
Found injected dll C%3a%5cWINDOWS%5csystem32%5c668_0x00040000-0x00060fff.VAD
Found 1 injected dll(s)
From the output of the find_injected_dll, there is just one injected DLL and that is in services.exe.

Both methods help to determine if and what process might have been compromised. The first method did not definitively tell the analyst where in memory the injected DLL was. If the analyst were to combine the first method to identify the process, then acquire the processes memory and run find_injected_dll.py the results would be the same as running find_injected_dll.py on all questionable processes.

Identifying Compromised Machines

Part of malware analysis is to develop some kind of way to identify infected machines. This identification should be based on the malware's behavior. The analyst can use Memoryze to identify infected machines by filtering a given process or drivers behavior. The filter could be return all processes that have a file handle open to "spamlist.txt". Or return any driver that hooks function's "X and Y." Filters can be simpler, if some malware creates a unique process or driver name that can be filtered on as well.

Creating filters for malware using Memoryze is relatively easy to do. Memoryze has the ability to apply xpath filters to its results. In this case, the rootkit has a few behaviors that can be made into a filter.
  • The malicious driver has a unique driver object \Driver\Buritio*
  • The malicious driver has unique behavior in the hooks it installed
The first filter, filters out all drivers that don't have a driver object that matches burito.*:
<?xml version="1.0" encoding="utf-8"?>
<script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" chaining="implicit">
  <commands>
    <command xsi:type="ExecuteModuleCommand">
      <module name="w32drivers-signature" version="1.0.34.0" />
      <filters>                                                                                                                
        <filter>                                                                                                               
          <module name="xpath" />                                                                                              
          <config xsi:type="ParameterListModuleConfig">                                                                       
            <parameters>                                                                                                       
              <param name="expression">                        
                <value xsi:type="xsd:string">//*[(matches(lower-case(DriverName), 'burito.*'))]             
              </param>                                                                                                         
            </parameters>                                                                                                      
          </config>                                                                                                            
        </filter>                                                                                                              
      </filters>                                                                                                                                                       
    </command>                                                                                                                 
  </commands>                                                                                                                  
</script>                          
The second filter will identify any malware with the following behavior:
  • Driver has a hook installed and its name matches burito.*sys.
  • The hooking driver is hooking tcpip.sys and specifically is hooking the IRP_MJ_DEVICE_CONTROL function.
<?xml version="1.0" encoding="utf-8"?>
<script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" chaining="implicit">
  <commands>
    <command xsi:type="ExecuteModuleCommand">
      <module name="w32kernel-rootkitdetection" version="1.0.30.0" />
      <config xsi:type="ParameterListModuleConfig">
        <parameters>
   	<param name="drivers">
            <value xsi:type="xsd:boolean">true</value>
        </param>
        </parameters>
       </config>                                                                                           
      <filters>                                                                                                                
        <filter>                                                                                                               
          <module name="xpath" />                                                                                              
          <config xsi:type="ParameterListModuleConfig">                                                                        
            <parameters>                                                                                                       
              <param name="expression">                                                                    
                    <value xsi:type="xsd:string">//*[(matches(lower-case(HookingModule), 'burito.*sys') and contains(lower-case(HookedFunction), 'irp_mj_device_control') and contains(lower-case(HookedModule), 'tcpip.sys'))]</value>            
              </param>                                                                                                         
            </parameters>                                                                                                      
          </config>                                                                                                            
        </filter>                                                                                                              
      </filters>
    </command>                                                                                                                 
  </commands>                                                                                                                  
</script>                   
Conclusion

Hardcore malware analysis will probably always involve some insight from a disassembler like IDA. However the insight required can be lessened with good runtime/post runtime analysis tools like Memoryze. Using Memoryze, some common sense combined with the AuditViewer. It should be clear how this combination can help to solve the basic quick malware analysis problem.

This is the first post in a series of articles that will be put up on http://blog.mandiant.com, dealing with a wide variety of topics from malware analysis and reverse engineering to disk and memory forensics.

All the tools mentioned in the article can be found at the following locations: A good write up on a variant of the malware used in this article can be found at http://www.offensivecomputing.net/papers/storm-3-9-2008.pdf.

Article Comments Write Comment / View Complete Comments

    Username Comment Excerpt Date
cirix good job,thx Wednesday, August 8 2012 21:33.24 CDT
zezo010 I'm waite for next lessons. Nice work, thanks! Sunday, August 14 2011 04:26.00 CDT
eaescob Very nice work, thanks! Monday, June 27 2011 19:28.08 CDT
slolurner For folks coming late to the party like me, I w... Monday, October 25 2010 10:40.36 CDT
cyberpsych0z nice thing :) Sunday, September 26 2010 07:14.56 CDT
Silkut The tool has been updated, it now works with Wi... Friday, September 24 2010 02:22.10 CDT
laramies Nice article, and great tools, keep sharing mem... Thursday, November 19 2009 03:09.51 CST
Silkut Nice, thx. Tuesday, November 17 2009 10:13.55 CST
gemoroy Very informative, thanks a lot! Enjoyed reading. Sunday, June 14 2009 06:14.28 CDT
Genius perfect ! we'll wait for your future articles a... Monday, March 23 2009 15:54.52 CDT
  g6123 How information! Monday, March 2 2009 00:59.51 CST
step1515 I was excited to try your tools and techniques ... Friday, January 16 2009 11:52.26 CST
  echephron Peter - email in route. Error is different. A... Monday, December 15 2008 09:12.59 CST
peter echephron, Thanks for the bug report. I assume... Saturday, December 13 2008 10:02.13 CST
  echephron Peter, excellent work. I am having one issue, ... Friday, December 12 2008 18:00.09 CST
naggingmachine Thanks for your cool article. Wednesday, December 10 2008 20:20.59 CST
peter Thanks for pointing that out. I've fixed it. Thursday, November 27 2008 18:51.41 CST
k05tya Peter, thank you for Memoryze, AuditViewer and ... Thursday, November 27 2008 18:11.59 CST

There are 30,780 total registered users.


Recently Created Topics
How to decompile a f...
Sep/16
How to trap mouse cl...
Sep/03
Intel pin in loaded ...
Jun/27
Going to do today wi...
Jun/27
how to create delphi...
Jun/27
enabling menu in a s...
Jun/18
How to get the Image...
Jun/17
OllyDBG Process Term...
Apr/28
Reversing opcode
Apr/24
Question about debbu...
Apr/16


Recent Forum Posts
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n
OOP_RE tool available?
van7hu
Should binaries be n...
Kolisar
Problem with ollydbg
nullx42
!findtrampoline Immu...
skycrack
looking for a softwa...
raxen
Documenting reversed...
raxen
.orpc section what's...
mbin
Pydbg load() issue
phreak


Recent Blog Entries
oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

oleavr
Apr/17
frida.re 1.2.0 is out, with...

gareebnavas
Jan/21
Android Malware Analysis

oleavr
Dec/21
frida.github.io: scriptable...

More ...


Recent Blog Comments
pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

newlulu on:
Jun/10
Branch tracing and LBR acce...

newlulu on:
Jun/10
Advanced debugging techniques

newlulu on:
Jun/10
2 anti-trace mechanisms spe...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit