summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMalfurious <m@lfurio.us>2021-12-17 22:23:11 -0500
committerMalfurious <m@lfurio.us>2021-12-17 22:23:11 -0500
commit7bf3df5ca773cb6141afcec2fe1c830c0cbed4a6 (patch)
treea07690944ca3c5562d4756d1ac17d280278e5479 /tools
parent2d871847bca0fe530b286246b9c041162c175781 (diff)
parent76e068420455a067d22ef2d4a45d65e2875e58b6 (diff)
downloadlib-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
Diffstat (limited to 'tools')
-rw-r--r--tools/sploit/sploit/comm.py57
-rw-r--r--tools/sploit/sploit/log.py36
-rw-r--r--tools/sploit/sploit/main.py57
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)