forked from fox-it/dissect.target
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add plugins for volatile Linux artefacts (fox-it#241)
Co-authored-by: pyrco <105293448+pyrco@users.noreply.github.com> Co-authored-by: Erik Schamper <1254028+Schamper@users.noreply.github.com>
- Loading branch information
1 parent
1984d3c
commit d471551
Showing
22 changed files
with
1,469 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from typing import Iterator | ||
|
||
from dissect.target.helpers.record import TargetRecordDescriptor | ||
from dissect.target.plugin import Plugin, export | ||
|
||
CmdlineRecord = TargetRecordDescriptor( | ||
"linux/proc/cmdline", | ||
[ | ||
("datetime", "ts"), | ||
("string", "name"), | ||
("varint", "pid"), | ||
("string", "state"), | ||
("string", "cmdline"), | ||
], | ||
) | ||
|
||
|
||
class CmdlinePlugin(Plugin): | ||
def check_compatible(self) -> None: | ||
self.target.proc | ||
|
||
@export(record=CmdlineRecord) | ||
def cmdline(self) -> Iterator[CmdlineRecord]: | ||
"""Return the complete command line for all processes. | ||
If, after an execve(2), the process modifies its argv strings, those changes will show up here. This is not the | ||
same thing as modifying the argv array. | ||
Think of this output as the command line that the process wants you to see. | ||
Yields CmdlineRecord with the following fields: | ||
hostname (string): The target hostname. | ||
domain (string): The target domain. | ||
ts (datetime): The starttime of the process. | ||
name (string): The name of the process. | ||
pid (int): The process ID of the process. | ||
cmdline (string): The complete commandline of the process. | ||
""" | ||
|
||
for process in self.target.proc.processes(): | ||
yield CmdlineRecord( | ||
ts=process.starttime, | ||
name=process.name, | ||
pid=process.pid, | ||
state=process.state, | ||
cmdline=process.cmdline, | ||
_target=self.target, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from typing import Iterator | ||
|
||
from dissect.target.helpers.record import TargetRecordDescriptor | ||
from dissect.target.plugin import Plugin, export | ||
|
||
EnvironmentVariableRecord = TargetRecordDescriptor( | ||
"linux/proc/environ", | ||
[ | ||
("datetime", "ts"), | ||
("string", "name"), | ||
("varint", "pid"), | ||
("string", "variable"), | ||
("string", "content"), | ||
], | ||
) | ||
|
||
|
||
class EnvironPlugin(Plugin): | ||
def check_compatible(self) -> None: | ||
self.target.proc | ||
|
||
@export(record=EnvironmentVariableRecord) | ||
def environ(self) -> Iterator[EnvironmentVariableRecord]: | ||
"""Return the initial environment for all processes when they were started via execve(2). | ||
If the process modified its environment (e.g., by calling functions such as putenv(3) or modifying | ||
the environ(7) variable directly), this plugin will not reflect those changes. | ||
Yields EnvironmentVariableRecord with the following fields: | ||
hostname (string): The target hostname. | ||
domain (string): The target domain. | ||
ts (datetime): The modification timestamp of the processes' environ file. | ||
name (string): The name associated to the pid. | ||
pid (varint): The process id (pid) of the process. | ||
variable (string): The name of the environment variable. | ||
content (string): The contents of the environment variable. | ||
""" | ||
for process in self.target.proc.processes(): | ||
for environ in process.environ(): | ||
yield EnvironmentVariableRecord( | ||
ts=process.get("environ").stat().st_mtime, | ||
name=process.name, | ||
pid=process.pid, | ||
variable=environ.variable, | ||
content=environ.contents, | ||
_target=self.target, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from itertools import chain | ||
from typing import Iterator | ||
|
||
from dissect.target.plugin import Plugin, export | ||
|
||
NETSTAT_HEADER = f"Active Internet connections (only servers)\n{'Proto':<10}{'Recv-Q':^10}{'Send-Q':^10}{'Local Address':^20}{'Foreign Address':^20}{'State':^10}{'User':^15}{'Inode':^10}{'PID/Program name':^10}{'Command':>10}" # noqa | ||
NETSTAT_TEMPLATE = "{protocol:<12}{receive_queue:<10}{transmit_queue:<11}{local_addr:<19}{remote_addr:<20}{state:<13}{owner:<12}{inode:<8}{pid_program:<19}{cmdline}" # noqa | ||
|
||
|
||
class NetstatPlugin(Plugin): | ||
def check_compatible(self) -> None: | ||
self.target.proc | ||
|
||
@export(output="yield") | ||
def netstat(self) -> Iterator[str]: | ||
"""This plugin mimics the output `netstat -tunelwap` would generate on a Linux machine.""" | ||
sockets = chain( | ||
self.target.sockets.tcp(), | ||
self.target.sockets.udp(), | ||
self.target.sockets.raw(), | ||
) | ||
|
||
yield NETSTAT_HEADER | ||
|
||
for record in sockets: | ||
local_addr = f"{record.local_ip}:{record.local_port}" | ||
remote_addr = f"{record.remote_ip}:{record.remote_port}" | ||
pid_program = f"{record.pid}/{record.name}" | ||
|
||
yield NETSTAT_TEMPLATE.format( | ||
protocol=record.protocol, | ||
receive_queue=record.rx_queue, | ||
transmit_queue=record.tx_queue, | ||
local_addr=local_addr, | ||
remote_addr=remote_addr, | ||
state=record.state, | ||
owner=record.owner, | ||
inode=record.inode, | ||
pid_program=pid_program, | ||
cmdline=record.cmdline, | ||
) |
Oops, something went wrong.