Agent

Client

A full working example of a simple ClientAgent is the following:

import logging
from typing import List
from libpastis.agent import ClientAgent
from libpastis.types import SeedType, FuzzingEngine, ExecMode, CoverageMode, SeedInjectLoc, CheckMode, LogLevel, State

def start_received(fname: str, binary: bytes, engine: FuzzingEngine, exmode: ExecMode, chkmode: CheckMode,
                   covmode: CoverageMode, seed_inj: SeedInjectLoc,
                   engine_args: str, argv: List[str], kl_report: str=None):
    pass # commencer la campagne

def seed_received(typ: SeedType, seed: bytes):
    logging.info(f"[SEED] { seed.hex()} ({ typ} )")

def stop_received():
    logging.info(f"[STOP]")

if __name__ == "__main__":
    agent = ClientAgent()
    agent.connect() # default is localhost:5555
    agent.register_start_callback(start_received)
    agent.register_seed_callback(seed_received)
    agent.register_stop_callback(stop_received)
    agent.start() # start reception thread
    agent.send_hello([(FuzzingEngine.TRITON, "v0.8")])
class libpastis.ClientAgent[source]

Bases: NetworkAgent

Subclass of NetworkAgent to connect to PASTIS as a fuzzing agent. The class provides helper methods to interact with the broker.

bind(port: int = 5555, ip: str = '*') None

Bind on the given IP and port, to listen incoming messages.

Parameters:
  • port – listen port

  • ip – IP, can be “*” to listen on all interfaces

Returns:

None

connect(remote: str = 'localhost', port: int = 5555) bool

Connect to a remote server on the given remote IP and port.

Parameters:
  • remote – IP address or DNS

  • port – port to connect to

Returns:

Always true

critical(message: str) None[source]

Send a critical (level) message to the broker.

Parameters:

message – message to send

debug(message: str) None[source]

Send a debug message to the broker

Parameters:

message – message as a string

error(message: str) None[source]

Send an error (level) message to the broker.

Parameters:

message – message to send

info(message: str) None[source]

Send an info (level) message to the broker

Parameters:

message – message to send

static msg_to_type(msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg) MessageType

Get the MessageType from a protobuf object.

Parameters:

msg – Protobuf message

Returns:

message type

register_callback(typ: MessageType, callback: Callable) None

Register a callback function on a given message type.

Parameters:
  • typ – type of the message

  • callback – Callback function taking the protobuf object as parameter

Returns:

None

register_data_callback(cb: Callable) None[source]

Register callback called when data is received. At the moment data are necessarily AlertData messages.

Parameters:

cb – callback function

register_seed_callback(cb: Callable) None[source]

Register a callback called when an input seed is received from the broker. The callback function take 2 parameters seed type and content.

Parameters:

cb – callback function

register_start_callback(cb: Callable) None[source]

Register a callback that will be called when a start message will be received. The callback should take 11 parameters.

Parameters:

cb – callback function.

register_stop_callback(cb: Callable) None[source]

Register a callback called when the broker send a STOP message. The fuzzing has to stop running and sending data.

Parameters:

cb – callback function

run() None

Run receiving loop in a blocking manner.

send(msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg, msg_type: MessageType = None) None

Send a message on the socket (thus to the broker). Should only be used as a client (fuzzing agent).

Parameters:
  • msg – Protobuf message to send

  • msg_type – Type of the message

send_alert_data(alert_data: AlertData) None[source]

Send information related to the coverage or validation of a specific SAST alert.

Parameters:

alert_data – alert object

send_hello(engines: List[FuzzingEngineInfo], arch: Arch = None, platform: Platform = None) bool[source]

Send the hello message to the broker. engines parameter is the list of fuzzing engines that “we” as client support. E.g: Pastisd is meant to be an interface for all engines locally, so it will advertise multiple engines.

Parameters:
  • engines – list of engines, the client is able to launch

  • arch – the architecture supported (if None, local one is used)

  • platform – the platform supported (if None local one used)

send_log(level: LogLevel, message: str) None[source]

Log message to be sent and printed by the broker. All logs received by the broker are logged in a client specific logfile.

Parameters:
  • level – level of the log message

  • message – message as a string

send_seed(typ: SeedType, seed: bytes) None[source]

Send an input seed to the broker. The typ indicates the type of the seed, namely, input, crash or hang.

Parameters:
  • typ – type of the input

  • seed – bytes of the input

