Fix up Intel support with test cases for 32, PAE and 32e modes.

This commit is contained in:
Mike Auty
2013-05-19 13:24:19 +01:00
parent 05d2789b5b
commit dff1c167b2
3 changed files with 126 additions and 36 deletions
+35 -1
View File
@@ -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()
+1 -1
View File
@@ -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"""
+90 -34
View File
@@ -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 = "<I"
self._maxphyaddr = 32
self._bits_per_register = 32
self._index_shift = int(math.log(struct.calcsize(self._entry_format), 2))
self._structure = [('page directory', 10, False),
('page table', 10, True)]
def _mask(self, value, high_bit, low_bit):
"""Returns the bits of a value between highbit and lowbit inclusive"""
high_mask = (2 ** (high_bit + 1)) - 1
low_mask = (2 ** (low_bit)) - 1
mask = (high_mask ^ low_mask)
# print(high_bit, low_bit, bin(mask), bin(value))
return value & mask
def _page_is_valid(self, entry):
"""Returns whether a particular page is valid based on its entry"""
return (entry & 1)
def _translate(self, offset):
"""Translates a specific offset based on paging tables
Returns the offset and the pagesize
"""
# Setup the entry and how far we are through the offset
# Position maintains the number of bits left to process
# We or with 0x1 to ensure our page_map_offset is always valid
entry = self._mask(self._page_map_offset, self._bits_per_register - 1, 0) | 0x1
position = min(self._maxphyaddr, self._bits_per_register) - 1
# Run through the offset in various chunks
for (name, size, large_page) in self._structure:
# Check we're valid
if not self._page_is_valid(entry):
raise exceptions.InvalidAddressException("Page Fault at entry " + hex(entry) + " in table " + name)
# Check if we're a large page
if large_page and (entry & (1 << 7)):
# We're a large page, the rest is finished below
break
# Figure out how much of the offset we should be using
start = position
position -= size
index = self._mask(offset, start, position + 1) >> (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("<I", self._context.memory[self._basename].read(index, 4))[0]
# print(name, "entry", hex(entry))
return index
result, _ = self._translate(offset)
return result
def _entry(self, entry, offset, entry_start, entry_length, entry_map, offset_start, offset_length, offset_map):
"""Returns the entry to the next lookup table from the previous entry and the offset"""
return (self._map_and_mask(entry, entry_start, entry_length, entry_map) |
self._map_and_mask(offset, offset_start, offset_length, offset_map))
class IntelPAE(Intel):
"""Class for handling Physical Address Extensions for Intel architectures"""
def _map_and_mask(self, value, value_start, value_length, value_map = None):
"""Returns the value starting at value_start bits, for value_length bits, and mapped to start at value_map bits"""
value_map = value_map or value_start
value_mask = ((1 << value_length) - 1) << (value_map - value_length + 1)
def __init__(self, *args, **kwargs):
Intel.__init__(self, *args, **kwargs)
# Shift the offset around
value = (value >> (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 = "<Q"
self._index_shift = int(math.log(struct.calcsize(self._entry_format), 2))
self._structure = [('page directory pointer', 2, False),
('page directory', 9, True),
('page table', 9, True)]
class Intel32e(Intel):
def __init__(self, *args, **kwargs):
Intel.__init__(self, *args, **kwargs)
# These can vary depending on the type of space
self._maxphyaddr = 48
self._bits_per_register = 64
self._entry_format = "<Q"
self._index_shift = int(math.log(struct.calcsize(self._entry_format), 2))
self._structure = [('page map layer 4', 9, False),
('page directory pointer', 9, True),
('page directory', 9, True),
('page table', 9, True)]