Tuesday, June 25, 2013

Memory Forensics Training - Reston, VA - November 2013

The next journey to the center of Windows Memory Forensics starts in Reston, VA this November!

This event will be the 5th public offering of the Windows Malware and Memory Forensics Training by The Volatility Project. This is the only memory forensics course officially designed, sponsored, and taught by the Volatility developers. One of the main reasons we made Volatility open-source is to encourage and facilitate a deeper understanding of how memory analysis works, where the evidence originates, and how to interpret the data collected by the framework's extensive set of plugins. Now you can learn about these benefits first hand from the developers of the most powerful, flexible, and innovative memory forensics tool.

Dates: Monday, November 11th through Friday, November 15th 2013
Location: Reston, VA (exact location will be shared upon registration)
Instructors: Michael Ligh (@iMHLv2), Andrew Case (@attrc), Jamie Levy (@gleeda)

For more information about the course, view the Volatility Training Flyer (to download a copy of the PDF, click File > Download). To request a link to the online registration site or to receive a detailed course agenda/outline, please send an email voltraining [[ at ]] memoryanalysis.net.

Curious what our past attendees have been saying about the class? Here are some testimonials from our recent class in Reston:
"One of the best technical classes I've taken in 10 years" - Rich M. (HP)
"Excellent memory forensics training. Definitely would recommend it to anyone in DFIR or malware analysis" - Q.M. (McAfee) 
"Realistic labs and the one-on-one instruction make the entire class worth it. Everything else is icing" - Anonymous 
"Super technical and awesome" - Sarah E. (Harris)
"Best forensic and winternal training I've ever experienced. Raises the bar really high" - Lance B.
"This is as valuable an education as any of you have had in your career" - Ash K. (Intersections)
"Great, great course. Most malware classes out there walk through analysis of some IRC bot from the 90's and call it good. This was an excellent trip into modern, highly sophisticated malware and gave real methodologies to quickly analyze them" - Brian H. (Harris)

Thursday, June 20, 2013

The Perfect Combination of IR, Malware, Forensics, and Winternals

Our Windows Malware and Memory Forensics training course has been described as the "...perfect combination of incident response, malware analysis, memory forensics, and Windows internals." As you can see below, we do in fact disseminate quite a bit of information. If you're used to instructors dropping knowledge bombs, we parade you with missiles. Not literally of course, you will leave with in one piece - we promise.

The next opportunity to join us in the journey to the center of memory forensics is September 9-13th in Amsterdam, The Netherlands and then November 11-14th in Reston Virginia. Email us at voltraining [[ @ ]] memoryanalysis.net for a full course outline or a registration invite to either of our upcoming events. We have no doubt you'll enjoy the course as much as our students did last week:
"Excellent memory forensics training. Definitely would recommend it to anyone in DFIR or malware analysis" - Q.M. (McAfee) 
"Realistic labs and the one-on-one instruction make the entire class worth it. Everything else is icing" - Anonymous  
"One of the best technical classes I've taken in 10 years" - Rich M. (HP) 
"Best memory forensics class and tool in the business" - Brian R. (Harris) 
"This course was invaluable for the hands-on experience dissecting real-world malware from memory dumps. Terrific, would absolutely recommend it to anyone in the security field" - Marco C. 
"Huge props to the entire Volatility team for the amazing DFIR work they do and excellent training" - Kyle O. (GE) 
"The Volatility Team crammed a years worth of answers into one week - they are fantastic" - Tim R. (Intersections)  
"Best forensic and winternal training I've ever experienced. Raises the bar really high" - Lance B. 
"Super technical and awesome" - Sarah E. (Harris) 
"In the past I've avoided forensics because it seemed tedious and slightly boring...this class has completely changed my perspective" - Chris T. (Booz Allen) 
"I was amazed at the amount of artifacts that could be obtained from memory dumps through the use of the Volatility Framework" - Scott H.  
"This is as valuable an education as any of you have had in your career" - Ash K. (Intersections) 
"The best technical course I've ever attended. Many practical labs, technical info...simply love it" - Salah. A. (KACST) 
"The lab exercises were fantastic; technically challenging and true to life. I really enjoyed the class" - Christopher G.  
"Great, great course. Most malware classes out there walk through analysis of some IRC bot from the 90's and call it good. This was an excellent trip into modern, highly sophisticated malware and gave real methodologies to quickly analyze them" - Brian H. (Harris)  
"This was the most relevant hands-on DFIR training I've ever had. The topics covered in class are a must for anyone tasked with enterprise security" - William P. (GE) 
"Spending a week learning from the Volatility creators is worth every penny. The course is well designed and presented and will help me in my role at work immediately" - Akira M.  
"Mind blowing crash course in Windows internals, malware research, and Volatility packed in just five days" - Marc R.  
"Tons of well presented information on Windows internals and how they relate to memory forensics. Lots of hands-on" - Ron H. (Dell Secureworks) 
"Everything you ever wanted to know about Windows memory forensics and beyond. A must take for any incident responder" - Mark P. (NIH) 
"This is an amazing course that will not only provide the skills and knowledge you need to run Volatility, but also give you a much deeper insight into Windows memory internals" - Dave L.  
"This is much more than a class on how to use a tool. By far the best training I've attended in several years. Instructors are top notch. Excellent class for even the most experienced of analysts" - Adam W.  
"Definitely the most advanced forensics course that one can imagine. I believe that it attempts the impossible - of actually giving a complete overview and state-of-the-art knowledge about memory forensics" - Greg I. (E & Y) 
"Best DFIR course there is" - John P. 

Tuesday, June 11, 2013

MOVP II - 4.5 - Mac Volatility vs the Rubilyn Kernel Rootkit

In our final Month of Volatility Plugins post, we are going to demonstrate a number of plugins that can be used to detect kernel level OS X rootkits. To show these capabilities I am going to analyze a system that is infected with the rubilyn rootkit. I want to thank @osxreverser for providing me with the infected memory sample that I did this analysis on.


This rootkit was released on full disclosure last year, and claimed the following capabilities:

* works across multiple kernel versions (tested 11.0.0+)
* give root privileges to pid
* hide files / folders
* hide a process
* hide a user from 'who'/'w'
* hide a network port from netstat
* sysctl interface for userland control
* execute a binary with root privileges via magic ICMP ping 
The release notes claim to use system call hooking and DKOM to accomplish these goals. 

Detecting Hidden Processes

