mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-20 05:35:41 +02:00
215 lines
7.4 KiB
Python
215 lines
7.4 KiB
Python
# This file is Copyright 2023 Volatility Foundation and licensed under the Volatility Software License 1.0
|
|
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
|
#
|
|
|
|
from typing import List
|
|
from volatility3.framework import interfaces, renderers, constants
|
|
from volatility3.framework.configuration import requirements
|
|
from volatility3.framework.interfaces import plugins
|
|
from volatility3.framework.symbols.linux import network
|
|
from volatility3.framework.symbols.linux.extensions import network as net_extensions
|
|
|
|
|
|
class Addr(plugins.PluginInterface):
|
|
"""Lists network interface information for all devices"""
|
|
|
|
_required_framework_version = (2, 22, 0)
|
|
|
|
_version = (1, 0, 2)
|
|
|
|
@classmethod
|
|
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
|
return [
|
|
requirements.ModuleRequirement(
|
|
name="kernel",
|
|
description="Linux kernel",
|
|
architectures=["Intel32", "Intel64"],
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="Net", component=network.NetSymbols, version=(1, 0, 0)
|
|
),
|
|
]
|
|
|
|
def _gather_net_dev_info(self, net_dev: net_extensions.net_device):
|
|
mac_addr = net_dev.get_mac_address()
|
|
promisc = net_dev.promisc
|
|
operational_state = net_dev.get_operational_state()
|
|
iface_name = net_dev.get_device_name()
|
|
iface_ifindex = net_dev.ifindex
|
|
try:
|
|
net_ns_id = net_dev.get_net_namespace_id()
|
|
except AttributeError:
|
|
net_ns_id = None
|
|
|
|
# Interface IPv4 Addresses
|
|
in_device = net_dev.ip_ptr.dereference().cast("in_device")
|
|
for in_ifaddr in in_device.get_addresses():
|
|
prefix_len = in_ifaddr.get_prefix_len()
|
|
scope_type = in_ifaddr.get_scope_type()
|
|
ip_addr = in_ifaddr.get_address()
|
|
yield (
|
|
net_ns_id,
|
|
iface_ifindex,
|
|
iface_name,
|
|
mac_addr,
|
|
promisc,
|
|
ip_addr,
|
|
prefix_len,
|
|
scope_type,
|
|
operational_state,
|
|
)
|
|
|
|
# Interface IPv6 Addresses
|
|
inet6_dev = net_dev.ip6_ptr.dereference().cast("inet6_dev")
|
|
for inet6_ifaddr in inet6_dev.get_addresses():
|
|
prefix_len = inet6_ifaddr.get_prefix_len()
|
|
scope_type = inet6_ifaddr.get_scope_type()
|
|
ip6_addr = inet6_ifaddr.get_address()
|
|
yield (
|
|
net_ns_id,
|
|
iface_ifindex,
|
|
iface_name,
|
|
mac_addr,
|
|
promisc,
|
|
ip6_addr,
|
|
prefix_len,
|
|
scope_type,
|
|
operational_state,
|
|
)
|
|
|
|
def _enumerate_net_namespace_list(self):
|
|
vmlinux = self.context.modules[self.config["kernel"]]
|
|
|
|
net_type_symname = vmlinux.symbol_table_name + constants.BANG + "net"
|
|
net_device_symname = vmlinux.symbol_table_name + constants.BANG + "net_device"
|
|
network.NetSymbols.apply(self.context.symbol_space[vmlinux.symbol_table_name])
|
|
|
|
# 'net_namespace_list' exists from kernels >= 2.6.24
|
|
net_namespace_list = vmlinux.object_from_symbol("net_namespace_list")
|
|
for net_ns in net_namespace_list.to_list(net_type_symname, "list"):
|
|
yield from net_ns.dev_base_head.to_list(net_device_symname, "dev_list")
|
|
|
|
def _generator(self):
|
|
for net_dev in self._enumerate_net_namespace_list():
|
|
for (
|
|
net_ns_id,
|
|
iface_ifindex,
|
|
iface_name,
|
|
mac_addr,
|
|
promisc,
|
|
ip6_addr,
|
|
prefix_len,
|
|
scope_type,
|
|
operational_state,
|
|
) in self._gather_net_dev_info(net_dev):
|
|
yield (
|
|
0,
|
|
(
|
|
net_ns_id or renderers.NotAvailableValue(),
|
|
iface_ifindex,
|
|
iface_name,
|
|
mac_addr,
|
|
promisc,
|
|
ip6_addr,
|
|
prefix_len,
|
|
scope_type,
|
|
operational_state,
|
|
),
|
|
)
|
|
|
|
def run(self):
|
|
headers = [
|
|
("NetNS", int),
|
|
("Index", int),
|
|
("Interface", str),
|
|
("MAC", str),
|
|
("Promiscuous", bool),
|
|
("IP", str),
|
|
("Prefix", int),
|
|
("Scope Type", str),
|
|
("State", str),
|
|
]
|
|
|
|
return renderers.TreeGrid(headers, self._generator())
|
|
|
|
|
|
class Link(plugins.PluginInterface):
|
|
"""Lists information about network interfaces similar to `ip link show`"""
|
|
|
|
_required_framework_version = (2, 0, 0)
|
|
_version = (1, 0, 0)
|
|
|
|
@classmethod
|
|
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
|
return [
|
|
requirements.ModuleRequirement(
|
|
name="kernel",
|
|
description="Linux kernel",
|
|
architectures=["Intel32", "Intel64"],
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="Net", component=network.NetSymbols, version=(1, 0, 0)
|
|
),
|
|
]
|
|
|
|
def _gather_net_dev_link_info(self, net_device):
|
|
mac_addr = net_device.get_mac_address()
|
|
operational_state = net_device.get_operational_state()
|
|
iface_name = net_device.get_device_name()
|
|
mtu = net_device.mtu
|
|
qdisc_name = net_device.get_qdisc_name()
|
|
qlen = net_device.get_queue_length()
|
|
try:
|
|
net_ns_id = net_device.get_net_namespace_id()
|
|
except AttributeError:
|
|
net_ns_id = renderers.NotAvailableValue()
|
|
|
|
# Format flags to string. Drop IFF_ to match iproute2 'ip link' output.
|
|
# Also, note that iproute2 removes IFF_RUNNING, see print_link_flags()
|
|
flags_list = [
|
|
flag.replace("IFF_", "")
|
|
for flag in net_device.get_flag_names()
|
|
if flag != "IFF_RUNNING"
|
|
]
|
|
flags_str = ",".join(flags_list)
|
|
|
|
yield (
|
|
net_ns_id or renderers.NotAvailableValue(),
|
|
iface_name,
|
|
mac_addr,
|
|
operational_state,
|
|
mtu,
|
|
qdisc_name or renderers.NotAvailableValue(),
|
|
qlen,
|
|
flags_str,
|
|
)
|
|
|
|
def _generator(self):
|
|
vmlinux = self.context.modules[self.config["kernel"]]
|
|
|
|
network.NetSymbols.apply(self.context.symbol_space[vmlinux.symbol_table_name])
|
|
|
|
net_type_symname = vmlinux.symbol_table_name + constants.BANG + "net"
|
|
net_device_symname = vmlinux.symbol_table_name + constants.BANG + "net_device"
|
|
|
|
# 'net_namespace_list' exists from kernels >= 2.6.24
|
|
net_namespace_list = vmlinux.object_from_symbol("net_namespace_list")
|
|
for net_ns in net_namespace_list.to_list(net_type_symname, "list"):
|
|
for net_dev in net_ns.dev_base_head.to_list(net_device_symname, "dev_list"):
|
|
for fields in self._gather_net_dev_link_info(net_dev):
|
|
yield 0, fields
|
|
|
|
def run(self):
|
|
headers = [
|
|
("NS", int),
|
|
("Interface", str),
|
|
("MAC", str),
|
|
("State", str),
|
|
("MTU", int),
|
|
("Qdisc", str),
|
|
("Qlen", int),
|
|
("Flags", str),
|
|
]
|
|
|
|
return renderers.TreeGrid(headers, self._generator())
|