mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 09:35:39 +01:00
Added automatic IP address checks for 'lhost'
This commit is contained in:
parent
be2da59710
commit
830907d1a5
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from typing import Type
|
from typing import Type, List
|
||||||
|
|
||||||
from pwncat.downloader.base import Downloader, DownloadError
|
from pwncat.downloader.base import Downloader, DownloadError
|
||||||
from pwncat.downloader.nc import NetcatDownloader
|
from pwncat.downloader.nc import NetcatDownloader
|
||||||
@ -11,6 +11,11 @@ downloaders = [NetcatDownloader, CurlDownloader]
|
|||||||
fallback = ShellDownloader
|
fallback = ShellDownloader
|
||||||
|
|
||||||
|
|
||||||
|
def get_names() -> List[str]:
|
||||||
|
""" get the names of all downloaders """
|
||||||
|
return [d.NAME for d in all_downloaders]
|
||||||
|
|
||||||
|
|
||||||
def find(pty: "pwncat.pty.PtyHandler", hint: str = None) -> Type[Downloader]:
|
def find(pty: "pwncat.pty.PtyHandler", hint: str = None) -> Type[Downloader]:
|
||||||
""" Locate an applicable downloader """
|
""" Locate an applicable downloader """
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class PtyHandler:
|
|||||||
self.input = b""
|
self.input = b""
|
||||||
self.lhost = None
|
self.lhost = None
|
||||||
self.known_binaries = {}
|
self.known_binaries = {}
|
||||||
self.vars = {"lhost": None}
|
self.vars = {"lhost": util.get_ip_addr()}
|
||||||
self.prompt = PromptSession(
|
self.prompt = PromptSession(
|
||||||
[("", "(local) "), ("#ff0000", "pwncat"), ("", "$ ")]
|
[("", "(local) "), ("#ff0000", "pwncat"), ("", "$ ")]
|
||||||
)
|
)
|
||||||
@ -255,6 +255,7 @@ class PtyHandler:
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--method",
|
"--method",
|
||||||
"-m",
|
"-m",
|
||||||
|
choices=downloader.get_names(),
|
||||||
default=None,
|
default=None,
|
||||||
help="set the download method (default: auto)",
|
help="set the download method (default: auto)",
|
||||||
)
|
)
|
||||||
@ -329,6 +330,7 @@ class PtyHandler:
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--method",
|
"--method",
|
||||||
"-m",
|
"-m",
|
||||||
|
choices=uploader.get_names(),
|
||||||
default=None,
|
default=None,
|
||||||
help="set the download method (default: auto)",
|
help="set the download method (default: auto)",
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from typing import Type
|
from typing import Type, List
|
||||||
|
|
||||||
from pwncat.uploader.base import Uploader, UploadError
|
from pwncat.uploader.base import Uploader, UploadError
|
||||||
from pwncat.uploader.nc import NetcatUploader
|
from pwncat.uploader.nc import NetcatUploader
|
||||||
@ -11,6 +11,11 @@ uploaders = [NetcatUploader, CurlUploader]
|
|||||||
fallback = ShellUploader
|
fallback = ShellUploader
|
||||||
|
|
||||||
|
|
||||||
|
def get_names() -> List[str]:
|
||||||
|
""" Return the names of all uploaders """
|
||||||
|
return [u.NAME for u in all_uploaders]
|
||||||
|
|
||||||
|
|
||||||
def find(pty: "pwncat.pty.PtyHandler", hint: str = None) -> Type[Uploader]:
|
def find(pty: "pwncat.pty.PtyHandler", hint: str = None) -> Type[Uploader]:
|
||||||
""" Locate an applicable uploader """
|
""" Locate an applicable uploader """
|
||||||
|
|
||||||
|
184
pwncat/util.py
184
pwncat/util.py
@ -5,6 +5,7 @@ from socketserver import TCPServer, BaseRequestHandler
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
|
import netifaces
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
@ -15,73 +16,6 @@ import sys
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class SingleFileServer(BaseHTTPRequestHandler):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
request,
|
|
||||||
addr,
|
|
||||||
server,
|
|
||||||
name: str,
|
|
||||||
path: str,
|
|
||||||
content_type="application/octet-stream",
|
|
||||||
progress=None,
|
|
||||||
):
|
|
||||||
self.file_name = name
|
|
||||||
self.file_path = path
|
|
||||||
self.content_type = content_type
|
|
||||||
self.progress = progress
|
|
||||||
|
|
||||||
super(SingleFileServer, self).__init__(request, addr, server)
|
|
||||||
|
|
||||||
def do_GET(self):
|
|
||||||
""" Handle GET requests """
|
|
||||||
|
|
||||||
# We only serve this one file
|
|
||||||
if self.path != f"/{self.file_name}":
|
|
||||||
self.send_error(404)
|
|
||||||
return
|
|
||||||
|
|
||||||
length = os.path.getsize(self.file_path)
|
|
||||||
|
|
||||||
# Send response headers
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-Type", self.content_type)
|
|
||||||
self.send_header("Content-Length", str(length))
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
# Send data
|
|
||||||
with open(self.file_path, "rb") as fp:
|
|
||||||
copyfileobj(fp, self.wfile, self.progress)
|
|
||||||
|
|
||||||
def log_message(self, fmt, *args):
|
|
||||||
""" BE QUIET """
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class SingleFileReceiver(BaseHTTPRequestHandler):
|
|
||||||
def __init__(self, request, addr, server, name, dest_path, progress):
|
|
||||||
self.dest_path = dest_path
|
|
||||||
self.file_name = name
|
|
||||||
self.progress = progress
|
|
||||||
super(SingleFileReceiver, self).__init__(request, addr, server)
|
|
||||||
|
|
||||||
def do_POST(self):
|
|
||||||
""" handle http POST request """
|
|
||||||
|
|
||||||
if self.path != f"/{self.file_name}":
|
|
||||||
self.send_error(404)
|
|
||||||
return
|
|
||||||
|
|
||||||
self.send_response(200)
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
with open(self.dest_path, "wb") as fp:
|
|
||||||
copyfileobj(self.rfile, fp, self.progress)
|
|
||||||
|
|
||||||
def log_message(self, *args, **kwargs):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def copyfileobj(src, dst, callback):
|
def copyfileobj(src, dst, callback):
|
||||||
""" Copy a file object to another file object with a callback.
|
""" Copy a file object to another file object with a callback.
|
||||||
This method assumes that both files are binary and support readinto
|
This method assumes that both files are binary and support readinto
|
||||||
@ -169,94 +103,42 @@ def restore_terminal(state):
|
|||||||
info("local terminal restored")
|
info("local terminal restored")
|
||||||
|
|
||||||
|
|
||||||
def serve_http_file(
|
def get_ip_addr() -> str:
|
||||||
path: str, name: str, port: int = 0, progress: Callable = None
|
""" Retrieve the current IP address. This will return the first tun/tap
|
||||||
) -> HTTPServer:
|
interface if availabe. Otherwise, it will return the first "normal"
|
||||||
""" Serve a single file on the given port over HTTP. """
|
interface with no preference for wired/wireless. """
|
||||||
|
|
||||||
# Create an HTTP server
|
PROTO = netifaces.AF_INET
|
||||||
server = HTTPServer(
|
ifaces = [
|
||||||
("0.0.0.0", port),
|
iface
|
||||||
partial(SingleFileServer, name=name, path=path, progress=progress),
|
for iface in netifaces.interfaces()
|
||||||
)
|
if not iface.startswith("virbr")
|
||||||
|
and not iface.startswith("lo")
|
||||||
|
and not iface.startswith("docker")
|
||||||
|
]
|
||||||
|
targets = []
|
||||||
|
|
||||||
# Start serving the file
|
# look for a tun/tap interface
|
||||||
thread = threading.Thread(target=lambda: server.serve_forever(), daemon=True)
|
for iface in ifaces:
|
||||||
thread.start()
|
if iface.startswith("tun") or iface.startswith("tap"):
|
||||||
|
addrs = netifaces.ifaddresses(iface)
|
||||||
|
print(addrs)
|
||||||
|
if PROTO not in addrs:
|
||||||
|
continue
|
||||||
|
for a in addrs[PROTO]:
|
||||||
|
if "addr" in a:
|
||||||
|
return a["addr"]
|
||||||
|
|
||||||
return server
|
# Try again. We don't care what kind now
|
||||||
|
for iface in ifaces:
|
||||||
|
addrs = netifaces.ifaddresses(iface)
|
||||||
|
if PROTO not in addrs:
|
||||||
|
continue
|
||||||
|
for a in addrs[PROTO]:
|
||||||
|
if "addr" in a:
|
||||||
|
return a["addr"]
|
||||||
|
|
||||||
|
return None
|
||||||
def receive_http_file(
|
|
||||||
dest_path: str, name: str, port: int = 0, progress: Callable = None
|
|
||||||
) -> HTTPServer:
|
|
||||||
""" Serve a single file on the given port over HTTP. """
|
|
||||||
|
|
||||||
# Create an HTTP server
|
|
||||||
server = HTTPServer(
|
|
||||||
("0.0.0.0", port),
|
|
||||||
partial(SingleFileReceiver, name=name, dest_path=dest_path, progress=progress),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Start serving the file
|
|
||||||
thread = threading.Thread(target=lambda: server.serve_forever(), daemon=True)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
return server
|
|
||||||
|
|
||||||
|
|
||||||
def receive_raw_file(
|
|
||||||
dest_path: str, name: str, port: int = 0, progress: Callable = None
|
|
||||||
) -> TCPServer:
|
|
||||||
""" Serve a file on the given port """
|
|
||||||
|
|
||||||
class SocketWrapper:
|
|
||||||
def __init__(self, sock):
|
|
||||||
self.s = sock
|
|
||||||
|
|
||||||
def read(self, n: int):
|
|
||||||
try:
|
|
||||||
return self.s.recv(n)
|
|
||||||
except socket.timeout:
|
|
||||||
return b""
|
|
||||||
|
|
||||||
class ReceiveFile(BaseRequestHandler):
|
|
||||||
def handle(self):
|
|
||||||
# We shouldn't block that long during a streaming transfer
|
|
||||||
self.request.settimeout(1)
|
|
||||||
with open(dest_path, "wb") as fp:
|
|
||||||
copyfileobj(SocketWrapper(self.request), fp, progress)
|
|
||||||
|
|
||||||
server = TCPServer(("0.0.0.0", port), ReceiveFile)
|
|
||||||
thread = threading.Thread(target=lambda: server.serve_forever(), daemon=True)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
return server
|
|
||||||
|
|
||||||
|
|
||||||
def serve_raw_file(
|
|
||||||
path: str, name: str, port: int = 0, progress: Callable = None
|
|
||||||
) -> TCPServer:
|
|
||||||
""" Serve a file on the given port """
|
|
||||||
|
|
||||||
class SocketWrapper:
|
|
||||||
def __init__(self, sock):
|
|
||||||
self.s = sock
|
|
||||||
|
|
||||||
def write(self, n: int):
|
|
||||||
return self.s.send(n)
|
|
||||||
|
|
||||||
class SendFile(BaseRequestHandler):
|
|
||||||
def handle(self):
|
|
||||||
with open(path, "rb") as fp:
|
|
||||||
copyfileobj(fp, SocketWrapper(self.request), progress)
|
|
||||||
self.request.close()
|
|
||||||
|
|
||||||
server = TCPServer(("0.0.0.0", port), SendFile)
|
|
||||||
thread = threading.Thread(target=lambda: server.serve_forever(), daemon=True)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
return server
|
|
||||||
|
|
||||||
|
|
||||||
LAST_LOG_MESSAGE = ("", False)
|
LAST_LOG_MESSAGE = ("", False)
|
||||||
|
Loading…
Reference in New Issue
Block a user