The first capability of Rubilyn that we will detect is the hiding of processes. If we run the mac_psxview plugin on our infected image, we immediately see a suspicious process:

$ python vol.py -f rubilyn.vmem --profile=MacLion_10_7_5_AMDx64 mac_psxview
Volatile Systems Volatility Framework 2.3_beta
Offset(P)          Name                    PID pslist parents pid_hash pgrp_hash_table session leaders task processes
------------------ -------------------- ------ ------ ------- -------- --------------- --------------- --------------
0xffffff80008d8d40 kernel_task               0 True   True    False    True            True            True
0xffffff8005ee4b80 launchd                   1 False  True    True     True            True            True
0xffffff8005ee4300 kextd                    10 True   True    True     True            True            True
0xffffff8005ee3ec0 UserEventAgent           11 True   False   True     True            True            True
0xffffff8005ee3640 notifyd                  12 True   False   True     True            True            True
0xffffff8005ee3200 mDNSResponder            13 True   False   True     True            True            True
0xffffff8005ee2dc0 opendirectoryd           14 True   False   True     True            True            True
0xffffff8005ee2980 diskarbitrationd         15 True   False   True     True            True            True
0xffffff8005ee2540 configd                  16 True   False   True     True            True            True
0xffffff8005ee2100 syslogd                  17 True   False   True     True            True            True

The launchd process of PID 1, appears in all columns but 'pslist'. This shows us that the rootkit was used to hide the particular process from the kernel's process list. In a real investigation this would be a process related to the attacker's activity (network listener, keylogger, etc), and we could then immediately focus our investigation on it. See our previous post from this week, MOVP 3.2 - Dumping, Scanning, and Searching Mac OSX Process Memory, to learn how to investigate individual processes.

System Call Hooking

Since the documentation claims to use system call hooking, it makes sense to check this. Volatility's mac_check_syscalls is able to determine hooks to the system call table and print the address of the hook. This reveals three hooked system calls:

$ python vol.py -f rubilyn.vmem --profile=MacLion_10_7_5_AMDx64 mac_check_syscalls | grep HOOK
Volatile Systems Volatility Framework 2.3_beta
SyscallTable       222 0xffffff7f807ff41d HOOKED
SyscallTable       344 0xffffff7f807ff2ee HOOKED
SyscallTable       397 0xffffff7f807ffa7e HOOKED

Looking up the system call table indexes for entries 222, 344, and 397 reveal that getdirentriesattr, getdirentries64, and write_nocancel are hooked. getdentires (get directory entries) are calls involved with reading of directories from active filesystems. These are almost always used to hide files and directories.

Reading the source code of the write_nocancel hook shows that it is looking for processes named 'grep', 'who', and 'netstat', and then filters out entries related to the rootkit. This will effectively hide data from these userland tools.

Custom Sysctl Handlers  

Rubilyn loads a kernel module, and if we use the mac_lsmod plugin, we see it listed as the first entry (note: modules are stored in the reverse order of when they loaded).

$ python vol.py -f rubilyn.vmem --profile=MacLion_10_7_5_AMDx64 mac_lsmod
Address                          Size   Refs   Version      Name
------------------ ------------------ -------- ------------ ----
0xffffff7f807fe000             0x5000    0     1            com.hackerfantastic.rubilyn
0xffffff7f8159d000             0xa000    0     0081.82.01   com.vmware.kext.vmhgfs
0xffffff7f80ad3000             0x6000    0     5.1.0        com.apple.driver.AppleUSBMergeNub
0xffffff7f80a7a000             0x8000    0     5.0.0        com.apple.iokit.IOUSBHIDDriver
0xffffff7f80a82000             0x6000    1     5.0.0        com.apple.driver.AppleUSBComposite

The mac_check_sysctl plugin lists all active sysctl entries and their handlers, and prints "OK" if the handler points to a known address within the kernel or a kernel module or prints "HOOKED" if is not found in these places.

In the case of Rubilyn, its handlers will be listed, but marked "OK" as the kernel module is still in the module list. Since we know the rootkit is malicious, we have two choices:

1) filter out the module in mac_lsmod so it appears hidden to other plugins
2) leverage mac_volshell to print out the sysctl handlers inside the module

Since 1) is fairly straightforward and many people have never used mac_volshell, I chose to do 2).

$ python vol.py -f rubilyn.vmem --profile=MacLion_10_7_5_AMDx64 mac_volshell
Volatile Systems Volatility Framework 2.3_beta
Current context: process kernel_task, pid=0 DTB=0x100000
Welcome to volshell! Current memory image is:
To get help, type 'hh()'
>>> import volatility.plugins.mac.check_sysctl as check_sysctl
>>> for (sysctl, name, val, _) in check_sysctl.mac_check_sysctl(self._config).calculate():
...     handler = sysctl.oid_handler
...     if 0xffffff7f807fe000 <= handler < 0xffffff7f807fe000+0x5000:
...         print "name: %s val: %s handler: %x" % (name, str(val), handler)
name: pid2 val: 0 handler: ffffff7f807ff14b
name: pid3 val: 0 handler: ffffff7f807ff1ed
name: dir val:  handler: ffffff7f807ff2aa
name: cmd val:  handler: ffffff7f807ff2bb
name: user val:  handler: ffffff7f807ff2cc
name: port val:  handler: ffffff7f807ff2dd
>>> dis(0xffffff7f807ff14b, 32)
0xffffff7f807ff14b 55                               PUSH RBP
0xffffff7f807ff14c 4889e5                           MOV RBP, RSP
0xffffff7f807ff14f 4157                             PUSH R15
0xffffff7f807ff151 4156                             PUSH R14
0xffffff7f807ff153 4154                             PUSH R12
0xffffff7f807ff155 53                               PUSH RBX
0xffffff7f807ff156 8b5720                           MOV EDX, [RDI+0x20]
0xffffff7f807ff159 488b7718                         MOV RSI, [RDI+0x18]
0xffffff7f807ff15d e8fea3d57f                       CALL 0xffffff8000559560
>>> dis(0xffffff7f807ff1ed, 32)
0xffffff7f807ff1ed 55                               PUSH RBP
0xffffff7f807ff1ee 4889e5                           MOV RBP, RSP
0xffffff7f807ff1f1 4157                             PUSH R15
0xffffff7f807ff1f3 4156                             PUSH R14
0xffffff7f807ff1f5 4155                             PUSH R13
0xffffff7f807ff1f7 4154                             PUSH R12
0xffffff7f807ff1f9 53                               PUSH RBX
0xffffff7f807ff1fa 50                               PUSH RAX
0xffffff7f807ff1fb 8b5720                           MOV EDX, [RDI+0x20]

