// NetAttack Lab - Interactive JavaScript class NetAttackLab { constructor() { this.activeAttacks = new Map(); this.sessionUpdateInterval = null; this.init(); } init() { this.initTabs(); this.initEventListeners(); this.updateSystemTime(); this.startSessionMonitoring(); this.setupRangeInputs(); // Add some startup effects setTimeout(() => { this.addLog('recon-logs', 'π₯ Vsi sistemi pripravljeni', 'success'); }, 1000); } // Tab Management initTabs() { const tabBtns = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); tabBtns.forEach(btn => { btn.addEventListener('click', () => { const targetTab = btn.getAttribute('data-tab'); // Remove active classes tabBtns.forEach(b => b.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); // Add active classes btn.classList.add('active'); document.getElementById(targetTab).classList.add('active'); // Special handling for monitoring tab if (targetTab === 'monitoring') { this.updateSessionsTable(); } }); }); } // Event Listeners initEventListeners() { // Range input updates const durationRange = document.getElementById('duration'); const intensityRange = document.getElementById('intensity'); if (durationRange) { durationRange.addEventListener('input', (e) => { document.getElementById('duration-value').textContent = e.target.value + 's'; }); } if (intensityRange) { intensityRange.addEventListener('input', (e) => { document.getElementById('intensity-value').textContent = e.target.value; }); } // Keyboard shortcuts document.addEventListener('keydown', (e) => { if (e.ctrlKey) { switch(e.key) { case '1': e.preventDefault(); this.switchTab('reconnaissance'); break; case '2': e.preventDefault(); this.switchTab('attacks'); break; case '3': e.preventDefault(); this.switchTab('monitoring'); break; case 'Enter': e.preventDefault(); if (document.querySelector('.tab-content.active').id === 'attacks') { this.startAttack(); } break; } } }); } switchTab(tabName) { const btn = document.querySelector(`[data-tab="${tabName}"]`); if (btn) btn.click(); } // Range Input Setup setupRangeInputs() { const duration = document.getElementById('duration'); const intensity = document.getElementById('intensity'); if (duration) { document.getElementById('duration-value').textContent = duration.value + 's'; } if (intensity) { document.getElementById('intensity-value').textContent = intensity.value; } } // System Time updateSystemTime() { const updateTime = () => { const now = new Date(); const timeStr = now.toISOString().replace('T', ' ').split('.')[0]; const timeElement = document.getElementById('system-time'); if (timeElement) { timeElement.textContent = timeStr; } }; updateTime(); setInterval(updateTime, 1000); } // Logging addLog(containerId, message, type = 'info') { const container = document.getElementById(containerId); if (!container) return; const logLine = document.createElement('div'); logLine.className = `log-line ${type}`; const timestamp = new Date().toLocaleTimeString(); const icons = { info: 'βΉοΈ', success: 'β ', warning: 'β οΈ', error: 'β' }; logLine.innerHTML = `[${timestamp}] ${icons[type]} ${message}`; container.appendChild(logLine); container.scrollTop = container.scrollHeight; // Limit log entries while (container.children.length > 100) { container.removeChild(container.firstChild); } } clearOutput(containerId) { const container = document.getElementById(containerId); if (container) { container.innerHTML = ''; this.addLog(containerId.replace('-output', '-logs'), 'π Logs cleared', 'info'); } } // API Calls async makeRequest(endpoint, data) { try { const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams(data) }); return await response.json(); } catch (error) { console.error('API Error:', error); return { error: 'Network error occurred' }; } } // Reconnaissance Functions async runPing() { const target = document.getElementById('recon-target').value; if (!target.trim()) { this.addLog('recon-logs', 'Please enter a target IP or hostname', 'warning'); return; } this.addLog('recon-logs', `π Starting ping test to ${target}...`, 'info'); const result = await this.makeRequest('/api/ping', { target }); if (result.error) { this.addLog('recon-logs', `β Ping failed: ${result.error}`, 'error'); } else { this.addLog('recon-logs', `β Ping to ${target} completed`, 'success'); // Add output to terminal const outputLines = result.output.split('\n'); outputLines.forEach(line => { if (line.trim()) { this.addLog('recon-logs', line, 'info'); } }); } } async runTraceroute() { const target = document.getElementById('recon-target').value; if (!target.trim()) { this.addLog('recon-logs', 'Please enter a target IP or hostname', 'warning'); return; } this.addLog('recon-logs', `πΊοΈ Starting traceroute to ${target}...`, 'info'); const result = await this.makeRequest('/api/traceroute', { target }); if (result.error) { this.addLog('recon-logs', `β Traceroute failed: ${result.error}`, 'error'); } else { this.addLog('recon-logs', `β Traceroute to ${target} completed`, 'success'); // Add output to terminal const outputLines = result.output.split('\n'); outputLines.forEach(line => { if (line.trim()) { this.addLog('recon-logs', line, 'info'); } }); } } // Attack Functions async startAttack() { const target = document.getElementById('attack-target').value; const type = document.getElementById('attack-type').value; const duration = document.getElementById('duration').value; const intensity = document.getElementById('intensity').value; if (!target.trim()) { this.addLog('attack-logs', 'Please enter a target IP', 'warning'); return; } // Disable attack button const attackBtn = document.getElementById('attack-btn'); const stopBtn = document.getElementById('stop-btn'); attackBtn.disabled = true; stopBtn.disabled = false; // Add attack start log this.addLog('attack-logs', `π₯ Initiating ${type} attack on ${target}`, 'warning'); this.addLog('attack-logs', `βοΈ Parameters: ${duration}s duration, ${intensity} req/sec`, 'info'); const result = await this.makeRequest('/api/attack', { target, type, duration, intensity }); if (result.error) { this.addLog('attack-logs', `β Attack failed to start: ${result.error}`, 'error'); attackBtn.disabled = false; stopBtn.disabled = true; } else { this.addLog('attack-logs', `β Attack session ${result.sessionId} started`, 'success'); this.activeAttacks.set(result.sessionId, { target, type, started: Date.now() }); // Start progress tracking this.trackAttackProgress(result.sessionId, parseInt(duration)); } } trackAttackProgress(sessionId, duration) { let elapsed = 0; const progressInterval = setInterval(() => { elapsed++; const remaining = duration - elapsed; if (remaining > 0) { this.addLog('attack-logs', `π Attack progress: ${elapsed}/${duration}s (${remaining}s remaining)`, 'info'); } else { this.addLog('attack-logs', `π Attack session ${sessionId} completed`, 'success'); clearInterval(progressInterval); // Re-enable attack button document.getElementById('attack-btn').disabled = false; if (this.activeAttacks.size <= 1) { document.getElementById('stop-btn').disabled = true; } this.activeAttacks.delete(sessionId); } }, 1000); } async stopAllAttacks() { this.addLog('attack-logs', 'π Emergency stop initiated...', 'warning'); for (const sessionId of this.activeAttacks.keys()) { await this.makeRequest('/api/stop', { sessionId }); this.addLog('attack-logs', `π Session ${sessionId} stopped`, 'info'); } this.activeAttacks.clear(); document.getElementById('attack-btn').disabled = false; document.getElementById('stop-btn').disabled = true; this.addLog('attack-logs', 'β All attacks stopped', 'success'); } // Session Monitoring startSessionMonitoring() { this.sessionUpdateInterval = setInterval(() => { this.updateSessionStats(); }, 2000); } async updateSessionStats() { try { const response = await fetch('/api/status'); const sessions = await response.json(); // Update stats let totalSessions = sessions.length; let activeSessions = sessions.filter(s => s.active).length; let totalSuccess = sessions.reduce((sum, s) => sum + s.success, 0); let totalFailed = sessions.reduce((sum, s) => sum + s.failed, 0); let successRate = totalSuccess + totalFailed > 0 ? Math.round((totalSuccess / (totalSuccess + totalFailed)) * 100) : 0; document.getElementById('total-sessions').textContent = totalSessions; document.getElementById('active-attacks').textContent = activeSessions; document.getElementById('total-packets').textContent = totalSuccess + totalFailed; document.getElementById('success-rate').textContent = successRate + '%'; } catch (error) { console.error('Failed to update session stats:', error); } } async updateSessionsTable() { try { const response = await fetch('/api/status'); const sessions = await response.json(); const tbody = document.getElementById('sessions-body'); if (sessions.length === 0) { tbody.innerHTML = '