mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-30 19:59:46 +02:00
Windows Crash Layer
This commit is contained in:
@@ -23,7 +23,7 @@ except ImportError:
|
||||
|
||||
from volatility import framework
|
||||
from volatility.framework import constants, validity
|
||||
from volatility.framework.layers import intel, lime, physical, segmented, vmware
|
||||
from volatility.framework.layers import intel, lime, physical, segmented, vmware, crash
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# Volatility
|
||||
# Copyright (C) 2018 Volatility Foundation
|
||||
#
|
||||
# Authors:
|
||||
# awalters@4tphi.net (AAron Walters)
|
||||
#
|
||||
# This file is part of Volatility 3.
|
||||
|
||||
import struct
|
||||
import typing
|
||||
import os.path as os_path
|
||||
|
||||
from volatility.framework import constants, exceptions, interfaces, validity
|
||||
from volatility.framework.layers import segmented
|
||||
from volatility.framework.symbols import intermed
|
||||
|
||||
class WindowsCrashDump32FormatException(exceptions.LayerException):
|
||||
"""Thrown when an error occurs with the underlying Crash file format"""
|
||||
|
||||
class WindowsCrashDump32Layer(segmented.SegmentedLayer):
|
||||
"""A Windows crash format TranslationLayer. This TranslationLayer supports
|
||||
Microsoft complete memory dump files. It currently does not support
|
||||
kernel or small memory dump files."""
|
||||
|
||||
provides = {"type": "physical"}
|
||||
priority = 23
|
||||
|
||||
SIGNATURE = 0x45474150
|
||||
VALIDDUMP = 0x504d5544
|
||||
_magic_struct = struct.Struct('<II')
|
||||
headerpages = 1
|
||||
|
||||
def __init__(self,
|
||||
context: interfaces.context.ContextInterface,
|
||||
config_path: str,
|
||||
name: str) -> None:
|
||||
|
||||
# Construct these so we can use self.config
|
||||
self._context = context
|
||||
self._config_path = config_path
|
||||
self._page_size = 0x1000
|
||||
#self._base_layer, self._meta_layer = self.config["base_layer"], self.config["meta_layer"]
|
||||
self._base_layer = self.config["base_layer"]
|
||||
|
||||
|
||||
# Create a custom SymbolSpace
|
||||
self._crash_table_name = context.symbol_space.free_table_name("crash")
|
||||
crash_path = "file://" + os_path.join(os_path.dirname(__file__), '..', \
|
||||
'symbols', 'windows', 'crash.json')
|
||||
table = intermed.IntermediateSymbolTable(context = context,
|
||||
config_path = config_path,
|
||||
name = self._crash_table_name,
|
||||
isf_url = crash_path)
|
||||
context.symbol_space.append(table)
|
||||
|
||||
# Check Header
|
||||
hdr_layer = self._context.memory[self._base_layer]
|
||||
hdr_offset = 0
|
||||
self._check_header(hdr_layer, hdr_offset)
|
||||
|
||||
# Need to create a header object
|
||||
self.header = self.context.object(self._crash_table_name + constants.BANG +
|
||||
"_DMP_HEADER", offset = hdr_offset,
|
||||
layer_name = self._base_layer)
|
||||
|
||||
# Extract the DTB
|
||||
self.dtb = self.header.DirectoryTableBase
|
||||
|
||||
# Verify that it is a supported format
|
||||
if self.header.DumpType != 0x1:
|
||||
raise WindowsCrashDump32FormatException("unsupported dump format 0x{:x}".format(self.header.DumpType))
|
||||
|
||||
# Then call the super, which will call load_segments
|
||||
super().__init__(context, config_path, name)
|
||||
|
||||
#self._load_segments()
|
||||
|
||||
def _load_segments(self) -> None:
|
||||
"""Loads up the segments from the meta_layer"""
|
||||
|
||||
segments = []
|
||||
|
||||
offset = self.headerpages
|
||||
for x in self.header.PhysicalMemoryBlockBuffer.Run:
|
||||
segments.append((x.BasePage * 0x1000,
|
||||
offset * 0x1000,
|
||||
x.PageCount * 0x1000))
|
||||
#print("Segments {:x} {:x} {:x}".format(x.BasePage * 0x1000,
|
||||
# offset * 0x1000,
|
||||
# x.PageCount * 0x1000))
|
||||
offset += x.PageCount
|
||||
|
||||
if len(segments) == 0:
|
||||
raise WindowsCrashDump32FormatException("No Crash segments defined in {}".format(self._base_layer))
|
||||
|
||||
self._segments = segments
|
||||
|
||||
@classmethod
|
||||
def _check_header(cls,
|
||||
base_layer: interfaces.layers.DataLayerInterface,
|
||||
offset: int = 0) -> typing.Tuple[int, int]:
|
||||
|
||||
# Verify the Window's crash dump file magic
|
||||
header_data = base_layer.read(offset, cls._magic_struct.size)
|
||||
(signature, validdump) = cls._magic_struct.unpack(header_data)
|
||||
|
||||
if signature != cls.SIGNATURE:
|
||||
raise WindowsCrashDump32FormatException("bad signature 0x{:x} at file offset 0x{:x}".format(signature, offset))
|
||||
if validdump != cls.VALIDDUMP:
|
||||
raise WindowsCrashDump32FormatException("invalid dump 0x{:x} at file offset 0x{:x}".format(validdump, offset))
|
||||
|
||||
return
|
||||
|
||||
|
||||
class WindowsCrashDump32Stacker(interfaces.automagic.StackerLayerInterface):
|
||||
stack_order = 11
|
||||
|
||||
@classmethod
|
||||
def stack(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
progress_callback: validity.ProgressCallback = None) \
|
||||
-> typing.Optional[interfaces.layers.DataLayerInterface]:
|
||||
try:
|
||||
WindowsCrashDump32Layer._check_header(context.memory[layer_name])
|
||||
except WindowsCrashDump32FormatException:
|
||||
return None
|
||||
new_name = context.memory.free_layer_name("WindowsCrashDump32Layer")
|
||||
context.config[interfaces.configuration.path_join(new_name, "base_layer")] = layer_name
|
||||
return WindowsCrashDump32Layer(context, new_name, new_name)
|
||||
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"symbols": {
|
||||
},
|
||||
"user_types": {
|
||||
"_DMP_HEADER": {
|
||||
"fields": {
|
||||
"Signature": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"count": 4,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ValidDump": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"count": 4,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MajorVersion": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"MinorVersion": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"DirectoryTableBase": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"PhysicalMemoryBlockBuffer": {
|
||||
"offset": 100,
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"name": "_PHYSICAL_MEMORY_DESCRIPTOR"
|
||||
}
|
||||
},
|
||||
"DumpType": {
|
||||
"offset": 3976,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 4096
|
||||
},
|
||||
"_PHYSICAL_MEMORY_DESCRIPTOR": {
|
||||
"fields": {
|
||||
"NumberOfPages": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"NumberOfRuns": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"Run": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"count": 1,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "struct",
|
||||
"name": "_PHYSICAL_MEMORY_RUN"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"_PHYSICAL_MEMORY_RUN": {
|
||||
"fields": {
|
||||
"BasePage": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"PageCount": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 8
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
},
|
||||
"base_types": {
|
||||
"unsigned char": {
|
||||
"endian": "little",
|
||||
"kind": "char",
|
||||
"signed": false,
|
||||
"size": 1
|
||||
},
|
||||
"unsigned short": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": false,
|
||||
"size": 2
|
||||
},
|
||||
"long": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": true,
|
||||
"size": 4
|
||||
},
|
||||
"char": {
|
||||
"endian": "little",
|
||||
"kind": "char",
|
||||
"signed": true,
|
||||
"size": 1
|
||||
},
|
||||
"unsigned long": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": false,
|
||||
"size": 4
|
||||
},
|
||||
"long long": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": true,
|
||||
"size": 8
|
||||
},
|
||||
"unsigned long long": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": false,
|
||||
"size": 8
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"producer": {
|
||||
"version": "0.0.1",
|
||||
"name": "ikelos-by-hand",
|
||||
"datetime": "2017-09-04T22:45:22"
|
||||
},
|
||||
"format": "4.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user