mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-06 09:47:38 +02:00
Add API for mapping kernel addresses to kernel symbols or a specific kext
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
import logging
|
||||
import struct
|
||||
from typing import Optional, Iterable, Set
|
||||
from typing import Optional, Iterable, Set, Iterator, Any
|
||||
|
||||
from volatility.framework import interfaces, constants, layers, exceptions, objects
|
||||
from volatility.framework import symbols
|
||||
@@ -118,6 +118,66 @@ class MacintelStacker(interfaces.automagic.StackerLayerInterface):
|
||||
class MacUtilities(object):
|
||||
"""Class with multiple useful mac functions."""
|
||||
|
||||
@classmethod
|
||||
def mask_mods_list(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
mods: Iterator[Any]) -> Iterator[Any]:
|
||||
|
||||
"""
|
||||
A helper function to mask the starting and end address of kernel modules
|
||||
"""
|
||||
mask = context.layers[layer_name].address_mask
|
||||
|
||||
return [(objects.utility.array_to_string(mod.name), mod.address & mask, (mod.address & mask) + mod.size) for mod in mods]
|
||||
|
||||
@classmethod
|
||||
def generate_kernel_handler_info(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
kernel, # ikelos - how to type this??
|
||||
mods_list: Iterator[Any]):
|
||||
|
||||
try:
|
||||
start_addr = kernel.object_from_symbol("vm_kernel_stext")
|
||||
except exceptions.SymbolError:
|
||||
start_addr = kernel.object_from_symbol("stext")
|
||||
|
||||
try:
|
||||
end_addr = kernel.object_from_symbol("vm_kernel_etext")
|
||||
except exceptions.SymbolError:
|
||||
end_addr = kernel.object_from_symbol("etext")
|
||||
|
||||
mask = context.layers[layer_name].address_mask
|
||||
|
||||
start_addr = start_addr & mask
|
||||
end_addr = end_addr & mask
|
||||
|
||||
return [("__kernel__", start_addr, end_addr)] + \
|
||||
MacUtilities.mask_mods_list(context, layer_name, mods_list)
|
||||
|
||||
@classmethod
|
||||
def lookup_module_address(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
handlers: Iterator[Any],
|
||||
target_address):
|
||||
mod_name = "UNKNOWN"
|
||||
symbol_name = "N/A"
|
||||
|
||||
for name, start, end in handlers:
|
||||
if start <= target_address <= end:
|
||||
mod_name = name
|
||||
if name == "__kernel__":
|
||||
symbols = list(context.symbol_space.get_symbols_by_location(target_address))
|
||||
|
||||
if len(symbols) > 0:
|
||||
symbol_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \
|
||||
str(symbols[0])
|
||||
|
||||
break
|
||||
|
||||
return mod_name, symbol_name
|
||||
|
||||
@classmethod
|
||||
def aslr_mask_symbol_table(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
import logging
|
||||
from typing import List
|
||||
from typing import List, Iterator, Any
|
||||
|
||||
from volatility.framework import exceptions, interfaces
|
||||
from volatility.framework import renderers, constants, contexts
|
||||
@@ -10,6 +10,7 @@ from volatility.framework.automagic import mac
|
||||
from volatility.framework.configuration import requirements
|
||||
from volatility.framework.interfaces import plugins
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.plugins.mac import lsmod
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -23,13 +24,16 @@ class Check_syscall(plugins.PluginInterface):
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
|
||||
requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0))
|
||||
]
|
||||
|
||||
def _generator(self):
|
||||
def _generator(self, mods: Iterator[Any]):
|
||||
mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary'])
|
||||
|
||||
kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0)
|
||||
|
||||
handlers = mac.MacUtilities.generate_kernel_handler_info(self.context, self.config['primary'], kernel, mods)
|
||||
|
||||
nsysent = kernel.object_from_symbol(symbol_name = "nsysent")
|
||||
table = kernel.object_from_symbol(symbol_name = "sysent")
|
||||
@@ -48,16 +52,15 @@ class Check_syscall(plugins.PluginInterface):
|
||||
if not call_addr or call_addr == 0:
|
||||
continue
|
||||
|
||||
symbols = list(self.context.symbol_space.get_symbols_by_location(call_addr))
|
||||
module_name, symbol_name = mac.MacUtilities.lookup_module_address(self.context, handlers, call_addr)
|
||||
|
||||
if len(symbols) > 0:
|
||||
sym_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \
|
||||
str(symbols[0])
|
||||
else:
|
||||
sym_name = "UNKNOWN"
|
||||
|
||||
yield (0, (format_hints.Hex(table.vol.offset), "SysCall", i, format_hints.Hex(call_addr), sym_name))
|
||||
yield (0, (format_hints.Hex(table.vol.offset), "SysCall", i, format_hints.Hex(call_addr), module_name, symbol_name))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Table Address", format_hints.Hex), ("Table Name", str), ("Index", int),
|
||||
("Handler Address", format_hints.Hex), ("Handler Symbol", str)], self._generator())
|
||||
("Handler Address", format_hints.Hex), ("Handler Module", str), ("Handler Symbol", str)],
|
||||
self._generator(
|
||||
lsmod.Lsmod.list_modules(self.context, self.config['primary'],
|
||||
self.config['darwin'])))
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
import logging
|
||||
from typing import List
|
||||
from typing import List, Iterator, Any
|
||||
|
||||
import volatility
|
||||
from volatility.framework import exceptions, interfaces
|
||||
@@ -12,6 +12,7 @@ from volatility.framework.configuration import requirements
|
||||
from volatility.framework.interfaces import plugins
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.framework.objects import utility
|
||||
from volatility.plugins.mac import lsmod
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,7 +26,8 @@ class Check_sysctl(plugins.PluginInterface):
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
|
||||
requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0))
|
||||
]
|
||||
|
||||
def _parse_global_variable_sysctls(self, kernel, name):
|
||||
@@ -109,30 +111,28 @@ class Check_sysctl(plugins.PluginInterface):
|
||||
except exceptions.InvalidAddressException:
|
||||
break
|
||||
|
||||
def _generator(self):
|
||||
def _generator(self, mods: Iterator[Any]):
|
||||
mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary'])
|
||||
|
||||
kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0)
|
||||
|
||||
handlers = mac.MacUtilities.generate_kernel_handler_info(self.context, self.config['primary'], kernel, mods)
|
||||
|
||||
sysctl_list = kernel.object_from_symbol(symbol_name = "sysctl__children")
|
||||
|
||||
for sysctl, name, val in self._process_sysctl_list(kernel, sysctl_list):
|
||||
check_addr = sysctl.oid_handler
|
||||
try:
|
||||
check_addr = sysctl.oid_handler
|
||||
except exceptions.InvalidAddressException:
|
||||
continue
|
||||
|
||||
if check_addr == 0:
|
||||
sym_name = "<No Handler>"
|
||||
else:
|
||||
symbols = list(self.context.symbol_space.get_symbols_by_location(check_addr))
|
||||
module_name, symbol_name = mac.MacUtilities.lookup_module_address(self.context, handlers, check_addr)
|
||||
|
||||
if len(symbols) > 0:
|
||||
sym_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \
|
||||
str(symbols[0])
|
||||
else:
|
||||
sym_name = "UNKNOWN"
|
||||
|
||||
yield (0, (name, sysctl.oid_number, sysctl.get_perms(), format_hints.Hex(check_addr), val, sym_name))
|
||||
yield (0, (name, sysctl.oid_number, sysctl.get_perms(), format_hints.Hex(check_addr), val, module_name, symbol_name))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Name", str), ("Number", int), ("Perms", str),
|
||||
("Handler Address", format_hints.Hex), ("Value", str), ("Handler Symbol", str)],
|
||||
self._generator())
|
||||
return renderers.TreeGrid([("Name", str), ("Number", int), ("Perms", str), ("Handler Address", format_hints.Hex),
|
||||
("Value", str), ("Handler Module", str), ("Handler Symbol", str)],
|
||||
self._generator(
|
||||
lsmod.Lsmod.list_modules(self.context, self.config['primary'],
|
||||
self.config['darwin'])))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
from typing import List
|
||||
from typing import List, Iterator, Any
|
||||
|
||||
from volatility.framework import exceptions, interfaces
|
||||
from volatility.framework import renderers, constants, contexts
|
||||
@@ -11,6 +11,7 @@ from volatility.framework.automagic import mac
|
||||
from volatility.framework.configuration import requirements
|
||||
from volatility.framework.interfaces import plugins
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.plugins.mac import lsmod
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -24,35 +25,40 @@ class Check_trap_table(plugins.PluginInterface):
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
|
||||
requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0))
|
||||
]
|
||||
|
||||
def _generator(self):
|
||||
def _generator(self, mods: Iterator[Any]):
|
||||
mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary'])
|
||||
|
||||
kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0)
|
||||
|
||||
handlers = mac.MacUtilities.generate_kernel_handler_info(self.context, self.config['primary'], kernel, mods)
|
||||
|
||||
table = kernel.object_from_symbol(symbol_name = "mach_trap_table")
|
||||
|
||||
for i, ent in enumerate(table):
|
||||
try:
|
||||
call_addr = ent.mach_trap_function.dereference().vol.offset
|
||||
except exceptions.InvalidPagedAddressException:
|
||||
except exceptions.InvalidAddressException:
|
||||
continue
|
||||
|
||||
if not call_addr or call_addr == 0:
|
||||
continue
|
||||
|
||||
symbols = list(self.context.symbol_space.get_symbols_by_location(call_addr))
|
||||
module_name, symbol_name = mac.MacUtilities.lookup_module_address(self.context, handlers, call_addr)
|
||||
|
||||
if len(symbols) > 0:
|
||||
sym_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \
|
||||
str(symbols[0])
|
||||
else:
|
||||
sym_name = "UNKNOWN"
|
||||
|
||||
yield (0, (format_hints.Hex(table.vol.offset), "TrapTable", i, format_hints.Hex(call_addr), sym_name))
|
||||
yield (0, (format_hints.Hex(table.vol.offset), "TrapTable", i, format_hints.Hex(call_addr), module_name, symbol_name))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Table Address", format_hints.Hex), ("Table Name", str), ("Index", int),
|
||||
("Handler Address", format_hints.Hex), ("Handler Symbol", str)], self._generator())
|
||||
("Handler Address", format_hints.Hex), ("Handler Module", str), ("Handler Symbol", str)],
|
||||
self._generator(
|
||||
lsmod.Lsmod.list_modules(self.context, self.config['primary'],
|
||||
self.config['darwin'])))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
import logging
|
||||
from typing import List
|
||||
from typing import List, Iterator, Any
|
||||
|
||||
import volatility
|
||||
from volatility.framework import exceptions, interfaces
|
||||
@@ -12,6 +12,7 @@ from volatility.framework.configuration import requirements
|
||||
from volatility.framework.interfaces import plugins
|
||||
from volatility.framework.renderers import format_hints
|
||||
from volatility.framework.objects import utility
|
||||
from volatility.plugins.mac import lsmod
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,13 +26,16 @@ class Timers(plugins.PluginInterface):
|
||||
requirements.TranslationLayerRequirement(name = 'primary',
|
||||
description = 'Memory layer for the kernel',
|
||||
architectures = ["Intel32", "Intel64"]),
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
|
||||
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
|
||||
requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0))
|
||||
]
|
||||
|
||||
def _generator(self):
|
||||
def _generator(self, mods: Iterator[Any]):
|
||||
mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary'])
|
||||
|
||||
kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0)
|
||||
kernel = contexts.Module(self.context, self.config['darwin'], self.config['primary'], 0)
|
||||
|
||||
handlers = mac.MacUtilities.generate_kernel_handler_info(self.context, self.config['primary'], kernel, mods)
|
||||
|
||||
real_ncpus = kernel.object_from_symbol(symbol_name = "real_ncpus")
|
||||
|
||||
@@ -45,7 +49,7 @@ class Timers(plugins.PluginInterface):
|
||||
offset = cpu_data_ptrs_addr,
|
||||
subtype = kernel.get_type('cpu_data'),
|
||||
count = real_ncpus)
|
||||
|
||||
|
||||
for cpu_data_ptr in cpu_data_ptrs:
|
||||
try:
|
||||
queue = cpu_data_ptr.rtclock_timer.queue.head
|
||||
@@ -54,26 +58,24 @@ class Timers(plugins.PluginInterface):
|
||||
|
||||
for timer in queue.walk_list(queue, "q_link", "call_entry"):
|
||||
try:
|
||||
handler = timer.func
|
||||
handler = timer.func.dereference().vol.offset
|
||||
except exceptions.InvalidAddressException:
|
||||
continue
|
||||
|
||||
symbols = list(self.context.symbol_space.get_symbols_by_location(handler))
|
||||
|
||||
if len(symbols) > 0:
|
||||
sym_name = str(symbols[0].split(constants.BANG)[1]) if constants.BANG in symbols[0] else \
|
||||
str(symbols[0])
|
||||
else:
|
||||
sym_name = "UNKNOWN"
|
||||
|
||||
if hasattr(timer, "entry_time"):
|
||||
if timer.has_member("entry_time"):
|
||||
entry_time = timer.entry_time
|
||||
else:
|
||||
entry_time = -1
|
||||
|
||||
yield (0, (format_hints.Hex(handler), format_hints.Hex(timer.param0), format_hints.Hex(timer.param1), timer.deadline, entry_time, "kernel", sym_name))
|
||||
module_name, symbol_name = mac.MacUtilities.lookup_module_address(self.context, handlers, handler)
|
||||
|
||||
yield (0, (format_hints.Hex(handler), format_hints.Hex(timer.param0), format_hints.Hex(timer.param1), \
|
||||
timer.deadline, entry_time, module_name, symbol_name))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Function", format_hints.Hex), ("Param 0", format_hints.Hex), ("Param 1", format_hints.Hex),
|
||||
("Deadline", int), ("Entry Time", int), ("Module", str), ("Symbol", str)],
|
||||
self._generator())
|
||||
self._generator(
|
||||
lsmod.Lsmod.list_modules(self.context, self.config['primary'],
|
||||
self.config['darwin'])))
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ class trustedbsd(plugins.PluginInterface):
|
||||
mac.MacUtilities.aslr_mask_symbol_table(self.context, self.config['darwin'], self.config['primary'])
|
||||
|
||||
kernel = contexts.Module(self._context, self.config['darwin'], self.config['primary'], 0)
|
||||
|
||||
handlers = mac.MacUtilities.generate_kernel_handler_info(self.context, self.config['primary'], kernel, mods)
|
||||
|
||||
policy_list = kernel.object_from_symbol(symbol_name = "mac_policy_list").cast("mac_policy_list")
|
||||
|
||||
@@ -41,10 +43,7 @@ class trustedbsd(plugins.PluginInterface):
|
||||
offset = policy_list.entries.dereference().vol.offset,
|
||||
subtype = kernel.get_type('mac_policy_list_element'),
|
||||
count = policy_list.staticmax + 1)
|
||||
|
||||
mask = self.context.layers[self.config['primary']].address_mask
|
||||
mods_list = [(mod.name, mod.address & mask, (mod.address & mask) + mod.size) for mod in mods]
|
||||
|
||||
|
||||
for i, ent in enumerate(entries):
|
||||
# I don't know how this can happen, but the kernel makes this check all over the place
|
||||
# the policy isn't useful without any ops so a rootkit can't abuse this
|
||||
@@ -65,23 +64,13 @@ class trustedbsd(plugins.PluginInterface):
|
||||
if call_addr is None or call_addr == 0:
|
||||
continue
|
||||
|
||||
found_module = None
|
||||
module_name, symbol_name = mac.MacUtilities.lookup_module_address(self.context, handlers, call_addr)
|
||||
|
||||
for mod_name_info, mod_base, mod_end in mods_list:
|
||||
if call_addr >= mod_base and call_addr <= mod_end:
|
||||
found_module = mod_name_info
|
||||
break
|
||||
|
||||
if found_module:
|
||||
symbol_module = utility.array_to_string(found_module)
|
||||
else:
|
||||
symbol_module = "UNKNOWN"
|
||||
|
||||
yield (0, (check, ent_name, symbol_module, format_hints.Hex(call_addr)))
|
||||
yield (0, (check, ent_name, format_hints.Hex(call_addr), module_name, symbol_name))
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid([("Member", str), ("Policy Name", str), ("Handler Module", str),
|
||||
("Handler Address", format_hints.Hex)],
|
||||
return renderers.TreeGrid([("Member", str), ("Policy Name", str), ("Handler Address", format_hints.Hex), ("Handler Module", str),
|
||||
("Handler Symbol", str)],
|
||||
self._generator(
|
||||
lsmod.Lsmod.list_modules(self.context, self.config['primary'],
|
||||
self.config['darwin'])))
|
||||
|
||||
Reference in New Issue
Block a user