Core

Agent

client.py client side responsible for the managing clients and scan execution flow.

class dscan.client.Agent(config)[source]

Bases: object

Agent client implementation.

do_auth()[source]

Initiate the authentication.

Returns:True if the status code of the last operation is dscan.models.structures.Status.SUCCESS False otherwise.
Return type:bool
do_ready()[source]

This is recursive method and is responsible for, notifying the server is ready to execute a new scan, launch the scan and save the report. Until the server returns no target to scan.

is_connected()[source]

Check if the agent is still connected and not yet finished.

Returns:True if the client has disconnected or the terminate event has been triggered, else False.
Return type:bool
send_status(status)[source]
Parameters:status – int of a valid dscan.models.structures.Status
shutdown()[source]

Set the terminate event On, to shutdown the agent.

start()[source]

Start the client connects to the server and authenticates.

Returns:True if was able to connect and authentication was successful else False.
Return type:bool

Server

server.py server side responsible for the managing clients and scan execution flow.

class dscan.server.AgentHandler(*args, terminate_event, context, **kwargs)[source]

Bases: socketserver.BaseRequestHandler

HEADER = '<B'

Created when an agent connects, holds all the agents available actions. Terminates when scan targets finishes or an agent disconnects.

agent

string representation of a connection ip:port.

Returns:str format of agent name ip:port
dispatcher()[source]

Command dispatcher all logic to decode and dispatch the call.

do_auth()[source]

Handles the agent’s authentication.

do_ready()[source]

After the authentication the agent notifies the server, that is ready to start scanning. This will handle the request and send a target to be scanned.

do_report()[source]

When the scan the ends, the agent notifies the server that is ready to send the report. This method will handle the report transfer save the report in the reports directory and make the target as finished if the file hashes match.

handle()[source]

First method to be called by BaseRequestHandler. responsible for initial call to authentication do_auth, and dispatcher, the connection is kept alive as long as agent is connected and their are targets to be delivered.

is_connected

Check if the client is still connected, the terminate event has not been set and all stages are finished or not.

Returns:True if the client has disconnected or the terminate event has been triggered, else False
Return type:bool
send_status(code)[source]

Sends a status code to the server.

Parameters:code (dscan.models.structures.Status) –
class dscan.server.DScanServer(*args, options, **kwargs)[source]

Bases: socketserver.ThreadingMixIn, socketserver.TCPServer

Foundation of the Server. Implements the shutdown with threading.Event, and ssl configurations. and injects threading.Event to the RequestHandlerClass

allow_reuse_address = True
daemon_threads = True
finish_request(request, client_address) → socketserver.BaseRequestHandler[source]

Finish one request by instantiating RequestHandlerClass.

Returns:RequestHandlerClass
Return type:´RequestHandlerClass´
get_request() → tuple[source]

Used to add ssl support.

Returns:returns a ssl.wrap_socket
Return type:´ssl.wrap_socket´
secret_key
Returns:str secret key generated in the config based on the certificate
shutdown()[source]

An override to allow a local terminate event to be set!

Output

out.py Display the information and status.

class dscan.out.ContextDisplay(context)[source]

Bases: dscan.out.Display

Context is displayed as a table.

ACTIVE_STAGES_HEADERS = ['Stage', 'Nº Targets', 'Nº Finished', 'Completion %']
STAGES_HEADERS = ['Nº Stages', 'Nº Pending Tasks', 'Completion %']
TASK_HEADERS = ['Agent', 'Stage', 'Task Status', 'Target Ip']
show()[source]

Takes the context’s status, active stages status, and task status and prints them in a tabular format.

class dscan.out.Display[source]

Bases: object

Visualisation of the current execution status.

CLEAR_CURRENT_LINE = '\x1b[1K\x1b[0G'
CLEAR_SCREEN = '\x1bc'
TITLE = 'Distributed Scan Status'
inline(message)[source]
Parameters:message – string message to print underneath the table printer.
print_table(headers, data, clear=False)[source]

Created based on active code recepie.

Parameters:
  • headerslist of str table headers.
  • data – a list of tuple with the data to be showed.
  • clearbool clear the previous print.
static print_title(title)[source]
Parameters:title – Title of the tabular output.
show()[source]

meant to be overwritten

Models Parsers

