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
from typing import Type
from typing import Type, List
from pwncat.downloader.base import Downloader, DownloadError
from pwncat.downloader.nc import NetcatDownloader
@ -11,6 +11,11 @@ downloaders = [NetcatDownloader, CurlDownloader]
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]:
""" Locate an applicable downloader """

View File

@ -61,7 +61,7 @@ class PtyHandler:
self.input = b""
self.lhost = None
self.known_binaries = {}
self.vars = {"lhost": None}
self.vars = {"lhost": util.get_ip_addr()}
self.prompt = PromptSession(
[("", "(local) "), ("#ff0000", "pwncat"), ("", "$ ")]
)
@ -255,6 +255,7 @@ class PtyHandler:
parser.add_argument(
"--method",
"-m",
choices=downloader.get_names(),
default=None,
help="set the download method (default: auto)",
)
@ -329,6 +330,7 @@ class PtyHandler:
parser.add_argument(
"--method",
"-m",
choices=uploader.get_names(),
default=None,
help="set the download method (default: auto)",
)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
from typing import Type
from typing import Type, List
from pwncat.uploader.base import Uploader, UploadError
from pwncat.uploader.nc import NetcatUploader
@ -11,6 +11,11 @@ uploaders = [NetcatUploader, CurlUploader]
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]:
""" Locate an applicable uploader """

View File

@ -5,6 +5,7 @@ from socketserver import TCPServer, BaseRequestHandler
from functools import partial
from colorama import Fore, Style
from io import TextIOWrapper
import netifaces
import socket
import threading
import logging
@ -15,73 +16,6 @@ import sys
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):
""" Copy a file object to another file object with a callback.
This method assumes that both files are binary and support readinto
@ -169,94 +103,42 @@ def restore_terminal(state):
info("local terminal restored")
def serve_http_file(
path: str, name: str, port: int = 0, progress: Callable = None
) -> HTTPServer:
""" Serve a single file on the given port over HTTP. """
def get_ip_addr() -> str:
""" Retrieve the current IP address. This will return the first tun/tap
interface if availabe. Otherwise, it will return the first "normal"
interface with no preference for wired/wireless. """
# Create an HTTP server
server = HTTPServer(
("0.0.0.0", port),
partial(SingleFileServer, name=name, path=path, progress=progress),
)
PROTO = netifaces.AF_INET
ifaces = [
iface
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
thread = threading.Thread(target=lambda: server.serve_forever(), daemon=True)
thread.start()
# look for a tun/tap interface
for iface in ifaces:
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"]
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
return None
LAST_LOG_MESSAGE = ("", False)