Hacking

Obtaining information from dumping memory

Dejan Lukan
June 20, 2014 by
Dejan Lukan

In this article, I'll present whether it's possible to get access to passwords lying around in memory by using a fully patched Linux x64 operating system. First, it's not superfluous to emphasize that the distribution of the Linux operating system doesn't matter, since the system is managing memory similarly with minor differences, which are not important for the purpose of this article: most often the memory is managed by following the same principle on multiple distributions.

FREE role-guided training plans

FREE role-guided training plans

Get 12 cybersecurity training plans — one for each of the most common roles requested by employers.

Let's put ourselves into the shoes of an attacker, where we've already gained access to the system by exploiting an existing vulnerability or by using a social engineering attack to lure the victim into visiting our web page. Social engineering is the easiest way to get the keys to the castle, but an attacker can just as well exploit a vulnerability in an arbitrary application like OpenOffice, Pidgin, Chrome, Firefox, etc. At this point, we're already in the system, and the details of how we've gained access to the system are not important. Let's also suppose that we've been able to escalate privileges by exploiting a well known vulnerability in the Linux kernel to gain administrative privileges. After we've done so, nothing is stopping us from changing the system however we want: we can install a backdoor into the system and the victim wouldn't even know it. If we don't want to change the files on the filesystem or leave anything else for the forensics examiner, we have to be very stealth when exploiting the system.

Dumping memory

There are various tools that we can use to dump memory under the Linux operating system, some of which are presented below. At the very basic level, we can divide the tools between those that dump a memory of just one process or the whole system.

  • Tools for Dumping Memory of a Single Process: the Process Dumper [1] program can be used to dump memory of single processes. It dumps memory of a running process where all data and code sections are dumped. The memory dump is outputted to stdout, so we need to use the program together with other tools like netcat, tar, etc.

# http://www.trapkit.de/research/forensic/pd/pd_v1.1_lnx.bz2

# bunzip2 pd_v1.1_lnx.bz2

# ./pd_v1.1_lnx

  • Tools for Dumping Memory of a Whole System: LiME (Linux Memory Extractor) [2]: can be used to dump memory of a whole Linux system. To install LiME, we have to execute the following commands:

# svn checkout http://lime-forensics.googlecode.com/svn/trunk/ lime

# cd lime/src/

# make

When LiME is being compiled, a kernel .ko module is created, which needs to be inserted into the kernel by using insmod command. The memory dump can be saved to the filesystem or sent over the network. When inserting a module into the kernel, we can pass a number of parameters to insmod command, which are presented below:

  • path: a filename on local filesystem where the memory dump will be written or a tcp:<port>.
  • format: LiME can output the memory dump in various formats, like raw, padded and lime. A raw format concatenates all system RAM into an image. A padded format pads non-system RAM with zeros and starts from physical address 0x0. A lime format appends an special header to each memory range to describe the address space information – also the Volatility program supports parsing this format, which is also the reason we'll use it in this article.
  • dio: when this parameter is set to 1 (the default), the Direct IO will be used, while the value of 0 disables it.

Now that we've described all three parameters that can be passed to lime.ko kernel module, we can issue the command as root to obtain the system's memory. The command presented below will acquire whole system's memory and save it into the /tmp/memdump.lime file by using lime format. Note that the process can take a while if you have large amount of physical memory available in the system; also note that there should be enough disk space to save the entire contents of physical memory to disk.

[plain]

# insmod lime.ko "path=/tmp/memdump.lime format=lime"

[/plain]

In Qemu we can dump memory of a running virtual machine by using the pmemsave command as follows. Note that the windows7.dump memory dump will be stored to the current directory if relative path is used. If we want to save the memory dump to an arbitrary location, we can enclose the whole path of the memory image in double quotation marks.

[plain]

(qemu) pmemsave 0 0x3FFFFFFF windows7.dump

[/plain]

Note that as long as the memory dumping is in progress, the virtual machine will be paused and we won't be able to interact with it. In the command above, the start address is 0x0 to start dumping memory at the beginning and its size is 0x3FFFFFFF, which will dump 1GB of memory. If we go to system settings, we can see that the system has only 1GB of memory available, so we shouldn't dump 4GB if it only has 1GB of memory.

Creating a profile in source distributions