send_stop_coverage_criteria() None[source]

Send a message to the broker indicating, the program has been fully covered in accordance to the coverage criteria (metric).

send_telemetry(state: State = None, exec_per_sec: int = None, total_exec: int = None, cycle: int = None, timeout: int = None, coverage_block: int = None, coverage_edge: int = None, coverage_path: int = None, last_cov_update: int = None) None[source]

Send a telemetry message to the broker. These data could be used on the broker side to plot statistics.

Parameters:
  • state – current state of the fuzzer

  • exec_per_sec – number of execution per seconds

  • total_exec – total number of executions

  • cycle – number of cycles

  • timeout – timeout numbers

  • coverage_block – coverage count in blocks

  • coverage_edge – coverage count in edges

  • coverage_path – coverage count in paths

  • last_cov_update – last coverage update

send_to(id: bytes, msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg, msg_type: MessageType = None) None

Send a message to a given client. Only meant to be used when running as a server.

Parameters:
  • id – bytes id of the client

  • msg – protobuf Message object

  • msg_type – type of the message

start() None

Start the listening thread.

stop() None

Stop the listening thread.

warning(message: str) None[source]

Send a warning (level) message to the broker.

Parameters:

message – message to send

Broker

class libpastis.BrokerAgent[source]

Bases: NetworkAgent

bind(port: int = 5555, ip: str = '*') None

Bind on the given IP and port, to listen incoming messages.

Parameters:
  • port – listen port

  • ip – IP, can be “*” to listen on all interfaces

Returns:

None

connect(remote: str = 'localhost', port: int = 5555) bool

Connect to a remote server on the given remote IP and port.

Parameters:
  • remote – IP address or DNS

  • port – port to connect to

Returns:

Always true

static msg_to_type(msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg) MessageType

Get the MessageType from a protobuf object.

Parameters:

msg – Protobuf message

Returns:

message type

register_callback(typ: MessageType, callback: Callable) None

Register a callback function on a given message type.

Parameters:
  • typ – type of the message

  • callback – Callback function taking the protobuf object as parameter

Returns:

None

register_data_callback(cb: Callable) None[source]
register_hello_callback(cb: Callable) None[source]
register_log_callback(cb: Callable) None[source]
register_seed_callback(cb: Callable) None[source]
register_stop_coverage_callback(cb: Callable) None[source]
register_telemetry_callback(cb: Callable) None[source]
run() None

Run receiving loop in a blocking manner.

send(msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg, msg_type: MessageType = None) None

Send a message on the socket (thus to the broker). Should only be used as a client (fuzzing agent).

Parameters:
  • msg – Protobuf message to send

  • msg_type – Type of the message

send_seed(id: bytes, typ: SeedType, seed: bytes) None[source]

Send the given input to the client id.

Parameters:
  • id – raw id of the client

  • typ – Type of the input

  • seed – Bytes the of input

send_start(id: bytes, name: str, package: str | Path, argv: List[str], exmode: ExecMode, fuzzmode: FuzzMode, ckmode: CheckMode, covmode: CoverageMode, engine: FuzzingEngineInfo, engine_args: str, seed_loc: SeedInjectLoc, sast_report: bytes = None) None[source]

Send a START message to a fuzzing agent with all the parameters it is meant to run with.

Parameters:
  • id – raw id of the client

  • name – name of the executable file or binary package

  • package – filepath of BinaryPackage or program executable to send

  • argv – argumnets to be provided on command line

  • exmode – execution mode

  • fuzzmode – fuzzing mode

  • ckmode – checking mode

  • covmode – coverage metric to use

  • engine – descriptor of the fuzzing engine

  • engine_args – engine’s additional arguments or configuration file

  • seed_loc – location where to provide inputs (stdin or argv)

  • sast_report – SAST report if applicable

send_stop(id: bytes) None[source]

Send a stop message to the client.

Parameters:

id – raw id of the client

send_to(id: bytes, msg: InputSeedMsg | StartMsg | StopMsg | HelloMsg | LogMsg | TelemetryMsg | StopCoverageCriteria | DataMsg, msg_type: MessageType = None) None

Send a message to a given client. Only meant to be used when running as a server.

Parameters:
  • id – bytes id of the client

  • msg – protobuf Message object

  • msg_type – type of the message

start() None

Start the listening thread.

stop() None

Stop the listening thread.