In this output you can see that I import the mac_check_sysctl plugin. I then use it to enumerate every sysctl, and the generator gives me the sysctl structure, the name of entry, and the current value. I then use the information given from mac_lsmod about the Rubilyn module to filter out entries only belonging to the module. Since we have the handler address of each systcl handler, we could then reverse engineer the handler to see what it does (the 'dis' command).

The names of the discovered sysctl values seem to relate to the capabilities -- hiding ports & processes, running commands, and so on.

IP Filters 

The mac_ip_filters plugin lists any IP filters actived within the kernel. On a default system, there will be no output from this plugin.  It is likely that software firewalls will use this infrastructure to filter packets although we have not fully tested any. During our analysis of the rootkit, we see that it installs a handler for both incoming and outgoing packets:

# python vol.py -f rubilyn.vmem --profile=MacLion_10_7_5_AMDx64 mac_ip_filters
Volatile Systems Volatility Framework 2.3_beta
Context    Filter           Pointer            Status
---------- ---------------- ------------------ ------
INPUT      rubilyn          0xffffff7f807ff577 OK
OUTPUT     rubilyn          0xffffff7f807ff5ff OK
DETACH     rubilyn          0xffffff7f807ff607 OK

Analysis of the INPUT handler shows that it is used to implement an ICMP-based command & control backdoor. The OUTPUT and DETACH are stubs.

Escalation of Process Privleges  

The only capability not detected so far is the escalation of privileges of userland processes. The current version of Volatility is not able to detect this directly on Mac systems as we can on Linux. There are a number of indirect ways to detect this, such as bash history, strings/grep, and others, but those are not something that would be implemented as a plugin. Adding this capability to the next release of Volatility after 2.3 is on the TODO list.

Even with the current release of Volatility it would be hard for rootkits to hide this activity. Process privilege escalation is generally used when the rootkit lives long term in the kernel, but the attacker sparsely uses the infected machine. Upon logging into the system through an SSH or other backdoor, the attacker can then communicate with the kernel rootkit to elevate privileges, and the rouge communication channels (sysctl, system call table, etc) can be detected by Volatility.


We have demonstrated a number of ways to detect the Rubilyn kernel rootkit. The techniques shown will detect a wide range of other rootkits as well as there are only so many places that rootkits can utilize to accomplish their goals.

Sunday, June 9, 2013

MOVP II - 4.4 - What's in Your Mac OSX Kernel Memory?

Today's post will discuss a number of plugins that can retrieve forensically interesting information from within the kernel. Keep in mind, you can also use mac_yarascan to search kernel memory with yara signatures and you can use mac_volshell as an interactive tool to print kernel data structures, display kernel memory addresses as bytes, dword, qwords, or disassemble code in kernel space.


This plugin lists the loaded kernel extensions, their base addresses and size, reference count, and version number.

Note: The last several entries in the output of this plugin will likely have no base address and size. These represent the 'dummy' drivers that Mac loads as the system startup and do not correspond to real kernel modules.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_lsmod
Volatile Systems Volatility Framework 2.3_alpha
Address                          Size   Refs   Version      Name
------------------ ------------------ -------- ------------ ----
0xffffff7f91847000             0x3000    0     3.0.2        com.atc-nycorp.devmem.kext
0xffffff7f91841000             0x6000    0     10.1.24      com.vmware.kext.vmioplug.10.1.24
0xffffff7f91834000             0xd000    0     0104.03.86   com.vmware.kext.vmx86
0xffffff7f9182a000             0xa000    0     0104.03.86   com.vmware.kext.vmnet
0xffffff7f9181a000            0x10000    0     90.4.23      com.vmware.kext.vsockets
0xffffff7f91808000            0x12000    1     90.4.18      com.vmware.kext.vmci
0xffffff7f916d2000             0xe000    0     75.19        com.apple.driver.AppleBluetoothMultitouch


This plugin shows the mounted file systems, which is particularly useful when external media is plugged on or network shares are mounted.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_mount
Volatile Systems Volatility Framework 2.3_alpha
Device                         Mount Point                                                  Type
------------------------------ ------------------------------------------------------------ ----
/                              /dev/disk3                                                   hfs
/dev                           devfs                                                        devfs
/net                           map -hosts                                                   autofs
/home                          map auto_home                                                autofs
/Volumes/LaCie                 /dev/disk2s2                                                 hfs


This plugin enumerates sessions from the session hash table. You can use this information to link processes to user names.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_list_sessions
Volatile Systems Volatility Framework 2.3_alpha
Leader (Pid) Leader (Name)        Login Name               
------------ -------------------- -------------------------
           0 kernel_task                                   
         257 apsd                 _softwareupdate          
           1 launchd              _securityagent           
          -1      mike              
          11 UserEventAgent       root                     
          12 kextd                root                     
          14 notifyd              root                     
          15 securityd            root                     
          16 diskarbitrationd     root     


This plugin recovers the kernel debug buffer, which can contain a wide range of system activity, such as device insertion, hardware configurations, wireless activity, and more.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_dmesg
Volatile Systems Volatility Framework 2.3_alpha
deny mach-lookup com.apple.coresymbolicationd
MacAuthEvent en1   Auth result for: 00:26:bb:77:d2:a7  MAC AUTH succeeded
wlEvent: en1 en1 Link UP virtIf = 0
AirPort: RSN handshake complete on en1
wl0: Roamed or switched channel, reason #8, bssid 00:26:bb:77:d2:a7
en1: BSSID changed to 00:26:bb:77:d2:a7
en1::IO80211Interface::postMessage bssid changed
MacAuthEvent en1   Auth result for: 00:26:bb:77:d2:a7  MAC AUTH succeeded
wlEvent: en1 en1 Link UP virtIf = 0
AirPort: RSN handshake complete on en1


