Tuesday, May 14, 2013

MoVP II - 1.1 - Mach-O Address Space

One of the major new features of the Volatility 2.3 release is official support for memory dumps from Mac OSX systems. We support over 38 versions of Mac, from 10.5 to 10.8.3 Mountain Lion, both 32- and 64-bit kernels. Over the next month you'll be exposed to over 30 different plugins for analyzing these systems. Today, we'll begin with the Mach-O address space.

Address Spaces

An address space is a layer of abstraction between Volatility plugins and the underlying format or layout of the memory dump. If you've ever wondered how you can write a single plugin (for example to list processes) and automatically it works against Microsoft crash dumps, hibernation files, raw dd-style memory dumps, etc., despite those files all having drastically different formats - that is the work of address spaces. They provide a common and consistent API for finding, reading, and writing data in RAM along with translating addresses between layers. In fact, most of the time, you won't even know address spaces are there - their role is critical, yet often silent.

As we say in our training courses, memory analysis is like a box of chocolates - you never know what you're going to get. If you're not the one acquiring memory, you don't get to choose the tool being used to save the memory dump or the format its saved in. Without a tool like Volatility that provides a framework for interfacing with the various formats that memory dumps are frequently found in, most analysts would be SOL to say the least. If someone hands you a hibernation file and your tool only supports raw memory dumps, what are you going to do? 

Today's MoVP II post introduces the Mach-O Address Space for Volatility. The Mach-O file format is similar to Microsoft's PE format and Linux's ELF format in that its a standard for binaries, but its specific to the Mac/BSD platform. Supporting the Mach-O file format is a major breakthrough in our ability to provide thorough support of Mac memory dumps. One of the most popular tools for acquiring physical memory on Mac systems is ATC-NY's MacMemoryReader. Although the tool can save memory in a raw/padded (-P) and raw/unpadded (-p) format given the proper command-line arguments, the default is Mach-O. Thus in most cases, if someone uses MacMemoryReader to dump memory, you will likely receive a Mach-O file.


Here is an example of the MacMemoryReader program's help menu:

$ ./MacMemoryReader 
ATC-NY Mac Marshal Mac Memory Reader 3.0.2 ($Revision: 1.24 $)
Copyright (c) Architecture Technology Corporation.  All rights reserved.

Usage: ./MacMemoryReader [-g] [-d] [-H hashtype] [-r] [-p] [-P] [-k] 

   -g print progress messages suitable for parsing by a GUI
   -d print verbose debugging information to stderr
   -H compute the given hash on the output data (where hashtype
      is one of MD5, SHA-1, SHA-256, or SHA-512); can be given
      multiple times; hash is printed on stderr
   -r also copy "reserved" areas of memory, such as that used
      by shared-memory graphics adapters; EXPERIMENTAL
   -p dump memory in plain raw DD format instead of Mach-O, then write
      a table of contents to stderr listing file offsets versus
      physical memory offsets
   -P dump memory in plain raw DD format, inserting zeros for un-mapped
      regions in the memory map; no table of contents is needed,
      because file offsets will correspond to physical memory
      offsets, but the resulting file may be much larger than RAM
   -k load the RAM dump kernel extension and set up /dev/mem and
      /dev/pmap, but do not dump memory; for EXPERTS ONLY

   dumps physical memory to  in Mach-O (the default) or
   raw/DD format.  The resulting file may be slightly larger than
   physical memory due to the Mach-O header and alignment constraints.
   If the filename is '-', memory is dumped to stdout.

If you plan to do analysis with Volatility, you must either use the default Mach-O or raw/padded. We do not, and never will, support raw/un-padded.

Please also note you must run MacMemoryReader as root to load the required kernel extension for dumping memory.

File Format

If your Mac memory dump is in the Mach-O format will begin with a mach_header or mach_header_64 structure, as shown below. The magic is MH_MAGIC (0xFEEDFACE) for mach_header and MH_MAGIC_64 (0xFEEDFACF) for mach_header_64.

Note: if you're not familiar with the dt() command or the layout of the data structures shown, see the volshell command.

>>> dt("mach_header_64")
'mach_header_64' (32 bytes)
0x0   : magic                          ['unsigned int']
0x4   : cputype                        ['int']
0x8   : cpusubtype                     ['int']
0xc   : filetype                       ['unsigned int']
0x10  : ncmds                          ['unsigned int']
0x14  : sizeofcmds                     ['unsigned int']
0x18  : flags                          ['unsigned int']
0x1c  : reserved                       ['unsigned int']

Immediately following the header, one or more segment_command or segment_command_64 structures can be found. These describe the memory runs, in particular the virtual address and size of the run and the offset within the file where the data can be found.

>>> dt("segment_command_64")
'segment_command_64' (72 bytes)
0x0   : cmd                            ['unsigned int']
0x4   : cmdsize                        ['unsigned int']
0x8   : segname                        ['array', 16, ['char']]
0x18  : vmaddr                         ['unsigned long long']
0x20  : vmsize                         ['unsigned long long']
0x28  : fileoff                        ['unsigned long long']
0x30  : filesize                       ['unsigned long long']
0x38  : maxprot                        ['int']
0x3c  : initprot                       ['int']
0x40  : nsects                         ['unsigned int']
0x44  : flags                          ['unsigned int']

This is the information Volatility uses when a plugin tries to read a virtual address. First the virtual address is translated to a physical address by the Intel x86 or AMD x64 address space. The result is passed down to the next layer, which would be Mach-O. The Mach-O layer reads the segment_command structures and determines at which offset in the file we can find a physical memory block. Remember, since there are Mach-O specific headers, an offset in physical memory is not the same as an offset in the file. Finally, the lowest address space in the chain (FileAddressSpace) retrieves the requested data from the file.


If you want to view some of the metadata nicely packed into the Mach-O file, you can use the machoinfo plugin.

$ ./vol.py --profile=MacMountainLion_10_8_3_AMDx64 -f mac.dmp machoinfo
Volatile Systems Volatility Framework 2.3_alpha
Magic: 0xfeedfacf
Architecture: 64-bit
File Offset        Memory Offset      Size               Name
------------------ ------------------ ------------------ ----
0x0000000000004000 0x0000000000000000 0x000000000008e000 available
0x0000000000092000 0x0000000000090000 0x0000000000010000 available
0x00000000000a2000 0x0000000000100000 0x000000000f200000 available
0x000000000f2a2000 0x000000000f300000 0x0000000000013000 LoaderData
0x000000000f2b5000 0x000000000f313000 0x00000000000ed000 available
0x000000000f3a2000 0x000000000f400000 0x0000000000535000 LoaderData
0x000000000f8d7000 0x000000000f935000 0x00000000000cb000 available
0x000000000f9a2000 0x000000000fa00000 0x00000000021f2000 LoaderData
0x0000000011b94000 0x0000000011bf2000 0x0000000000053000 RT_data
0x0000000011be7000 0x0000000011c45000 0x0000000000028000 RT_code


If you want thorough support of memory dumps from Mac OSX systems, you must be able to understand and analyze the Mach-O file format, in addition to the traditional raw/dd-style. Don't get caught unprepared, not knowing what to do with a Mach-O file - it wastes valuable time during an investigation. Be ready, know your tools, and solve the questions before everyone else knows where to start looking. 

No comments:

Post a Comment