pylinting round3

pull/10/head
Thorsten Sick 3 years ago
parent ab6787241c
commit 12a481da70

@ -1,23 +1,25 @@
#!/usr/bin/env python3
""" Module to control Metasploit and related tools (MSFVenom) on the attack server """
import time
import socket
import os
import random
import requests
from pymetasploit3.msfrpc import MsfRpcClient
# from app.machinecontrol import Machine
from app.attack_log import AttackLog
from app.interface_sfx import CommandlineColors
import time
import socket
from app.exceptions import MetasploitError, ServerError
import requests
import random
import os
# https://github.com/DanMcInerney/pymetasploit3
class Metasploit():
""" Metasploit class for basic Metasploit wrapping """
def __init__(self, password, attack_logger, **kwargs):
"""
@ -42,7 +44,7 @@ class Metasploit():
time.sleep(3) # Waiting for server to start. Or we would get https connection errors when getting the client.
def start_exploit_stub_for_external_payload(self, payload='linux/x64/meterpreter_reverse_tcp', exploit='exploit/multi/handler'):
"""
""" Start a metasploit handler and wait for external payload to connect
@:returns: res, which contains "job_id" and "uuid"
"""
@ -128,18 +130,18 @@ class Metasploit():
# Get_ip can also return a network name. Matching a session needs a real ip
name_resolution_worked = True
try:
ip = socket.gethostbyname(target.get_ip())
target_ip = socket.gethostbyname(target.get_ip())
except socket.gaierror:
ip = target.get_ip() # Limp on feature if we can not get a name resolution
target_ip = target.get_ip() # Limp on feature if we can not get a name resolution
name_resolution_worked = False
print(f"Name resolution for {target.get_ip()} failed. Sessions are: {self.get_client().sessions.list}")
retries = 100
while retries > 0:
for k, v in self.get_client().sessions.list.items():
if v["session_host"] == ip:
for key, value in self.get_client().sessions.list.items():
if value["session_host"] == target_ip:
# print(f"session list: {self.get_client().sessions.list}")
return k
return key
time.sleep(1)
retries -= 1
@ -180,12 +182,12 @@ class Metasploit():
shell.write(cmd)
time.sleep(delay)
retries = 20
r = ""
shell_result = ""
while retries > 0:
r += shell.read()
shell_result += shell.read()
time.sleep(0.5) # Command needs time to execute
retries -= 1
res.append(r)
res.append(shell_result)
return res
@ -223,6 +225,8 @@ class Metasploit():
class MSFVenom():
""" Class to remote controll payload generator MSFVenom on the attacker machine """
def __init__(self, attacker, target, attack_logger: AttackLog):
"""
@ -348,23 +352,18 @@ class MetasploitInstant(Metasploit):
"""
def __init__(self, password, attack_logger, **kwargs):
"""
:param password: password for the msfrpcd
:param attack_logger: The attack logging
:param kwargs: Relevant ones: uri, port, server, username
"""
super().__init__(password, attack_logger, **kwargs)
def parse_ps(self, ps_output):
d = []
""" Parses the data from ps
:param ps_output: Metasploit ps output
:return: A list of dicts
"""
ps_data = []
for line in ps_output.split("\n")[6:]:
pieces = line.split(" ")
cleaned_pieces = []
for p in pieces:
if len(p):
cleaned_pieces.append(p)
for piece in pieces:
if len(piece):
cleaned_pieces.append(piece)
if len(cleaned_pieces) > 2:
rep = {"PID": int(cleaned_pieces[0].strip()),
@ -382,9 +381,9 @@ class MetasploitInstant(Metasploit):
rep["User"] = cleaned_pieces[5].strip()
if len(cleaned_pieces) >= 7:
rep["Path"] = cleaned_pieces[6].strip()
d.append(rep)
ps_data.append(rep)
return d
return ps_data
def filter_ps_results(self, data, user=None, name=None, arch=None):
""" Filter the process lists for certain

@ -1,7 +1,6 @@
#!/usr/bin/env python3
""" Manage plugins """
import straight.plugin
from glob import glob
import os
@ -10,6 +9,7 @@ from plugins.base.attack import AttackPlugin
from plugins.base.machinery import MachineryPlugin
from plugins.base.sensor import SensorPlugin
from plugins.base.vulnerability_plugin import VulnerabilityPlugin
import straight.plugin
from app.interface_sfx import CommandlineColors
# from app.interface_sfx import CommandlineColors
@ -180,15 +180,16 @@ class PluginManager():
# TODO: Add verify command to verify all plugins (or a specific one)
def print_default_config(self, subclass_name, name):
""" Pretty prints the default config for this plugin """
subclass = None
for a in sections:
if a["name"] == subclass_name:
subclass = a["subclass"]
for section in sections:
if section["name"] == subclass_name:
subclass = section["subclass"]
if subclass is None:
print("Use proper subclass. Available subclasses are: ")
"\n- ".join([a for a in sections["name"]])
"\n- ".join(list(sections["name"]))
plugins = self.get_plugins(subclass, [name])
for plugin in plugins:

@ -3,11 +3,10 @@
""" Base class for classes to control any kind of machine: vm, bare metal, cloudified """
from enum import Enum
import os
from app.config import MachineConfig
from app.interface_sfx import CommandlineColors
from plugins.base.plugin_base import BasePlugin
import os
class MachineStates(Enum):

@ -20,28 +20,20 @@ class SensorPlugin(BasePlugin):
super().__init__() # pylint:disable=useless-super-delegation
self.debugit = False
def set_sysconf(self, config):
""" Set system config
@param config: A dict with system configuration relevant for all plugins
"""
super().set_sysconf(config)
def prime(self):
def prime(self): # pylint: disable=no-self-use
""" prime sets hard core configs in the target. You can use it to call everything that permanently alters the OS by settings.
If your prime function returns True the machine will be rebooted after prime-ing it. This is very likely what you want. Only use prime if install is not sufficient.
"""
return False
def install(self):
def install(self): # pylint: disable=no-self-use
""" Install the sensor. Executed on the target. Take the sensor from the share and (maybe) copy it to its destination. Do some setup
"""
return True
def start(self, disown=None):
def start(self, disown=None): # pylint: disable=unused-argument, no-self-use
""" Start the sensor. The connection to the client is disowned here. = Sent to background. This keeps the process running.
@param disown: Send async into background
@ -49,7 +41,7 @@ class SensorPlugin(BasePlugin):
return True
def stop(self):
def stop(self): # pylint: disable=no-self-use
""" Stop the sensor """
return True

@ -1,22 +1,28 @@
#!/usr/bin/env python3
""" A class you can use to add SSH features to you plugin. Useful for vm_controller/machinery classes """
import os.path
import socket
import time
import paramiko
from fabric import Connection
from app.exceptions import NetworkError
from invoke.exceptions import UnexpectedExit
import paramiko
import time
import socket
from app.exceptions import NetworkError
from plugins.base.plugin_base import BasePlugin
class SSHFeatures(BasePlugin):
""" A Mixin class to add SSH features to all kind of VM machinery """
def __init__(self):
self.config = None
super().__init__()
self.connection = None
def get_ip(self):
""" Get the IP of a machine, must be overwritten in the machinery class """
raise NotImplementedError
def connect(self):
""" Connect to a machine """
@ -79,14 +85,13 @@ class SSHFeatures(BasePlugin):
result = self.connection.run(cmd, disown=disown)
print(result)
# paramiko.ssh_exception.SSHException in the next line is needed for windows openssh
except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit, paramiko.ssh_exception.SSHException):
except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit, paramiko.ssh_exception.SSHException) as error:
if retry <= 0:
raise NetworkError
else:
self.disconnect()
self.connect()
retry -= 1
self.vprint("Got some SSH errors. Retrying", 2)
raise NetworkError from error
self.disconnect()
self.connect()
retry -= 1
self.vprint("Got some SSH errors. Retrying", 2)
else:
break
@ -122,8 +127,8 @@ class SSHFeatures(BasePlugin):
time.sleep(retry_sleep)
self.disconnect()
self.connect()
except FileNotFoundError as e:
self.vprint(f"File not found: {e}", 0)
except FileNotFoundError as error:
self.vprint(f"File not found: {error}", 0)
break
else:
return res
@ -146,16 +151,15 @@ class SSHFeatures(BasePlugin):
while retry > 0:
try:
res = self.connection.get(src, dst)
except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit):
except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit) as error:
if retry <= 0:
raise NetworkError
else:
self.disconnect()
self.connect()
retry -= 1
self.vprint("Got some SSH errors. Retrying", 2)
except FileNotFoundError as e:
self.vprint(e, 0)
raise NetworkError from error
self.disconnect()
self.connect()
retry -= 1
self.vprint("Got some SSH errors. Retrying", 2)
except FileNotFoundError as error:
self.vprint(error, 0)
break
else:
break

Loading…
Cancel
Save