This plugin enumerates Mac zones, which are very similar to Linux kmem_cache backed structures. You can use it to determine how many of a particular type of structure (i.e. a process object) are active and freed. For example, below you can see that 133 proc structures are active on the system. Other plugins can inherit from mac_list_zones and actually collect the addresses of each active object type, leading to a wealthy source of information regarding where to find allocated objects in memory dumps.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_list_zones
Volatile Systems Volatility Framework 2.3_alpha
Name                           Active Count Free Count Element Size
------------------------------ ------------ ---------- ------------
zones                                   182          0          592
vm.objects                           153401    8832498          224
vm.object.hash.entries               135206     882875           40
maps                                    149      34033          232
VM.map.entries                        26463   24372727           80
Reserved.VM.map.entries                  35      13164           80
VM.map.copies                             0     220097           80
pmap                                    139       7962          256
pagetable.anchors                       139       7962         4096
proc                                    133       4042         1120


This plugin prints terminated/dead processes that it gathers by leveraging the zone enumeration API. In most cases, the UID, GID, PGID, Bits, and DTB columns will show invalid data since we could be looking at partially overwritten data structures. Also please note in some rare cases, active processes are also found in this list. We are currently investigating conditions that lead to active processes showing up in the freed process object list.  We believe the cause is related to the same issue that affects mac_pslist (see the mac_pslist discussion in MoVP II - 4.1 - Leveraging Process Cross-View Analysis for Mac Rootkit Detection).
$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_dead_procs
Volatile Systems Volatility Framework 2.3_alpha
Offset             Name                 Pid      Uid      Gid      PGID     Bits         DTB                Start Time
------------------ -------------------- -------- -------- -------- -------- ------------ ------------------ ----------
0xffffff8036349760 diskmanagementd      4158     -        -        -55...11              ------------------ 2013-03-29 12:14:31 UTC+0000
0xffffff8036349760 diskmanagementd      4158     -        -        -55...11              ------------------ 2013-03-29 12:14:31 UTC+0000
0xffffff8032c60d20 lssave               4161     -        -        -55...11              ------------------ 2013-03-29 12:14:43 UTC+0000
0xffffff803dfe08e0 com.apple.audio.     4146     -        -        -55...11              ------------------ 2013-03-29 12:12:59 UTC+0000
0xffffff803dfe0d40 com.apple.audio.     4145     -        -        -55...11              ------------------ 2013-03-29 12:12:59 UTC+0000
0xffffff8032c62300 com.apple.qtkits     4147     -        -        -55...11              ------------------ 2013-03-29 12:12:59 UTC+0000


In this post we have highlighted several plugins that can be useful in a number of investigative scenarios. Tomorrow we will look at a wide range of plugins as we analyze and detect the rubilyn kernel rootkit in memory.

Friday, June 7, 2013

MoVP II - 4.3 - Recovering Mac OS X Network Information from Memory

The 2.3 release of Volatility will contain four plugins that are capable of recovering networking information from Mac samples. Combined, these plugins allow for deep inspection of system network activity and can be used in conjunction with network forensics.


This plugin prints the ARP table, including sent/recv statistics, time the entry was created, and its expiration.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_arp
Volatile Systems Volatility Framework 2.3_alpha
Source IP                Dest. IP                    Name           Sent               Recv                     Time                 Exp.    Delta
------------------------ ------------------------ ---------- ------------------ ------------------ ------------------------------ ---------- -----          ff:ff:ff:ff:ff:ff          vmnet8           10                 0           2013-03-29 12:13:59 UTC+0000    39913    0           ff:ff:ff:ff:ff:ff          vmnet1           10                 0           2013-03-29 12:13:59 UTC+0000    39913    0               ff:ff:ff:ff:ff:ff           en1             12                 0           2013-03-29 12:13:59 UTC+0000    39913    0                 e8:8d:28:cb:67:07           en1             19                924          2013-03-29 11:56:30 UTC+0000    40065    1201                 ac:16:2d:32:fc:d7           en1             1                  47          2013-03-29 11:56:02 UTC+0000    40037    1201                 00:26:bb:6c:8e:64           en1            4551               4517         2013-03-29 01:08:53 UTC+0000    40318    40310

This information is very useful when tracking lateral movement as systems that the investigated computer interacted with can be determined.


mac_ifconfig prints each interface on the system as well its IP addresses.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_ifconfig
Volatile Systems Volatility Framework 2.3_alpha
Interface  Address
---------- -------
lo0        fe80:1::1
lo0        ::1
en1        8c:2d:aa:41:1e:3b
en1        fe80:4::8e2d:aaff:fe41:1e3b
en0        10:dd:b1:9f:d5:ce
p2p0       0e:2d:aa:41:1e:3b
fw0        00:0a:27:02:00:4b:19:5c
vmnet1     00:50:56:c0:00:01
vmnet8     00:50:56:c0:00:08


The netstat plugin prints each active connection on a system along with its state. Analysis of listening sockets can reveal backdoors and established connections reveal remote connections.
$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_netstat
Volatile Systems Volatility Framework 2.3_alpha
UNIX /var/tmp/launchd/sock
UNIX /var/tmp/com.barebones.authd.socket
UNIX /var/run/com.apple.ActivityMonitor.socket
TCP :::548 :::0 TIME_WAIT
UNIX /var/run/mDNSResponder
UNIX /var/rpc/ncacn_np/lsarpc
UNIX /var/rpc/ncalrpc/lsarpc
UNIX /var/run/vpncontrol.sock
UNIX /var/run/portmap.socket
TCP :::5900 :::0 TIME_WAIT


The mac_route plugin prints the system's routing table. It also prints the number of packets sent and received on each route. This can especially useful during internal network breach investigations.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_route
Volatile Systems Volatility Framework 2.3_alpha
Source IP                Dest. IP                    Name           Sent               Recv                     Time                 Exp.    Delta
------------------------ ------------------------ ---------- ------------------ ------------------ ------------------------------ ---------- -----                            en1            4342              50431         2013-03-29 01:08:55 UTC+0000      0      0                                             en1            8331              31691         2013-03-29 01:08:56 UTC+0000      8      0                 00:26:bb:6c:8e:64           en1            4551               4517         2013-03-29 01:08:53 UTC+0000    40318    40310                 ac:16:2d:32:fc:d7           en1             1                  47          2013-03-29 11:56:02 UTC+0000    40037    1201                          lo0             0                 6168         2013-03-29 01:08:55 UTC+0000      0      0                 e8:8d:28:cb:67:07           en1             19                924          2013-03-29 11:56:30 UTC+0000    40065    1201               ff:ff:ff:ff:ff:ff           en1             12                 0           2013-03-29 12:13:59 UTC+0000    39913    0                        en1             39                 39          2013-03-29 01:08:55 UTC+0000      0      0                     en1             2                  60          2013-03-29 01:09:16 UTC+0000      0      0                     en1             0                  58          2013-03-29 01:09:46 UTC+0000      0      0

