Core concepts
Use-Cases and Agents
Naming is hard.
Usecase
We use the term 'Use-Case' for anything that can be executed within HackingBuddyGPT. That's the origin of the naming: HackingBuddyGPT is our tool, and it can run diverse use-cases.
Examples for use-cases include executing a Linux-based Privilege-Escalation Attack, Performing Web Penetration-Testing, or specialized version of the already mentioned Linux Privilege-Escalation Attack utilizing additional information such as human hints.
Custom usecases are subclasses of UseCase
and have to have to implement two abstract methods:
run
: this is the main method that will be called when a usecase is started throughhackingBuddyGPT
get_name
: this should return a name for the usecase, it will be used for logging and debugging.
Usecases automatically utilize our configuration mechanism. Usecases themselves are typically implemented using one or more agents.
Agent
The agent acts on behalf of the user and try to achieve a task given to them. In a security context, they are often given security-related tasks, i.e., they are given the goal to hack a test system.
Within hackingBuddyGPT
, agents can be created by sub-classing Agent
and implementing the perform_round
abstract method. While traditional agents often incorporate a control-loop and run continously, due to safety reasons, our agents do not contain the control loop but only the perform_round
step function which will be called through hackingBuddyGPT
. This allows our infrastructure to implement a hard round limit as well as keep the human in the loop after each performed round.
The following are fragments of an agent, showing off hackingBuddyGPT
features:
# ...
class MinimalLinuxPrivesc(Agent):
# configured through the configuration subsystem
conn: SSHConnection = None
# instance variables starting with _ are not auto-configured
_sliding_history: SlidingCliHistory = None
def init(self):
super().init()
self._sliding_history = SlidingCliHistory(self.llm)
# configure agent capabilities
self.add_capability(SSHRunCommand(conn=self.conn), default=True)
self.add_capability(SSHTestCredential(conn=self.conn))
# ..
# during each round, ask the configured LLM for a hacking command and execute it
def perform_round(self, turn: int) -> bool:
# do something ..
# if this method returns True, execution is stopped
return False
To summarize what is happening here:
- instance variables will automatically be set by the configuration subsystem. In this case, the variable
hack_level
will be exposed by hackingBuddyGPT and can be set within either an.env
file or through a command line option.wintermute.py
allows listing of all detected configuration options for each use-case. - The usecase itself is quite simple, we provide two over-writable methods:
init
should initially callsuper().init()
and then include all needed initialization code for this use-case.perform_round
will be called repeatably through hackingBuddyGPT
Matching Agents and UseCases
How do we connect usecases with agents? Typically, developers will create an autonomous agent which should be called by hackingBuddyGPT
until it returns True (the goal has been achieved) or the maximum round number has been reached.
hackingBuddyGPT
provides helper methods for this:
@use_case("Showcase Minimal Linux Priv-Escalation")
class MinimalLinuxPrivescUseCase(AutonomousAgentUseCase[MinimalLinuxPrivesc]):
pass
In this case we define a new UseCase (MinimalLinuxPrivescUseCase
) which inherits from AutonomousAgentUseCase
which in turn is parametrized with our MinimalLinuxPrivesc
agent. AutonomousAgentUseCase
incorporates all needed logic to make an agent runable.
Adding this subclass will achieve the following:
- through usage of the
use_case
annotation, hackingBuddyGPT will be able to automatically detect that this should be a callable use-case and adds it to the command line tool with the given name and description during run-time. - When called, the encapsulated agent will be configured and their
perform_round
method called until the task has been achieved or a configurable round limit reached - Both usecase and agent are configured using our Configuration System.
For a fully fleshed-out example, please see our Minimal LinuxPrivesc Usecase.