Thursday, May 30, 2013

MoVP II - 3.2 - Linux/Android Memory Forensics with Python and Yara

In this post we will describe the Linux volshell and yarascan plugins. In previous releases of Volatility, these plugins only supported Windows samples, but starting with 2.3 you can interactively explore your Linux memory dumps (from a Python shell) or scan process and kernel memory with Yara signatures. The plugins also work against Android memory dumps.

Linux Volshell 

To get the process started, simply run the "linux_volshell" plugin with no arguments.

# python vol.py --profile=LinuxMandriva2011x64 -f ~/mandriva.lime linux_volshell
Volatile Systems Volatility Framework 2.3_beta
Current context: process systemd, pid=1 DTB=0x106a3000
Welcome to volshell! Current memory image is:
file:///root/mandriva.lime
To get help, type 'hh()'
>>>


This drops you into a Python shell. At this point you have full access to the Volatility namespace as well as all of Python. If you type hh() you are given a help menu which displays the volshell-specific plugins:

>>> hh()
Use self.addrspace for Kernel/Virtual AS
Use self.addrspace.base for Physical AS
Use self.proc to get the current _EPROCESS object
  and self.proc.get_process_address_space() for the current process AS
  and self.proc.get_load_modules() for the current process DLLs

cc(offset=None, pid=None, name=None)     : Change current shell context.
db(address, length=128, space=None)      : Print bytes as canonical hexdump.
dd(address, length=128, space=None)      : Print dwords at address.
dis(address, length=128, space=None, mode=None) : Disassemble code at a given address.
dq(address, length=128, space=None)      : Print qwords at address.
dt(objct, address=None, space=None)      : Describe an object or show type info.
hh(cmd=None)                             : Get help on a command.
list_entry(head, objname, offset=-1, fieldname=None, forward=True) : Traverse a _LIST_ENTRY.
modules()                                : Print a module listing.
ps()                                     : Print a process listing.
sc()                                     : Show the current context.

For help on a specific command, type 'hh(<command>)'


When you first enter volshell you are in the context of PID 1 which is generally init or "systemd", the process which spawns all other processes. At this point, self.proc is instanitated to the task struct for this process:

>>> self.proc
[task_struct task_struct] @ 0xFFFF8800159B8000
>>> self.proc.pid
 [int]: 1

>>> str(self.proc.comm)
'systemd'


if we want to change to another process, we must use the cc() command:

>>> cc(pid=7326)
Current context: process insmod, pid=7326 DTB=0x176a4000
>>> self.proc.pid, str(self.proc.comm)
( [int]: 7326, 'insmod')


If we want to read from the address space of a process, we can use the db, dd, and dq commands:

>>> db(self.proc.comm.obj_offset)
0xffff880001cac848  69 6e 73 6d 6f 64 00 00 00 00 00 00 00 00 00 00   insmod..........
0xffff880001cac858  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xffff880001cac868  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xffff880001cac878  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xffff880001cac888  00 40 2f 11 00 88 ff ff 38 38 2f 11 00 88 ff ff   .@/.....88/.....
0xffff880001cac898  e8 a5 ab c1 ff 7f 00 00 00 00 00 00 00 00 00 00   ................
0xffff880001cac8a8  00 57 f6 ba 5a 7f 00 00 00 00 00 00 00 00 00 00   .W..Z...........
0xffff880001cac8b8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
>>> dd(self.proc.comm.obj_offset)
ffff880001cac848  6d736e69 0000646f 00000000 00000000
ffff880001cac858  00000000 00000000 00000000 00000000
ffff880001cac868  00000000 00000000 00000000 00000000
ffff880001cac878  00000000 00000000 00000000 00000000
ffff880001cac888  112f4000 ffff8800 112f3838 ffff8800
ffff880001cac898  c1aba5e8 00007fff 00000000 00000000
ffff880001cac8a8  baf65700 00007f5a 00000000 00000000
ffff880001cac8b8  00000000 00000000 00000000 00000000
>>> dq(self.proc.comm.obj_offset)
0xffff880001cac848 0x646f6d736e69
0xffff880001cac850 0x0
0xffff880001cac858 0x0
0xffff880001cac860 0x0
0xffff880001cac868 0x0
0xffff880001cac870 0x0
0xffff880001cac878 0x0
0xffff880001cac880 0x0
0xffff880001cac888 0xffff8800112f4000
0xffff880001cac890 0xffff8800112f3838
0xffff880001cac898 0x7fffc1aba5e8
0xffff880001cac8a0 0x0
0xffff880001cac8a8 0x7f5abaf65700
0xffff880001cac8b0 0x0
0xffff880001cac8b8 0x0
0xffff880001cac8c0 0x0


 We can also use the read() function of the address space to read arbitrary addresses and lengths. In this example we are reading the command line arguments to the insmod process:

