diff options
author | Malfurious <m@lfurio.us> | 2021-12-17 22:23:11 -0500 |
---|---|---|
committer | Malfurious <m@lfurio.us> | 2021-12-17 22:23:11 -0500 |
commit | 7bf3df5ca773cb6141afcec2fe1c830c0cbed4a6 (patch) | |
tree | a07690944ca3c5562d4756d1ac17d280278e5479 | |
parent | 2d871847bca0fe530b286246b9c041162c175781 (diff) | |
parent | 76e068420455a067d22ef2d4a45d65e2875e58b6 (diff) | |
download | lib-des-gnux-7bf3df5ca773cb6141afcec2fe1c830c0cbed4a6.tar.gz lib-des-gnux-7bf3df5ca773cb6141afcec2fe1c830c0cbed4a6.zip |
Merge branch 'sploit-io'
This branch features changes to Sploit's 'user-interface' and some QoL
fixes pertaining to target communications.
Sploit's logging module is rewritten to make the normal text
output more readable, and all console output is now globally
filtered through it.
Explicit daemon mode is removed (now implicit) to support a new
Sploit invocation method: shebangs!
Some logging inconsistencies are addressed in the comms
front-end, and Sploit now shuts down the output stream after
user-supplied scripts finish.
* sploit-io:
sploit: Automatically shutdown outgoing comms after script execution
sploit: Catch KeyboardInterrupt in Comm.readall()
sploit: Ensure the logonread option is restored by Comm.readuntil()
sploit: Add logonwrite option to comms
sploit: Check logonread in function Comm.readall()
sploit: Add startup banner
sploit: Rework logger
sploit: Remove -d/--daemon option
-rw-r--r-- | tools/sploit/sploit/comm.py | 57 | ||||
-rw-r--r-- | tools/sploit/sploit/log.py | 36 | ||||
-rw-r--r-- | tools/sploit/sploit/main.py | 57 |
3 files changed, 93 insertions, 57 deletions
diff --git a/tools/sploit/sploit/comm.py b/tools/sploit/sploit/comm.py index 7d6cd8c..604045c 100644 --- a/tools/sploit/sploit/comm.py +++ b/tools/sploit/sploit/comm.py @@ -4,35 +4,42 @@ import os import sys import select -from sploit.log import log +from sploit.log import * from sploit.until import bind class Comm: logonread = True + logonwrite = False flushonwrite = True def __init__(self, backend): self.back = backend + def shutdown(self): + self.back.stdout.close() + def read(self, size): data = os.read(self.back.stdin.fileno(), size) if(data == b''): raise BrokenPipeError('Tried to read on broken pipe') - if self.logonread : log(data) + if self.logonread : ilog(data, file=sys.stdout, color=NORMAL) return data def readline(self): data = self.back.stdin.readline() if(data == b''): raise BrokenPipeError('Tried to read on broken pipe') - if self.logonread : log(data) + if self.logonread : ilog(data, file=sys.stdout, color=NORMAL) return data def readall(self): data = b'' - for line in self.back.stdin: - log(line) - data += line + try: + for line in self.back.stdin: + if self.logonread : ilog(line, file=sys.stdout, color=NORMAL) + data += line + except KeyboardInterrupt: + pass return data def readuntil(self, pred, /, *args, **kwargs): @@ -40,12 +47,14 @@ class Comm: pred = bind(pred, *args, **kwargs) l = self.logonread self.logonread = False - while(True): - data += self.read(1) - if(pred(data)): - break - self.logonread = l - if self.logonread : log(data) + try: + while(True): + data += self.read(1) + if(pred(data)): + break + finally: + self.logonread = l + if self.logonread : ilog(data, file=sys.stdout, color=NORMAL) return data def readlineuntil(self, pred, /, *args, **kwargs): @@ -60,12 +69,13 @@ class Comm: def write(self, data): self.back.stdout.write(data) if self.flushonwrite : self.back.stdout.flush() + if self.logonwrite : ilog(data, file=sys.stdout, color=ALT) def writeline(self, data): self.write(data + b'\n') def interact(self): - print("<--Interact Mode-->") + ilog("<--Interact Mode-->") stdin = sys.stdin.buffer os.set_blocking(self.back.stdin.fileno(), False) os.set_blocking(stdin.fileno(), False) @@ -79,9 +89,11 @@ class Comm: if(data == b''): break write(data) + def writeinput(write): + ilog(write, file=sys.stdout, color=NORMAL) readtable = { stdin.fileno() : lambda : readall(stdin.readline, self.write), - self.back.stdin.fileno() : lambda : readall(self.back.stdin.readline, log) + self.back.stdin.fileno() : lambda : readall(self.back.stdin.readline, writeinput) } readtable[self.back.stdin.fileno()]() while(not brk): @@ -97,17 +109,17 @@ class Comm: break os.set_blocking(self.back.stdin.fileno(), True) os.set_blocking(stdin.fileno(), True) - print("<--Interact Mode Done-->") + ilog("<--Interact Mode Done-->") class Process: def __init__(self, args): - print(f"Running: {' '.join(args)}") + ilog(f"Running: {' '.join(args)}") self.proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=lambda : os.setpgrp()) - print(f"PID: {self.proc.pid}") + ilog(f"PID: {self.proc.pid}") self.stdin = self.proc.stdout self.stdout = self.proc.stdin @@ -116,8 +128,8 @@ class Process: if(self.proc.poll() != None): return try: - print("Waiting on Target Program to End...") - print("Press Ctrl+C to Forcefully Kill It...") + ilog("Waiting on Target Program to End...") + ilog("Press Ctrl+C to Forcefully Kill It...") self.proc.wait() except KeyboardInterrupt: self.proc.kill() @@ -135,11 +147,11 @@ class Pipes: self.pathout = os.path.join(dirname, "out") os.mkfifo(self.pathin) os.mkfifo(self.pathout) - print("Waiting on Target to Connect...") - print("<"+self.pathin+" >"+self.pathout) + ilog("Waiting on Target to Connect...", file=sys.stdout) + ilog(f"<{self.pathin} >{self.pathout}", file=sys.stdout) self.stdout = open(self.pathin, "wb") self.stdin = open(self.pathout, "rb") - print("Connected!") + ilog("Connected!") def __del__(self): try: @@ -149,4 +161,3 @@ class Pipes: pass if getattr(self,'pathin',None) and os.path.exists(self.pathin) : os.unlink(self.pathin) if getattr(self,'pathout',None) and os.path.exists(self.pathout) : os.unlink(self.pathout) - diff --git a/tools/sploit/sploit/log.py b/tools/sploit/sploit/log.py index cd9c3be..823b252 100644 --- a/tools/sploit/sploit/log.py +++ b/tools/sploit/sploit/log.py @@ -1,6 +1,32 @@ -ENCODING = '' -def log(s): - if ENCODING != '': - s = s.decode(ENCODING) - print(s) +import codecs +import sys +# https://docs.python.org/3/library/codecs.html#standard-encodings +ENCODING = None + +ERROR = 31 +WARNING = 33 +STATUS = 32 +NORMAL = 0 +ALT = 90 + +def enc_value(value, enc): + if type(value) is bytes: + if enc is not None: + value = codecs.encode(value, enc) + elif ENCODING is not None: + value = codecs.encode(value, ENCODING) + value = str(value)[2:-1] # strip b'' + return str(value) + +def generic_log(*values, sep, end, file, flush, enc, color): + string = sep.join([ enc_value(x, enc) for x in values ]) + print(f'\033[{color}m{string}\033[0m', end=end, file=file, flush=flush) + +# For library internal use +def ilog(*values, sep=' ', end='\n', file=sys.stderr, flush=True, enc=None, color=STATUS): + generic_log(*values, sep=sep, end=end, file=file, flush=flush, enc=enc, color=color) + +# For external use in user script (via print = elog) +def elog(*values, sep=' ', end='\n', file=sys.stdout, flush=True, enc=None, color=ALT): + generic_log(*values, sep=sep, end=end, file=file, flush=flush, enc=enc, color=color) diff --git a/tools/sploit/sploit/main.py b/tools/sploit/sploit/main.py index 77ef49e..b0fe3eb 100644 --- a/tools/sploit/sploit/main.py +++ b/tools/sploit/sploit/main.py @@ -1,61 +1,60 @@ -import argparse +from argparse import ArgumentParser, REMAINDER +import gc import tempfile import traceback -import gc from sploit.comm import * +from sploit.log import * + +def print_banner(color, line1='', line2='', line3=''): + ilog() + ilog(' ░▒█▀▀▀█░▒█▀▀█░▒█░░░░▒█▀▀▀█░▀█▀░▀▀█▀▀ ', end='', color=ALT) + ilog(line1, color=ALT) + ilog(' ░░▀▀▀▄▄░▒█▄▄█░▒█░░░░▒█░░▒█░▒█░░░▒█░░ ', end='', color=color) + ilog(line2, color=ALT) + ilog(' ░▒█▄▄▄█░▒█░░░░▒█▄▄█░▒█▄▄▄█░▄█▄░░▒█░░ ', end='', color=ALT) + ilog(line3, color=ALT) + ilog() def main(): - parser = argparse.ArgumentParser(description='Execute Sploit Script Against Target') - parser.add_argument('-d', '--daemon', action='store_true', - help='run in "daemon" mode with pipes instead of a designated target') - parser.add_argument('script', - help='exploit script to run') - parser.add_argument('target', nargs=argparse.REMAINDER, - help='target program to exploit') + parser = ArgumentParser(description='Execute Sploit script against target') + parser.add_argument('script', help='Exploit script to run') + parser.add_argument('target', nargs=REMAINDER, help='Target program to exploit') args = parser.parse_args() if(len(args.target)>0): - if(args.daemon): - print("Target Given. Ignoring Daemon Flag...") target(args.script, args.target) else: - if(args.daemon): - daemon(args.script) - else: - pipe(args.script) + pipe(args.script) -def daemon(script): - print("Running in Pipe Daemon Mode...") +def pipe(script): + print_banner(ERROR, line3='Pipe Mode') with tempfile.TemporaryDirectory() as tmpdir: while(True): try: p = Pipes(tmpdir) except KeyboardInterrupt: break - runscript(script, Comm(p)); + runscript(script, Comm(p)) del p -def pipe(script): - print("Running in Pipe Mode..."); - runscript(script, Comm(Pipes())); - def target(script, target): - print("Running in Target Mode...") - runscript(script, Comm(Process(target))); + print_banner(STATUS, line3='Subprocess Mode') + runscript(script, Comm(Process(target))) def runscript(script, comm): try: - print("Running Script...") + ilog("Running Script...") code = compile(open(script).read(), script, 'exec') - exec(code, {'io': comm}) - print("Script Finished!") + exec(code, {'io': comm, 'print': elog}) + ilog("Script Finished!") + comm.shutdown() comm.readall() return except KeyboardInterrupt: pass except: - traceback.print_exc() + ilog(traceback.format_exc(), end='', color=ERROR) finally: gc.collect() - print("Script Ended Early!") + ilog("Script Ended Early!", color=WARNING) |