Once the memory has been dumped, we have to analyze it in order to obtain useful information. Prior to doing that with Volatility, we have to create a profile, which contains kernel data structures and debug symbols that Volatility uses to locate critical information inside the memory dump [3]. It's imperative that the profile is created on the same machine as we would like to analyze, since kernel data structure and debug symbols are specific to Linux distribution and kernel used. If we're running a binary Linux distribution, it's likely that some user has already created a profile and shared it with the rest of the world – in such cases we can use his profile to do our analysis. But if we're running a source Linux distribution, we need to create the profile for ourselves. Each Linux profile depends upon three important factors:

  • Linux distribution
  • Kernel version
  • CPU architecture

To build a profile, we must first download volatility source code from here and install it normally with make / make install. After successful installation, we need to enter the tools/linux/ directory in the Volatility source directory and issue a make command to create the required kernel's data structures. By doing that, the Makefile will instruct the make command to compile module.c against the currently used Linux kernel, which we want to analyze. By doing that, a special file module.dwarf will be created.

The next step is getting the kernel symbols of the current kernel, which can be found in /boot/ directory for most binary Linux distributions. In source code distributions, the System.map can be found in the /usr/src/linux/ directory.

When creating a profile, we have to archive the module.dwarf as well as System.map into a .zip file and move the .zip file under plugins/overlays/linux/ directory.

[plain]

# cd volatility-2.3.1/volatility/plugins/overlays/linux/

# cp ../../../../tools/linux/module.dwarf .

# cp /usr/src/linux/System.map .

# zip Gentoo.zip System.map module.dwarf

[/plain]

To see whether the profile has been successfully created, we need to execute the vol.py command with the --info parameter and check if the Gentoo profile is presented in the output. In the output below, we can see that we've successfully added the Gentoo profile to Volatility.

[plain]

# ./vol.py --info | grep Linux

Volatility Foundation Volatility Framework 2.3.1

LinuxGentoox64 - A Profile for Linux Gentoo x64

linux_banner - Prints the Linux banner information

linux_yarascan - A shell in the Linux memory image

[/plain]

After that we can run Volatility normally with the following command, which will print all the supported commands that we can use when analyzing the memory dump of the Linux system.

[plain]

# ./vol.py -f memdump.lime --profile=LinuxGentoox64 -h

Supported Plugin Commands:

linux_arp Print the ARP table

linux_banner Prints the Linux banner information

linux_bash Recover bash history from bash process memory

linux_check_afinfo Verifies the operation function pointers of network protocols

linux_check_creds Checks if any processes are sharing credential structures

linux_check_fop Check file operation structures for rootkit modifications

linux_check_idt Checks if the IDT has been altered

linux_check_modules Compares module list to sysfs info, if available

linux_check_syscall Checks if the system call table has been altered

linux_check_tty Checks tty devices for hooks

linux_cpuinfo Prints info about each active processor

linux_dentry_cache Gather files from the dentry cache

linux_dmesg Gather dmesg buffer

linux_dump_map Writes selected memory mappings to disk

linux_find_file Recovers tmpfs filesystems from memory

linux_ifconfig Gathers active interfaces

linux_iomem Provides output similar to /proc/iomem

linux_keyboard_notifier Parses the keyboard notifier call chain

linux_lsmod Gather loaded kernel modules

linux_lsof Lists open files

linux_memmap Dumps the memory map for linux tasks

linux_moddump Extract loaded kernel modules

linux_mount Gather mounted fs/devices

linux_mount_cache Gather mounted fs/devices from kmem_cache

linux_netstat Lists open sockets

linux_pidhashtable Enumerates processes through the PID hash table

linux_pkt_queues Writes per-process packet queues out to disk

linux_proc_maps Gathers process maps for linux

linux_psaux Gathers processes along with full command line and start time

linux_pslist Gather active tasks by walking the task_struct->task list

linux_pslist_cache Gather tasks from the kmem_cache

linux_pstree Shows the parent/child relationship between processes

linux_psxview Find hidden processes with various process listings

linux_route_cache Recovers the routing cache from memory

linux_sk_buff_cache Recovers packets from the sk_buff kmem_cache

linux_slabinfo Mimics /proc/slabinfo on a running machine

linux_tmpfs Recovers tmpfs filesystems from memory

