CoolFace
Apppublic

itsmrop/Kali-Linux

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes
app.py275 linesDownload Raw Back to root
1import os2import sys3import json4import subprocess5import shlex6import threading7import time8from flask import Flask, request, jsonify, render_template9from flask_socketio import SocketIO, emit10from flask_cors import CORS11import pexpect12 13app = Flask(__name__)14app.config['SECRET_KEY'] = os.urandom(24)15 16CORS(app, resources={17    r"/api/*": {18        "origins": ["*"]19    }20})21 22# FIX: Force threading mode (eventlet fails in this container)23socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')24 25SPACE_NAME = "itsmrop/Kali-Linux"26ALLOWED_TOOLS = {27    'ls': 'List directory', 'pwd': 'Print working directory', 'cat': 'View files',28    'echo': 'Echo text', 'whoami': 'Current user', 'id': 'User identity',29    'uname': 'System info', 'ps': 'Process status', 'grep': 'Search text',30    'awk': 'Text processing', 'sed': 'Stream editor', 'curl': 'Transfer data',31    'wget': 'Downloader', 'nmap': 'Network scanner', 'hashcat': 'Password cracker',32    'hashid': 'Hash identifier', 'hydra': 'Login cracker', 'dirb': 'Web scanner',33    'gobuster': 'Directory buster', 'sqlmap': 'SQL injection', 'john': 'John the Ripper',34    'nc': 'Netcat', 'ping': 'Network test', 'traceroute': 'Route trace',35    'netstat': 'Network stats', 'ifconfig': 'Network interfaces', 'tcpdump': 'Packet capture',36    'aircrack-ng': 'Wireless tools', 'nikto': 'Web scanner'37}38 39class CommandRunner:40    def __init__(self):41        self.processes = {}42        self.process_counter = 043    44    def execute_streaming(self, command, session_id):45        self.process_counter += 146        proc_id = self.process_counter47        48        try:49            interactive_keywords = ['hydra', 'sqlmap', 'john', 'msfconsole', 'burp', 'nc -l', 'ncat']50            is_interactive = any(k in command for k in interactive_keywords)51            52            if is_interactive:53                self._run_interactive(command, session_id, proc_id)54            else:55                self._run_standard(command, session_id, proc_id)56        except Exception as e:57            socketio.emit('command_error', {58                'proc_id': proc_id, 'error': str(e), 'session_id': session_id59            })60    61    def _run_standard(self, command, session_id, proc_id):62        try:63            process = subprocess.Popen(64                shlex.split(command),65                stdout=subprocess.PIPE,66                stderr=subprocess.STDOUT,67                text=True,68                bufsize=1,69                cwd='/app',70                env={**os.environ, 'TERM': 'xterm-256color'}71            )72            self.processes[proc_id] = process73            74            for line in iter(process.stdout.readline, ''):75                if line:76                    socketio.emit('command_output', {77                        'proc_id': proc_id, 'data': line, 'session_id': session_id78                    })79                    socketio.sleep(0.01)80            81            process.stdout.close()82            return_code = process.wait()83            84            if proc_id in self.processes:85                del self.processes[proc_id]86            87            socketio.emit('command_complete', {88                'proc_id': proc_id, 'returncode': return_code, 'session_id': session_id89            })90        except Exception as e:91            socketio.emit('command_error', {92                'proc_id': proc_id, 'error': str(e), 'session_id': session_id93            })94 95    def _run_interactive(self, command, session_id, proc_id):96        try:97            child = pexpect.spawn(command, encoding='utf-8', timeout=None, cwd='/app')98            child.setwinsize(24, 80)99            self.processes[proc_id] = child100            101            # FIX: Raw strings for regex patterns102            patterns = [103                pexpect.EOF, 104                pexpect.TIMEOUT,105                r'[Pp]assword:\s*',106                r'[Uu]sername:\s*',107                r'[Ee]nter\s+.*:\s*',108                r'[Yy]es/[Nn]o',109                r'[Cc]ontinue\?',110                r'.*\$\s*',111                r'.*#\s*',112                r'\n'113            ]114            115            while True:116                try:117                    idx = child.expect(patterns, timeout=0.1)118                    119                    if idx == 0:120                        break121                    elif idx == 1:122                        socketio.sleep(0.05)123                        continue124                    elif idx in [2, 3, 4, 5, 6, 7, 8]:125                        output = child.before126                        if output:127                            socketio.emit('command_output', {128                                'proc_id': proc_id, 'data': output, 'session_id': session_id129                            })130                        socketio.emit('command_prompt', {131                            'proc_id': proc_id,132                            'prompt': child.after,133                            'type': 'input_required',134                            'session_id': session_id135                        })136                        break137                    elif idx == 9:138                        if child.before:139                            socketio.emit('command_output', {140                                'proc_id': proc_id, 'data': child.before + '\n', 'session_id': session_id141                            })142                except:143                    break144            145            if child.isalive():146                child.close()147            148            if proc_id in self.processes:149                del self.processes[proc_id]150            151            socketio.emit('command_complete', {152                'proc_id': proc_id,153                'returncode': child.exitstatus if child.exitstatus else 0,154                'session_id': session_id155            })156        except Exception as e:157            socketio.emit('command_error', {158                'proc_id': proc_id, 'error': str(e), 'session_id': session_id159            })160 161runner = CommandRunner()162 163@app.route('/')164def index():165    return render_template('index.html', space_name=SPACE_NAME)166 167@app.route('/api/execute', methods=['POST'])168def execute_sync():169    data = request.json or {}170    command = data.get('command', '').strip()171    timeout = data.get('timeout', 60)172    173    if not command:174        return jsonify({'error': 'Empty command'}), 400175    176    base_cmd = command.split()[0]177    if base_cmd not in ALLOWED_TOOLS and not data.get('force'):178        return jsonify({179            'error': f'Command not allowed: {base_cmd}',180            'allowed': list(ALLOWED_TOOLS.keys())[:20]181        }), 403182    183    try:184        process = subprocess.run(185            shlex.split(command),186            capture_output=True,187            text=True,188            timeout=timeout,189            cwd='/app'190        )191        return jsonify({192            'stdout': process.stdout,193            'stderr': process.stderr,194            'returncode': process.returncode,195            'command': command,196            'space': SPACE_NAME197        })198    except subprocess.TimeoutExpired:199        return jsonify({'error': 'Timeout'}), 408200    except Exception as e:201        return jsonify({'error': str(e)}), 500202 203@app.route('/api/tools')204def list_tools():205    available = {}206    for tool, desc in ALLOWED_TOOLS.items():207        if tool in ['ls', 'pwd', 'cat', 'echo', 'whoami']:208            continue209        try:210            subprocess.run(['which', tool], capture_output=True, check=True)211            available[tool] = desc212        except:213            pass214    return jsonify({215        'space': SPACE_NAME,216        'tools': available,217        'basic_commands': ['ls', 'pwd', 'cat', 'echo', 'whoami', 'grep', 'curl']218    })219 220@app.route('/api/system')221def system_info():222    try:223        uname = subprocess.run(['uname', '-a'], capture_output=True, text=True).stdout.strip()224        return jsonify({225            'space': SPACE_NAME,226            'uname': uname,227            'workspace': '/app',228            'user': 'root'229        })230    except Exception as e:231        return jsonify({'error': str(e)}), 500232 233@socketio.on('connect')234def handle_connect():235    emit('connected', {'status': 'Connected', 'space': SPACE_NAME})236 237@socketio.on('execute_command')238def handle_execute(data):239    command = data.get('command', '').strip()240    session_id = data.get('session_id', 'default')241    if not command:242        return243    244    thread = threading.Thread(target=runner.execute_streaming, args=(command, session_id))245    thread.daemon = True246    thread.start()247 248@socketio.on('send_input')249def handle_input(data):250    proc_id = data.get('proc_id')251    user_input = data.get('input', '')252    if proc_id in runner.processes:253        process = runner.processes[proc_id]254        if isinstance(process, pexpect.spawn):255            process.sendline(user_input)256 257@socketio.on('kill_command')258def handle_kill(data):259    proc_id = data.get('proc_id')260    if proc_id in runner.processes:261        process = runner.processes[proc_id]262        try:263            if isinstance(process, pexpect.spawn):264                process.close(force=True)265            else:266                process.kill()267            del runner.processes[proc_id]268            emit('command_killed', {'proc_id': proc_id})269        except Exception as e:270            emit('error', {'error': str(e)})271 272if __name__ == '__main__':273    os.makedirs('/app/workspace', exist_ok=True)274    print(f"[*] Starting {SPACE_NAME} on port 7860")275    socketio.run(app, host='0.0.0.0', port=7860, debug=False, allow_unsafe_werkzeug=True)