>>> dq(self.proc.mm.arg_start, length=8)
0x7fffc1abb055 0x6c00646f6d736e69
>>> self.proc.get_process_address_space().read(0x7fffc1abb055, 79)
'insmod\x00lime-2.6.38.7-desktop-1mnb2.ko\x00path=/home/mhl/mandriva.lime format=lime\x00'


Volatility also provides conveniences functions, such as ps() and modules():

>>> ps()
Name             PID    Offset
systemd          1      0xffff8800159b8000
kthreadd         2      0xffff8800159b96b0
ksoftirqd/0      3      0xffff8800159bad60
kworker/u:0      5      0xffff8800159bdac0
migration/0      6      0xffff8800159e8000
cpuset           7      0xffff8800159e96b0
khelper          8      0xffff8800159ead60
netns            9      0xffff8800159ec410

[snip]
>>> modules()
lime                     8734
fuse                     71414
af_packet                21188
joydev                   10468
rfcomm                   67790
nfs                      310764
lockd                    79366
fscache                  61155
nfs_acl                  2725
auth_rpcgss              43775
sunrpc                   224700
sco                      17185

[snip]

For users wishing to explore data structures and potentially write their own plugins, the dt() command is very helpful. It can display data structures based on the current profile and also list the values of a particular instance.

>>> ps()
<snip>
insmod           7326   0xffff880001cac410
>>> dt("mm_struct")
'mm_struct' (864 bytes)
0x0   : mmap                           ['pointer', ['vm_area_struct']]
0x8   : mm_rb                          ['rb_root']

<snip>
0x120 : arg_start                      ['unsigned long']
0x128 : arg_end                        ['unsigned long']
0x130 : env_start                      ['unsigned long']
0x138 : env_end                        ['unsigned long'] >>> ts = obj.Object("task_struct", offset = 0xffff880001cac410, vm = self.addrspace)
>>> dt("mm_struct", ts.mm)

[CType mm_struct] @ 0xFFFF880010763B80
0x0   : mmap                           18446612132338969288
0x8   : mm_rb                          18446612132590402440
<snip>
0x120 : arg_start                      140736442642517
0x128 : arg_end                        140736442642596
0x130 : env_start                      140736442642596
0x138 : env_end                        140736442646507


Linux Yarascan

The yarascan plugin allows for searching of physical memory, the kernel AS, or the AS of any process for everything from simple strings to complex yara rules.

If we search for insmod inside of its parent bash process, we find many copies of the invocation used to capture the memory dump and whose command line arguments we previously looked at in volshell:

# python vol.py --profile=LinuxMandriva2011x64 -f ~/mandriva.lime linux_yarascan -Y insmod -p 7284
Volatile Systems Volatility Framework 2.3_beta
Task: bash pid 7284 rule r1 addr 0x10eded0
0x010eded0  69 6e 73 6d 6f 64 20 6c 69 6d 65 2d 32 2e 36 2e   insmod.lime-2.6.
0x010edee0  33 38 2e 37 2d 64 65 73 6b 74 6f 70 2d 31 6d 6e   38.7-desktop-1mn
0x010edef0  62 32 2e 6b 6f 20 22 70 61 74 68 3d 2f 68 6f 6d   b2.ko."path=/hom
0x010edf00  65 2f 6d 68 6c 2f 6d 61 6e 64 72 69 76 61 2e 6c   e/mhl/mandriva.l


Additionally, if we search the firefox process for "http://", we find many references to LiME, which was the tool downloaded to capture memory:

# python vol.py --profile=LinuxMandriva2011x64 -f ~/mandriva.lime linux_yarascan -p 6977 -Y "http://"
Task: firefox-bin pid 6977 rule r1 addr 0x7f1824b72bfc
0x7f1824b72bfc  68 74 74 70 3a 2f 2f 6c 69 6d 65 2d 66 6f 72 65   http://lime-fore
0x7f1824b72c0c  6e 73 69 63 73 2e 67 6f 6f 67 6c 65 63 6f 64 65   nsics.googlecode
0x7f1824b72c1c  2e 63 6f 6d 2f 66 69 6c 65 73 2f 6c 69 6d 65 2d   .com/files/lime-
0x7f1824b72c2c  66 6f 72 65 6e 73 69 63 73 2d 31 2e 31 2d 72 31   forensics-1.1-r1


Conclusion

Hopefully you have enjoyed and learned from this post and can use it to enhance your own Linux investigations. In tomorrow's blog post we will learn about scanning for bash history in memory and how to recover such records along with their timestamps. If you have any questions or comments please leave a reply below or you can find us on Twitter - @volatility.

No comments:

Post a Comment