linux_vma_cache Gather VMAs from the vm_area_struct cache

linux_volshell Shell in the memory image

linux_yarascan A shell in the Linux memory image

mbrparser Scans for and parses potential Master Boot Records (MBRs)

patcher Patches memory based on page scans

[/plain]

Since I was running a newer version of the Gentoo kernel than was officially supported, I wasn't able to analyze the memory of Gentoo Linux. The supported Linux kernel versions are 2.6.11 – 3.5.x. If you have a kernel which falls in the range above, then Volatility is most probable to work just fine.

Analyzing memory

In this part of the article, we'll analyze the memory dump of a Qemu Windows 7 system. To dump all available profiles we can use with the acquired image, we can use the --info parameter, which will display all available profiles as well as a lot of other information.

[plain]

# ./vol.py --info

Volatility Foundation Volatility Framework 2.3.1

Profiles

--------

LinuxGentoox64 - A Profile for Linux Gentoo x64

VistaSP0x64 - A Profile for Windows Vista SP0 x64

VistaSP0x86 - A Profile for Windows Vista SP0 x86

VistaSP1x64 - A Profile for Windows Vista SP1 x64

VistaSP1x86 - A Profile for Windows Vista SP1 x86

VistaSP2x64 - A Profile for Windows Vista SP2 x64

VistaSP2x86 - A Profile for Windows Vista SP2 x86

Win2003SP0x86 - A Profile for Windows 2003 SP0 x86

Win2003SP1x64 - A Profile for Windows 2003 SP1 x64

Win2003SP1x86 - A Profile for Windows 2003 SP1 x86

Win2003SP2x64 - A Profile for Windows 2003 SP2 x64

Win2003SP2x86 - A Profile for Windows 2003 SP2 x86

Win2008R2SP0x64 - A Profile for Windows 2008 R2 SP0 x64

Win2008R2SP1x64 - A Profile for Windows 2008 R2 SP1 x64

Win2008SP1x64 - A Profile for Windows 2008 SP1 x64

Win2008SP1x86 - A Profile for Windows 2008 SP1 x86

Win2008SP2x64 - A Profile for Windows 2008 SP2 x64

Win2008SP2x86 - A Profile for Windows 2008 SP2 x86

Win7SP0x64 - A Profile for Windows 7 SP0 x64

Win7SP0x86 - A Profile for Windows 7 SP0 x86

Win7SP1x64 - A Profile for Windows 7 SP1 x64

Win7SP1x86 - A Profile for Windows 7 SP1 x86

WinXPSP1x64 - A Profile for Windows XP SP1 x64

WinXPSP2x64 - A Profile for Windows XP SP2 x64

WinXPSP2x86 - A Profile for Windows XP SP2 x86

WinXPSP3x86 - A Profile for Windows XP SP3 x86

[/plain]

Since we're running Windows 7 SP1, we should use the Win7SP1x86 as the profile. To print all supported commands we can use with the memory dump, we can pass the -h as a parameter after we've already specified the memory image dump and profile.

[plain]

./vol.py -f windows7.dump –profile=Win7SP1x86

Supported Plugin Commands:

apihooks Detect API hooks in process and kernel memory

atoms Print session and window station atom tables

atomscan Pool scanner for _RTL_ATOM_TABLE

bioskbd Reads the keyboard buffer from Real Mode memory

callbacks Print system-wide notification routines

clipboard Extract the contents of the windows clipboard

cmdscan Extract command history by scanning for _COMMAND_HISTORY

consoles Extract command history by scanning for _CONSOLE_INFORMATION

crashinfo Dump crash-dump information

deskscan Poolscaner for tagDESKTOP (desktops)

devicetree Show device tree

dlldump Dump DLLs from a process address space

dlllist Print list of loaded dlls for each process

driverirp Driver IRP hook detection

driverscan Scan for driver objects _DRIVER_OBJECT

dumpcerts Dump RSA private and public SSL keys

dumpfiles Extract memory mapped and cached files

envars Display process environment variables

eventhooks Print details on windows event hooks

filescan Scan Physical memory for _FILE_OBJECT pool allocations

gahti Dump the USER handle type information

gditimers Print installed GDI timers and callbacks

gdt Display Global Descriptor Table

getservicesids Get the names of services in the Registry and return Calculated SID

getsids Print the SIDs owning each process