Thursday, June 6, 2013

MoVP II - 4.2 - Dumping, Scanning, and Searching Mac OSX Process Memory

In our previous post we discussed multiple ways of finding process structures in memory. Today we will discuss analysis of a process' address space. First we'll describe how Volatility handles all the possible scenarios that must be understood and properly implemented before you can access process memory on all Mac systems. Then we'll summarize some of the plugins that unlock the potential of Mac memory forensics once you have access to process memory - scanning for bash command history, looking for URLs or passwords in browser processes, dumping shared libraries and mapped files, etc.

Reading Mac Process Memory

The development phase of adding support for Mac process address spaces was a bit challenging. Mac setups have very unusual sharing of user and kernel virtual addressing and they use different architectures for processes and the kernel. This is drastically different from Windows and Linux.

To determine which hardware architecture to assign a process both the value of "x86_64_flag" as well as the process architecture must be known. The "x86_64_flag" tells whether the hardware used on the computer from the memory sample is capable of running in 64 bit mode or not.

With this information we can discuss all of the possibilities that Mac presents. If you would like to see the code that implements this logic, read the get_process_address_space function.

32 bit process on non-64 bit capable systems

This occurs on old computers that are not capable of running in 64 bit mode. The only sample we received like this came from a very old Mac that was running 10.5.x. On these systems, there is no splitting of the virtual addresses between userland processes and the kernel. This means we need to instantiate a new 32 bit PAE address space with the dtb value of the process.

32 bit process on 64 bit capable systems

This occurs when a 32 bit process is running on a 64 bit capable system. For this we must force a 64 bit address space to correctly translate process memory even though the process is running as 32 bit. 

64 bit process running on a 32 bit system

This occurs when 64 bit processes are running on a 32 bit kernel (no other major operating system supports this). We must force a 64 bit address space to properly translate process memory.

64 bit process on a 64 bit system

This is true 64 bit addressing and simply requires the use of the 64 bit address to correctly translate addresses.

Mac's very odd combinations of translation requirements is one of the stranger things we have encountered during memory forensics research and required a team effort to get all the details and possibilities sorted and tested.


This plugin walks a process' memory mappings and prints the PID and name of the process along with the starting and ending address, permissions, and path of mapped file (if any), for each mapping.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_proc_maps --pid=1 
Volatile Systems Volatility Framework 2.3_alpha
Pid      Name                 Start              End                Perms     Map Name
-------- -------------------- ------------------ ------------------ --------- --------
1        launchd              0x000000010630c000 0x0000000106333000 r-x       Macintosh HD/sbin/launchd 
1        launchd              0x0000000106333000 0x0000000106335000 rw-       Macintosh HD/sbin/launchd
1        launchd              0x0000000106335000 0x000000010633b000 r--       Macintosh HD/sbin/launchd
1        launchd              0x000000010633b000 0x000000010633c000 r--        
1        launchd              0x000000010633c000 0x000000010633f000 r-x       Macintosh HD/usr/lib/libauditd.0.dylib
1        launchd              0x000000010633f000 0x0000000106340000 rw-       Macintosh HD/usr/lib/libauditd.0.dylib
1        launchd              0x0000000106340000 0x0000000106343000 r--       Macintosh HD/usr/lib/libauditd.0.dylib
1        launchd              0x0000000106343000 0x0000000106344000 r--       
1        launchd              0x0000000106344000 0x0000000106345000 rw-       Macintosh HD/private/var/db/dyld/dyld_shared_cache_x86_64

This can be used to determine which shared libraries a process is using as well as where the stack and the heap are. If you want to analyze a specific region of memory, you will need to know the starting address of the mapping in order to pass it to mac_dump_maps.


This plugin writes specified regions of process memory to disk. If no filters are specified then it dumps all regions from all processes to disk, which will likely be overwhelming unless you are looking to mass scan using tools such as AV or Yara.

In this example we dump the launchd binary from memory to disk. It could then be loaded into any reverse engineering tool. The starting address comes from the previous mac_proc_maps output.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_dump_maps --pid=1 --map-address=0x000000010630c000 --outputfile=launchd.binary.dmp
Volatile Systems Volatility Framework 2.3_alpha

Wrote 159744 bytes

$ file launchd
.binary.dmp: Mach-O 64-bit executable x86_64


Volatility already provides you with the ability to scan Windows and Linux memory dumps with yara signatures. There's no reason Mac should be an exception! Now you can run your rules against all of your Mac memory dumps as well.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/Desktop/Storage/memory/Mac/10.8.3/10.8.3.mmr.rawpad mac_yarascan -p 261 -Y "http"
Volatile Systems Volatility Framework 2.3_beta

Task: Google Chrome pid 261 rule r1 addr 0x73c6a0d
0x00000000073c6a0d  68 74 74 70 73 3a 2f 2f 63 6f 64 65 2e 67 6f 6f   https://code.goo
0x00000000073c6a1d  67 6c 65 2e 63 6f 6d 2f 70 2f 76 6f 6c 61 74 69   gle.com/p/volati
0x00000000073c6a2d  6c 69 74 79 2f 77 69 6b 69 2f 52 65 6c 65 61 73   lity/wiki/Releas
0x00000000073c6a3d  65 32 33 52 65 6c 65 61 73 65 32 33 20 2d 20 76   e23Release23.-.v

Task: Google Chrome pid 261 rule r1 addr 0x73c6acf
0x00000000073c6acf  68 74 74 70 3a 2f 2f 65 6e 2e 77 69 6b 69 70 65   http://en.wikipe
0x00000000073c6adf  64 69 61 2e 6f 72 67 2f 77 69 6b 69 2f 54 7a 5f   dia.org/wiki/Tz_
0x00000000073c6aef  64 61 74 61 62 61 73 65 01 00 00 2e 37 9a ee 58   database....7..X
0x00000000073c6aff  90 57 00 00 81 3d 8b 25 0a 00 82 27 41 01 01 06   .W...=.%...'A...

