From dff1c167b2ee33316ab35d59af6db863344970df Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 19 May 2013 13:24:19 +0100 Subject: [PATCH] Fix up Intel support with test cases for 32, PAE and 32e modes. --- test_rig.py | 36 ++++++- volatility/framework/layers/__init__.py | 2 +- volatility/framework/layers/intel.py | 124 +++++++++++++++++------- 3 files changed, 126 insertions(+), 36 deletions(-) diff --git a/test_rig.py b/test_rig.py index 73663e6d8..9a8d4ee10 100644 --- a/test_rig.py +++ b/test_rig.py @@ -47,6 +47,39 @@ def test_memory(): val = ctx.object('ntkrnlmp!TEST_POINTER', 'data', 0) print(hex(val.point1.test1), val.point1.test2) +def intel32(ctx): + base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/xp-laptop-2005-06-25.img') + ctx.memory.add_layer(base) + intel = layers.intel.Intel(ctx, 'intel', 'data', page_map_offset = 0x39000) + x = [0x823c87c0, 0x81fdf020, 0x81f5a3b8, 0x81f8eb10, 0x820e0da0, 0x82199668, 0x81fa5aa0, 0x81fa8650, 0x81faba78, 0x81fa8240, 0x81f8dda0, 0x81f6e7e8, 0x81f9a670, 0x81f5f020, 0x8202bda0, 0x82113c48, 0x81f67500, 0x81f6ca90, 0x820dd588, 0x82025608, 0x81faf280, 0x821125d0, 0x82076558, 0x81f68518, 0x82059da0, 0x81f6db28, 0x82021a78, 0x81f48da0, 0x820238e0, 0x82081da0, 0x821ca3d0, 0x821ce4d8, 0x821d4da0, 0x81343790, 0xffab8020, 0x8205eda0, 0xffaa0c10, 0x82218020, 0x814b13b0, 0x81ed76b0, 0x81f269e0, 0xffadc9d0, 0x821fb3b8, 0x82079c18, 0x82000980, 0x822148f0, 0x81ed84e8] + return intel, x + +def intelpae(ctx): + base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/private/jon-fres.dmp') + ctx.memory.add_layer(base) + intel = layers.intel.IntelPAE(ctx, 'intel', 'data', page_map_offset = 0x319000) + x = [0x81bcc830, 0x81989940, 0x81915020, 0x8192ad18, 0x818fa7b8, 0x818f6da0, 0x818d1020, 0x818b2878, 0x8189f180, 0x8188db58, 0x81884a40, 0x818766b0, 0x8185a948, 0x8183ad70, 0x81826020, 0x818a64c8, 0x81818020, 0x81800020, 0x817ff460, 0x817eb020, 0x817e9020, 0x817a62a8, 0x817a4b28, 0x81865020, 0x817972c0] + return intel, x + +def intel32e(ctx): + base = layers.physical.FileLayer(ctx, 'data', filename = '/home/mike/memory/private/ikelos-winxpsp2-x64.dmp') + ctx.memory.add_layer(base) + intel = layers.intel.Intel32e(ctx, 'intel', 'data', page_map_offset = 0x3c3000) + x = [0xfffffadffa517c20, 0xfffffadffa2c9510, 0xfffffadffb16a660, 0xfffffadff9d77c20, 0xfffffadffb0fe040, 0xfffffadffb0f2040, 0xfffffadffb0c2040, 0xfffffadffb0b7c20, 0xfffffadffb087c20, 0xfffffadffb06a760, 0xfffffadffb039c20, 0xfffffadffb02c040, 0xfffffadffafe9c20, 0xfffffadffafa7040, 0xfffffadffaf2e040, 0xfffffadffaf279a0, 0xfffffadffaf24600, 0xfffffadffaed3040, 0xfffffadffaecf040, 0xfffffadffaeb35a0, 0xfffffadffae747b0, 0xfffffadffae30040, 0xfffffadffae2b040, 0xfffffadffae1d8b0, 0xfffffadffae1a040, 0xfffffadffae34810] + return intel, x + + +def test_translation(): + nativelst = native.x86NativeTable + ctx = framework.Context(nativelst) + intel, x = intel32e(ctx) + + for val in x: + print(hex(val), hex(intel.translate(val))) + #print(bin(0x39000), bin(0xffab8020)) + #print(hex(intel.translate(0xffab8020))) + + # TODO: # # Config system @@ -61,7 +94,8 @@ if __name__ == '__main__': # print(timeit.Timer(main).timeit(10)) try: # test_symbols() - test_memory() + # test_memory() + test_translation() except Exception as e: print(repr(e)) pdb.post_mortem() diff --git a/volatility/framework/layers/__init__.py b/volatility/framework/layers/__init__.py index 7522ecea7..1ae76394f 100644 --- a/volatility/framework/layers/__init__.py +++ b/volatility/framework/layers/__init__.py @@ -5,7 +5,7 @@ Created on 4 May 2013 ''' from volatility.framework import validity, interfaces, exceptions -from volatility.framework.layers import physical +from volatility.framework.layers import physical, intel class Memory(validity.ValidityRoutines): """Container for multiple layers of data""" diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index e6474debc..dc4a5a694 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -4,55 +4,111 @@ Created on 7 May 2013 @author: mike ''' +import math import struct -from volatility.framework import interfaces +from volatility.framework import interfaces, exceptions class Intel(interfaces.layers.TranslationLayerInterface): """Translation Layer for the Intel IA32 memory mapping""" def __init__(self, context, name, memory_layer, pagefile_layer = None, page_map_offset = None): interfaces.layers.TranslationLayerInterface.__init__(self, context, name) - self._basename = memory_layer + self._base_layer = memory_layer self._pagefile = pagefile_layer - - # AMD64 - #self._structure = [('pml4', 51, 40, None, 47, 9, 11, None, None, None), - # ('pdpt', 51, 40, None, 38, 9, 11, None, None, None), - # ('pd', 51, 40, None, 29, 9, 11, None, None, None), - # ('pt', 51, 40, None, 20, 9, 11, None, None, None)] - self._structure = [('pd', 31, 20, None, 31, 10, 11, None, None, None), - ('pt', 31, 20, None, 21, 10, 11, None, None, None), - ('p', 31, 20, None, 11, 10, 11, None, None, None) ] - self._page_map_offset = page_map_offset + # All Intel address spaces work on 4096 byte pages + self._page_size_in_bits = 12 + + # These can vary depending on the type of space + self._entry_format = "> (position + 1) + + # Grab the first chunk of the entry we should be using + base_address = self._mask(entry, self._maxphyaddr - 1, size + self._index_shift) + # Create the offset for the next entry + table_offset = base_address | (index << self._index_shift) + # Read out the new entry from memory + entry, = struct.unpack(self._entry_format, self._context.memory.read(self._base_layer, table_offset, struct.calcsize(self._entry_format))) + + # Now we're do + if not self._page_is_valid(entry): + raise exceptions.InvalidAddressException("Page Fault at entry " + hex(entry) + " in page entry") + page = self._mask(entry, self._maxphyaddr - 1, position + 1) | self._mask(offset, position, 0) + return page, 1 << position def translate(self, offset): """Translates a specific offset based on the paging tables""" - entry = self._page_map_offset - for (name, entry_start, entry_len, entry_map, offset_start, offset_len, offset_map, page_start, page_len, page_map) in self._structure: - # Check page is present - # Check for large pages - if page_start is not None and (entry & (0x1 << 7)): - return self._entry(entry, offset, entry_start, entry_len, entry_map, page_start, page_len, page_map) - index = self._entry(entry, offset, entry_start, entry_len, entry_map, offset_start, offset_len, offset_map) - # print(name, "index", hex(index)) - entry = struct.unpack("> (value_start - value_length + 1)) << (value_map - value_length + 1) - return (value & value_mask) + # These can vary depending on the type of space + self._maxphyaddr = 36 + self._bits_per_register = 32 + self._entry_format = "