diff --git a/routes/wifi.py b/routes/wifi.py
index d4392ab..e1316cb 100644
--- a/routes/wifi.py
+++ b/routes/wifi.py
@@ -973,6 +973,83 @@ def stop_pmkid():
return jsonify({'status': 'stopped'})
+@wifi_bp.route('/handshake/crack', methods=['POST'])
+def crack_handshake():
+ """Crack a captured handshake using aircrack-ng."""
+ data = request.json
+ capture_file = data.get('capture_file', '')
+ target_bssid = data.get('bssid', '')
+ wordlist = data.get('wordlist', '')
+
+ # Validate paths to prevent path traversal
+ if not capture_file.startswith('/tmp/intercept_handshake_') or '..' in capture_file:
+ return jsonify({'status': 'error', 'message': 'Invalid capture file path'}), 400
+
+ if '..' in wordlist:
+ return jsonify({'status': 'error', 'message': 'Invalid wordlist path'}), 400
+
+ if not os.path.exists(capture_file):
+ return jsonify({'status': 'error', 'message': 'Capture file not found'}), 404
+
+ if not os.path.exists(wordlist):
+ return jsonify({'status': 'error', 'message': 'Wordlist file not found'}), 404
+
+ if target_bssid and not is_valid_mac(target_bssid):
+ return jsonify({'status': 'error', 'message': 'Invalid BSSID format'}), 400
+
+ aircrack_path = get_tool_path('aircrack-ng')
+ if not aircrack_path:
+ return jsonify({'status': 'error', 'message': 'aircrack-ng not found'}), 500
+
+ try:
+ cmd = [aircrack_path, '-a', '2', '-w', wordlist]
+ if target_bssid:
+ cmd.extend(['-b', target_bssid])
+ cmd.append(capture_file)
+
+ logger.info(f"Starting aircrack-ng: {' '.join(cmd)}")
+
+ # Run aircrack-ng with a timeout (this could take a while)
+ result = subprocess.run(
+ cmd,
+ capture_output=True,
+ text=True,
+ timeout=300 # 5 minute timeout
+ )
+
+ output = result.stdout + result.stderr
+
+ # Check if password was found
+ # Aircrack-ng outputs "KEY FOUND! [ password ]" when successful
+ if 'KEY FOUND!' in output:
+ # Extract the password
+ import re
+ match = re.search(r'KEY FOUND!\s*\[\s*(.+?)\s*\]', output)
+ if match:
+ password = match.group(1)
+ logger.info(f"Password cracked for {target_bssid}: {password}")
+ return jsonify({
+ 'status': 'success',
+ 'password': password,
+ 'bssid': target_bssid
+ })
+
+ # Password not found
+ return jsonify({
+ 'status': 'not_found',
+ 'message': 'Password not in wordlist'
+ })
+
+ except subprocess.TimeoutExpired:
+ return jsonify({
+ 'status': 'timeout',
+ 'message': 'Cracking timed out after 5 minutes. Try a smaller wordlist or use hashcat.'
+ })
+ except Exception as e:
+ logger.error(f"Crack error: {e}")
+ return jsonify({'status': 'error', 'message': str(e)}), 500
+
+
@wifi_bp.route('/networks')
def get_wifi_networks():
"""Get current list of discovered networks."""
diff --git a/templates/index.html b/templates/index.html
index 9a987ae..7cbdfd5 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -611,26 +611,6 @@
-
-
-
π PMKID Capture
-
-
- Target:
- --
-
-
- Status:
- --
-
-
-
-
-
-
-
β οΈ BEACON FLOOD DETECTED
@@ -1210,12 +1190,28 @@
Click a network or client to view details
+
+
+
Channel Utilization (2.4 GHz)
-
-
-
-
πΈοΈ Network Topology
-
-
-
-
+
π‘ Channel Recommendation
@@ -5114,8 +5086,7 @@
-
-
+
`;
@@ -5233,6 +5204,24 @@
clearInterval(activeCapture.pollInterval);
}
document.getElementById('handshakeCount').style.animation = '';
+
+ // Show crack button in the capture panel
+ const panel = document.getElementById('captureStatusPanel');
+ const existingCrackBtn = panel.querySelector('.crack-btn');
+ if (!existingCrackBtn) {
+ const crackDiv = document.createElement('div');
+ crackDiv.style.marginTop = '10px';
+ crackDiv.innerHTML = `
+
+ `;
+ panel.querySelector('.section') ? panel.querySelector('.section').appendChild(crackDiv) : panel.appendChild(crackDiv);
+ }
+
+ // Store the captured file for later use
+ activeCapture.captured = true;
+ activeCapture.capturedFile = data.file;
} else if (data.file_exists) {
const sizeKB = (data.file_size / 1024).toFixed(1);
statusSpan.textContent = 'Capturing... (' + sizeKB + ' KB, ' + elapsedStr + ')';
@@ -5272,97 +5261,44 @@
activeCapture = null;
}
- // PMKID Capture
- let activePmkid = null;
+ // Crack handshake with aircrack-ng
+ function crackHandshake(captureFile, bssid) {
+ const wordlist = prompt('Enter path to wordlist file:\n\nCommon locations:\n- /usr/share/wordlists/rockyou.txt\n- /usr/share/john/password.lst', '/usr/share/wordlists/rockyou.txt');
- async function capturePmkid(bssid, channel) {
- if (!confirm('Start PMKID capture for ' + bssid + '?\n\nThis uses hcxdumptool to capture PMKID without needing clients.\n\nβ Only use on networks you own or have authorization to test!')) {
+ if (!wordlist) {
+ showInfo('Cracking cancelled');
return;
}
- const iface = monitorInterface || document.getElementById('wifiInterfaceSelect').value;
- if (!iface) {
- showError('No monitor interface available. Enable monitor mode first.');
- return;
- }
+ showInfo('Starting aircrack-ng... This may take a while.');
- // Stop any existing scan first
- if (isWifiRunning) {
- showInfo('Stopping current scan...');
- try {
- await fetch('/wifi/scan/stop', {method: 'POST'});
- if (wifiEventSource) {
- wifiEventSource.close();
- wifiEventSource = null;
- }
- setWifiRunning(false);
- await new Promise(resolve => setTimeout(resolve, 500));
- } catch (e) {
- console.error('Error stopping scan:', e);
- }
- }
-
- try {
- const response = await fetch('/wifi/pmkid/capture', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ interface: iface, bssid: bssid, channel: channel })
- });
- const data = await response.json();
-
- if (data.status === 'started') {
- activePmkid = { bssid: bssid, file: data.file, startTime: Date.now() };
- document.getElementById('pmkidPanel').style.display = 'block';
- document.getElementById('pmkidTargetBssid').textContent = bssid;
- document.getElementById('pmkidStatus').textContent = 'Capturing...';
- document.getElementById('pmkidStatus').style.color = '#9933ff';
- showInfo('PMKID capture started for ' + bssid);
-
- // Poll for PMKID
- activePmkid.pollInterval = setInterval(checkPmkidStatus, 3000);
- } else {
- showError('PMKID capture failed: ' + (data.message || 'Unknown error'));
- }
- } catch (err) {
- showError('PMKID capture error: ' + err.message);
- console.error('PMKID capture error:', err);
- }
- }
-
- function checkPmkidStatus() {
- if (!activePmkid) return;
-
- fetch('/wifi/pmkid/status', {
+ fetch('/wifi/handshake/crack', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ file: activePmkid.file })
+ body: JSON.stringify({
+ capture_file: captureFile,
+ bssid: bssid,
+ wordlist: wordlist
+ })
})
.then(r => r.json())
.then(data => {
- if (data.pmkid_found) {
- document.getElementById('pmkidStatus').textContent = 'β PMKID CAPTURED!';
- document.getElementById('pmkidStatus').style.color = 'var(--accent-green)';
- showInfo('π PMKID captured! File: ' + data.file);
- showNotification('π PMKID Captured!', `Target: ${activePmkid.bssid}`);
- clearInterval(activePmkid.pollInterval);
+ if (data.status === 'success' && data.password) {
+ showInfo('π PASSWORD FOUND: ' + data.password);
+ showNotification('π Password Cracked!', data.password);
+ alert('Password found!\n\n' + data.password + '\n\nThis has been logged.');
+ } else if (data.status === 'not_found') {
+ showInfo('Password not found in wordlist. Try a different wordlist.');
+ alert('Password not found in wordlist.\n\nTry using a larger or different wordlist.');
+ } else if (data.status === 'running') {
+ showInfo('Aircrack-ng is running in background. Check terminal for progress.');
} else {
- const elapsed = Math.floor((Date.now() - activePmkid.startTime) / 1000);
- document.getElementById('pmkidStatus').textContent = 'Scanning... (' + elapsed + 's)';
+ showError('Crack failed: ' + (data.message || 'Unknown error'));
}
- });
- }
-
- function stopPmkidCapture() {
- if (activePmkid && activePmkid.pollInterval) {
- clearInterval(activePmkid.pollInterval);
- }
-
- fetch('/wifi/pmkid/stop', { method: 'POST' })
- .then(() => {
- document.getElementById('pmkidStatus').textContent = 'Stopped';
- document.getElementById('pmkidStatus').style.color = 'var(--text-dim)';
- showInfo('PMKID capture stopped');
- activePmkid = null;
+ })
+ .catch(err => {
+ showError('Crack error: ' + err.message);
+ console.error('Crack error:', err);
});
}