예제 #1
0
 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
예제 #2
0
    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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
 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))
예제 #6
0
    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)
예제 #7
0
 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)
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
 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
예제 #11
0
 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
예제 #12
0
 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'))
예제 #13
0
 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
예제 #14
0
 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)