parsers.py parsers models, input ip address list collapse, or scanner results to parse.

class dscan.models.parsers.ReportsParser(reports_path, pattern)[source]

Bases: object

XML Nmap results parser.

hosts_up()[source]
Returns:list of hosts up.
Return type:list
class dscan.models.parsers.TargetOptimization(fpath, cidr='/24')[source]

Bases: object

This class takes lists of hosts or networks, and attempts to optimize
them by either split big cidr like /8 /16 in /24 or in rage format 192.168.10.1-4.
save(targets)[source]

Takes a list of targets to optimize and saves it in the workspace path.

Parameters:targetslist of targets (str and top optimize.
Type:targets: list of str
dscan.models.parsers.parse_args()[source]

Used by main to parse the user arguments.

Returns:argparse instance.
Return type:argparse.ArgumentParser

Models Scanner

scanner.py scanner runtime models

class dscan.models.scanner.Config(config, options)[source]

Bases: object

Runtime configurations

BASE = ('base', 'reports')
SSL_CERTS = ('certs', 'sslcert', 'sslkey', 'ciphers', 'cert-hostname')
get_workPath(path)[source]
class dscan.models.scanner.Context(options)[source]

Bases: object

Context is a thread safe proxy like class, responsible for all the execution flow and inherent logic. Acts as a proxy between the active stages and the stage implementation.

active_stages_status()[source]
Returns:list of tuples with active stages status.
Return type:list of tuples
completed(agent)[source]

Marks a agent task as complete.

Parameters:agent (str) – ip:port of agent
classmethod create(options)[source]
Parameters:options (´ServerConfig´) – instance of ServerConfig
Returns:instance of Context
Return type:´Context`
ctx_status()[source]
downloading(agent)[source]

Marks a agent task as Downloading, notifying that the report download has started.

Parameters:agent (str) – ip:port of agent
get_report(agent, file_name)[source]
Parameters:
  • agent (str) – str with ipaddress and port in ip:port format
  • file_name (str) – name of the file sent by the agent.
Returns:

file descriptor to save the scan report.

interrupted(agent)[source]

Marks a task as interrupted, when agent disconnects for example.

Parameters:agent (str) – ip:port of agent
is_finished
Returns:bool iterates the active stages and collects all the finished properties, returns True if all of them are true.
pop(agent)[source]

Gets the next Task from the current Active Stage, if their are no pending Tasks to be executed. Pending tasks are tasks that are canceled or restored from a previous interrupted session. If a stage is finished (no more targets), the next stage will take another stage from the list until its finished.

Parameters:agent – str with ipaddress and port in ip:port format, this allows the server to manage multiple agents in one host. to run multiple clients at once.
Returns:A target to scan! task
Return type:tuple
running(agent)[source]

After the server sends a target the agent notifies the task has started.

Parameters:agent (str) – ip:port of agent
tasks_status()[source]
Returns:list of tuple of active task’s status.
Return type:list of `tuple`s
class dscan.models.scanner.DiscoveryStage(targets_path, options, outdir, ltargets_path)[source]

Bases: dscan.models.scanner.Stage

process_results()[source]

When this stage is finished the Context will call this method to create a list of live targets.

class dscan.models.scanner.File(path)[source]

Bases: object

Creates a stateful file object allows file to restore its previous state.

exists()[source]
Returns a Boolean if the path is a valid file.
proxy call to os.path.isfile.
Returns:True if path is a valid file.
isempty()[source]

Check if the file is emtpy.

Returns:True if the file is empty
open(mode='r')[source]
readable()[source]
Returns:True if file is readable.
readline()[source]
class dscan.models.scanner.STATUS[source]

Bases: enum.Enum

Each Scan task has the following states: - Scheduled: the default state set when its created. - Running: Set after the agent has confirmed the task has started executing. - Interrupted: Set when the task is aborted by agent, or the server has been halted. - Downloading: Set when the agent notifies its ready to sent the report. - Completed: Set only after the report has been received successfully

COMPLETED = 5
DOWNLOADING = 4
INTERRUPTED = 3
RUNNING = 2
SCHEDULED = 1
class dscan.models.scanner.ScanProcess(output)[source]

Bases: object

Used by the agent (client side), its a proxy class to provide an interface to interact with libnmap responsible for the actual execution. Its implementation allows handling, duplicate file names, with numeric prefix, as well as keeping status on the execution process.

TASK_HEADERS = ['Target', 'Nª completed Scans', 'Status']
print(target, progress)[source]
report_name(extension)[source]

Checks if a report with the current target.extension exists, and prepends a number if it does.

Parameters:extension – xml, nmap.
Returns:path str path and filename, the filename will be prefixed, by a number if the base+extension already exists in the outdir.
Return type:str
run(target, options, callback)[source]

Executes the scan on a given target.

Parameters:
  • target
  • options
  • callback – callback function to report status to the server.
Returns:

report object

Return type:

dscan.models.structures.Report

show_status(nmapscan=None)[source]
Parameters:nmapscan (libnmap.process.NmapProcess) – takes libnmap.process.NmapProcess instance to display the current status of the scan.
class dscan.models.scanner.ServerConfig(config, options, outdir)[source]

Bases: object

Server configuration parser.

SCAN_CONF = 'nmap-scan'
SERVER = ('server', 'stats', 'targets', 'live-targets', 'trace')
save_context(ctx)[source]

Serializes the context to resume later.

Parameters:ctx (Context) – instance of Context
target_optimization(targets)[source]

Takes a list of ip Addresses and groups all sequential ips in cidr notation.

Parameters:targetslist of str
Type:list of str
class dscan.models.scanner.Stage(stage_name, targets_path, options, outdir)[source]

Bases: object

as_tuple()[source]

Returns the information as tuple, nlines, finished targets and %, used by Display to print scanner status.

Returns:tuple of strings.
Return type:tuple of str.
close()[source]
inc_finished()[source]
isfinished
Returns True if the number of lines is equal to the number of
finished targets.
Returns:bool
Return type:bool
next_task()[source]

Get next target from the file.

Returns:Task.
Return type:Task
percentage

Calculates the completion of this stage.

Returns:float of of the % completion.
Return type:float
process_results()[source]

Meant to be overwritten, like for example stages like ping sweep aka discovery.

class dscan.models.scanner.Task(stage_name, options, target)[source]

Bases: object

Representation of a scan task. A scan task is sent to an agent with a target and, scan options. Each task has the following states: - Scheduled: the default state set when its created. - Running: Set after the agent has confirmed the task has started executing. - Interrupted: Set when the task is aborted by agent, or the server has been halted. - Downloading: Set when the agent notifies its ready to sent the report. - Completed: Set only after the report has been received successfully.

as_tuple()[source]

returns a tuple with the target and scan options.

Returns:tuple options, target
Rtype tuple:
update(status)[source]

Models Structures

structures.py network elements of the scanner

class dscan.models.structures.Auth(*args, sock=None)[source]

Bases: dscan.models.structures.Structure

Authentication Request from an Agent to server!

data
op_code = 1
class dscan.models.structures.Command(*args, sock=None)[source]

Bases: dscan.models.structures.Structure

Scan task information ! Send by the server to the agent. final format is <BB?s?s

op_code = 3
options
target
class dscan.models.structures.Operations[source]

Bases: enum.IntEnum

Commands available!

AUTH = 1
COMMAND = 3
READY = 2
REPORT = 6
STATUS_REQ = 4
STATUS_RESP = 5
class dscan.models.structures.Ready(*args, sock=None)[source]

Bases: dscan.models.structures.Structure

Ready to start Scan ! Sent by an Agent to the server With the client’s current user id

alias
op_code = 2
uid
class dscan.models.structures.Report(*args, sock=None)[source]

Bases: dscan.models.structures.Structure

When an agent’s task terminates, it initiates a report transfer request

filehash
filename
filesize
op_code = 6
class dscan.models.structures.Status[source]

Bases: enum.IntEnum

Code values for the response status.

FAILED = 255
FINISHED = 2
SUCCESS = 0
UNAUTHORIZED = 1
class dscan.models.structures.Structure(*args, sock=None)[source]

Bases: object

HEADER = '<B'

The object representation for the info exchanged between agents and servers.

classmethod create(sock)[source]
op_code = None
pack()[source]

Returns a struct.pack string ready to be sent :return: struct.pack

setData(*args)[source]
unpack(sock)[source]

Unpacks a known command based on the predefined :param sock: :return: Instance of a message subclass