handles Print list of open handles for each process

hashdump Dumps passwords hashes (LM/NTLM) from memory

hibinfo Dump hibernation file information

hivedump Prints out a hive

hivelist Print list of registry hives.

hivescan Scan Physical memory for _CMHIVE objects (registry hives)

hpakextract Extract physical memory from an HPAK file

hpakinfo Info on an HPAK file

idt Display Interrupt Descriptor Table

iehistory Reconstruct Internet Explorer cache / history

imagecopy Copies a physical address space out as a raw DD image

imageinfo Identify information for the image

impscan Scan for calls to imported functions

kdbgscan Search for and dump potential KDBG values

kpcrscan Search for and dump potential KPCR values

ldrmodules Detect unlinked DLLs

lsadump Dump (decrypted) LSA secrets from the registry

machoinfo Dump Mach-O file format information

malfind Find hidden and injected code

mbrparser Scans for and parses potential Master Boot Records (MBRs)

memdump Dump the addressable memory for a process

memmap Print the memory map

messagehooks List desktop and thread window message hooks

mftparser Scans for and parses potential MFT entries

moddump Dump a kernel driver to an executable file sample

modscan Scan Physical memory for _LDR_DATA_TABLE_ENTRY objects

modules Print list of loaded modules

mutantscan Scan for mutant objects _KMUTANT

netscan Scan a Vista, 2008 or Windows 7 image for connections and sockets

patcher Patches memory based on page scans

printkey Print a registry key, and its subkeys and values

privs Display process privileges

procexedump Dump a process to an executable file sample

procmemdump Dump a process to an executable memory sample

pslist Print all running processes by following the EPROCESS lists

psscan Scan Physical memory for _EPROCESS pool allocations

pstree Print process list as a tree

psxview Find hidden processes with various process listings

raw2dmp Converts a physical memory sample to a windbg crash dump

screenshot Save a pseudo-screenshot based on GDI windows

sessions List details on _MM_SESSION_SPACE (user logon sessions)

shellbags Prints ShellBags info

shimcache Parses the Application Compatibility Shim Cache registry key

ssdt Display SSDT entries

strings Match physical offsets to virtual addresses (may take a while, VERY verbose)

svcscan Scan for Windows services

symlinkscan Scan for symbolic link objects

thrdscan Scan physical memory for _ETHREAD objects

threads Investigate _ETHREAD and _KTHREADs

timeliner Creates a timeline from various artifacts in memory

timers Print kernel timers and associated module DPCs

unloadedmodules Print list of unloaded modules

userassist Print userassist registry keys and information

userhandles Dump the USER handle tables

vaddump Dumps out the vad sections to a file

vadinfo Dump the VAD info

vadtree Walk the VAD tree and display in tree format

vadwalk Walk the VAD tree

vboxinfo Dump virtualbox information

vmwareinfo Dump VMware VMSS/VMSN information

volshell Shell in the memory image

windows Print Desktop Windows (verbose details)

wintree Print Z-Order Desktop Windows Tree

wndscan Pool scanner for tagWINDOWSTATION (window stations)

yarascan Scan process or kernel memory with Yara signatures

[/plain]

Note that there are a lot of commands we can use to analyze the system memory. First we can list active processes by using the pslist command:

[plain]

# ./vol.py -f windows7.dump --profile=Win7SP1x86 pslist

[/plain]

After that we can use any number of commands to gather the information that we need.

Conclusion

In this article we've presented how we can dump memory of a Linux system and create our own profile that can be used together with Volatility to analyze memory. We've also dumped memory of a Qemu virtual machine and printed its processes. At such point, we can start looking for interesting information like passwords and certificates that security-unaware applications may have left in memory for an attacker to obtain.

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.

Sources

Dejan Lukan
Dejan Lukan

Dejan Lukan is a security researcher for InfoSec Institute and penetration tester from Slovenia. He is very interested in finding new bugs in real world software products with source code analysis, fuzzing and reverse engineering. He also has a great passion for developing his own simple scripts for security related problems and learning about new hacking techniques. He knows a great deal about programming languages, as he can write in couple of dozen of them. His passion is also Antivirus bypassing techniques, malware research and operating systems, mainly Linux, Windows and BSD. He also has his own blog available here: http://www.proteansec.com/.