-
-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathpwntomate.py
More file actions
executable file
·156 lines (137 loc) · 6.66 KB
/
Copy pathpwntomate.py
File metadata and controls
executable file
·156 lines (137 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python
# This software must not be used by military or secret service organisations.
# License: TODO
import argparse
import glob
import json
import os
import subprocess
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from libnmap.parser import NmapParser
_PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
if _PROJECT_ROOT not in sys.path:
sys.path.insert(0, _PROJECT_ROOT)
from modules.security_sanitizers import ( # noqa: E402
CommandRedactor,
build_default_config,
)
greeter = '''[31m
██▓███ █ ████▄ █▄▄▄█████▓▒█████ ███▄ ▄███▓▄▄▄ ▄▄▄█████▓█████
▓██░ ██▓█░ █ ░███ ▀█ █▓ ██▒ ▓▒██▒ ██▓██▒▀█▀ ██▒████▄ ▓ ██▒ ▓▓█ ▀
▓██░ ██▓▒█░ █ ░▓██ ▀█ ██▒ ▓██░ ▒▒██░ ██▓██ ▓██▒██ ▀█▄▒ ▓██░ ▒▒███
▒██▄█▓▒ ░█░ █ ░▓██▒ ▐▌██░ ▓██▓ ░▒██ ██▒██ ▒██░██▄▄▄▄█░ ▓██▓ ░▒▓█ ▄
▒██▒ ░ ░░██▒██▒██░ ▓██░ ▒██▒ ░░ ████▓▒▒██▒ ░██▒▓█ ▓██▒▒██▒ ░░▒████▒
▒▓▒░ ░ ░ ▓░▒ ▒░ ▒░ ▒ ▒ ▒ ░░ ░ ▒░▒░▒░░ ▒░ ░ ░▒▒ ▓▒█░▒ ░░ ░░ ▒░ ░
░▒ ░ ▒ ░ ░░ ░░ ░ ▒░ ░ ░ ▒ ▒░░ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░
░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░
[0m'''
cred_path = 'sessions/credentials.txt'
version = "0.0.33#beta"
parser = argparse.ArgumentParser(description="pwntomate version " + version + "\nhttps://github.com/honze-net/pwntomate", epilog="This software must not be used by military or secret service organisations.", formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("xml", help="path to Nmap XML file")
parser.add_argument("-b", help="path to base directory for tool output (default: ~/.pwntomate)", default="~/.pwntomate", dest="basedir")
parser.add_argument("-t", help="path to custom tool directory (default: ./tools)", default="./tools", dest="tooldir")
parser.add_argument("-x", help="Executes the generated script automatically. (Be careful!)", action="store_true", dest="execute")
parser.add_argument("--strict-domain", help="Preserve legacy behaviour: crash when 'domain' is missing from payload.json. Disabled by default.", action="store_true", dest="strict_domain")
if len(sys.argv) == 1: # If no arguments are specified, print greeter, help and exit.
print(greeter)
parser.print_help()
sys.exit(1)
args = parser.parse_args()
try:
report = NmapParser.parse_fromfile(args.xml)
except OSError:
print(f'file {args.xml} not found')
sys.exit(1)
shellscript = f'''#!/bin/bash
# autogenerated script by pwntomate {version}
# https://github.com/honze-net/pwntomate
'''
with open('payload.json', 'r') as file:
config = json.load(file)
rhost = config.get("rhost")
domain = config.get("domain")
dirworlist = config.get("dirworlist")
_SECURITY_CONFIG = build_default_config(config)
_REDACTOR = CommandRedactor(_SECURITY_CONFIG)
if os.path.exists(cred_path):
with open(cred_path, 'r') as file:
text_cred = file.read().strip()
array_cred = text_cred.split(":")
username = array_cred[0]
password = f" -p '{array_cred[1]}' "
else:
username = _SECURITY_CONFIG.placeholder_username_marker
password = ''
if domain:
adomain = domain.split(".")
ext = adomain[1] if len(adomain) > 1 else adomain[0]
nameserver = adomain[0]
else:
if args.strict_domain:
raise AttributeError(
"'domain' is missing from payload.json. Legacy mode (--strict-domain) "
"requires it to be set; either provide a domain or drop --strict-domain."
)
ext = ""
nameserver = ""
def _build_substitutions(host_addr, port, toolname_value, basedir_value):
"""Return the non-credential substitution map for a tool template.
Credentials are deliberately excluded so they only enter the
command string through :class:`CommandRedactor.render`, which
guarantees the display copy never contains a real credential
byte-for-byte.
"""
return {
"s": "",
"outputdir": "{baseoutputdir}/{ip}/{port}/{toolname}",
"ip": host_addr,
"port": str(port),
"domain": domain,
"ext": ext,
"nameserver": nameserver,
"baseoutputdir": basedir_value,
"toolname": toolname_value,
}
cmds = []
for host in report.hosts:
for service in host.services:
for filename in glob.glob(args.tooldir+"/*.tool"):
tool = json.load(open(filename, 'r'))
if tool["active"] and (service.service in tool["trigger"] or 'all' in tool["trigger"]):
cmd_template = tool["command"]
if service.tunnel == 'ssl':
cmd = cmd_template.replace("{s}", "s")
else:
base_escaped = args.basedir.replace(" ", r"\ ")
tool_escaped = tool["toolname"].replace(" ", r"\ ")
substitutions = _build_substitutions(
host.address,
service.port,
tool_escaped,
base_escaped,
)
cmd, display_cmd = _REDACTOR.render(
cmd_template,
substitutions,
username,
password,
)
print(display_cmd)
mkdir_cmd = f'mkdir -p {base_escaped}/{host.address}/{service.port}/{tool_escaped}'
shellscript += mkdir_cmd + '\n'
shellscript += f'{cmd}\n'
cmds.append(f'{mkdir_cmd} && {cmd}')
if args.execute:
def _run_tool(cmd):
return subprocess.run(cmd, shell=True, capture_output=True, text=True)
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(_run_tool, cmd): cmd for cmd in cmds}
for future in as_completed(futures):
result = future.result()
os.system("chown 1000:1000 sessions -R")
os.system("chmod 755 sessions -R")
else:
print(shellscript)