Files
volatility3/volatility/framework/plugins/mac/netstat.py
T

107 lines
4.4 KiB
Python

# This file is Copyright 2019 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 typing import Iterable, Callable
from volatility.framework import exceptions, renderers, interfaces
from volatility.framework.automagic import mac
from volatility.framework.configuration import requirements
from volatility.framework.interfaces import plugins
from volatility.framework.objects import utility
from volatility.framework.renderers import format_hints
from volatility.plugins.mac import tasks
vollog = logging.getLogger(__name__)
class Netstat(plugins.PluginInterface):
"""Lists all network connections for all processes."""
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Kernel Address Space',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac Kernel"),
requirements.PluginRequirement(name = 'tasks', plugin = tasks.Tasks, version = (1, 0, 0))
]
@classmethod
def list_sockets(cls,
context: interfaces.context.ContextInterface,
layer_name: str,
darwin_symbols: str,
filter_func: Callable[[int], bool] = lambda _: False) -> \
Iterable[interfaces.objects.ObjectInterface]:
"""
Returns the open socket descriptors of a process
Return values:
A tuple of 3 elements:
1) The name of the process that opened the socket
2) The process ID of the processed that opened the socket
3) The address of the associated socket structure
"""
for task in tasks.Tasks.list_tasks(context, layer_name, darwin_symbols, filter_func):
task_name = utility.array_to_string(task.p_comm)
pid = task.p_pid
for filp, _, _ in mac.MacUtilities.files_descriptors_for_process(context, darwin_symbols, task):
try:
ftype = filp.f_fglob.get_fg_type()
except exceptions.InvalidAddressException:
continue
if ftype != 'SOCKET':
continue
try:
socket = filp.f_fglob.fg_data.dereference().cast("socket")
except exceptions.InvalidAddressException:
continue
yield task_name, pid, socket
def _generator(self):
filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)])
for task_name, pid, socket in self.list_sockets(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func):
family = socket.get_family()
if family == 1:
try:
upcb = socket.so_pcb.dereference().cast("unpcb")
path = utility.array_to_string(upcb.unp_addr.sun_path)
except exceptions.InvalidAddressException:
continue
yield (0, (format_hints.Hex(socket.vol.offset), "UNIX", path, 0, "", 0, "",
"{}/{:d}".format(task_name, pid)))
elif family in [2, 30]:
state = socket.get_state()
proto = socket.get_protocol_as_string()
vals = socket.get_converted_connection_info()
if vals:
(lip, lport, rip, rport) = vals
yield (0, (format_hints.Hex(socket.vol.offset), proto, lip, lport, rip, rport, state,
"{}/{:d}".format(task_name, pid)))
def run(self):
# mac.MacUtilities.aslr_mask_symbol_table(self.config, self.context)
return renderers.TreeGrid([("Offset", format_hints.Hex), ("Proto", str), ("Local IP", str), ("Local Port", int),
("Remote IP", str), ("Remote Port", int), ("State", str), ("Process", str)],
self._generator())