def hosts(self, args): get_hosts = self.client.remote('ssh', 'ssh_hosts') records = get_hosts() if args.host: for user, hosts in records.iteritems(): for alias, host in hosts.iteritems(): if args.host == alias or args.host == host.get('hostname'): self.log( Table( [{ 'KEY': k, 'VALUE': ','.join(v) if type(v) == list else v } for k, v in host.iteritems()], ['KEY', 'VALUE'], Color('{}, user={}'.format(alias, user), 'yellow'))) else: for user, hosts in records.iteritems(): self.log( Table( [{ 'ALIAS': alias, 'USER': hosts[alias].get('user', user), 'HOST': hosts[alias]['hostname'], 'PORT': hosts[alias].get('port', 22), 'KEY': ','.join(hosts[alias].get( 'identityfile', [])) } for alias in hosts if 'hostname' in hosts[alias] and not alias == '*'], ['ALIAS', 'USER', 'HOST', 'PORT', 'KEY'], Color('User: {}'.format(user), 'yellow')))
def run(self, args): if args.list: ListSids = self.client.remote('pupwinutils.security', 'ListSids') sids = ListSids() process_table = [] sids_table = [] sids_dict = {} for (pid, process, sid, username) in sids: process_table.append({ 'pid': pid, 'process': process, 'sid': sid, 'username': username }) sids_dict[sid] = username for sid, username in sids_dict.iteritems(): sids_table.append({ 'sid': sid, 'username': username }) self.log(MultiPart([ Table(process_table, [ 'pid', 'process', 'username', 'sid' ], caption='Process table'), Table(sids_table, [ 'sid', 'username' ], caption='Available Sids') ])) elif args.impersonate: if args.migrate: create_proc_as_sid = self.client.remote('pupwinutils.security', 'create_proc_as_sid', False) proc_pid = create_proc_as_sid(args.impersonate) migrate(self, proc_pid, keep=True) else: impersonate_sid_long_handle = self.client.remote( 'pupwinutils.security', 'impersonate_sid_long_handle', False) self.client.impersonated_dupHandle = impersonate_sid_long_handle(args.impersonate, close=False) self.success('Sid {} impersonated !'.format(args.impersonate)) elif args.rev2self: rev2self = self.client.remote('pupwinutils.security', 'rev2self', False) rev2self() self.client.impersonated_dupHandle = None self.success('rev2self called') else: self.error('no option supplied')
def pupygen(args, config, pupsrv, display): scriptlets = load_scriptlets(args.os, args.arch) if args.list: display(MultiPart([ Table([{ 'FORMAT': f, 'DESCRIPTION': d } for f,d in { 'client': 'generate client binary (linux/windows/apk/..)', 'py': 'fully packaged python file', 'py_oneliner': 'same as \'py\' format but served over http', 'ps1': 'generate ps1 file which embeds pupy dll (x86-x64) and inject it to current process', 'ps1_oneliner': 'load pupy remotely from memory with a single command line using powershell', 'csharp': 'generate C# source (.cs) that executes pupy', '.NET': 'compile a C# payload into a windows executable.', '.NET_oneliner': 'Loads .NET assembly from memory via powershell' }.iteritems()], ['FORMAT', 'DESCRIPTION'], Color('Available formats (usage: -f <format>)', 'yellow')), Table([{ 'TRANSPORT': name, 'DESCRIPTION': t.info } for name, t in transports.iteritems()], ['TRANSPORT', 'DESCRIPTION'], Color('Available transports (usage: -t <transport>)', 'yellow')), Table([{ 'SCRIPTLET': name, 'DESCRIPTION': sc.description, 'ARGS': '; '.join( '{}={}'.format(k,v) for k,v in sc.arguments.iteritems() ) } for name, sc in scriptlets.iteritems()], ['SCRIPTLET', 'DESCRIPTION', 'ARGS'], Color( 'Available scriptlets for {}/{} ' '(usage: -s <scriptlet>[,arg1=value1,arg2=value2]'.format( args.os or 'any', args.arch or 'any'), 'yellow')) ])) raise NoOutput() if args.workdir: os.chdir(args.workdir) script_code="" try: if args.scriptlet: script_code = pack_scriptlets( display, scriptlets, args.scriptlet, os=args.os, arch=args.arch, debug=args.debug_scriptlets) except ValueError, e: display(Error(e.message)) raise NoOutput()
def run(self, args): users = self.client.remote('pupyutils.users', 'users') users_list = users() objects = [] 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' objects.append({ 'C': u'➤' if users_list['current'] == user['name'] else '', 'NAME': Color(user['name'], color), 'GROUPS': Color(','.join(user['groups']), color), 'HOME': Color(user['home'], color) }) headers = ['C', 'NAME', 'HOME'] if args.groups: headers.insert(2, 'GROUPS') self.log(Table(objects, headers))
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, modargs): data = [] clients = server.get_clients(handler.default_filter) if not clients: return for client in clients: tags = config.tags(client.node()) if modargs.remove: tags.remove(*modargs.remove) if modargs.add: tags.add(*modargs.add) data.append({ 'ID': client.node(), 'TAGS': tags }) config.save( project=modargs.write_project, user=modargs.write_user ) handler.display(Table(data))
def run(self, args): if args.privileges: enable_privilege = self.client.remote('pupwinutils.security', 'EnablePrivilege', False) for privilege in args.privileges: try: enable_privilege(privilege) self.success('{} enabled'.format(privilege)) except Exception as e: self.error('{} was not enabled: {}'.format( privilege, e.args[1])) else: get_currents_privs = self.client.remote('pupwinutils.security', 'get_currents_privs', False) privs = get_currents_privs() content = [] for (privilege, enabled) in privs: color = 'grey' if enabled: color = 'green' content.append({ 'Privilege': Color(privilege, color), 'Enabled': Color(enabled, color) }) self.log( Table(content, ['Privilege', 'Enabled'], caption='Current priviliges'))
def run(self, args): try: interfaces = self.client.remote('pupyps', 'interfaces') families = { int(k):v for k,v in self.client.remote_const( 'pupyps', 'families' ).iteritems() } data = interfaces() families = { int(x):y for x,y in families.iteritems() } objects = [] for addr, addresses in data['addrs'].iteritems(): if args.iface and addr not in args.iface: continue color = "" if 'stats' in data and data['stats']: if addr in data['stats'] and not data['stats'][addr].get('isup'): color = 'darkgrey' elif not any([families[x.get('family')] == 'INET' for x in addresses]): color = 'grey' else: color = 'white' record = {} record['K'] = Color(addr, color or 'cyan') first = True for address in addresses: if first: first = False else: record = {} record['K'] = '' record['F'] = Color(families[address.get('family')], color) V = Color(address.get('address', '').split('%')[0], color or 'yellow') if address.get('netmask') != 'None': V = Line(V, Color(address.get('netmask'), color)) V.dm = '/' if address.get('broadcast') != 'None': V = Line(V, Color('brd '+address.get('broadcast'), color)) record['V'] = Line(V) objects.append(record) self.log(Table(objects, ['K', 'F', 'V'], legend=False)) except Exception, e: logging.exception(e)
def tables(self, args): tables = self.client.remote('odbc', 'tables') catalogs = tables(args.alias) if not catalogs: return re_filter = None if args.filter: re_filter = re_compile(' '.join(args.filter), IGNORECASE) for catalog, records in catalogs.iteritems(): if args.views: self.log( Table([{ 'TABLE': table, 'TYPE': tabletype } for (table, tabletype) in records if not re_filter or re_filter.match(table)], ['TABLE', 'TYPE'], caption=catalog)) else: self.log( List([ table for (table, tabletype) in records if not re_filter or re_filter.match(table) and tabletype == 'TABLE' ], caption=catalog))
def bounded(self, args): bounded = self.client.remote('ad', 'bounded') self.log( Table([{ 'TYPE': btype, 'REALM': realm } for (btype, realm) in bounded()], ['TYPE', 'REALM']))
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 run(self, args): wql = self.client.remote('pupyutils.psexec', 'wql') if args.query: cmdline = ' '.join(args.query) else: cmdline = 'SELECT DatabaseDirectory,BuildVersion,LoggingDirectory '\ 'FROM Win32_WMISetting' if "/" in args.target[0]: hosts = IPNetwork(args.target[0]) else: hosts = list() hosts.append(args.target[0]) for host in hosts: try: columns, values = wql(str(host), args.port, args.user, args.domain, args.passwd, args.hash, cmdline, args.timeout) if not columns: return elif len(columns) == 1: self.log( List(list(_stringify(x[0]) for x in values), caption=columns[0])) else: if not values: return elif len(values) == 1: records = [{ 'KEY': column, 'VALUE': _stringify(values[0][idx]) } for idx, column in enumerate(columns)] self.log(Table(records, ['KEY', 'VALUE'])) else: records = [{ column: _stringify(value[idx]) for idx, column in enumerate(columns) } for value in values] self.log(Table(records, columns)) except Exception as e: self.error(e)
def describe(self, args): describe = self.client.remote('odbc', 'describe') description = describe(args.alias, args.table) self.log( Table([{ 'COLUMN': col, 'TYPE': coltype } for (col, coltype) in description], ['COLUMN', 'TYPE']))
def listenv(self, args, environ): envvars = obtain(environ.data) self.log( TruncateToTerm( Table([{ 'VAR': k, 'VAL': repr(v) } for k, v in envvars.iteritems()], ['VAR', 'VAL'], legend=False)))
def on_data(code, payload): if code == END: completion.set() if args.verbose: self.info('DONE [Total: {}]'.format(total)) elif code == HEADER: del header[:] header.extend(payload) if output or args.tabs: tabbed = u'\t'.join(_asunicode(col[0]) for col in header) if output: output.write(tabbed + '\n') else: self.log(tabbed) elif code == LOG: if args.verbose: self.info(payload) elif code == ERROR: self.error(payload) completion.set() elif code != DATA: self.error('Unexpected code {}'.format(code)) elif payload is None: return elif output or args.tabs: total.inc(len(payload)) for record in payload: tabbed = '\t'.join(_asunicode(col) for col in record) if output: output.write(tabbed + '\n') else: self.log(tabbed) elif args.table: titles = tuple(col[0] for col in header) total.inc(len(payload)) self.log( Table([{ title: value for title, value in zip(titles, values) } for values in payload], titles)) else: total.inc(len(payload)) titles = tuple(col[0] for col in header) if len(header) == 1: for record in payload: self.log(record[0]) else: for record in payload: self.log( List([ u'{}: {}'.format(title, value) for (title, value) in zip(titles, record) ])) self.log(NewLine())
def bounded(self, args): bounded = self.client.remote('odbc', 'bounded') aliased = bounded() if not aliased: return self.log( Table([{ 'ALIAS': alias, 'CONNSTR': connstr } for (alias, connstr) in aliased], ['ALIAS', 'CONNSTR']))
def run(self, args): is_linux = False if self.client.is_linux(): get_services = self.client.remote('services', 'get_services_systemd') is_linux = True elif self.client.is_windows(): get_services = self.client.remote('pupyps', 'get_win_services') else: raise ValueError('Unsupported target') services = get_services() columns = [('pid', 'PID'), ('name', 'SERVICE'), ('binpath', 'PATH')] if args.info: columns = [('pid', 'PID'), ('name', 'SERVICE'), ('username', 'USER'), ('binpath', 'PATH')] if args.display_name: columns = [ x if x[0] != 'name' else ('display_name', 'SERVICE') for x in columns ] data = [] for service in services: username = service.get('username') status = service.get('status') binpath = service.get('binpath') color = None if not status == 'running': if not args.all: continue color = 'grey' elif all([x not in binpath for x in LIKELY_KNOWN]) and not is_linux: color = 'cyan' if username.upper() in ADMINS: color = 'lightyellow' if color is not None: service = { k: Color(v if v is not None else '', color) for k, v in service.iteritems() } data.append(service) self.log(TruncateToTerm(Table(data, columns)))
def run(self, args): self.terminated = threading.Event() scanthread = self.client.remote('network.lib.scan', 'scanthread_parse', False) connectable = [] def set_connectable(addrs): connectable.extend(addrs) self.terminated.set() def on_exception(exception): self.error('Internal Error: {}'.format(exception)) self.terminated.set() self.abort = scanthread(args.target, args.ports, set_connectable, on_exception=on_exception, timeout=args.timeout, portion=args.portion) self.terminated.wait() if connectable: objects = {} for host, port in connectable: try: host = IPAddress(host) except AddrFormatError: pass port = int(port) if host in objects: objects[host].add(port) else: objects[host] = set([port]) self.log( Table( list({ 'IP': str(host), 'PORTS': ', '.join([ str(port) for port in sorted(list(objects[host])) ]) } for host in sorted(objects.keys())), ['IP', 'PORTS'])) else: self.error('No connectable ports found') self.abort = None
def _draw_creds(self, creds): columns = [ 'schema', 'hostname', 'ip', 'port', 'path', 'domain', 'username', 'password', 'realm' ] objects = [] for cred in creds: objects.append(dict(cred)) self.log(Table(objects, columns))
def _format_multi(self, results, wide=False, remove=None): keys = [] values = [] legend = ['NAME', 'TYPE', 'VALUE'] if not remove: legend.insert(0, 'KEY') for record in results: is_key, key, rest = record[0], record[1], record[2:] if remove and key.startswith(remove): key = key[len(remove) + 1:] if is_key: keys.append(key) continue name, value, ktype = rest ktype = TYPES[ktype] color = TYPE_COLORS[ktype] if not wide and type(value) in (str, unicode): value = value.strip() values.append({ 'KEY': Color(key, color), 'NAME': Color(name, color), 'VALUE': Color(value if ktype != 'BINARY' else repr(value), color), 'TYPE': Color(ktype, color) }) results = [] if keys: results.append(List(keys, caption='{ Keys }')) if values: results.append(Table(values, legend, caption='Values')) if not keys and not values: self.log('Empty') else: results = MultiPart(results) if not wide: results = TruncateToTerm(results) self.log(results)
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 do(server, handler, config, modargs): for client in server.get_clients(handler.default_filter): objects = [] with client.conn._conn._local_objects._lock: for klass, refcnt in \ client.conn._conn._local_objects._dict.itervalues(): objects.append({ 'OID': id(klass), 'Object': repr(klass), 'Refs': refcnt }) handler.display( Table(objects, headers=['OID', 'Object', 'Refs'], caption=client.short_name()))
def _output_search_results(self, results, fields, table=False, realm=None): if not results: return is_list = False is_table = False if len(fields) == 1: _results = [_get_field(line, fields[0]) for line in results] is_list = all(not isinstance(record, (dict, tuple, list)) for record in _results) if is_list: results = _results elif table and fields: results = [{field: _get_field(result, field) for field in fields} for result in results] is_table = all( all(not isinstance(value, (dict, tuple, list)) for value in record.itervalues()) for record in results) if is_list: self.log(List(results, caption=realm)) elif is_table: self.log(Table(results, fields or None, caption=realm)) else: filtered = results if fields: filtered = [{ field: _get_field(result, field) for field in fields } for result in results] formatted_json = dumps(filtered, indent=2, sort_keys=True, default=json_default, ensure_ascii=False) if realm: self.log('+ ' + realm) self.log(Pygment(lexers.JsonLexer(), formatted_json))
def run(self, args): wql = self.client.remote('wql', 'execute_final') if args.query: cmdline = ' '.join(args.query) else: cmdline = 'SELECT DatabaseDirectory,BuildVersion,LoggingDirectory '\ 'FROM Win32_WMISetting' try: columns, result = wql(cmdline) except Exception as e: self.error(e.strerror) return if args.columns_only: self.log(List(columns, caption='Columns')) return def _stringify(x): if type(x) in (str, unicode): return x elif type(x) in (list, tuple): return ';'.join(_stringify(y) for y in x) elif type(x) is None: return '' else: return str(x) if not columns: return elif len(columns) == 1: records = [] for record in result: for item in record: if item[0] == columns[0]: records.append(_stringify(item[1])) self.log(List(records, caption=columns[0])) else: records = [{k: _stringify(v) for k, v in record} for record in result] self.log(Table(records, columns))
def run(self, args): pupy = self.client.remote('pupy') active = obtain(pupy.manager.status) data = [] for task, state in active.iteritems(): color = 'grey' if state['active']: color = 'lightgreen' elif state['results']: color = 'cyan' data.append({ 'TASK': Color(task, color), 'ACTIVE': Color('Y' if state['active'] else 'N', color), 'RESULTS': Color('Y' if state['results'] else 'N', color), }) self.log(Table(data, ['TASK', 'ACTIVE', 'RESULTS']))
def _show_exception(self, e): if hasattr(e, 'message') and hasattr(e, 'type'): report = [] if hasattr(e, 'childs') and e.childs and not isinstance( e.childs, str): for (authentication, ldap_server, domain, user, _, emessage) in e.childs: report.append({ 'Method': authentication, 'Server': ldap_server, 'Domain': domain, 'User': user, 'Message': emessage }) self.error( Table(report, ['Method', 'Server', 'Domain', 'User', 'Message'], caption=e.message)) else: self.error('AD Error ({}): {}'.format(e.type, e.message)) else: self.error(e)
def cache(self, args): if args.command in ('enable', 'disable'): set_use_cache = self.client.remote( 'pupyutils.psexec', 'set_use_cache', False) set_use_cache(args.command == 'enable') elif args.command == 'get': get_cache = self.client.remote( 'pupyutils.psexec', 'get_cache', False) try: cache = get_cache() self.log(Table([{ 'Host': host, 'User': user or '', 'Domain': domain or '' } for host, user, _, domain, _, _, _, _ in cache], [ 'Host', 'User', 'Domain' ])) except Exception as e: self.error(e) elif args.command == 'clear': clear_session_caches = self.client.remote( 'pupyutils.psexec', 'clear_session_caches', False) clear_session_caches()
columns = ['cid', 'login', 'secret', 'resource'] caption = category if all(not x['resource'] for x in info['creds']): del columns[columns.index('resource')] cids = set(x['cid'] for x in info['creds']) if len(cids) == 1: del columns[columns.index('cid')] caption += ' (cid={})'.format(list(cids)[0]) if credtype in ('plaintext', 'hash') or all( len(x['secret']) <= 64 for x in info['creds']): handler.display(TruncateToTerm( Table(info['creds'], columns, caption=Color(caption, 'yellow')))) else: caption = Line('{', Color(caption, 'yellow'), '}') handler.display(caption) parts = [] for cred in info['creds']: line = [] for column in columns: if column == 'secret' or not cred[column]: continue line.append(Color(column+':', 'yellow')) line.append(Color(cred[column], 'lightyellow')) line.append(NewLine()) line.append(cred['secret'])
def do(server, handler, config, args): tables = [] if args.module: if handler.commands.has(args.module): command = handler.commands.get(args.module) tables.append( Line(Color('Command:', 'yellow'), Color(args.module + ':', 'green'), command.usage or 'No description')) if command.parser.add_help: tables.append(command.parser.format_help()) else: tables.append(command.parser.parse_args(['--help'])) for module in server.iter_modules(): if module.get_name().lower() == args.module.lower(): if module.__doc__: doc = module.__doc__.strip() else: doc = '' tables.append( Line(Color('Module:', 'yellow'), Color(args.module + ':', 'green'), doc.title().split('\n')[0])) if command.parser.add_help: tables.append(command.parser.format_help()) else: tables.append(command.parser.parse_args(['--help'])) clients = server.get_clients(handler.default_filter) if clients: ctable = [] for client in clients: compatible = module.is_compatible_with(client) ctable.append({ 'OK': Color('Y' if compatible else 'N', 'green' if compatible else 'grey'), 'CLIENT': Color(str(client), 'green' if compatible else 'grey') }) tables.append( Table(ctable, ['OK', 'CLIENT'], Color('Compatibility', 'yellow'), False)) for command, alias in config.items("aliases"): if command == args.module: tables.append( Line(Color('Alias:', 'yellow'), Color(args.module + ':', 'green'), alias)) else: commands = [] for command, description in handler.commands.list(): commands.append({'COMMAND': command, 'DESCRIPTION': description}) tables.append( Table(commands, ['COMMAND', 'DESCRIPTION'], Color('COMMANDS', 'yellow'))) if args.modules: modules = sorted(list(server.iter_modules()), key=(lambda x: x.category)) table = [] for mod in modules: compatible = all( mod.is_compatible_with(client) for client in server.get_clients(handler.default_filter)) compatible_some = any( mod.is_compatible_with(client) for client in server.get_clients(handler.default_filter)) if mod.__doc__: doc = mod.__doc__.strip() else: doc = '' category = mod.category name = mod.get_name() brief = doc.title().split('\n')[0] if compatible: pass elif compatible_some: category = Color(category, 'grey') name = Color(name, 'grey') brief = Color(brief, 'grey') else: category = Color(category, 'darkgrey') name = Color(name, 'darkgrey') brief = Color(brief, 'darkgrey') table.append({ 'CATEGORY': category, 'NAME': name, 'HELP': brief }) tables.append( TruncateToTerm( Table(table, ['CATEGORY', 'NAME', 'HELP'], Color('MODULES', 'yellow')))) else: aliased = [] for module, description in server.get_aliased_modules(): aliased.append({'MODULE': module, 'DESCRIPTION': description}) if aliased: tables.append( Table(aliased, ['MODULE', 'DESCRIPTION'], Color('ALIASED MODULES', 'yellow'))) aliases = [] for command, alias in config.items("aliases"): aliases.append({'ALIAS': command, 'COMMAND': alias}) if aliases: tables.append( Table(aliases, ['ALIAS', 'COMMAND'], Color('ALIASES', 'yellow'))) if not args.modules: tables.append( Line('Use', Color('help -M', 'green'), 'command to show all available modules')) handler.display(MultiPart(tables))
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))