Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>LOIC - Low Orbit Ion Cannon | Network Stress Testing Tool</title> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Roboto+Mono:wght@300;400;500&display=swap'); | |
| :root { | |
| --primary-color: #00ff88; | |
| --secondary-color: #ff0080; | |
| --accent-color: #00ffff; | |
| --bg-dark: #0a0a0a; | |
| --bg-darker: #050505; | |
| --bg-card: rgba(20, 20, 20, 0.8); | |
| --text-primary: #ffffff; | |
| --text-secondary: #b0b0b0; | |
| --border-color: #333333; | |
| --danger-color: #ff0040; | |
| --warning-color: #ffaa00; | |
| --success-color: #00ff88; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Roboto Mono', monospace; | |
| background: linear-gradient(135deg, var(--bg-darker) 0%, var(--bg-dark) 100%); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| position: relative; | |
| } | |
| body::before { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: | |
| radial-gradient(circle at 20% 50%, rgba(0, 255, 136, 0.1) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 80%, rgba(255, 0, 128, 0.1) 0%, transparent 50%), | |
| radial-gradient(circle at 40% 80%, rgba(0, 255, 255, 0.05) 0%, transparent 50%); | |
| pointer-events: none; | |
| z-index: -1; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| header { | |
| text-align: center; | |
| padding: 40px 0; | |
| position: relative; | |
| } | |
| .logo { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: clamp(2rem, 5vw, 4rem); | |
| font-weight: 900; | |
| background: linear-gradient(45deg, var(--primary-color), var(--accent-color), var(--secondary-color)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| text-shadow: 0 0 30px rgba(0, 255, 136, 0.5); | |
| animation: glow 2s ease-in-out infinite alternate; | |
| } | |
| @keyframes glow { | |
| from { filter: brightness(1); } | |
| to { filter: brightness(1.2); } | |
| } | |
| .subtitle { | |
| font-size: 1rem; | |
| color: var(--text-secondary); | |
| margin-top: 10px; | |
| letter-spacing: 3px; | |
| text-transform: uppercase; | |
| } | |
| .warning-banner { | |
| background: linear-gradient(90deg, var(--warning-color), var(--danger-color)); | |
| padding: 15px; | |
| text-align: center; | |
| border-radius: 10px; | |
| margin: 20px 0; | |
| font-weight: 500; | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.8; } | |
| } | |
| .main-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); | |
| gap: 30px; | |
| margin-top: 30px; | |
| } | |
| .card { | |
| background: var(--bg-card); | |
| border: 1px solid var(--border-color); | |
| border-radius: 15px; | |
| padding: 30px; | |
| backdrop-filter: blur(10px); | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card::before { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: -2px; | |
| right: -2px; | |
| bottom: -2px; | |
| background: linear-gradient(45deg, var(--primary-color), var(--secondary-color), var(--accent-color)); | |
| border-radius: 15px; | |
| opacity: 0; | |
| z-index: -1; | |
| transition: opacity 0.3s ease; | |
| } | |
| .card:hover::before { | |
| opacity: 0.3; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 30px rgba(0, 255, 136, 0.2); | |
| } | |
| .card-title { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 1.5rem; | |
| margin-bottom: 20px; | |
| color: var(--primary-color); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .input-group { | |
| margin-bottom: 20px; | |
| } | |
| label { | |
| display: block; | |
| margin-bottom: 8px; | |
| color: var(--text-secondary); | |
| font-size: 0.9rem; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| input, select { | |
| width: 100%; | |
| padding: 12px; | |
| background: rgba(0, 0, 0, 0.5); | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| color: var(--text-primary); | |
| font-family: 'Roboto Mono', monospace; | |
| transition: all 0.3s ease; | |
| } | |
| input:focus, select:focus { | |
| outline: none; | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 10px rgba(0, 255, 136, 0.3); | |
| } | |
| .slider-container { | |
| margin: 20px 0; | |
| } | |
| .slider { | |
| width: 100%; | |
| height: 6px; | |
| border-radius: 3px; | |
| background: var(--border-color); | |
| outline: none; | |
| -webkit-appearance: none; | |
| } | |
| .slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: var(--primary-color); | |
| cursor: pointer; | |
| box-shadow: 0 0 10px rgba(0, 255, 136, 0.5); | |
| } | |
| .slider::-moz-range-thumb { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: var(--primary-color); | |
| cursor: pointer; | |
| border: none; | |
| box-shadow: 0 0 10px rgba(0, 255, 136, 0.5); | |
| } | |
| .slider-value { | |
| text-align: center; | |
| margin-top: 10px; | |
| color: var(--primary-color); | |
| font-weight: 500; | |
| } | |
| .button-group { | |
| display: flex; | |
| gap: 15px; | |
| margin-top: 30px; | |
| } | |
| button { | |
| flex: 1; | |
| padding: 15px 30px; | |
| border: none; | |
| border-radius: 8px; | |
| font-family: 'Orbitron', sans-serif; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| button::before { | |
| content: ''; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| width: 0; | |
| height: 0; | |
| border-radius: 50%; | |
| background: rgba(255, 255, 255, 0.2); | |
| transform: translate(-50%, -50%); | |
| transition: width 0.6s, height 0.6s; | |
| } | |
| button:active::before { | |
| width: 300px; | |
| height: 300px; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(45deg, var(--primary-color), var(--accent-color)); | |
| color: var(--bg-dark); | |
| } | |
| .btn-primary:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 5px 20px rgba(0, 255, 136, 0.4); | |
| } | |
| .btn-danger { | |
| background: linear-gradient(45deg, var(--danger-color), var(--warning-color)); | |
| color: white; | |
| } | |
| .btn-danger:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 5px 20px rgba(255, 0, 64, 0.4); | |
| } | |
| .btn-secondary { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: var(--text-primary); | |
| border: 1px solid var(--border-color); | |
| } | |
| .btn-secondary:hover { | |
| background: rgba(255, 255, 255, 0.2); | |
| border-color: var(--primary-color); | |
| } | |
| .status-panel { | |
| grid-column: 1 / -1; | |
| background: linear-gradient(135deg, rgba(0, 255, 136, 0.1), rgba(255, 0, 128, 0.1)); | |
| border: 1px solid var(--primary-color); | |
| } | |
| .status-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 20px; | |
| margin-top: 20px; | |
| } | |
| .status-item { | |
| background: rgba(0, 0, 0, 0.5); | |
| padding: 20px; | |
| border-radius: 10px; | |
| text-align: center; | |
| border: 1px solid var(--border-color); | |
| } | |
| .status-label { | |
| font-size: 0.8rem; | |
| color: var(--text-secondary); | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .status-value { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| margin-top: 10px; | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .status-value.active { | |
| color: var(--danger-color); | |
| animation: blink 1s infinite; | |
| } | |
| @keyframes blink { | |
| 0%, 50% { opacity: 1; } | |
| 51%, 100% { opacity: 0.5; } | |
| } | |
| .progress-bar { | |
| width: 100%; | |
| height: 10px; | |
| background: rgba(0, 0, 0, 0.5); | |
| border-radius: 5px; | |
| overflow: hidden; | |
| margin: 20px 0; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, var(--primary-color), var(--accent-color)); | |
| width: 0%; | |
| transition: width 0.3s ease; | |
| box-shadow: 0 0 10px rgba(0, 255, 136, 0.5); | |
| } | |
| .log-container { | |
| background: rgba(0, 0, 0, 0.8); | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| padding: 20px; | |
| height: 300px; | |
| overflow-y: auto; | |
| font-family: 'Roboto Mono', monospace; | |
| font-size: 0.85rem; | |
| line-height: 1.6; | |
| } | |
| .log-entry { | |
| margin-bottom: 5px; | |
| padding: 5px; | |
| border-left: 3px solid transparent; | |
| transition: all 0.3s ease; | |
| } | |
| .log-entry:hover { | |
| background: rgba(255, 255, 255, 0.05); | |
| border-left-color: var(--primary-color); | |
| } | |
| .log-entry.info { color: var(--text-secondary); } | |
| .log-entry.success { color: var(--success-color); } | |
| .log-entry.warning { color: var(--warning-color); } | |
| .log-entry.error { color: var(--danger-color); } | |
| .mode-selector { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| gap: 15px; | |
| margin: 20px 0; | |
| } | |
| .mode-option { | |
| padding: 15px; | |
| background: rgba(0, 0, 0, 0.5); | |
| border: 2px solid var(--border-color); | |
| border-radius: 10px; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .mode-option:hover { | |
| border-color: var(--primary-color); | |
| background: rgba(0, 255, 136, 0.1); | |
| } | |
| .mode-option.selected { | |
| border-color: var(--primary-color); | |
| background: linear-gradient(135deg, rgba(0, 255, 136, 0.2), rgba(0, 255, 255, 0.2)); | |
| box-shadow: 0 0 20px rgba(0, 255, 136, 0.3); | |
| } | |
| .mode-icon { | |
| font-size: 2rem; | |
| margin-bottom: 10px; | |
| } | |
| .mode-name { | |
| font-family: 'Orbitron', sans-serif; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .advanced-options { | |
| margin-top: 20px; | |
| padding-top: 20px; | |
| border-top: 1px solid var(--border-color); | |
| } | |
| .checkbox-group { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin: 10px 0; | |
| } | |
| input[type="checkbox"] { | |
| width: auto; | |
| accent-color: var(--primary-color); | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| gap: 15px; | |
| } | |
| .stat-box { | |
| background: rgba(0, 0, 0, 0.5); | |
| padding: 15px; | |
| border-radius: 8px; | |
| text-align: center; | |
| border: 1px solid var(--border-color); | |
| } | |
| .stat-label { | |
| font-size: 0.75rem; | |
| color: var(--text-secondary); | |
| text-transform: uppercase; | |
| } | |
| .stat-value { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| margin-top: 5px; | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .loading-animation { | |
| display: inline-block; | |
| width: 20px; | |
| height: 20px; | |
| border: 3px solid rgba(255, 255, 255, 0.3); | |
| border-radius: 50%; | |
| border-top-color: var(--primary-color); | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .ip-display { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 1.2rem; | |
| color: var(--accent-color); | |
| text-align: center; | |
| padding: 10px; | |
| background: rgba(0, 0, 0, 0.5); | |
| border-radius: 8px; | |
| margin: 10px 0; | |
| border: 1px solid var(--border-color); | |
| } | |
| @media (max-width: 768px) { | |
| .main-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .button-group { | |
| flex-direction: column; | |
| } | |
| .status-grid { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| .mode-selector { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .pulse-effect { | |
| animation: pulseEffect 2s infinite; | |
| } | |
| @keyframes pulseEffect { | |
| 0%, 100% { box-shadow: 0 0 20px rgba(0, 255, 136, 0.3); } | |
| 50% { box-shadow: 0 0 40px rgba(0, 255, 136, 0.6); } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1 class="logo">LOIC v2.0</h1> | |
| <p class="subtitle">Low Orbit Ion Cannon - Network Stress Testing Tool</p> | |
| <div class="warning-banner"> | |
| ⚠️ WARNING: FOR EDUCATIONAL AND AUTHORIZED TESTING PURPOSES ONLY. UNAUTHORIZED USE IS ILLEGAL. ⚠️ | |
| </div> | |
| <p style="margin-top: 10px; font-size: 0.9rem; color: var(--text-secondary);"> | |
| Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: var(--primary-color); text-decoration: none;">anycoder</a> | |
| </p> | |
| </header> | |
| <div class="main-grid"> | |
| <!-- Target Configuration --> | |
| <div class="card fade-in"> | |
| <h2 class="card-title"> | |
| <span>🎯</span> Target Configuration | |
| </h2> | |
| <div class="input-group"> | |
| <label for="targetIP">Target IP / Hostname</label> | |
| <input type="text" id="targetIP" placeholder="192.168.1.1 or example.com"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="targetPort">Port</label> | |
| <input type="number" id="targetPort" value="80" min="1" max="65535"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="protocol">Protocol</label> | |
| <select id="protocol"> | |
| <option value="tcp">TCP</option> | |
| <option value="udp">UDP</option> | |
| <option value="http">HTTP/HTTPS</option> | |
| </select> | |
| </div> | |
| <div class="ip-display" id="currentTarget" style="display: none;"> | |
| Current Target: <span id="targetDisplay">None</span> | |
| </div> | |
| </div> | |
| <!-- Attack Configuration --> | |
| <div class="card fade-in"> | |
| <h2 class="card-title"> | |
| <span>⚡</span> Attack Configuration | |
| </h2> | |
| <div class="slider-container"> | |
| <label>Threads: <span id="threadValue">10</span></label> | |
| <input type="range" class="slider" id="threads" min="1" max="100" value="10"> | |
| </div> | |
| <div class="slider-container"> | |
| <label>Speed (requests/sec): <span id="speedValue">1000</span></label> | |
| <input type="range" class="slider" id="speed" min="100" max="10000" value="1000" step="100"> | |
| </div> | |
| <div class="slider-container"> | |
| <label>Duration (seconds): <span id="durationValue">30</span></label> | |
| <input type="range" class="slider" id="duration" min="1" max="300" value="30"> | |
| </div> | |
| <div class="checkbox-group"> | |
| <input type="checkbox" id="randomize"> | |
| <label for="randomize">Randomize Data</label> | |
| </div> | |
| <div class="checkbox-group"> | |
| <input type="checkbox" id="waitReply"> | |
| <label for="waitReply">Wait for Reply</label> | |
| </div> | |
| </div> | |
| <!-- Attack Mode --> | |
| <div class="card fade-in"> | |
| <h2 class="card-title"> | |
| <span>🚀</span> Attack Mode | |
| </h2> | |
| <div class="mode-selector"> | |
| <div class="mode-option selected" data-mode="tcp"> | |
| <div class="mode-icon">🔥</div> | |
| <div class="mode-name">TCP</div> | |
| </div> | |
| <div class="mode-option" data-mode="udp"> | |
| <div class="mode-icon">💥</div> | |
| <div class="mode-name">UDP</div> | |
| </div> | |
| <div class="mode-option" data-mode="http"> | |
| <div class="mode-icon">🌐</div> | |
| <div class="mode-name">HTTP</div> | |
| </div> | |
| </div> | |
| <div class="advanced-options"> | |
| <div class="input-group"> | |
| <label for="message">Custom Message (for TCP/UDP)</label> | |
| <input type="text" id="message" placeholder="Optional custom payload"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="urlPath">URL Path (for HTTP)</label> | |
| <input type="text" id="urlPath" value="/" placeholder="/path/to/resource"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Statistics --> | |
| <div class="card fade-in"> | |
| <h2 class="card-title"> | |
| <span>📊</span> Statistics | |
| </h2> | |
| <div class="stats-grid"> | |
| <div class="stat-box"> | |
| <div class="stat-label">Requests Sent</div> | |
| <div class="stat-value" id="requestsSent">0</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="stat-label">Success Rate</div> | |
| <div class="stat-value" id="successRate">0%</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="stat-label">Avg Response</div> | |
| <div class="stat-value" id="avgResponse">0ms</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="stat-label">Data Sent</div> | |
| <div class="stat-value" id="dataSent">0 MB</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Control Panel --> | |
| <div class="card fade-in"> | |
| <h2 class="card-title"> | |
| <span>🎮</span> Control Panel | |
| </h2> | |
| <div class="button-group"> | |
| <button class="btn-primary" id="startBtn"> | |
| <span id="startIcon">▶️</span> <span id="startText">START ATTACK</span> | |
| </button> | |
| <button class="btn-danger" id="stopBtn" disabled> | |
| ⏹️ STOP ATTACK | |
| </button> | |
| <button class="btn-secondary" id="clearBtn"> | |
| 🗑️ CLEAR LOGS | |
| </button> | |
| </div> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" id="progressFill"></div> | |
| </div> | |
| <div style="text-align: center; margin-top: 10px;"> | |
| <span id="statusText">Ready</span> | |
| <span class="loading-animation" id="loadingAnim" style="display: none;"></span> | |
| </div> | |
| </div> | |
| <!-- Status Panel --> | |
| <div class="card status-panel fade-in"> | |
| <h2 class="card-title"> | |
| <span>📡</span> Attack Status | |
| </h2> | |
| <div class="status-grid"> | |
| <div class="status-item"> | |
| <div class="status-label">Attack Status</div> | |
| <div class="status-value" id="attackStatus">IDLE</div> | |
| </div> | |
| <div class="status-item"> | |
| <div class="status-label">Threads Active</div> | |
| <div class="status-value" id="threadsActive">0</div> | |
| </div> | |
| <div class="status-item"> | |
| <div class="status-label">Current Speed</div> | |
| <div class="status-value" id="currentSpeed">0</div> | |
| </div> | |
| <div class="status-item"> | |
| <div class="status-label">Time Elapsed</div> | |
| <div class="status-value" id="timeElapsed">00:00</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Log Panel --> | |
| <div class="card fade-in" style="grid-column: 1 / -1;"> | |
| <h2 class="card-title"> | |
| <span>📝</span> Event Log | |
| </h2> | |
| <div class="log-container" id="logContainer"> | |
| <div class="log-entry info">[INFO] System initialized and ready.</div> | |
| <div class="log-entry info">[INFO] Please configure target and attack parameters.</div> | |
| <div class="log-entry warning">[WARNING] This tool is for authorized testing only.</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| class LOIC { | |
| constructor() { | |
| this.isRunning = false; | |
| this.threads = []; | |
| this.stats = { | |
| requestsSent: 0, | |
| successfulRequests: 0, | |
| totalResponseTime: 0, | |
| dataSent: 0, | |
| startTime: null | |
| }; | |
| this.selectedMode = 'tcp'; | |
| this.initializeElements(); | |
| this.attachEventListeners(); | |
| this.updateSliderValues(); | |
| } | |
| initializeElements() { | |
| // Input elements | |
| this.targetIP = document.getElementById('targetIP'); | |
| this.targetPort = document.getElementById('targetPort'); | |
| this.protocol = document.getElementById('protocol'); | |
| this.threadsSlider = document.getElementById('threads'); | |
| this.speedSlider = document.getElementById('speed'); | |
| this.durationSlider = document.getElementById('duration'); | |
| this.randomizeCheckbox = document.getElementById('randomize'); | |
| this.waitReplyCheckbox = document.getElementById('waitReply'); | |
| this.messageInput = document.getElementById('message'); | |
| this.urlPathInput = document.getElementById('urlPath'); | |
| // Display elements | |
| this.threadValue = document.getElementById('threadValue'); | |
| this.speedValue = document.getElementById('speedValue'); | |
| this.durationValue = document.getElementById('durationValue'); | |
| this.currentTarget = document.getElementById('currentTarget'); | |
| this.targetDisplay = document.getElementById('targetDisplay'); | |
| // Status elements | |
| this.attackStatus = document.getElementById('attackStatus'); | |
| this.threadsActive = document.getElementById('threadsActive'); | |
| this.currentSpeed = document.getElementById('currentSpeed'); | |
| this.timeElapsed = document.getElementById('timeElapsed'); | |
| this.progressFill = document.getElementById('progressFill'); | |
| this.statusText = document.getElementById('statusText'); | |
| this.loadingAnim = document.getElementById('loadingAnim'); | |
| // Statistics elements | |
| this.requestsSent = document.getElementById('requestsSent'); | |
| this.successRate = document.getElementById('successRate'); | |
| this.avgResponse = document.getElementById('avgResponse'); | |
| this.dataSent = document.getElementById('dataSent'); | |
| // Button elements | |
| this.startBtn = document.getElementById('startBtn'); | |
| this.stopBtn = document.getElementById('stopBtn'); | |
| this.clearBtn = document.getElementById('clearBtn'); | |
| this.startIcon = document.getElementById('startIcon'); | |
| this.startText = document.getElementById('startText'); | |
| // Log container | |
| this.logContainer = document.getElementById('logContainer'); | |
| // Mode options | |
| this.modeOptions = document.querySelectorAll('.mode-option'); | |
| } | |
| attachEventListeners() { | |
| // Slider events | |
| this.threadsSlider.addEventListener('input', () => this.updateSliderValues()); | |
| this.speedSlider.addEventListener('input', () => this.updateSliderValues()); | |
| this.durationSlider.addEventListener('input', () => this.updateSliderValues()); | |
| // Button events | |
| this.startBtn.addEventListener('click', () => this.startAttack()); | |
| this.stopBtn.addEventListener('click', () => this.stopAttack()); | |
| this.clearBtn.addEventListener('click', () => this.clearLogs()); | |
| // Mode selection | |
| this.modeOptions.forEach(option => { | |
| option.addEventListener('click', () => this.selectMode(option.dataset.mode)); | |
| }); | |
| // Target input | |
| this.targetIP.addEventListener('input', () => this.updateTargetDisplay()); | |
| } | |
| updateSliderValues() { | |
| this.threadValue.textContent = this.threadsSlider.value; | |
| this.speedValue.textContent = this.speedSlider.value; | |
| this.durationValue.textContent = this.durationSlider.value; | |
| } | |
| updateTargetDisplay() { | |
| const target = this.targetIP.value.trim(); | |
| if (target) { | |
| this.currentTarget.style.display = 'block'; | |
| this.targetDisplay.textContent = `${target}:${this.targetPort.value}`; | |
| } else { | |
| this.currentTarget.style.display = 'none'; | |
| } | |
| } | |
| selectMode(mode) { | |
| this.selectedMode = mode; | |
| this.modeOptions.forEach(option => { | |
| option.classList.toggle('selected', option.dataset.mode === mode); | |
| }); | |
| this.log(`Mode changed to: ${mode.toUpperCase()}`, 'info'); | |
| } | |
| startAttack() { | |
| const target = this.targetIP.value.trim(); | |
| if (!target) { | |
| this.log('Please enter a target IP or hostname', 'error'); | |
| return; | |
| } | |
| this.isRunning = true; | |
| this.stats.startTime = Date.now(); | |
| this.stats.requestsSent = 0; | |
| this.stats.successfulRequests = 0; | |
| this.stats.totalResponseTime = 0; | |
| this.stats.dataSent = 0; | |
| this.updateUIForAttack(); | |
| this.log(`Starting attack on ${target}:${this.targetPort.value}`, 'success'); | |
| const threadCount = parseInt(this.threadsSlider.value); | |
| const speed = parseInt(this.speedSlider.value); | |
| const duration = parseInt(this.durationSlider.value); | |
| // Create threads | |
| for (let i = 0; i < threadCount; i++) { | |
| this.createThread(i, speed, duration); | |
| } | |
| // Update progress | |
| this.updateProgress(duration); | |
| // Auto-stop after duration | |
| setTimeout(() => { | |
| if (this.isRunning) { | |
| this.stopAttack(); | |
| } | |
| }, duration * 1000); | |
| } | |
| createThread(threadId, speed, duration) { | |
| const thread = { | |
| id: threadId, | |
| active: true, | |
| requests: 0, | |
| interval: 1000 / (speed / this.threadsSlider.value) | |
| }; | |
| this.threads.push(thread); | |
| this.log(`Thread ${threadId} started`, 'info'); | |
| const attackLoop = () => { | |
| if (!thread.active || !this.isRunning) { | |
| this.log(`Thread ${threadId} stopped`, 'info'); | |
| return; | |
| } | |
| this.executeAttack(thread); | |
| if (thread.interval < 1) { | |
| // If interval is less than 1ms, run multiple requests per cycle | |
| const requestsPerCycle = Math.ceil(1 / thread.interval); | |
| for (let i = 1; i < requestsPerCycle; i++) { | |
| setTimeout(() => this.executeAttack(thread), i * thread.interval * 1000); | |
| } | |
| setTimeout(attackLoop, 1); | |
| } else { | |
| setTimeout(attackLoop, thread.interval); | |
| } | |
| }; | |
| attackLoop(); | |
| } | |
| executeAttack(thread) { | |
| const startTime = Date.now(); | |
| const target = this.targetIP.value.trim(); | |
| const port = parseInt(this.targetPort.value); | |
| const randomize = this.randomizeCheckbox.checked; | |
| const waitReply = this.waitReplyCheckbox.checked; | |
| // Simulate network request | |
| const simulateRequest = () => { | |
| return new Promise((resolve) => { | |
| // Simulate network latency (1-100ms) | |
| const latency = Math.random() * 99 + 1; | |
| setTimeout(() => { | |
| // Simulate success/failure (95% success rate) | |
| const success = Math.random() > 0.05; | |
| const responseSize = Math.floor(Math.random() * 1024) + 64; // 64-1088 bytes | |
| resolve({ success, latency, responseSize }); | |
| }, latency); | |
| }); | |
| }; | |
| simulateRequest().then(result => { | |
| thread.requests++; | |
| this.stats.requestsSent++; | |
| if (result.success) { | |
| this.stats.successfulRequests++; | |
| this.stats.totalResponseTime += result.latency; | |
| } | |
| this.stats.dataSent += randomize ? | |
| Math.floor(Math.random() * 1024) + 128 : 512; // Random or fixed payload size | |
| this.updateStatistics(); | |
| // Log every 100th request to avoid spam | |
| if (this.stats.requestsSent % 100 === 0) { | |
| this.log(`Thread ${thread.id}: ${thread.requests} requests sent`, 'info'); | |
| } | |
| }); | |
| } | |
| stopAttack() { | |
| this.isRunning = false; | |
| this.threads.forEach(thread => thread.active = false); | |
| this.threads = []; | |
| this.updateUIForStop(); | |
| this.log('Attack stopped', 'warning'); | |
| } | |
| updateProgress(duration) { | |
| const startTime = Date.now(); | |
| const updateInterval = setInterval(() => { | |
| if (!this.isRunning) { | |
| clearInterval(updateInterval); | |
| this.progressFill.style.width = '0%'; | |
| return; | |
| } | |
| const elapsed = (Date.now() - startTime) / 1000; | |
| const progress = Math.min((elapsed / duration) * 100, 100); | |
| this.progressFill.style.width = progress + '%'; | |
| if (progress >= 100) { | |
| clearInterval(updateInterval); | |
| } | |
| }, 100); | |
| } | |
| updateStatistics() { | |
| // Update requests sent | |
| this.requestsSent.textContent = this.stats.requestsSent.toLocaleString(); | |
| // Update success rate | |
| const successRate = this.stats.requestsSent > 0 ? | |
| ((this.stats.successfulRequests / this.stats.requestsSent) * 100).toFixed(1) : 0; | |
| this.successRate.textContent = successRate + '%'; | |
| // Update average response time | |
| const avgResponse = this.stats.successfulRequests > 0 ? | |
| (this.stats.totalResponseTime / this.stats.successfulRequests).toFixed(1) : 0; | |
| this.avgResponse.textContent = avgResponse + 'ms'; | |
| // Update data sent | |
| const dataSentMB = (this.stats.dataSent / (1024 * 1024)).toFixed(2); | |
| this.dataSent.textContent = dataSentMB + ' MB'; | |
| // Update status panel | |
| this.threadsActive.textContent = this.threads.filter(t => t.active).length; | |
| this.currentSpeed.textContent = Math.floor(this.stats.requestsSent / ((Date.now() - this.stats.startTime) / 1000) || 0); | |
| // Update elapsed time | |
| if (this.stats.startTime) { | |
| const elapsed = Math.floor((Date.now() - this.stats.startTime) / 1000); | |
| const minutes = Math.floor(elapsed / 60); | |
| const seconds = elapsed % 60; | |
| this.timeElapsed.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | |
| } | |
| } | |
| updateUIForAttack() { | |
| this.startBtn.disabled = true; | |
| this.stopBtn.disabled = false; | |
| this.startIcon.textContent = '🔥'; | |
| this.startText.textContent = 'ATTACKING...'; | |
| this.attackStatus.textContent = 'ACTIVE'; | |
| this.attackStatus.classList.add('active'); | |
| this.statusText.textContent = 'Attack in progress'; | |
| this.loadingAnim.style.display = 'inline-block'; | |
| this.startBtn.classList.add('pulse-effect'); | |
| } | |
| updateUIForStop() { | |
| this.startBtn.disabled = false; | |
| this.stopBtn.disabled = true; | |
| this.startIcon.textContent = '▶️'; | |
| this.startText.textContent = 'START ATTACK'; | |
| this.attackStatus.textContent = 'IDLE'; | |
| this.attackStatus.classList.remove('active'); | |
| this.statusText.textContent = 'Ready'; | |
| this.loadingAnim.style.display = 'none'; | |
| this.startBtn.classList.remove('pulse-effect'); | |
| this.progressFill.style.width = '0%'; | |
| } | |
| log(message, type = 'info') { | |
| const timestamp = new Date().toLocaleTimeString(); | |
| const logEntry = document.createElement('div'); | |
| logEntry.className = `log-entry ${type}`; | |
| logEntry.textContent = `[${timestamp}] ${message}`; | |
| this.logContainer.appendChild(logEntry); | |
| this.logContainer.scrollTop = this.logContainer.scrollHeight; | |
| // Keep only last 100 logs | |
| const logs = this.logContainer.querySelectorAll('.log-entry'); | |
| if (logs.length > 100) { | |
| logs[0].remove(); | |
| } | |
| } | |
| clearLogs() { | |
| this.logContainer.innerHTML = ''; | |
| this.log('Logs cleared', 'info'); | |
| } | |
| } | |
| // Initialize LOIC when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const loic = new LOIC(); | |
| // Add some demo functionality | |
| setTimeout(() => { | |
| loic.log('System ready. Configure your target and parameters.', 'success'); | |
| }, 1000); | |
| // Add keyboard shortcuts | |
| document.addEventListener('keydown', (e) => { | |
| if (e.ctrlKey && e.key === 'Enter') { | |
| if (!loic.isRunning) { | |
| loic.startAttack(); | |
| } | |
| } else if (e.key === 'Escape') { | |
| if (loic.isRunning) { | |
| loic.stopAttack(); | |
| } | |
| } | |
| }); | |
| }); | |
| // Add some visual effects | |
| document.addEventListener('mousemove', (e) => { | |
| const cursor = document.querySelector('.cursor'); | |
| if (!cursor) { | |
| const newCursor = document.createElement('div'); | |
| newCursor.className = 'cursor'; | |
| newCursor.style.cssText = ` | |
| position: fixed; | |
| width: 20px; | |
| height: 20px; | |
| background: radial-gradient(circle, var(--primary-color) 0%, transparent 70%); | |
| border-radius: 50%; | |
| pointer-events: none; | |
| z-index: 9999; | |
| transition: transform 0.1s ease; | |
| `; | |
| document.body.appendChild(newCursor); | |
| } | |
| const cursorElement = document.querySelector('.cursor'); | |
| cursorElement.style.left = e.clientX - 10 + 'px'; | |
| cursorElement.style.top = e.clientY - 10 + 'px'; | |
| }); | |
| </script> | |
| </body> | |
| </html> |