def _interactive(self) -> int: logger.info( "This is just an interactive window that continuously executes SQL statements. " ) logger.info("Type `exit` or `quit` or Ctrl-C to exit.") try: while True: prompt = colour.colorize('oracle', 'underline')+'('+colour.colorize(f"{self._user}@{self._host}", fore='green')+')'+\ f" [{colour.colorize(self._current_database, fore='yellow')}] > " sql = utils.input(prompt) if sql == '': continue elif sql in ('exit', 'quit'): break elif sql == 'clear': self.session.exec("clear") continue elif sql.startswith('use '): match = re.fullmatch(r'use\s+(\w+)', sql) if match: old = self._current_database self._current_database = match.group(1) if self._query(sql) == self.ERROR: self._current_database = old continue self._query(sql) except KeyboardInterrupt: print('') return self.SUCCESS
def _query(self, sql: str) -> int: ret = self.evalfile('payload/query', host=self._host, port=self._port, user=self._user, password=self._password, database=self._current_database, sql=sql) ret = ret.data if ret is None: return self.STOP ret = json.loads(ret) encoding = self.session.client.options.encoding if ret['code'] in (0, -1): msg = base64.b64decode(ret['msg'].encode()).decode( encoding, 'ignore') print(msg) if ret['code'] == -1: self._last_connect_status = False return self.STOP return self.ERROR elif ret['code'] == 1: result = [] fields = [] for row in ret['result']: if not fields: fields = [ base64.b64decode(i.encode()).decode( encoding, 'ignore') for i in row.keys() ] tmp = [] for val in row.values(): val = base64.b64decode(val.encode()).decode( encoding, 'ignore') tmp.append(val) result.append(tmp) table = [ fields, ] + result print(tablor(table, indent='')) logger.info(colour.colorize(f"{len(result)} rows in set.", 'bold')) elif ret['code'] == 2: affected = ret['affected'] logger.info( colour.colorize(f"Query OK, {affected} row affected.", 'bold')) elif ret['code'] == -2: logger.error( "Can't find function `oci_connect`, the server may not have the OCI extension installed." ) self._last_connect_status = False return self.STOP self._last_connect_status = True return self.SUCCESS
def _show(self) -> int: table = [['Host', self._host], ['Port', self._port], ['User', self._user], ['Password', self._password], ['Current database', self._current_database], [ 'Last connection', colour.colorize('Success', 'bold', 'green') if self._last_connect_status else colour.colorize( 'Failed', 'bold', 'red') ]] print(tablor(table, False, indent='')) return self.SUCCESS
def run(self, args: Cmdline) -> int: args = self.parse.parse_args(args.options) ret = self.SUCCESS if args.start: if self.proxy is not None and self.proxy.is_alive(): logger.error("SocksProxy is running!You must stop it first!") return self.STOP self.proxy = SocksProxy(self) self.proxy.host = args.lhost self.proxy.port = args.lport self.proxy.shost = args.rhost self.proxy.sport = args.rport self.proxy.upload_buf_size = args.uploadsize self.proxy.setDaemon(True) self.proxy.start() logger.info( f"SocksProxy Local Server running at ({self.proxy.host}, {self.proxy.port})", True) return self.SUCCESS elif args.restart: if self.proxy is not None and self.proxy.is_alive(): self.proxy.close() proxy = SocksProxy(self) if self.proxy is not None: proxy.host = self.proxy.host proxy.port = self.proxy.port proxy.shost = self.proxy.shost proxy.sport = self.proxy.sport proxy.upload_buf_size = self.proxy.upload_buf_size else: proxy.host = args.lhost proxy.port = args.lport proxy.shost = args.rhost proxy.sport = args.rport proxy.upload_buf_size = args.uploadsize proxy.setDaemon(True) proxy.start() self.proxy = proxy logger.info( f"SocksProxy Local Server restart at ({self.proxy.host}, {self.proxy.port})", True) return self.SUCCESS elif args.stop: ret = self.stop() else: # status if self.proxy is not None and self.proxy.is_alive(): logger.info("SocksProxy Local Server " + colour.colorize('Running', 'bold', 'green')) else: logger.info("SocksProxy Local Server " + colour.colorize('Stopped', 'bold', 'red')) return ret
def show_methods(self): print("Cuurent Method: ", self.executor.method) ok = list(self.executor.available_methods) for i in range(len(ok)): if self.executor.method == ok[i]: ok[i] = colour.colorize(ok[i], ['bold', 'invert']) print("All Methods: ", '|'.join(ok))
def _host_survival_scan_handler_by_ping(self, ip_list: list, timeout: int) -> tuple: '''使用ping命令探测主机是否存活 ''' result = [] ret = '' if self.session.server_info.isWindows(): ips = ','.join(ip_list) self.session.client.options.set_temp_option('timeout', 0) ret = self.exec_command( f'cmd /c "for %i in ({ips}) do ping -n 1 -w {timeout} %i && echo %iok"' ) else: ips = ' '.join(ip_list) self.session.client.options.set_temp_option('timeout', 0) ret = self.exec_command( f'for ip in {ips};do ping -c 1 -W {timeout//1000} $ip && echo $ip"ok";done' ) if ret is None: logger.error("host_survival_scan_handler_by_ping error!") return result, len(ip_list) ret = re.findall(r'^\s*(\d+\.\d+\.\d+\.\d+)ok\s*$', ret, re.M) for ip in ret: result.append(ip) ip = colour.colorize(ip.ljust(15), 'bold', 'yellow') logger.info(f"{ip} is alive!" + ' ' * 20, True) return result, len(ip_list)
def _port_scan_handler(self, ports_list: list, ip: str, connect_timeout: int, isudp: bool) -> tuple: '''端口扫描处理函数 ''' result = [] self.session.client.options.set_temp_option('timeout', 30) self.session.client.options.set_temp_option('verbose', 1) ret = self.evalfile("payload/port_scan", ip=ip, ports=','.join([str(i.port) for i in ports_list]), isudp=isudp, timeout=connect_timeout) ret = ret.data if ret is None: logger.error( f"Scan {'UDP' if isudp else 'TCP'} port on {ip} error!" + ' ' * 20) return result, len(ports_list) ret = json.loads(ret) if ret: for p, response in ret.items(): for port in ports_list: if port.port == int(p): port.response = base64.b64decode(response.encode()) self._update_port_note_by_response(port) result.append(port) p = colour.colorize(str(p).rjust(5), 'bold', 'yellow') logger.info( f"{'UDP' if isudp else 'TCP'} port {p} is opened on {ip}!" + ' ' * 20, True) break return result, len(ports_list)
def _create_from_client(self, session: Session, nosave: bool, save_id: int) -> int: '''从指定session中的webshell client建立连接 ''' webshell = session.client if webshell is None: logger.error('You must use a webshell client first.') return self.STOP if len(webshell.options.unset_list()) > 0: # 检测选项设置 logger.error("There are some unset options!") return self.STOP # explot 当前目标 if webshell.connect(): ID = 1 if len(self.manager.session_map) == 0 else max( self.manager.session_map) + 1 s = WebshellSession(webshell, ID) self.manager.session_map[ID] = s if save_id: s.state['save_id'] = save_id # 表示该session是从保存的连接建立的 if isinstance(session, MainSession): session.client = None session[ 'Prompt'] = lambda: f"{colour.colorize(config.app_name, 'underline')} {colour.colorize(config.prompt, fore='blue')} " logger.info(f'A session is created, id is `{ID}`', True) if not nosave: # 存储建立的连接 self._save(s) else: s.state['nosave'] = True # 给session增加一个不保存的标志 webshell.hook_start(s) s['Prompt'] = lambda :colour.colorize(s.server_info.domain+'\\'+s.server_info.user, 'bold', 'cyan')+'@'+\ colour.colorize(s.state['name'], fore='purple')+\ ':'+f"({colour.colorize(s.pwd, fore='red')})"+' \n'+colour.colorize(config.prompt, 'bold', 'blue')+' ' self.manager.loadexploit_to_session( self.manager.modules.get('exploit', {}), 'exploit', s) # 载入命令 # 全部命令加载成功后调用命令回调 s._hook_loaded() webshell.hook_loaded() self.manager.exec(["sessions", '-i', str(ID)]) return self.SUCCESS logger.warning("Session create failed!") return self.STOP
def _command_info(self, command=None) -> str: '''获取当前command的信息,若指定command则返回对应命令的帮助信息''' result = '' if command is None: for title, cmdmap in self.session['Command List'].items(): info = [] if len(cmdmap) > 0: info.append(['Command', 'Description']) for cmd, func in cmdmap.items(): des = func.help if des is None: des = colour.colorize('No description.', 'note') else: des = des.lstrip('\t\n\r ').split('\n')[0] info.append([cmd, des]) result += tablor(info, title=title, border=False, max_width="30-1, 100-2") + '\n' info = [['Command', 'Description', 'Value']] if len(self.session.alias_command) > 0: for cmd, func in self.session.alias_command.items(): des = func.help if des is None: des = colour.colorize('No description.', 'note') else: des = des.lstrip('\t\n\r ').split('\n')[0] info.append([cmd, des, func.value]) result += tablor(info, title="Alias Commands", border=False, max_width="30-1, 50-2, 50-3") + '\n' else: for cmd, func in self.session.command_map.items(): if cmd == command: des = func.help return colour.colorize('No description.', 'note') if des is None else des return colour.colorize('No description.', 'note') return result
def run(self, args: Cmdline) -> int: args = self.parse.parse_args(args.options) local = args.local if local is None: local = utils.pathsplit(args.source)[1] local = local.replace('/', os.sep) local = os.path.join(config.work_path, local) d, fname = utils.pathsplit(args.source) if os.path.exists(local): if os.path.isfile(local): logger.warning(f"Local file `{local}` is exist.") if utils.input( colour.colorize("Are you sure to overwrite it?(y/n) ", 'bold')).lower() != 'y': return self.STOP elif os.path.isdir(local): # 如果指定的本地路径为目录,那么会把下载的文件或目录放在该目录下 for f in os.listdir(local): if f.lower() == fname.lower(): if os.path.isdir(f): # 不准有同名目录 logger.error( f"Local folder `{local}` contain a same name directory `{f}`!" ) return self.STOP logger.warning( f"Local folder `{local}` contain a same name file `{fname}`." ) if utils.input( colour.colorize( "Are you sure to overwrite it?(y/n) ", 'bold')).lower() != 'y': return self.STOP break else: dirname = os.path.dirname(local.rstrip(os.sep)) if not os.path.exists(dirname): logger.error(f"Local directory `{dirname}` is not exist!") return self.STOP logger.info("Downloading...") ret = self.download(args.source, local, args.recursive) if ret == self.SUCCESS: logger.info("All items downloaded!") return ret
def _list(self): table = [['ID', 'Forwarding Rule', 'Upload limit', 'Alive Connections Count', 'State']] for ID, rule in self._forward_list.items(): tmp = [] tmp.append(ID) tmp.append(f"{rule['lhost']}:{rule['lport']} {'<=' if rule['lf'] else '=>'} {rule['rhost']}:{rule['rport']}") tmp.append(f"{'Unlimited' if rule['uploadsize'] == 0 else rule['uploadsize']}") cc = 0 if rule['forwd']: if rule['lf']: cc = len(rule['forwd'].connections) else: if rule['forwd'].is_alive() and rule['forwd'].connections and list(rule['forwd'].connections.values())[0]: cc = 1 tmp.append(cc) state = colour.colorize('Stopped', 'bold', 'red') if rule['forwd'] and rule['forwd'].is_alive(): state = colour.colorize('Running', 'bold', 'green') tmp.append(state) table.append(tmp) print(tablor(table, border=False, title="Forwarding Rule Table", aligning="right-3")) return self.SUCCESS
def show_last_result(self): if self._scan_result: hosts = [['Host', 'Opened Ports Count']] ports_list = [] for ip in self._scan_result: hosts.append([ip, len(self._scan_result[ip])]) ports = {'ip': ip, 'ports': [['Port', 'Note']]} for p in self._scan_result[ip]: ports['ports'].append([f"{p.port}/{p.type}", p.note]) ports_list.append(ports) print(tablor(hosts, border=False, title="Alive Host")) for p in ports_list: if len(p['ports']) > 1: print(tablor(p['ports'], border=False, title=p['ip'])) return print(colour.colorize('No scan result info!', ['bold', 'note'], 'red'))
def _format_filename(self, filename: str, perm: str) -> str: ret = filename key = 'back' if '-' not in perm[1:] else 'fore' color = {key: None} if perm[0] == 'd': color[key] = 'blue' elif perm[0] == 's': color[key] = 'purple' elif perm[0] == 'l': return colour(filename, [{ 'regexp': r'^(.*?) ->', 'color': ['bold', 'cyan', ''] }]) elif perm[0] == 'p': color[key] = 'red' if color[key] is not None: ret = colour.colorize(ret, 'bold', **color) return ret
def _host_survival_scan_handler_by_udp(self, ip_list: list, timeout: int) -> tuple: '''使用UDP探测主机是否存活 ''' result = [] self.session.client.options.set_temp_option('timeout', 0) self.session.client.options.set_temp_option('verbose', 1) ret = self.evalfile('payload/host_scan', hosts=','.join(ip_list), timeout=timeout) if not ret.is_success(): logger.error(f"Scan host error!" + ' ' * 30) return result, len(ip_list) ret = ret.data ret = json.loads(ret) for ip in ret: result.append(ip) ip = colour.colorize(ip.ljust(15), 'bold', 'yellow') logger.info(f"{ip} is alive!" + ' ' * 20, True) return result, len(ip_list)