Autarch/web/routes/c2_framework.py

135 lines
4.6 KiB
Python
Raw Normal View History

"""C2 Framework — web routes for command & control."""
from flask import Blueprint, render_template, request, jsonify, Response
from web.auth import login_required
c2_framework_bp = Blueprint('c2_framework', __name__)
def _svc():
from modules.c2_framework import get_c2_server
return get_c2_server()
@c2_framework_bp.route('/c2/')
@login_required
def index():
return render_template('c2_framework.html')
# ── Listeners ─────────────────────────────────────────────────────────────────
@c2_framework_bp.route('/c2/listeners', methods=['GET'])
@login_required
def list_listeners():
return jsonify({'ok': True, 'listeners': _svc().list_listeners()})
@c2_framework_bp.route('/c2/listeners', methods=['POST'])
@login_required
def start_listener():
data = request.get_json(silent=True) or {}
return jsonify(_svc().start_listener(
name=data.get('name', 'default'),
host=data.get('host', '0.0.0.0'),
port=data.get('port', 4444),
))
@c2_framework_bp.route('/c2/listeners/<name>', methods=['DELETE'])
@login_required
def stop_listener(name):
return jsonify(_svc().stop_listener(name))
# ── Agents ────────────────────────────────────────────────────────────────────
@c2_framework_bp.route('/c2/agents', methods=['GET'])
@login_required
def list_agents():
return jsonify({'ok': True, 'agents': _svc().list_agents()})
@c2_framework_bp.route('/c2/agents/<agent_id>', methods=['DELETE'])
@login_required
def remove_agent(agent_id):
return jsonify(_svc().remove_agent(agent_id))
# ── Tasks ─────────────────────────────────────────────────────────────────────
@c2_framework_bp.route('/c2/agents/<agent_id>/exec', methods=['POST'])
@login_required
def exec_command(agent_id):
data = request.get_json(silent=True) or {}
command = data.get('command', '')
if not command:
return jsonify({'ok': False, 'error': 'No command'})
return jsonify(_svc().execute_command(agent_id, command))
@c2_framework_bp.route('/c2/agents/<agent_id>/download', methods=['POST'])
@login_required
def download_file(agent_id):
data = request.get_json(silent=True) or {}
path = data.get('path', '')
if not path:
return jsonify({'ok': False, 'error': 'No path'})
return jsonify(_svc().download_file(agent_id, path))
@c2_framework_bp.route('/c2/agents/<agent_id>/upload', methods=['POST'])
@login_required
def upload_file(agent_id):
f = request.files.get('file')
data = request.form
path = data.get('path', '')
if not f or not path:
return jsonify({'ok': False, 'error': 'File and path required'})
return jsonify(_svc().upload_file(agent_id, path, f.read()))
@c2_framework_bp.route('/c2/tasks/<task_id>', methods=['GET'])
@login_required
def task_result(task_id):
return jsonify(_svc().get_task_result(task_id))
@c2_framework_bp.route('/c2/tasks', methods=['GET'])
@login_required
def list_tasks():
agent_id = request.args.get('agent_id', '')
return jsonify({'ok': True, 'tasks': _svc().list_tasks(agent_id)})
# ── Agent Generation ──────────────────────────────────────────────────────────
@c2_framework_bp.route('/c2/generate', methods=['POST'])
@login_required
def generate_agent():
data = request.get_json(silent=True) or {}
host = data.get('host', '').strip()
if not host:
return jsonify({'ok': False, 'error': 'Callback host required'})
result = _svc().generate_agent(
host=host,
port=data.get('port', 4444),
agent_type=data.get('type', 'python'),
interval=data.get('interval', 5),
jitter=data.get('jitter', 2),
)
# Don't send filepath in API response
result.pop('filepath', None)
return jsonify(result)
@c2_framework_bp.route('/c2/oneliner', methods=['POST'])
@login_required
def get_oneliner():
data = request.get_json(silent=True) or {}
host = data.get('host', '').strip()
if not host:
return jsonify({'ok': False, 'error': 'Host required'})
return jsonify(_svc().get_oneliner(host, data.get('port', 4444),
data.get('type', 'python')))