Task: Google Chrome pid 261 rule r1 addr 0x9bc70e0
0x0000000009bc70e0  68 74 74 70 73 3a 2f 2f 74 77 69 74 74 65 72 2e   https://twitter.
0x0000000009bc70f0  63 6f 6d 2f 67 6c 65 65 64 61 00 00 36 00 2c 00   com/gleeda..6.,.
0x0000000009bc7100  31 00 32 00 30 00 35 00 37 00 30 00 31 00 2c 00,.
0x0000000009bc7110  36 00 32 00 38 00 38 00 39 00 30 00 39 00 34 00


In this post we have discussed how to analyze and access userlarnd memory of Mac OS X processes. We have also discussed how Mac utilizes differing hardware architectures and virtual address translation schemes in ways not done by any other major operating system. The ability to dump, scan, and search process memory gives you the ability to attribute data back to its owning process and identify which process(es) had access to data that may be interesting to your investigation.

Wednesday, June 5, 2013

MOVP II - 4.1 - Leveraging Process Cross-View Analysis for Mac Rootkit Detection

In our final week of Month of Volatility Plugins II we will analyze the wide range of memory forensics capabilities against Mac OS X systems that are included in the latest release of Volatility (version 2.3). These capabilities span 38 different builds including 32- and 64-bit 10.5.x through 10.8.3, which is the latest version at the time of writing.

Our post today will cover finding processes in a number of places in kernel memory and analyzing information about them. In the end we will discuss the mac_psxview plugin, which is a powerful plugin for detecting hidden processes.


This plugin enumerates processes by walking the allproc list. It then prints the virtual address, name, PID, user and group ID, and architecture of the process (32 or 64 bit). Read our post tomorrow on process memory for the importance of accurately determining the per-process architecture.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f 10.8.3.mmr.macho mac_pslist
Volatile Systems Volatility Framework 2.3_alpha
Offset             Name                 Pid      Uid      Gid   PGID     Bits         DTB                Start Time
------------------ -------------------- -------- -------- ----- --------
0xffffff8032be4ea0 image              4175     0        0        4167     64BIT        0x317e7e000 2013-03-29 12:16:20 UTC+0000
0xffffff803dfdea40 coresymbolicatio   4173     0        0        4173     64BIT        0x4114c0000 2013-03-29 12:16:18 UTC+0000
0xffffff8032498d20 MacMemoryReader    4168     0        0        4167     64BIT        0x3f94a8000 2013-03-29 12:16:17 UTC+0000
0xffffff803dfe0020 sudo               4167     0        20       4167     64BIT        0x414a34000 2013-03-29 12:16:15 UTC+0000
0xffffff803dfe1a60 mdworker           4164     89       89       4164     64BIT        0x3f70cf000 2013-03-29 12:15:32 UTC+0000
0xffffff80370af760 DashboardClient    4160     501      20       275      64BIT        0x3e5bd9000 2013-03-29 12:14:36 UTC+0000
0xffffff803634ba60 CVMCompiler        4127     501      20       4127     64BIT        0x16692b000 2013-03-29 12:10:58 UTC+0000
0xffffff80370b11a0 cookied            4126     501      20       4126     64BIT        0x3137cc000 2013-03-29 12:10:58 UTC+0000
0xffffff803dfe1600 WebProcess         4124     501      20       4121     64BIT        0x3f235a000 2013-03-29 12:10:57 UTC+0000
0xffffff803249c600 taskgated          4122     0        0        4122     64BIT        0x3f3038000 2013-03-29 12:10:57 UTC+0000
0xffffff80314a9d40 Safari             4121     501      20       4121     64BIT        0x3f616c000 2013-03-29 12:10:57 UTC+0000

Our testing of Mac memory acquisition tools showed that at some point every tool smeared the process list and would throw the plugin into an endless loop on a process that was exiting/had exited after the acquisition began. These processes would have invalid "next" pointers due to their being out of sync with the rest of the acquired processes. Due to the frequency in which we saw this issue, we added a check in the plugin and once this condition is detected, the following is printed and the plugin exits:

"Recursive process list detected (a result of non-atomic acquisition). Use mac_tasks or mac_psxview"


This plugin enumerates processes, but instead of printing the name from the kernel buffer, it reads the command line arguments from process memory.  Knowing the arguments is very useful


The pstree plugin shows the parent/child relationship between processes. This is very helpful when trying to find the source of a process, such as user vs daemon, user vs malware, and so on. In general, there will be a kernel_task process with PID 0 followed by a launchd process with PID 1. All other processes will then be the child of this initial PID 1 process.  As can be seen in the following output, this relationship is shown by the number of dots before each process name.

$ python vol.py --profile=MacMountainLion_10_8_2_AMDx64 -f Mac-10.8.2.vmem mac_pstree
Volatile Systems Volatility Framework 2.3_beta
Name                 Pid             Uid
kernel_task          0               0
.launchd             1               0
..com.apple.dock.e   208             501
..IMRemoteURLConne   206             501
..filecoordination   205             0
..launchd            200             88
...cfprefsd          203             88
..xpcd               172             501
..coreaudiod         166             202
..apsd               154             0
..locationd          143             205
..launchd            128             92
...CVMCompiler       130             92
..CVMServer          127             0
..launchd            117             501


mac_tasks enumerates processes by walking the "tasks" list in the kernel and then using the "bsd_info" member of each task to determine the associated process. Due to the smearing issues with mac_pslist, the tasks plugin is used to generate a list of processes for the per-process information plugins we will learn about throughout the week.

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/10.8.3.mmr.macho mac_tasks
Volatile Systems Volatility Framework 2.3_alpha
Offset             Name                 Pid      Uid      Gid      PGID     Bits         DTB           Start Time
------------------ -------------------- -------- -------- -------- ------   ----         ------------  --------------------   
0xffffff800fada2d0 kernel_task          0        0        0        0        64BIT        0x11e9f000    2013-03-29 01:08:47 UTC+0000
0xffffff80314aaa60 launchd              1        0        0        1        64BIT        0x11234000    2013-03-29 01:08:47 UTC+0000
0xffffff80314a98e0 UserEventAgent       11       0        0        11       64BIT        0xbe18000     2013-03-29 01:08:49 UTC+0000
0xffffff80314aa1a0 kextd                12       0        0        12       64BIT        0xbecb000     2013-03-29 01:08:49 UTC+0000
0xffffff80314a9480 notifyd              14       0        0        14       64BIT        0x23b9b000    2013-03-29 01:08:49 UTC+0000
0xffffff80314a9020 securityd            15       0        0        15       64BIT        0x1dd43000    2013-03-29 01:08:49 UTC+0000

