Hacking

Obtaining information from dumping memory

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.

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.

Sources

Posted: June 20, 2014
Dejan Lukan
View Profile

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/.