1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-24 01:25:37 +01:00

Added automatic IP address checks for 'lhost'

This commit is contained in:
Caleb Stewart 2020-05-07 17:33:22 -04:00
parent be2da59710
commit 830907d1a5
4 changed files with 48 additions and 154 deletions

View File

@ -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 """

View File

@ -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)",
) )

View File

@ -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 """

View File

@ -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)