As shown in the output, mac_tasks uses the same rendering (print) function as mac_pslist.


This plugin enumerates processes by walking the process group hash table, pgrphashtbl. It uses the same rendering function as mac_pslist and mac_tasks.


This plugin enumerates processes by walking the process ID hash table, pidhashtbl.  It uses the same rendering function as mac_pslist and mac_tasks.


The process cross view function is used to find hidden processes by comparing the set of processes found from each source. If we look at the output of the plugin, we see the offset, name, and PID for each process along with a True or False if it was found in each source:

$ python vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f ~/Desktop/Storage/memory/Mac/10.8.3/10.8.3.mmr.macho mac_psxview
Volatile Systems Volatility Framework 2.3_alpha
Offset(P)          Name                    PID pslist parents pid_hash pgrp_hash_table session leaders task processes
------------------ -------------------- ------ ------ ------- -------- --------------- --------------- --------------
0xffffff800fada2d0 kernel_task               0 True   True    False    True            True            True          
0xffffff80314aaa60 launchd                   1 True   True    True     True            True            True          
0xffffff80314a98e0 UserEventAgent           11 True   False   True     True            True            True          
0xffffff80314aa1a0 kextd                    12 True   False   True     True            True            True          
0xffffff80314a9480 notifyd                  14 True   False   True     True            True            True          
0xffffff80314a9020 securityd                15 True   False   True     True            True            True          
0xffffff80314a8bc0 diskarbitrationd         16 True   False   True     True            True            True          
0xffffff80314a8760 configd                  17 True   False   True     True            True            True 

The columns that map directly to plugins we previously discussed are pslist, pid_hash, pgrp_hash_table, and task processes. The two columns that were not discussed are parents and 'session leaders'. Parents gathers tasks by walking the process list and retrieving the parent process pointer for each process. This would detect rootkits that unlink a process that has active children. 'Session leaders' leverages the mac_list_sessions plugin and gathers the process that is the leader of each session.

Note: As with the Windows and Linux versions of psxview, just because a column says False does not immediately mean a process is hidden. For example, every process does not spawn child processes, so they will not all appear in parents. Similarly, not every process is a session leader.

psxview is a very powerful plugin as a rootkit would have to hide the process from potentially six different sources while still keeping the system stable.


In this blog post we have covered a number of plugins that are able to recover processes from OS X kernel memory as well as the psxview plugin that can use these to detect rootkits. Tomorrow we will discuss OS X process memory as well as the oddities of the OS that caused us quite a few headaches while developing the capabilities.

Tuesday, June 4, 2013

MoVP II - 3.5 - Utilizing the kmem_cache for Android Memory Forensics

This post will discuss utilizing plugins that leverage the kmem_cache in order to perform deep memory forensics of Android devices. In previous Linux posts, we have briefly mentioned these plugins, but a full walk through has not been done. Also, as we will see, these plugins are highly effective on Android, while not as effective on recent Intel-based systems due to differences in memory allocation and de-allocation strategies.

kmem_cache, SLAB & SLUB

The Linux kmem_cache is part of the kernel's infrastructure for handling memory allocations and de-allocations that cannot experience delays (e.g. process creation, network packet handling). To accomplish this, memory pools for a particular structure type and size are pre-allocated upon system startup. Then, when a structure allocation is requested, the request can be immediately serviced without needing to allocate more regions. Also, the allocator keeps track of all free pages and can reuse chunks immediately after they are freed.

From a memory forensics perspective, we can leverage these features in a few ways. First, we can use active (allocated) structures in order to find instances of a particular structure type. This is best seen in the kmem_cache column of linux_psxview. This column is populated by enumerating all of the task structures active in the task_cachep kmem_cache at the time of the memory capture.

The second way we can leverage kmem_cache is to walk the free lists and recover as much information as possible from de-allocated entries. Structure members that are stored within the structure, such as simple integers or character arrays, will be left in-tact until the host structure is re-used and overwritten. Depending on how much time lapsed between de-allocation and the memory capture being taken, we may even be able to recover reference values as the pointer can still point to valid data.

The internals of these memory allocations and de-allocations depend entirely on the allocator chosen. There are currently two main allocators in-use, SLAB and SLUB, and they have a large effect on which objects are recoverable. SLAB was the original allocator and left many freed entries active and kept direct references to all active objects. SLUB on the other hand makes life much more difficult in both instances.

Luckily for us, all Android ROMs we have tested chose to use the SLAB allocator. This means that we cannot not only find active structures at will, but also recover a wealth of previous information "forgotten" by the operating system.

Recovering Data from kmem_cache


Each memory mapped file in Linux is represented by a vm_area_struct structure. The vma kmem_cache is responsible for allocating and de-allocating them. 

$ python vol.py --profile=LinuxEvo4GARM -f Evo4GRodeo.lime linux_vma_cache
Process          PID    Start      End        Path
---------------- ------ ---------- ---------- ----
                        0x48a4b000 0x48a4c000
                        0x46dfa000 0x46e12000
                        0x45496000 0x454a0000 app/htccalendarwidgets.apk
                        0x45136000 0x45137000 app/htccalendarwidgets.apk
                        0x443da000 0x443db000 app/htccalendarwidgets.apk
                        0x4513e000 0x451d6000 app/HtcDialer.odex

