#2689 Implemented initial agent actions and started on documentations. A few TODO's left to do such as validation and expanding unit tests.

This commit is contained in:
Archer.Bowen
2024-08-05 16:53:48 +01:00
parent 1933522e89
commit 4ae0275dc9
6 changed files with 412 additions and 21 deletions

View File

@@ -213,7 +213,7 @@ class AbstractC2(Application, identifier="AbstractC2"):
return True
else:
self.sys_log.warning(
f"{self.name}: failed to send a Keep Alive. The node may be unable to access the ``network."
f"{self.name}: failed to send a Keep Alive. The node may be unable to access networking resources."
)
return False
@@ -251,7 +251,7 @@ class AbstractC2(Application, identifier="AbstractC2"):
# This statement is intended to catch on the C2 Application that is listening for connection. (C2 Beacon)
if self.c2_remote_connection is None:
self.sys_log.debug(f"{self.name}: Attempting to configure remote C2 connection based off received output.")
self.c2_remote_connection = self.current_c2_session.with_ip_address
self.c2_remote_connection = IPv4Address(self.current_c2_session.with_ip_address)
self.c2_connection_active = True # Sets the connection to active
self.keep_alive_inactivity = 0 # Sets the keep alive inactivity to zero

View File

@@ -13,6 +13,7 @@ from primaite.simulator.network.transmission.network_layer import IPProtocol
from primaite.simulator.network.transmission.transport_layer import Port
from primaite.simulator.system.applications.application import ApplicationOperatingState
from primaite.simulator.system.applications.red_applications.c2.abstract_c2 import AbstractC2, C2Command, C2Payload
from primaite.simulator.system.applications.red_applications.ransomware_script import RansomwareScript
from primaite.simulator.system.software import SoftwareHealthState
@@ -44,8 +45,6 @@ class C2Beacon(AbstractC2, identifier="C2 Beacon"):
# TODO:
# Implement the placeholder command methods
# Implement the keep alive frequency.
# Implement a command output method that sends the RequestResponse to the C2 server.
# Uncomment the terminal Import and the terminal property after terminal PR
# @property
@@ -56,6 +55,14 @@ class C2Beacon(AbstractC2, identifier="C2 Beacon"):
# self.sys_log.warning(f"{self.__class__.__name__} cannot find a terminal on its host.")
# return host_terminal
@property
def _host_ransomware_script(self) -> RansomwareScript:
"""Return the RansomwareScript that is installed on the same machine as the C2 Beacon."""
ransomware_script: RansomwareScript = self.software_manager.software.get("RansomwareScript")
if ransomware_script is None:
self.sys_log.warning(f"{self.__class__.__name__} cannot find installed ransomware on its host.")
return ransomware_script
def _init_request_manager(self) -> RequestManager:
"""
Initialise the request manager.
@@ -87,6 +94,7 @@ class C2Beacon(AbstractC2, identifier="C2 Beacon"):
)
c2_remote_ip = IPv4Address(c2_remote_ip)
# TODO: validation.
frequency = request[-1].get("keep_alive_frequency")
protocol = request[-1].get("masquerade_protocol")
port = request[-1].get("masquerade_port")
@@ -127,7 +135,7 @@ class C2Beacon(AbstractC2, identifier="C2 Beacon"):
:param masquerade_port: The Port that the C2 Traffic will masquerade as. Defaults to FTP.
:type masquerade_port: Enum (Port)
"""
self.c2_remote_connection = c2_server_ip_address
self.c2_remote_connection = IPv4Address(c2_server_ip_address)
self.keep_alive_frequency = keep_alive_frequency
self.current_masquerade_port = masquerade_port
self.current_masquerade_protocol = masquerade_protocol
@@ -252,7 +260,10 @@ class C2Beacon(AbstractC2, identifier="C2 Beacon"):
:rtype: Request Response
"""
# TODO: replace and use terminal
return RequestResponse(status="success", data={"Reason": "Placeholder."})
# return RequestResponse(status="success", data={"Reason": "Placeholder."})
given_config = payload.payload
host_ransomware = self._host_ransomware_script
return RequestResponse.from_bool(host_ransomware.configure(server_ip_address=given_config["server_ip_address"]))
def _command_ransomware_launch(self, payload: MasqueradePacket) -> RequestResponse:
"""

