mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-06 09:47:38 +02:00
Update Symbol Table, Load Physical Layer
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
# This file is Copyright 2022 Volatility Foundation and licensed under the Volatility Software License 1.0
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from volatility3.framework import exceptions, interfaces, renderers
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.renderers import format_hints
|
||||
from volatility3.framework.symbols.windows.extensions import mbr
|
||||
from volatility3.plugins import yarascan
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MBRParser(interfaces.plugins.PluginInterface):
|
||||
""" Scans for and parses potential Master Boot Records (MBRs) """
|
||||
|
||||
_required_framework_version = (2, 0, 1)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls):
|
||||
return [
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.VersionRequirement(name = 'yarascanner', component = yarascan.YaraScanner,
|
||||
version = (2, 0, 0)),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def levenshtein(self, s1, s2):
|
||||
if len(s1) < len(s2):
|
||||
return self.levenshtein(s2, s1)
|
||||
|
||||
if len(s2) == 0:
|
||||
return len(s1)
|
||||
|
||||
previous_row = range(len(s2) + 1)
|
||||
for i, c1 in enumerate(s1):
|
||||
current_row = [i + 1]
|
||||
for j, c2 in enumerate(s2):
|
||||
insertions = previous_row[j + 1] + 1
|
||||
deletions = current_row[j] + 1
|
||||
substitutions = previous_row[j] + (c1 != c2)
|
||||
current_row.append(min(insertions, deletions, substitutions))
|
||||
previous_row = current_row
|
||||
|
||||
return previous_row[-1]
|
||||
|
||||
def _generator(self):
|
||||
layer = self.context.layers[self.config['primary']]
|
||||
# TODO : YARA RULE HEX
|
||||
rules = yarascan.YaraScan.process_yara_options({'yara_rules': "55 aa"})
|
||||
|
||||
for offset, _rule_name, _name, _value in layer.scan(context = self.context,
|
||||
scanner = yarascan.YaraScanner(rules = rules)):
|
||||
try:
|
||||
yield 0, (format_hints.Hex(offset), _name)
|
||||
|
||||
except exceptions.PagedInvalidAddressException:
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([
|
||||
('Offset', format_hints.Hex),
|
||||
("Name", str)
|
||||
], self._generator())
|
||||
@@ -0,0 +1,80 @@
|
||||
# This file is Copyright 2022 Volatility Foundation and licensed under the Volatility Software License 1.0
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from volatility3.framework import constants, interfaces, renderers, symbols
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.layers import scanners
|
||||
from volatility3.framework.renderers import format_hints
|
||||
from volatility3.framework.symbols import intermed
|
||||
from volatility3.framework.symbols.windows.extensions import mbr
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
class MBRScan(interfaces.plugins.PluginInterface):
|
||||
""" Scans for and parses potential Master Boot Records (MBRs) """
|
||||
|
||||
_required_framework_version = (2, 0, 1)
|
||||
_version = (1, 0, 0)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls):
|
||||
return [
|
||||
requirements.ModuleRequirement(name = 'kernel', description = 'Windows kernel',
|
||||
architectures = ["Intel32", "Intel64"])
|
||||
]
|
||||
|
||||
def _generator(self):
|
||||
kernel = self.context.modules[self.config['kernel']]
|
||||
physical_layer_name = self.context.layers[kernel.layer_name].config.get('memory_layer', None)
|
||||
|
||||
layer = self.context.layers[physical_layer_name]
|
||||
architecture = "intel" if not symbols.symbol_table_is_64bit(self.context, kernel.symbol_table_name) else "intel64"
|
||||
|
||||
symbol_table = intermed.IntermediateSymbolTable.create(context = self.context,
|
||||
config_path = self.config_path,
|
||||
sub_path = "windows",
|
||||
filename = "mbr",
|
||||
class_types = {
|
||||
'PARTITION_TABLE': mbr.PARTITION_TABLE,
|
||||
'PARTITION_ENTRY': mbr.PARTITION_ENTRY
|
||||
})
|
||||
|
||||
partition_table_object = symbol_table + constants.BANG + "PARTITION_TABLE"
|
||||
|
||||
mbr_signature = b"\x55\xAA"
|
||||
mbr_length = 0x200
|
||||
boot_code_length = 0x1B8
|
||||
|
||||
for offset, _value in layer.scan(context = self.context, scanner = scanners.MultiStringScanner(patterns = [mbr_signature])):
|
||||
mbr_start_offset = offset - (mbr_length - len(mbr_signature))
|
||||
partition_table = self.context.object(partition_table_object, offset = mbr_start_offset, layer_name = layer.name)
|
||||
|
||||
boot_code = layer.read(mbr_start_offset, boot_code_length, pad = True)
|
||||
|
||||
if boot_code:
|
||||
all_zeros = boot_code.count(b"\x00") == len(boot_code)
|
||||
|
||||
if not all_zeros:
|
||||
partition_type = partition_table.FirstEntry.PartitionType
|
||||
|
||||
|
||||
if partition_type.is_valid_choice:
|
||||
yield 0, (
|
||||
format_hints.Hex(offset),
|
||||
partition_type.lookup(),
|
||||
interfaces.renderers.Disassembly(boot_code, 0, architecture),
|
||||
format_hints.HexBytes(boot_code)
|
||||
)
|
||||
else:
|
||||
vollog.log(constants.LOGLEVEL_VV, f"Not a valid MBR: Data all zeroed out : {format_hints.Hex(offset)}")
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([
|
||||
('Offset', format_hints.Hex),
|
||||
('PartitionType', str),
|
||||
("Disasm", interfaces.renderers.Disassembly),
|
||||
("Hexdump", format_hints.HexBytes)
|
||||
], self._generator())
|
||||
@@ -6,106 +6,14 @@ from volatility3.framework import objects
|
||||
|
||||
import struct
|
||||
|
||||
PartitionTypes = {
|
||||
0x00:"Empty",
|
||||
0x01:"FAT12,CHS",
|
||||
0x04:"FAT16 16-32MB,CHS",
|
||||
0x05:"Microsoft Extended",
|
||||
0x06:"FAT16 32MB,CHS",
|
||||
0x07:"NTFS",
|
||||
0x0b:"FAT32,CHS",
|
||||
0x0c:"FAT32,LBA",
|
||||
0x0e:"FAT16, 32MB-2GB,LBA",
|
||||
0x0f:"Microsoft Extended, LBA",
|
||||
0x11:"Hidden FAT12,CHS",
|
||||
0x14:"Hidden FAT16,16-32MB,CHS",
|
||||
0x16:"Hidden FAT16,32MB-2GB,CHS",
|
||||
0x18:"AST SmartSleep Partition",
|
||||
0x1b:"Hidden FAT32,CHS",
|
||||
0x1c:"Hidden FAT32,LBA",
|
||||
0x1e:"Hidden FAT16,32MB-2GB,LBA",
|
||||
0x27:"PQservice",
|
||||
0x39:"Plan 9 partition",
|
||||
0x3c:"PartitionMagic recovery partition",
|
||||
0x42:"Microsoft MBR,Dynamic Disk",
|
||||
0x44:"GoBack partition",
|
||||
0x51:"Novell",
|
||||
0x52:"CP/M",
|
||||
0x63:"Unix System V",
|
||||
0x64:"PC-ARMOUR protected partition",
|
||||
0x82:"Solaris x86 or Linux Swap",
|
||||
0x83:"Linux",
|
||||
0x84:"Hibernation",
|
||||
0x85:"Linux Extended",
|
||||
0x86:"NTFS Volume Set",
|
||||
0x87:"NTFS Volume Set",
|
||||
0x9f:"BSD/OS",
|
||||
0xa0:"Hibernation",
|
||||
0xa1:"Hibernation",
|
||||
0xa5:"FreeBSD",
|
||||
0xa6:"OpenBSD",
|
||||
0xa8:"Mac OSX",
|
||||
0xa9:"NetBSD",
|
||||
0xab:"Mac OSX Boot",
|
||||
0xaf:"MacOS X HFS",
|
||||
0xb7:"BSDI",
|
||||
0xb8:"BSDI Swap",
|
||||
0xbb:"Boot Wizard hidden",
|
||||
0xbe:"Solaris 8 boot partition",
|
||||
0xd8:"CP/M-86",
|
||||
0xde:"Dell PowerEdge Server utilities (FAT fs)",
|
||||
0xdf:"DG/UX virtual disk manager partition",
|
||||
0xeb:"BeOS BFS",
|
||||
0xee:"EFI GPT Disk",
|
||||
0xef:"EFI System Partition",
|
||||
0xfb:"VMWare File System",
|
||||
0xfc:"VMWare Swap",
|
||||
}
|
||||
class PARTITION_TABLE(objects.StructType):
|
||||
|
||||
def get_disk_signature(self) -> str:
|
||||
signature = self.DiskSignature.values
|
||||
return signature
|
||||
|
||||
class PARTITION_ENTRY(objects.StructType):
|
||||
def get_value(self, char):
|
||||
padded = "\x00\x00\x00" + str(char)
|
||||
val = int(struct.unpack('>I', padded)[0])
|
||||
return val
|
||||
|
||||
def get_type(self):
|
||||
return PartitionTypes.get(self.get_value(self.PartitionType), "Invalid")
|
||||
|
||||
def is_bootable(self):
|
||||
return self.get_value(self.BootableFlag) == 0x80
|
||||
|
||||
def is_bootable_and_used(self):
|
||||
return self.is_bootable() and self.is_used()
|
||||
|
||||
def is_valid(self):
|
||||
return self.get_type() != "Invalid"
|
||||
|
||||
def is_used(self):
|
||||
return self.get_type() != "Empty" and self.is_valid()
|
||||
|
||||
def StartingSector(self):
|
||||
return self.StartingCHS[1] % 64
|
||||
|
||||
def StartingCylinder(self):
|
||||
return (self.StartingCHS[1] - self.StartingSector()) * 4 + self.StartingCHS[2]
|
||||
|
||||
def EndingSector(self):
|
||||
return self.EndingCHS[1] % 64
|
||||
|
||||
def EndingCylinder(self):
|
||||
return (self.EndingCHS[1] - self.EndingSector()) * 4 + self.EndingCHS[2]
|
||||
|
||||
def __str__(self):
|
||||
processed_entry = ""
|
||||
bootable = self.get_value(self.BootableFlag)
|
||||
processed_entry = "Boot flag: {0:#x} {1}\n".format(bootable, "(Bootable)" if self.is_bootable() else '')
|
||||
processed_entry += "Partition type: {0:#x} ({1})\n".format(self.get_value(self.PartitionType), self.get_type())
|
||||
processed_entry += "Starting Sector (LBA): {0:#x} ({0})\n".format(self.StartingLBA)
|
||||
processed_entry += "Starting CHS: Cylinder: {0} Head: {1} Sector: {2}\n".format(self.StartingCylinder(),
|
||||
self.StartingCHS[0],
|
||||
self.StartingSector())
|
||||
processed_entry += "Ending CHS: Cylinder: {0} Head: {1} Sector: {2}\n".format(self.EndingCylinder(),
|
||||
self.EndingCHS[0],
|
||||
self.EndingSector())
|
||||
processed_entry += "Size in sectors: {0:#x} ({0})\n\n".format(self.SizeInSectors)
|
||||
return processed_entry
|
||||
|
||||
def get_partition_type(self, type: int) -> str:
|
||||
|
||||
return "Hello"
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"metadata": {
|
||||
"producer": {
|
||||
"version": "0.0.1",
|
||||
"name": "Donghyun Kim",
|
||||
"comment": "Using structures defined in File System Forensic Analysis pg 353+",
|
||||
"datetime": "2022-01-03T13:37:00"
|
||||
"name": "Donghyun Kim (@digitalisx99)",
|
||||
"comment": "Using structures defined in File System Forensic Analysis pg 88+",
|
||||
"datetime": "2022-03-05T10:53:00"
|
||||
},
|
||||
"format": "6.1.0"
|
||||
},
|
||||
@@ -32,6 +32,12 @@
|
||||
"size": 4,
|
||||
"signed": false,
|
||||
"endian": "little"
|
||||
},
|
||||
"int": {
|
||||
"endian": "little",
|
||||
"kind": "int",
|
||||
"signed": true,
|
||||
"size": 4
|
||||
},
|
||||
"unsigned short": {
|
||||
"kind": "int",
|
||||
@@ -45,12 +51,204 @@
|
||||
"signed": false,
|
||||
"endian": "little"
|
||||
},
|
||||
"char": {
|
||||
"endian": "little",
|
||||
"kind": "char",
|
||||
"signed": true,
|
||||
"size": 1
|
||||
},
|
||||
"wchar": {
|
||||
"kind": "int",
|
||||
"size": 2,
|
||||
"signed": true,
|
||||
"endian": "little"
|
||||
}
|
||||
},
|
||||
"symbols": {}
|
||||
},
|
||||
"symbols": {},
|
||||
"enums": {
|
||||
"BootableFlag":{
|
||||
"base": "unsigned char",
|
||||
"constants": {
|
||||
"Bootable": 0,
|
||||
"Non-Bootable": 128
|
||||
},
|
||||
"size": 1
|
||||
},
|
||||
"PartitionTypes": {
|
||||
"base": "unsigned char",
|
||||
"constants": {
|
||||
"Empty": 0,
|
||||
"FAT12,CHS": 1,
|
||||
"FAT16 16-32MB,CHS": 4,
|
||||
"Microsoft Extended": 5,
|
||||
"FAT16 32MB,CHS": 6,
|
||||
"NTFS": 7,
|
||||
"FAT32,CHS": 11,
|
||||
"FAT32,LBA": 12,
|
||||
"FAT16, 32MB-2GB,LBA": 14,
|
||||
"Microsoft Extended, LBA": 15,
|
||||
"Hidden FAT12,CHS": 17,
|
||||
"Hidden FAT16,16-32MB,CHS": 20,
|
||||
"Hidden FAT16,32MB-2GB,CHS": 22,
|
||||
"AST SmartSleep Partition": 24,
|
||||
"Hidden FAT32,CHS": 27,
|
||||
"Hidden FAT32,LBA": 28,
|
||||
"Hidden FAT16,32MB-2GB,LBA": 30,
|
||||
"PQservice": 39,
|
||||
"Plan 9 partition": 57,
|
||||
"PartitionMagic recovery partition": 60,
|
||||
"Microsoft MBR,Dynamic Disk": 66,
|
||||
"GoBack partition": 68,
|
||||
"Novell": 81,
|
||||
"CP/M": 82,
|
||||
"Unix System V": 99,
|
||||
"PC-ARMOUR protected partition": 100,
|
||||
"Solaris x86 or Linux Swap": 130,
|
||||
"Linux": 131,
|
||||
"Hibernation": 132,
|
||||
"Linux Extended": 133,
|
||||
"NTFS Volume Set": 134,
|
||||
"NTFS Volume Set": 135,
|
||||
"BSD/OS": 159,
|
||||
"Hibernation": 160,
|
||||
"Hibernation": 161,
|
||||
"FreeBSD": 165,
|
||||
"OpenBSD": 166,
|
||||
"Mac OSX": 168,
|
||||
"NetBSD": 169,
|
||||
"Mac OSX Boot": 171,
|
||||
"MacOS X HFS": 175,
|
||||
"BSDI": 183,
|
||||
"BSDI Swap": 184,
|
||||
"Boot Wizard hidden": 187,
|
||||
"Solaris 8 boot partition": 190,
|
||||
"CP/M-86": 216,
|
||||
"Dell PowerEdge Server utilities (FAT fs)": 222,
|
||||
"DG/UX virtual disk manager partition": 223,
|
||||
"BeOS BFS": 235,
|
||||
"EFI GPT Disk": 238,
|
||||
"EFI System Partition": 239,
|
||||
"VMWare File System": 251,
|
||||
"VMWare Swap": 252
|
||||
},
|
||||
"size": 1
|
||||
}
|
||||
},
|
||||
"user_types": {
|
||||
"PARTITION_ENTRY":{
|
||||
"fields": {
|
||||
"BootableFlag": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "enum",
|
||||
"name": "BootableFlag"
|
||||
}
|
||||
},
|
||||
"StartingCHS": {
|
||||
"offset": 1,
|
||||
"type": {
|
||||
"count": 3,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PartitionType": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "enum",
|
||||
"name": "PartitionTypes"
|
||||
}
|
||||
},
|
||||
"EndingCHS": {
|
||||
"offset": 5,
|
||||
"type": {
|
||||
"count": 3,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StartingLBA": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned int"
|
||||
}
|
||||
},
|
||||
"SizeInSectors": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"PARTITION_TABLE":{
|
||||
"fields":{
|
||||
"DiskSignature": {
|
||||
"offset": 440,
|
||||
"type": {
|
||||
"count": 4,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Unused": {
|
||||
"offset": 444,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"FirstEntry":{
|
||||
"offset": 446,
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"name": "PARTITION_ENTRY"
|
||||
}
|
||||
},
|
||||
"SecondEntry":{
|
||||
"offset": 462,
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"name": "PARTITION_ENTRY"
|
||||
}
|
||||
},
|
||||
"ThirdEntry":{
|
||||
"offset": 478,
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"name": "PARTITION_ENTRY"
|
||||
}
|
||||
},
|
||||
"FourthEntry":{
|
||||
"offset": 494,
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"name": "PARTITION_ENTRY"
|
||||
}
|
||||
},
|
||||
"Signature":{
|
||||
"offset": 510,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user