In this we can see information on each mapping, including the path. Note that in this particular sample the Process and PID columns are empty due to the kernel not implementing the 'owner' member of mm_struct (the parent struct of a process' memory mappings). For kernels with this option enabled the columns would be populated.

If we pass the -u flag to any of the kmem_cache plugins, the unallocated entries will be recovered. For memory mappings this can be extremely useful as it shows files and paths that were mapped into a processes' address space, even if the process has since exited or the file deleted from disk.


This plugin recovers processes and their associated information. Data found includes the process ID, user ID and group ID, and the start time of the process. By recovering unallocated entries, not only can we determine processes that previously executed, but we can include their start time within a timeline of in-memory data.

$ python vol.py --profile=LinuxEvo4GARM -f Evo4GRodeo.lime linux_pslist_cache
0xcafb6000 Binder Thread #      1856            10034           10034  0x23d80000 2012-08-05 02:32:21 UTC+0000
0xcafb6400 oid.voicedialer      1841            10087           10087  0x27d78000 2012-08-05 02:32:21 UTC+0000
0xcafb6c00 HeapWorker           1842            10087           10087  0x27d78000 2012-08-05 02:32:21 UTC+0000
0xc3d3a400 Signal Catcher       884             10092           10092  0x28d7c000 2012-08-05 02:21:44 UTC+0000
0xc3d3a800 RefQueueWorker@      1647            10009           10009  0x2cc04000 2012-08-05 02:30:49 UTC+0000
0xc3d3ac00 com.htc.bg           1157            10009           10009  0x2cc04000 2012-08-05 02:22:16 UTC+0000
0xc8ecc000 Binder Thread #      888             10092           10092  0x28d7c000 2012-08-05 02:21:44 UTC+0000


Each opened and/or mapped file is represented by a file structure that contains a pointer to a dentry structure that holds the name of the file as well as other metadata. Enumeration of this cache gathers all opened files across the system. This can  be very useful to locate malware-specific files or processes that are interacting with files they should not. Unallocated entries can also be used to find files that were previously opened and now deleted. Use of this plugin reports all of the files across in the cache in body file format, so you can immediately add the MAC times of recovered files to your timeline.

$ python vol.py --profile=LinuxEvo4GARM -f Evo4GRodeo.lime linux_dentry_cache


Each mount point in the system is tracked through the kmem_cache. By recovering allocated entries, we can see all mountpoints on the system:

$ python vol.py --profile=LinuxEvo4GARM -f Evo4GRodeo.lime linux_mount_cache
none                      /acct                               cgroup       rw,relatime
/sys/kernel/debug         /sys/kernel/debug                   debugfs      rw,relatime
sysfs                     /sys                                sysfs        rw,relatime
proc                      /proc                               proc         rw,relatime
devpts                    /dev/pts                            devpts       rw,relatime
tmpfs                     /dev                                tmpfs        rw,relatime
/dev/block/vold/179:1     /mnt/sdcard                         vfat         rw,relatime,nosuid,nodev,noexec
/dev/block/vold/179:1     /mnt/secure/asec/.android_secure    vfat         rw,relatime,nosuid,nodev,noexec

If we pass the -u option, we can find mount points that previously existed. This can be useful when external media was present on the system, but later removed.

Building New kmem_cache Plugins

Volatility currently only supports a few caches that we have found useful during investigations. If you find another cache that seems interesting (note: linux_slabinfo can be used to list them all), then you can leverage our simple API to gather all the structures of the same type.

If you read the dentry_cache plugin, you see that one simple line of code, that takes the name of the cache and type of each cache member as parameters, is all that is needed to enumerate from kmem_cache. The API determines if the system is using SLAB or SLUB, enumerates the proper entries, and instantiates them as the chosen type.


This post has highlighted a number of plugins that can help discover the current and historical context of a number of user and application (malware) related activities on an Android system. Incorporating kmem_cache analysis into this process is a huge advantage for investigators and can recover details not accessible by any other memory forensics tool.

Monday, June 3, 2013

MoVP II - 3.4 - Checking the ARM (Android) System Call Table and Exception Vector Table for Signs of Rootkits

In this post we are going to discuss two Volatility plugins that are specific to the ARM platform. Both of these plugins were contributed by Joe Sylve.

The first, linux_check_syscall_arm, enumerates each entry of the system call table to see if it is defined by the debug symbols for the kernel. This ensures that the function pointed to by the entry is valid. If the function is valid, the symbol name is printed, if is not then "HOOKED" is printed to alert the user. This is the same as how the Linux Intel plugin works as well as the Mac system call and trap table plugins.

The linux_check_syscall_arm plugin differs from the Intel version in that it requires an ARM specific method to obtain the size of the system call table. The size of the system call table changes, sometimes drastically, between kernel versions and Linux distributions, so a hardcoded value cannot be used. To gather the size, the vector_swi function is statically disassembled until the compare instruction that checks the requested system call number against the number of system calls is found. Once found, the size is then extracted.  The people brave enough to read ARM disassembly may notice this size is compared to the NR_syscalls variable and wonder why we cannot read this variable directly. Unfortunately, this variable is not available on many kernel versions so we cannot generically rely on it to tell us the size of the table.

Partial output on a clean system can be seen below:

# python vol.py --profile=LinuxEvo4GARM -f ~/rodeo/Evo4GRodeo.lime linux_check_syscall_arm
Volatile Systems Volatility Framework 2.3_beta
     Index Address    Symbol
---------- ---------- ------------------------------
       0x0 0xc0092458 sys_restart_syscall
       0x1 0xc008a038 sys_exit
       0x2 0xc003982c sys_fork_wrapper
       0x3 0xc00f66d8 sys_read
       0x4 0xc00f6488 sys_write
       0x5 0xc00f4314 sys_open
       0x6 0xc00f4038 sys_close



The second plugin, linux_check_evt_arm, verifies the ARM exception vector table, which is very similar in purpose to Intel's interrupt descriptor table (IDT). This plugin works in three phases. It first verifies that the interrupt handling code has not been modified. It then verifies that the vector_swi slot in the table is not hooked (direct system call hooking of the entire table). It finishes by checking for the pointer to system call table within the code and that it has not been hooked. For each valid check, "PASS" is printed, while a failed check will print FAIL and stop processing since the subsequent data cannot be trusted. Sample output of from a clean system can be seen below:

# python vol.py --profile=LinuxEvo4GARM -f ~/rodeo/Evo4GRodeo.lime linux_check_evt_arm
Volatile Systems Volatility Framework 2.3_beta
Check                          PASS/FAIL Info
------------------------------ --------- ------------------------------
SWI Offset Instruction         PASS      Offset: 1048
vector_swi address             PASS      0xC0039180
vector_swi code modification   PASS      E28F8080

Effects of Both Plugins

Combined, the two plugins make it very difficult to hook system call table entries on ARM systems. The EVT checking ensures that an attacker has not replaced the actively used system call table by either modifying the hardware handler arrays or the instructions that reference the system call table itself. Once these checks pass, we know that the system call table defined by the kernel is used, and the check system call table plugin verifies that each entry of this table is what it should be.


In this blog post we have shown new plugins that are able to leverage ARM specific features in order to detect kernel level rootkits. We are also glad that members of the forensics community are contributing back very useful functionality to the project. If you are a researcher who would like to contribute something substantial to the project, consider submitting to our plugin contest, where you can win cash prizes and industry recognition.