minor polish / comments

This commit is contained in:
epi052
2020-01-21 06:59:22 -06:00
parent bc0c975d69
commit 210801b47f
3 changed files with 39 additions and 63 deletions

5
.gitignore vendored
View File

@@ -102,3 +102,8 @@ venv.bak/
# mypy
.mypy_cache/
.idea
.flake8
.pre-commit-config.yaml
pyproject.toml

View File

@@ -16,11 +16,11 @@ os.environ["PYTHONPATH"] = f"{os.environ.get('PYTHONPATH')}:{str(Path(__file__).
os.environ["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
# third party imports
import cmd2
from cmd2.ansi import style
import cmd2 # noqa: E402
from cmd2.ansi import style # noqa: E402
# project's module imports
from recon import get_scans, tools, scan_parser, install_parser
from recon import get_scans, tools, scan_parser, install_parser # noqa: F401,E402
# select loop, handles async stdout/stderr processing of subprocesses
selector = selectors.DefaultSelector()
@@ -150,15 +150,16 @@ class ReconShell(cmd2.Cmd):
)
)
# get_scans() returns mapping of {modulename: classname} in the recon module
# get_scans() returns mapping of {classname: [modulename, ...]} in the recon module
# each classname corresponds to a potential recon-pipeline command, i.e. AmassScan, CORScannerScan ...
scans = get_scans()
# command is a list that will end up looking something like what's below
# luigi --module recon.web.webanalyze WebanalyzeScan --target-file tesla --top-ports 1000 --interface eth0
command = ["luigi", "--module", scans.get(args.scantype)[0]]
command.extend(args.__statement__.arg_list)
self.async_alert(" ".join(command))
if args.verbose:
# verbose is not a luigi option, need to remove it
command.pop(command.index("--verbose"))
@@ -209,11 +210,7 @@ class ReconShell(cmd2.Cmd):
continue
self.async_alert(
style(
f"[!] {args.tool} has an unmet dependency; installing {dependency}",
fg="yellow",
bold=True,
)
style(f"[!] {args.tool} has an unmet dependency; installing {dependency}", fg="yellow", bold=True,)
)
# install the dependency before continuing with installation
@@ -238,18 +235,12 @@ class ReconShell(cmd2.Cmd):
if tools.get(args.tool).get("shell"):
# go tools use subshells (cmd1 && cmd2 && cmd3 ...) during install, so need shell=True
proc = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
else:
# "normal" command, split up the string as usual and run it
proc = subprocess.Popen(
shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# register stderr for more visually pleasing output on failed commands
# selector.register(proc.stderr, selectors.EVENT_READ, self._install_error_reporter)
out, err = proc.communicate()
if err:
@@ -281,7 +272,5 @@ class ReconShell(cmd2.Cmd):
if __name__ == "__main__":
rs = ReconShell(
persistent_history_file="~/.reconshell_history", persistent_history_length=10000
)
rs = ReconShell(persistent_history_file="~/.reconshell_history", persistent_history_length=10000)
sys.exit(rs.cmdloop())

View File

@@ -1,7 +1,9 @@
# flake8: noqa E231
import sys
import socket
import inspect
import pkgutil
import importlib
from pathlib import Path
from collections import defaultdict
@@ -25,11 +27,7 @@ tools = {
"shell": True,
},
"luigi": {"installed": False, "dependencies": ["pipenv"], "commands": ["pipenv install luigi"]},
"pipenv": {
"installed": False,
"dependencies": None,
"commands": ["apt-get install -y -q pipenv"],
},
"pipenv": {"installed": False, "dependencies": None, "commands": ["apt-get install -y -q pipenv"],},
"masscan": {
"installed": False,
"dependencies": None,
@@ -40,11 +38,7 @@ tools = {
"rm -rf /tmp/masscan",
],
},
"amass": {
"installed": False,
"dependencies": None,
"commands": ["apt-get install -y -q amass"],
},
"amass": {"installed": False, "dependencies": None, "commands": ["apt-get install -y -q amass"],},
"aquatone": {
"installed": False,
"dependencies": None,
@@ -88,10 +82,7 @@ tools = {
"subjack": {
"installed": False,
"dependencies": ["go"],
"commands": [
"go get github.com/haccer/subjack",
"(cd ~/go/src/github.com/haccer/subjack && go install)",
],
"commands": ["go get github.com/haccer/subjack", "(cd ~/go/src/github.com/haccer/subjack && go install)",],
"shell": True,
},
"webanalyze": {
@@ -122,20 +113,26 @@ def get_scans():
*** A contract exists here that says any scans need to end with the word scan in order to be found by this function.
Returns:
dict() containing mapping of {modulename: classname} for all potential recon-pipeline commands
dict() containing mapping of {classname: [modulename, ...]} for all potential recon-pipeline commands
ex: defaultdict(<class 'list'>, {'AmassScan': ['recon.amass'], 'MasscanScan': ['recon.masscan'], ... })
"""
scans = defaultdict(list)
# recursively walk packages; import each module in each package
for loader, module_name, is_pkg in pkgutil.walk_packages(recon.__path__, prefix="recon."):
_module = loader.find_module(module_name).load_module(module_name)
globals()[module_name] = _module
# walk_packages yields ModuleInfo objects for all modules recursively on path
# prefix is a string to output on the front of every module name on output.
for loader, module_name, is_pkg in pkgutil.walk_packages(path=recon.__path__, prefix="recon."):
importlib.import_module(module_name)
# walk all modules, grabbing classes that we've written and add them to the classlist set
# walk all modules, grabbing classes that we've written and add them to the classlist defaultdict
# getmembers returns all members of an object in a list of tuples (name, value)
for name, obj in inspect.getmembers(sys.modules[__name__]):
if inspect.ismodule(obj) and not name.startswith("_"):
# we're only interested in modules that don't begin with _ i.e. magic methods __len__ etc...
for subname, subobj in inspect.getmembers(obj):
if inspect.isclass(subobj) and subname.lower().endswith("scan"):
# now we only care about classes that end in [Ss]can
scans[subname].append(name)
return scans
@@ -143,9 +140,7 @@ def get_scans():
# options for ReconShell's 'install' command
install_parser = cmd2.Cmd2ArgumentParser()
install_parser.add_argument(
"tool", help="which tool to install", choices=list(tools.keys()) + ["all"]
)
install_parser.add_argument("tool", help="which tool to install", choices=list(tools.keys()) + ["all"])
# options for ReconShell's 'scan' command
@@ -160,9 +155,7 @@ scan_parser.add_argument(
"--exempt-list", completer_method=cmd2.Cmd.path_complete, help="list of blacklisted ips/domains"
)
scan_parser.add_argument(
"--results-dir",
completer_method=cmd2.Cmd.path_complete,
help="directory in which to save scan results",
"--results-dir", completer_method=cmd2.Cmd.path_complete, help="directory in which to save scan results",
)
scan_parser.add_argument(
"--wordlist", completer_method=cmd2.Cmd.path_complete, help="path to wordlist used by gobuster"
@@ -172,30 +165,19 @@ scan_parser.add_argument(
choices_function=lambda: [x[1] for x in socket.if_nameindex()],
help="which interface masscan should use",
)
scan_parser.add_argument(
"--recursive", action="store_true", help="whether or not to recursively gobust"
)
scan_parser.add_argument("--recursive", action="store_true", help="whether or not to recursively gobust")
scan_parser.add_argument("--rate", help="rate at which masscan should scan")
scan_parser.add_argument(
"--top-ports",
help="ports to scan as specified by nmap's list of top-ports (only meaningful to around 5000)",
)
scan_parser.add_argument(
"--ports", help="port specification for masscan (all ports example: 1-65535,U:1-65535)"
)
scan_parser.add_argument(
"--threads", help="number of threads for all of the threaded applications to use"
"--top-ports", help="ports to scan as specified by nmap's list of top-ports (only meaningful to around 5000)",
)
scan_parser.add_argument("--ports", help="port specification for masscan (all ports example: 1-65535,U:1-65535)")
scan_parser.add_argument("--threads", help="number of threads for all of the threaded applications to use")
scan_parser.add_argument("--scan-timeout", help="scan timeout for aquatone")
scan_parser.add_argument("--proxy", help="proxy for gobuster if desired (ex. 127.0.0.1:8080)")
scan_parser.add_argument("--extensions", help="list of extensions for gobuster (ex. asp,html,aspx)")
scan_parser.add_argument(
"--local-scheduler",
action="store_true",
help="use the local scheduler instead of the central scheduler (luigid)",
"--local-scheduler", action="store_true", help="use the local scheduler instead of the central scheduler (luigid)",
)
scan_parser.add_argument(
"--verbose",
action="store_true",
help="shows debug messages from luigi, useful for troubleshooting",
"--verbose", action="store_true", help="shows debug messages from luigi, useful for troubleshooting",
)