View File

@@ -48,8 +48,8 @@ class C2Server(AbstractC2, identifier="C2 Server"):
:rtype: RequestResponse
"""
# TODO: Parse the parameters from the request to get the parameters
placeholder: dict = {}
return self._send_command(given_command=C2Command.RANSOMWARE_CONFIGURE, command_options=placeholder)
ransomware_config = {"server_ip_address": request[-1].get("server_ip_address")}
return self._send_command(given_command=C2Command.RANSOMWARE_CONFIGURE, command_options=ransomware_config)
def _launch_ransomware_action(request: RequestFormat, context: Dict) -> RequestResponse:
"""Agent Action - Sends a RANSOMWARE_LAUNCH C2Command to the C2 Beacon with the given parameters.
@@ -61,9 +61,7 @@ class C2Server(AbstractC2, identifier="C2 Server"):
:return: RequestResponse object with a success code reflecting whether the ransomware was launched.
:rtype: RequestResponse
"""
# TODO: Parse the parameters from the request to get the parameters
placeholder: dict = {}
return self._send_command(given_command=C2Command.RANSOMWARE_LAUNCH, command_options=placeholder)
return self._send_command(given_command=C2Command.RANSOMWARE_LAUNCH, command_options={})
def _remote_terminal_action(request: RequestFormat, context: Dict) -> RequestResponse:
"""Agent Action - Sends a TERMINAL C2Command to the C2 Beacon with the given parameters.
@@ -77,18 +75,18 @@ class C2Server(AbstractC2, identifier="C2 Server"):
"""
# TODO: Parse the parameters from the request to get the parameters
placeholder: dict = {}
return self._send_command(given_command=C2Command.RANSOMWARE_LAUNCH, command_options=placeholder)
return self._send_command(given_command=C2Command.TERMINAL, command_options=placeholder)
rm.add_request(
name="c2_ransomware_configure",
name="ransomware_configure",
request_type=RequestType(func=_configure_ransomware_action),
)
rm.add_request(
name="c2_ransomware_launch",
name="ransomware_launch",
request_type=RequestType(func=_launch_ransomware_action),
)
rm.add_request(
name="c2_terminal_command",
name="terminal_command",
request_type=RequestType(func=_remote_terminal_action),
)
return rm
@@ -203,7 +201,6 @@ class C2Server(AbstractC2, identifier="C2 Server"):
self.sys_log.info(f"{self.name}: Attempting to send command {given_command}.")
command_packet = self._craft_packet(given_command=given_command, command_options=command_options)
# Need to investigate if this is correct.
if self.send(
payload=command_packet,
dest_ip_address=self.c2_remote_connection,

View File

@@ -2,6 +2,8 @@
from ipaddress import IPv4Address
from typing import Dict, Optional
from prettytable import MARKDOWN, PrettyTable
from primaite.interface.request import RequestFormat, RequestResponse
from primaite.simulator.core import RequestManager, RequestType
from primaite.simulator.network.transmission.network_layer import IPProtocol
@@ -169,3 +171,25 @@ class RansomwareScript(Application, identifier="RansomwareScript"):
else:
self.sys_log.warning("Attack Attempted to launch too quickly")
return False
def show(self, markdown: bool = False):
"""
Prints a table of the current status of the Ransomware Script.
Displays the current values of the following Ransomware Attributes:
``server_ip_address`:
The IP of the target database.
``payload``:
The payload (type of attack) to be sent to the database.
:param markdown: If True, outputs the table in markdown format. Default is False.
"""
table = PrettyTable(["Target Server IP Address", "Payload"])
if markdown:
table.set_style(MARKDOWN)
table.align = "l"
table.title = f"{self.name} Running Status"
table.add_row([self.server_ip_address, self.payload])
print(table)