Эх сурвалжийг харах

[MODULES][PMKIDAttack] Release v3.0

DSR! 2 жил өмнө
parent
commit
06c870cdc0

BIN
modules/build/PMKIDAttack.tar.gz


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
modules/build/modules.json


+ 69 - 69
modules/src/PMKIDAttack/api/module.php

@@ -7,30 +7,13 @@ require_once("/pineapple/modules/PineAP/api/PineAPHelper.php");
 class PMKIDAttack extends Module
 {
     const MODULE_PATH = "/pineapple/modules/PMKIDAttack";
+    const LOG_PATH = "/pineapple/modules/PMKIDAttack/log/module.log";
+    const CAPTURE_PATH = "/pineapple/modules/PMKIDAttack/pcapng";
     const DEPS_FLAG = "/tmp/PMKIDAttack.progress";
     const EXPORT_PATH = "/tmp/pmkid-handshake.tmp";
     const TOOLS_PATH = "/sbin/";
     const TOOLS_SD_PATH = "/sd/sbin/";
 
-    private $pineAPHelper;
-    private $moduleFolder;
-    private $captureFolder;
-    private $logPath;
-    private $hcxdumptoolPath;
-    private $hcxpcaptoolPath;
-
-    public function __construct($request, $moduleClass)
-    {
-        parent::__construct($request, $moduleClass);
-
-        $this->pineAPHelper = new PineAPHelper();
-        $this->moduleFolder = $this->getPathModule();
-        $this->captureFolder = "{$this->moduleFolder}/pcapng";
-        $this->logPath = "{$this->moduleFolder}/log/module.log";
-        $this->hcxdumptoolPath = $this->getToolPath("hcxdumptool");
-        $this->hcxpcaptoolPath = $this->getToolPath("hcxpcapngtool"); // old name hcxpcaptool
-    }
-
     public function route()
     {
         switch ($this->request->action) {
@@ -76,11 +59,6 @@ class PMKIDAttack extends Module
         }
     }
 
-    protected function getPathModule()
-    {
-        return self::MODULE_PATH;
-    }
-
     protected function getToolPath($tool)
     {
         $folder = ($this->isSDAvailable()) ?
@@ -98,36 +76,32 @@ class PMKIDAttack extends Module
 
     protected function clearLog()
     {
-        exec("rm {$this->logPath}");
+        exec("rm " . self::LOG_PATH);
     }
 
     protected function getLog()
     {
-        if (!file_exists($this->logPath)) {
-            touch($this->logPath);
+        if (!file_exists(self::LOG_PATH)) {
+            touch(self::LOG_PATH);
         }
 
-        $this->response = array("moduleLog" => file_get_contents($this->logPath));
+        $this->response = ["moduleLog" => file_get_contents(self::LOG_PATH)];
     }
 
     protected function addLog($massage)
     {
-        file_put_contents($this->logPath, $this->formatLog($massage), FILE_APPEND);
-    }
-
-    protected function formatLog($massage)
-    {
-        return "[" . date("Y-m-d H:i:s") . "] {$massage}\n";
+        $entry = "[" . date("Y-m-d H:i:s") . "] {$massage}\n";
+        file_put_contents(self::LOG_PATH, $entry, FILE_APPEND);
     }
 
     protected function getDependenciesStatus()
     {
-        $response = array(
+        $response = [
             "installed" => false,
             "install" => "Install",
             "installLabel" => "success",
             "processing" => false
-        );
+        ];
 
         if (file_exists(self::DEPS_FLAG)) {
             $response["install"] = "Installing...";
@@ -169,15 +143,18 @@ class PMKIDAttack extends Module
 
     protected function managerDependencies()
     {
-        $this->stopAttack();
         $action = $this->checkDependencyInstalled() ? "remove" : "install";
-        $this->execBackground("{$this->moduleFolder}/scripts/dependencies.sh {$action}");
+        $command = self::MODULE_PATH . "/scripts/dependencies.sh";
+
+        $this->stopAttack();
+        $this->execBackground("{$command} {$action}");
+
         $this->response = ["success" => true];
     }
 
     protected function getDependenciesInstallStatus()
     {
-        $this->response = array("success" => !file_exists(self::DEPS_FLAG));
+        $this->response = ["success" => !file_exists(self::DEPS_FLAG)];
     }
 
     protected function getMonitorInterface()
@@ -187,27 +164,38 @@ class PMKIDAttack extends Module
 
     protected function startAttack()
     {
-        $this->pineAPHelper->disablePineAP();
+        $ssid = $this->request->ssid;
+        $bssid = $this->request->bssid;
+        $cleanStart = $this->request->cleanStart === "true";
 
         //$this->execBackground("{$this->moduleFolder}/scripts/PMKIDAttack.sh start " . $this->request->bssid);
-        $this->uciSet("pmkidattack.@config[0].ssid", $this->request->ssid);
-        $this->uciSet("pmkidattack.@config[0].bssid", $this->request->bssid);
+        $this->uciSet("pmkidattack.@config[0].ssid", $ssid);
+        $this->uciSet("pmkidattack.@config[0].bssid", $bssid);
         $this->uciSet("pmkidattack.@config[0].attack", "1");
 
-        $BSSID = $this->getBSSID(true);
+        $cleanBSSID = $this->getBSSID(true);
         $interface = $this->getMonitorInterface();
         $capPath = $this->getCapPath();
-        $filterPath = "{$this->moduleFolder}/scripts/filter.txt";
+        $hcxdumptoolPath = $this->getToolPath("hcxdumptool");
+        $filterPath = self::MODULE_PATH . "/scripts/filter.txt";
+
+        if ($cleanStart) {
+            $originalInterface = str_replace('mon', '', $interface);
+            exec("airmon-ng start {$originalInterface}");
+        }
 
-        exec("echo {$BSSID} > {$filterPath}");
-        $command = "{$this->hcxdumptoolPath} " . 
+        $pineAPHelper = new PineAPHelper();
+        $pineAPHelper->disablePineAP();
+
+        exec("echo {$cleanBSSID} > {$filterPath}");
+        $command = "{$hcxdumptoolPath} " . 
             "-o {$capPath} " .
             "-i {$interface} " .
             "--filterlist_ap={$filterPath} " .
             "--filtermode=2 " .
-            "--enable_status=1";
+            "--enable_status=1 &> /dev/null &";
         $this->execBackground($command);
-        $this->addLog("Start attack {$this->request->bssid}");
+        $this->addLog("Start attack {$bssid}");
         //$this->addLog($command);
 
         $this->response = ["success" => true];
@@ -215,7 +203,6 @@ class PMKIDAttack extends Module
 
     protected function stopAttack()
     {
-        $BSSID = $this->getBSSID(true);
         $BSSIDFormatted = $this->getBSSID();
         $capPath = $this->getCapPath();
 
@@ -236,14 +223,18 @@ class PMKIDAttack extends Module
     {
         $check = $this->checkPMKID();
         if ($check['status']) {
-            $this->addLog("PMKID " . $this->getBSSID() . " intercepted!");
+            $BSSID = $this->getBSSID(true);
+            $BSSIDFormatted = $this->getBSSID();
+            $capPath = $this->getCapPath();
+            $captureFolder = self::CAPTURE_PATH;
 
+            $this->addLog("PMKID {$BSSIDFormatted} intercepted!");
             $metadata = json_encode([
                 'ssid' => $this->uciGet("pmkidattack.@config[0].ssid"),
                 'bssid' => $BSSIDFormatted
             ]);
-            file_put_contents("{$this->captureFolder}/{$BSSID}.data", $metadata);
-            exec("cp {$capPath} {$this->captureFolder}/");
+            file_put_contents("{$captureFolder}/{$BSSID}.data", $metadata);
+            exec("cp {$capPath} {$captureFolder}/");
         }
 
         $this->response = [
@@ -263,6 +254,7 @@ class PMKIDAttack extends Module
     {
         $capPath = $this->getCapPath();
         $exportPath = self::EXPORT_PATH;
+        $hcxpcaptoolPath = $this->getToolPath("hcxpcapngtool"); // old name hcxpcaptool
         if (!file_exists($capPath)) {
             return false;
         }
@@ -270,26 +262,27 @@ class PMKIDAttack extends Module
         // hcxpcaptool 6.0   : -z <file> : output PMKID file (hashcat hashmode -m 16800 old format and john)
         // hcxpcapngtool 6.1 : -o <file> : output WPA-PBKDF2-PMKID+EAPOL (hashcat -m 22000)hash file
         //exec("{$this->moduleFolder}/scripts/PMKIDAttack.sh check-bg " . $this->getBSSID(true));
-        exec("{$this->hcxpcaptoolPath} -o {$exportPath} {$capPath}", $result);
-        $pmkidLog = implode("\n", $result);
+        exec("{$hcxpcaptoolPath} -o {$exportPath} {$capPath}", $result);
+        $log = implode("\n", $result);
 
         return [
-            'log' => $pmkidLog,
+            'log' => $log,
 
             // on hcxpcaptool 6.0
-            //'status' => strpos($pmkidLog, " handshake(s) written to") !== false && strpos($pmkidLog, "0 handshake(s) written to") === false,
+            //'status' => strpos($log, " handshake(s) written to") !== false && strpos($log, "0 handshake(s) written to") === false,
 
-            // on hcxpcaptool 6.1
-            'status' => strpos($pmkidLog, "Information: no hashes written to hash files") === false,
+            // on hcxpcaptool 6.1/6.2
+            'status' => strpos($log, "Information: no hashes written to hash files") === false && strpos($log, "This dump file does not contain enough EAPOL") === false,
         ];
     }
 
     protected function getPMKIDFiles()
     {
+        $captureFolder = self::CAPTURE_PATH;
         $pmkids = [];
-        foreach (glob("{$this->captureFolder}/*.pcapng") as $capture) {
+        foreach (glob("{$captureFolder}/*.pcapng") as $capture) {
             $file = basename($capture, ".pcapng");
-            $metadata = file_get_contents("{$this->captureFolder}/{$file}.data");
+            $metadata = file_get_contents("{$captureFolder}/{$file}.data");
             if ($metadata) {
                 $captureMetadata = json_decode($metadata, true);
                 $name = "{$captureMetadata['ssid']} ({$captureMetadata['bssid']})";
@@ -310,30 +303,36 @@ class PMKIDAttack extends Module
     {
         $file = $this->request->file;
         $workingDir = "/tmp/PMKIDAttack";
+        $captureFolder = self::CAPTURE_PATH;
+        $hcxpcaptoolPath = $this->getToolPath("hcxpcapngtool");
 
         exec("mkdir {$workingDir}");
-        exec("cp {$this->captureFolder}/{$file}.pcapng {$workingDir}/");
-        exec("{$this->hcxpcaptoolPath} -o {$workingDir}/pmkid.22000 {$workingDir}/{$file}.pcapng &> {$workingDir}/report.txt");
+        exec("cp {$captureFolder}/{$file}.pcapng {$workingDir}/");
+        exec("{$hcxpcaptoolPath} -o {$workingDir}/pmkid.22000 {$workingDir}/{$file}.pcapng &> {$workingDir}/report.txt");
         exec("cd {$workingDir}/ && tar -czf /tmp/{$file}.tar.gz *");
         exec("rm -rf {$workingDir}/");
 
-        $this->response = array("download" => $this->downloadFile("/tmp/{$file}.tar.gz"));
+        $this->response = ["download" => $this->downloadFile("/tmp/{$file}.tar.gz")];
     }
 
     protected function deletePMKID()
     {
         $file = escapeshellarg($this->request->file);
-        exec("rm {$this->captureFolder}/{$file}.pcapng {$this->captureFolder}/{$file}.data");
+        $captureFolder = self::CAPTURE_PATH;
+        exec("rm {$captureFolder}/{$file}.pcapng {$captureFolder}/{$file}.data");
 
         $this->response = ["success" => true];
     }
 
     protected function viewAttackLog()
     {
-        $exportPath = self::EXPORT_PATH;
         $file = $this->request->file;
-        $capPath = empty($file) ? $this->getCapPath() : escapeshellarg("{$this->captureFolder}/{$file}.pcapng");
-        exec("{$this->hcxpcaptoolPath} -o {$exportPath} {$capPath}", $result);
+        $exportPath = self::EXPORT_PATH;
+        $captureFolder = self::CAPTURE_PATH;
+        $hcxpcaptoolPath = $this->getToolPath("hcxpcapngtool");
+
+        $capPath = empty($file) ? $this->getCapPath() : escapeshellarg("{$captureFolder}/{$file}.pcapng");
+        exec("{$hcxpcaptoolPath} -o {$exportPath} {$capPath}", $result);
 
         $this->response = ["pmkidLog" => implode("\n", $result)];
     }
@@ -343,7 +342,8 @@ class PMKIDAttack extends Module
         $this->response = [
             "ssid" => $this->uciGet("pmkidattack.@config[0].ssid"),
             "bssid" => $this->uciGet("pmkidattack.@config[0].bssid"),
-            "success" => $this->uciGet("pmkidattack.@config[0].attack") === true,
+            "attack" => $this->uciGet("pmkidattack.@config[0].attack") === true,
+            "process" => \helper\checkRunning($this->getToolPath("hcxdumptool")),
         ];
     }
-}
+}

+ 158 - 359
modules/src/PMKIDAttack/js/module.js

@@ -2,19 +2,16 @@ registerController('PMKIDAttack_Dependencies', ['$api', '$scope', '$rootScope',
     $scope.install = "Loading...";
     $scope.installLabel = "";
     $scope.processing = false;
-    $rootScope.installedDependencies = false;
-    $rootScope.handshakeInfo = false;
-    $rootScope.running = false;
-    $rootScope.captureRunning = false;
+    $rootScope.pmkid_installedDependencies = false;
 
     $scope.refreshStatus = function () {
-        $rootScope.installedDependencies = false;
+        $rootScope.pmkid_installedDependencies = false;
 
         $api.request({
             module: "PMKIDAttack",
             action: "getDependenciesStatus"
         }, function (response) {
-            $rootScope.installedDependencies = response.installed;
+            $rootScope.pmkid_installedDependencies = response.installed;
             $scope.processing = response.processing;
             $scope.install = response.install;
             $scope.installLabel = response.installLabel;
@@ -41,7 +38,7 @@ registerController('PMKIDAttack_Dependencies', ['$api', '$scope', '$rootScope',
     };
 
     $scope.managerDependencies = function () {
-        $scope.install = $rootScope.installedDependencies ? "Removing..." : "Installing...";
+        $scope.install = $rootScope.pmkid_installedDependencies ? "Removing..." : "Installing...";
         $api.request({
             module: 'PMKIDAttack',
             action: 'managerDependencies'
@@ -57,470 +54,264 @@ registerController('PMKIDAttack_Dependencies', ['$api', '$scope', '$rootScope',
     $scope.refreshStatus();
 }]);
 
-registerController('PMKIDAttack_ScanSettings', ['$api', '$scope', '$rootScope', '$interval', '$timeout', '$cookies', function ($api, $scope, $rootScope, $interval, $timeout, $cookies) {
-    $rootScope.accessPoints = [];
-    $rootScope.unassociatedClients = [];
-    $rootScope.outOfRangeClients = [];
+
+registerController('PMKIDAttack_ScanLoad', ['$api', '$scope', '$rootScope', '$timeout', function ($api, $scope, $rootScope, $timeout) {
     $scope.scans = [];
+    $scope.scanLocation = "";
     $scope.selectedScan = "";
     $scope.loadedScan = null;
-    $scope.scanType = '0';
-    $scope.paused = false;
-    $scope.percent = 0;
+    $scope.loadingScan = false;
     $scope.error = false;
-    $scope.pineAPDRunning = true;
-    $scope.pineAPDStarting = false;
-    $scope.percentageInterval = 300;
-    $scope.wsAuthToken = "";
-    $scope.scanSettings = {
-        scanDuration: $cookies.get('scanDuration') !== undefined ? $cookies.get('scanDuration') : '0',
-        live: $cookies.get('liveScan') !== undefined ? $cookies.get('liveScan') === 'true' : true
-    };
+    $scope.scanID = null;
+    $scope.statusObtained = false;
 
-    function checkScanStatus() {
-        if ($scope.scanSettings.scanDuration < 1) {
-            return;
-        }
-        if (!$scope.updatePercentageInterval) {
-            $scope.updatePercentageInterval = $interval(function () {
-                var percentage = $scope.percentageInterval / ($scope.scanSettings.scanDuration * 10);
-                if (($scope.percent + percentage) >= 100 && $rootScope.running && !$scope.loading) {
-                    $scope.percent = 100;
-                    $scope.checkScan();
-                } else if ($scope.percent + percentage < 100 && $rootScope.running) {
-                    $scope.percent += percentage;
-                }
-            }, $scope.percentageInterval);
-        }
-    }
-
-    function parseScanResults(results) {
+    // helpers
+    $scope.parseScanResults = function (results) {
         annotateMacs();
         var data = results['results'];
-        $rootScope.accessPoints = data['ap_list'];
-        $rootScope.unassociatedClients = data['unassociated_clients'];
-        $rootScope.outOfRangeClients = data['out_of_range_clients'];
+        $rootScope.pmkid_accessPoints = data['ap_list'];
+        $rootScope.pmkid_unassociatedClients = data['unassociated_clients'];
+        $rootScope.pmkid_outOfRangeClients = data['out_of_range_clients'];
     }
 
-    $scope.updateScanSettings = function () {
-        $cookies.put('scanDuration', $scope.scanSettings.scanDuration);
-        if ($scope.scanSettings.scanDuration === "0") {
-            $scope.scanSettings.live = true;
-        }
-        $cookies.put('liveScan', $scope.scanSettings.live);
-        ($cookies.getAll());
-    };
-
-    $scope.startScan = function () {
-        $scope.percent = 0;
-        if ($rootScope.running) {
-            return;
-        }
-        if ($scope.scanSettings.scanDuration === "0") {
-            $scope.scanSettings.live = true;
-        }
-        if ($scope.scanSettings.live === true) {
-            $scope.startLiveScan();
-        } else {
-            $scope.startNormalScan();
-        }
-        $rootScope.accessPoints = [];
-        $rootScope.unassociatedClients = [];
-        $rootScope.outOfRangeClients = [];
-        checkScanStatus();
+    $scope.convertDateToBrowserTime = function(scanDate) {
+        var m = [
+            "01", "02", "03",
+            "04", "05", "06",
+            "07", "08", "09",
+            "10", "11", "12"
+        ];
+
+        var ts = scanDate.replace(' ', 'T');
+        ts += 'Z';
+
+        var d = new Date(ts);
+        var day = `${d.getDate()}`.padStart(2, '0');
+        var year = d.getFullYear();
+        var month = d.getMonth();
+        var hour = `${d.getHours()}`.padStart(2, '0');
+        var mins = `${d.getMinutes()}`.padStart(2, '0');
+        var secs = `${d.getSeconds()}`.padStart(2, '0');
+
+        return year + '-' + m[month] + '-' + day + ' ' + hour + ':' + mins + ':' + secs;
     };
 
-    $scope.startLiveScan = function () {
-        $scope.loading = true;
-
+    // requests
+    $scope.getScans = function() {
         $api.request({
             module: 'Recon',
-            action: 'startLiveScan',
-            scanType: $scope.scanType,
-            scanDuration: $scope.scanSettings.scanDuration
-        }, function (response) {
-            if (response.success) {
-                $scope.loading = false;
-                $rootScope.running = true;
-                $scope.scanID = response.scanID;
-                if ($scope.wsStarted !== true) {
-                    $scope.startWS();
-                }
+            action: 'getScans'
+        }, function(response) {
+            if(response.error === undefined) {
+                $scope.scans = response.scans;
+                $scope.scans.forEach((scan) => {
+                    scan.date = $scope.convertDateToBrowserTime(scan.date);
+                });
+                $scope.selectedScan = response.scans[0];
+                $scope.statusObtained = true;
             } else {
-                if (response.error === "The PineAP Daemon must be running.") {
-                    $scope.pineAPDRunning = false;
-                }
                 $scope.error = response.error;
             }
         });
     };
 
-    $scope.startWS = (function () {
-        $scope.wsStarted = true;
+    $scope.setScanLocation = function() {
         $api.request({
             module: 'Recon',
-            action: 'getWSAuthToken'
-        }, function (response) {
-            if (response.success === true) {
-                $scope.wsAuthToken = response.wsAuthToken;
-                $scope.doWS();
-            } else {
-                $scope.wsTimeout = $timeout($scope.startWS, 1500);
-            }
-        });
-    });
-
-    $scope.doWS = (function () {
-        if ($scope.ws !== undefined && $scope.ws.readyState !== WebSocket.CLOSED) {
-            return;
-        }
-        $scope.ws = new WebSocket("ws://" + window.location.hostname + ":1337/?authtoken=" + $scope.wsAuthToken);
-        $scope.ws.onerror = (function () {
-            $scope.wsTimeout = $timeout($scope.startWS, 1000);
-        });
-        $scope.ws.onopen = (function () {
-            $scope.ws.onerror = (function () {
-            });
-            $rootScope.running = true;
-
-        });
-        $scope.ws.onclose = (function () {
-            $scope.listening = false;
-            $scope.closeWS();
-        });
-
-        $scope.ws.onmessage = (function (message) {
-            $scope.listening = true;
-            if ($scope.paused) {
-                return;
-            }
-            var data = JSON.parse(message.data);
-            if (data.scan_complete === true) {
-                $scope.checkScan();
-                return;
-            }
-            $rootScope.accessPoints = data.ap_list;
-            $rootScope.unassociatedClients = data.unassociated_clients;
-            $rootScope.outOfRangeClients = data.out_of_range_clients;
-            annotateMacs();
-        });
-    });
-
-    $scope.startNormalScan = function () {
-        if ($rootScope.running) {
-            return;
-        }
-
-        $scope.loading = true;
-
-        $api.request({
-            module: 'Recon',
-            action: 'startNormalScan',
-            scanType: $scope.scanType,
-            scanDuration: $scope.scanSettings.scanDuration
-        }, function (response) {
+            action: 'setScanLocation',
+            scanLocation: $scope.scanLocation
+        }, function(response) {
             if (response.success) {
-                $scope.loading = false;
-                $rootScope.running = true;
-                $scope.scanID = response.scanID;
+                $scope.getScanLocation();
+                $scope.setLocationSuccess = true;
+                $timeout(function () {
+                    $scope.setLocationSuccess = false;
+                }, 2000);
             } else {
-                if (response.error === "The PineAP Daemon must be running.") {
-                    $scope.pineAPDRunning = false;
-                }
-                $scope.error = response.error;
-            }
-        });
-    };
-
-    $scope.pauseLiveScan = function () {
-        $scope.paused = true;
-    };
-
-    $scope.resumeLiveScan = function () {
-        $scope.paused = false;
-    };
-
-    $scope.stopScan = function () {
-        $scope.percent = 0;
-        $scope.paused = false;
-        $rootScope.running = false;
-
-        $api.request({
-            module: 'Recon',
-            action: 'stopScan'
-        }, function (response) {
-            if (response.success === true) {
-                $rootScope.running = false;
-                $scope.closeWS();
-            }
-        });
-    };
-
-    $scope.checkScan = function () {
-        $api.request({
-            module: 'Recon',
-            action: 'checkScanStatus',
-            scanID: $scope.scanID
-        }, function (response) {
-            $scope.percent = response.scanPercent;
-            if (response.error) {
                 $scope.error = response.error;
-            } else if (response.completed === true) {
-                if (!$rootScope.running && !$scope.loading) {
-                    $scope.percent = 100;
-                }
-                if ($rootScope.running) {
-                    $scope.stopScan();
-                    $scope.scans = $scope.scans || [];
-                    
-                    // fix missing logic
-                    //$scope.selectedScan = $scope.scans[$scope.scans.length - 1];
-                    $scope.selectedScan = {};
-                    $scope.selectedScan['scan_id'] = $scope.scanID;
-                    
-                    $scope.displayScan();
-                }
-            } else if (response.completed === false) {
-                if (response.scanID !== null && response.scanID !== undefined) {
-                    $scope.scanID = response.scanID;
-                }
             }
         });
     };
 
-    $scope.displayScan = function () {
-        if ($scope.selectedScan === undefined) {
-            return;
-        }
-
-        $scope.loadingScan = true;
+    $scope.getScanLocation = function() {
         $api.request({
             module: 'Recon',
-            action: 'getScans'
-        }, function (response) {
+            action: 'getScanLocation'
+        }, function(response) {
             if (response.error === undefined) {
-                $scope.scans = response.scans;
-                $api.request({
-                    module: 'Recon',
-                    action: 'loadResults',
-                    scanID: $scope.selectedScan['scan_id']
-                }, function (response) {
-                    parseScanResults(response);
-                    $scope.loadingScan = false;
-                    $scope.loadedScan = $scope.selectedScan;
-                    $scope.scanID = $scope.selectedScan['scan_id'];
-                });
+                $scope.scanLocation = response.scanLocation;
+                $scope.getScans();
             } else {
                 $scope.error = response.error;
             }
         });
     };
 
-    $scope.cancelIntervals = function () {
-        if ($scope.checkScanInterval) {
-            $interval.cancel($scope.checkScanInterval);
-        }
-        if ($scope.updatePercentageInterval) {
-            $interval.cancel($scope.updatePercentageInterval);
-        }
-
-        if ($scope.wsTimeout) {
-            $timeout.cancel($scope.wsTimeout);
-        }
-        $scope.checkScanInterval = null;
-        $scope.updatePercentageInterval = null;
-        $scope.wsTimeout = null;
-    };
-
-    $scope.closeWS = (function () {
-        if ($scope.ws !== undefined) {
-            $scope.ws.close();
-            $scope.wsStarted = false;
-        }
-    });
-
-    $scope.displayCurrentScan = function () {
+    $scope.displayScan = function() {
+        $scope.loadingScan = true;
         $api.request({
             module: 'Recon',
-            action: 'checkScanStatus'
-        }, function (response) {
-            if (!response.completed && response.scanID !== null) {
-                $scope.scanID = response.scanID;
-                $scope.loading = true;
-                if (response.continuous) {
-                    $scope.scanSettings.scanDuration = "0";
-                    $scope.scanSettings.live = true;
-                    $scope.percent = response.scanPercent;
-                }
-                $api.request({
-                    module: 'Recon',
-                    action: 'startReconPP'
-                }, function () {
-                    if ($scope.wsStarted !== true) {
-                        $scope.startWS();
-                    }
-                    $rootScope.running = true;
-                    checkScanStatus();
-                    $scope.loading = false;
-                });
-            }
+            action: 'loadResults',
+            scanID: $scope.selectedScan['scan_id']
+        }, function(response) {
+            $scope.parseScanResults(response);
+            $scope.loadingScan = false;
+            $scope.loadedScan = $scope.selectedScan;
+            $scope.scanID = $scope.selectedScan['scan_id'];
         });
     };
 
-    $scope.startPineAP = function () {
-        $scope.pineAPDStarting = true;
+    $scope.removeScan = function() {
         $api.request({
             module: 'Recon',
-            action: 'startPineAPDaemon'
-        }, function (response) {
-            $scope.pineAPDStarting = false;
-            if (response.error === undefined) {
-                $scope.pineAPDRunning = true;
-                $scope.startScan();
-                $scope.error = null;
+            action: 'removeScan',
+            scanID: $scope.selectedScan['scan_id']
+        }, function(response) {
+            if(response.error === undefined) {
+                $scope.removedScan = true;
+                $scope.loadedScan = null;
+                $rootScope.pmkid_accessPoints = [];
+                $rootScope.pmkid_unassociatedClients = [];
+                $rootScope.pmkid_outOfRangeClients = [];
+                $timeout(function() {
+                    $scope.removedScan = false;
+                }, 2000);
+                $scope.getScans();
             } else {
                 $scope.error = response.error;
             }
         });
     };
 
-    $scope.checkScan();
-
-    $scope.$on('$destroy', function () {
-        $scope.cancelIntervals();
-        $scope.closeWS();
-    });
-
-    $api.onDeviceIdentified(function (device) {
-        $scope.updateScanSettings();
-        $scope.device = device;
-        $scope.displayCurrentScan();
-    }, $scope);
+    $scope.getScanLocation();
 }]);
 
 
-registerController('PMKIDAttack_ScanResults', ['$api', '$scope', '$interval', '$rootScope', function ($api, $scope, $interval, $rootScope) {
-    $rootScope.ssid = '';
-    $rootScope.bssid = '';
-    $rootScope.pmkidLog = '';
-    $rootScope.pmkids = [];
-    $rootScope.pmkidsLoading = false;
-    $scope.reverseSort = false;
-    $scope.orderByName = 'ssid';
+registerController('PMKIDAttack_AttackResults', ['$api', '$scope', '$rootScope', '$interval', function ($api, $scope, $rootScope, $interval) {
+    $scope.ssid = '';
+    $scope.pmkids = [];
+    $scope.pmkidsLoading = false;
+    $rootScope.pmkid_bssid = '';
+    $rootScope.pmkid_pmkidLog = '';
+    $rootScope.pmkid_captureRunning = false;
+    $rootScope.pmkid_intervalCheckHash = null;
 
     $scope.getStatusAttack = function () {
         $api.request({
             action: "getStatusAttack",
             module: "PMKIDAttack"
         }, function (response) {
-            if (response.success) {
-                $rootScope.ssid = response.ssid;
-                $rootScope.bssid = response.bssid;
+            if (response.process && response.attack) {
+                $scope.ssid = response.ssid;
+                $rootScope.pmkid_bssid = response.bssid;
                 $scope.checkPMKID();
+            } else if (!response.process && response.attack) {
+                $rootScope.pmkid_startAttack(response.ssid, response.bssid, "true");
             }
         });
     };
 
     $scope.checkPMKID = function() {
-        $rootScope.captureRunning = true;
-        if (!$rootScope.intervalCheckHash) {
-            $rootScope.intervalCheckHash = $interval(function () {
-                if ($rootScope.captureRunning) {
-                    $rootScope.catchPMKID();
+        $rootScope.pmkid_captureRunning = true;
+        if (!$rootScope.pmkid_intervalCheckHash) {
+            $rootScope.pmkid_intervalCheckHash = $interval(function () {
+                if ($rootScope.pmkid_captureRunning) {
+                    $scope.catchPMKID();
                 } else {
-                    $rootScope.stopAttack();
+                    $rootScope.pmkid_stopAttack();
                 }
-            }, 5000);
+            }, 30000);
         }
     };
 
-    $scope.startAttack = function (ssid, bssid) {
-        $rootScope.pmkidLog = '';
-        $rootScope.ssid = ssid;
-        $rootScope.bssid = bssid;
-
+    $scope.catchPMKID = function () {
         $api.request({
-            action: 'startAttack',
-            module: 'PMKIDAttack',
-            ssid: ssid,
-            bssid: bssid
+            action: 'catchPMKID',
+            module: 'PMKIDAttack'
         }, function (response) {
+            $rootScope.pmkid_pmkidLog = response.pmkidLog;
             if (response.success) {
-                $scope.checkPMKID();
+                $rootScope.pmkid_captureRunning = false;
             }
         });
     };
 
-    $rootScope.stopAttack = function () {
+    $scope.getPMKIDFiles = function () {
+        $scope.pmkids = [];
+        $scope.pmkidsLoading = true;
+
         $api.request({
-            action: 'stopAttack',
+            action: 'getPMKIDFiles',
             module: 'PMKIDAttack',
-            bssid: $rootScope.bssid
         }, function (response) {
-            $interval.cancel($rootScope.intervalCheckHash);
-            delete $rootScope.intervalCheckHash;
-            $rootScope.captureRunning = false;
-            $rootScope.getPMKIDFiles();
+            $scope.pmkids = response.pmkids;
+            $scope.pmkidsLoading = false;
         });
     };
 
-    $rootScope.viewAttackLog = function (file = '') {
-        $rootScope.pmkidLog = '';
+    $scope.downloadPMKID = function (file) {
         $api.request({
-            action: 'viewAttackLog',
+            action: 'downloadPMKID',
             module: 'PMKIDAttack',
             file: file
         }, function (response) {
-            $rootScope.pmkidLog = response.pmkidLog;
+            window.location = '/api/?download=' + response.download;
         });
     };
 
-    $rootScope.catchPMKID = function () {
+    $scope.deletePMKID = function (file) {
         $api.request({
-            action: 'catchPMKID',
-            module: 'PMKIDAttack'
+            action: 'deletePMKID',
+            module: 'PMKIDAttack',
+            file: file
         }, function (response) {
-            $rootScope.pmkidLog = response.pmkidLog;
-            if (response.success) {
-                $rootScope.captureRunning = false;
-            }
+            $scope.getPMKIDFiles();
         });
     };
 
-    $rootScope.getPMKIDFiles = function () {
-        $rootScope.pmkids = [];
-        $rootScope.pmkidsLoading = true;
-
+    $scope.viewAttackLog = function (file) {
+        $rootScope.pmkid_pmkidLog = '';
         $api.request({
-            action: 'getPMKIDFiles',
+            action: 'viewAttackLog',
             module: 'PMKIDAttack',
+            file: file
         }, function (response) {
-            $rootScope.pmkids = response.pmkids;
-            $rootScope.pmkidsLoading = false;
+            $rootScope.pmkid_pmkidLog = response.pmkidLog;
         });
     };
 
-    $rootScope.downloadPMKID = function (file) {
+    $rootScope.pmkid_startAttack = function (ssid, bssid, cleanStart) {
+        $scope.ssid = ssid;
+        $rootScope.pmkid_bssid = bssid;
+        $rootScope.pmkid_pmkidLog = '';
+
         $api.request({
-            action: 'downloadPMKID',
+            action: 'startAttack',
             module: 'PMKIDAttack',
-            file: file
+            ssid: ssid,
+            bssid: bssid,
+            cleanStart: cleanStart
         }, function (response) {
-            window.location = '/api/?download=' + response.download;
+            if (response.success) {
+                $scope.checkPMKID();
+            }
         });
     };
 
-    $rootScope.deletePMKID = function (file) {
+    $rootScope.pmkid_stopAttack = function () {
         $api.request({
-            action: 'deletePMKID',
+            action: 'stopAttack',
             module: 'PMKIDAttack',
-            file: file
+            bssid: $rootScope.pmkid_bssid
         }, function (response) {
-            $rootScope.getPMKIDFiles();
+            $interval.cancel($rootScope.pmkid_intervalCheckHash);
+            delete $rootScope.pmkid_intervalCheckHash;
+            $rootScope.pmkid_captureRunning = false;
+            $scope.getPMKIDFiles();
         });
     };
 
-    $rootScope.getPMKIDFiles();
+    $scope.getPMKIDFiles();
     $scope.getStatusAttack();
 
     $scope.$on('$destroy', function() {
@@ -528,7 +319,15 @@ registerController('PMKIDAttack_ScanResults', ['$api', '$scope', '$interval', '$
     });
 }]);
 
-registerController('PMKIDAttack_Log', ['$api', '$scope', '$rootScope', '$interval', function ($api, $scope, $rootScope, $interval) {
+
+registerController('PMKIDAttack_ScanResults', ['$api', '$scope', '$rootScope', function ($api, $scope, $rootScope) {
+    $rootScope.pmkid_accessPoints = [];
+    $rootScope.pmkid_unassociatedClients = [];
+    $rootScope.pmkid_outOfRangeClients = [];
+}]);
+
+
+registerController('PMKIDAttack_Log', ['$api', '$scope', function ($api, $scope) {
     $scope.moduleLog = '';
     $scope.moduleLogLading = false;
 

+ 52 - 96
modules/src/PMKIDAttack/module.html

@@ -23,8 +23,8 @@
     </div>
 </div>
 
-<div class="row" ng-show="$root.installedDependencies">
-    <div class="col-md-6" ng-controller="PMKIDAttack_ScanResults">
+<div class="row" ng-show="$root.pmkid_installedDependencies">
+    <div class="col-md-6" ng-controller="PMKIDAttack_AttackResults">
         <div class="panel panel-default">
             <div class="panel-heading">
                 <h3 class="panel-title">
@@ -75,89 +75,54 @@
         </div>
     </div>
 
-    <div class="col-md-6" ng-controller="PMKIDAttack_ScanSettings">
+    <div class="col-md-6" ng-controller="PMKIDAttack_ScanLoad">
         <div class="panel panel-default">
             <div class="panel-heading">
                 <h3 class="panel-title">
-                    Scan Settings
-                    <span class="label label-warning" ng-show="captureRunning">Running Attack on {{ $root.bssid }}</span>
+                    Scan Results
+                    <span class="label label-warning" ng-show="$root.pmkid_captureRunning">Running Attack on {{ $root.pmkid_bssid }}</span>
+                    <span class="pull-right">
+                        <button type="button" class="btn btn-default btn-xs btn-fixed-length pull-right" ng-click="getScans();">
+                            Refresh
+                        </button>
+                    </span>
                 </h3>
             </div>
             <div class="panel-body">
-                <div class="col-md-8">
-                    <div class="row">
-                        <div class="input-group">
-                            <div ng-show="device == 'tetra'">
-                                <label class="radio-inline"><input type="radio" ng-model="scanType" value="0"
-                                                                   ng-disabled="running">2.4GHz</label>
-                                <label class="radio-inline"><input type="radio" ng-model="scanType" value="1"
-                                                                   ng-disabled="running">5GHz</label>
-                                <label class="radio-inline"><input type="radio" ng-model="scanType" value="2"
-                                                                   ng-disabled="running">Both</label>
-                            </div>
-                            <label class="checkbox-inline"><input type="checkbox" ng-model="scanSettings.live"
-                                                                  ng-disabled="running || scanSettings.scanDuration === '0'"
-                                                                  ng-change="updateScanSettings()">Live</label>
-                        </div>
-                    </div>
-                    <br/>
-                    <div class="row form-inline">
-                        <select class="fixed-width-200 form-control" ng-model="scanSettings.scanDuration"
-                                ng-change="updateScanSettings()" ng-disabled="running">
-                            <option value="0">Continuous</option>
-                            <option value="30">30 Seconds</option>
-                            <option value="60">1 Minute</option>
-                            <option value="120">2 Minutes</option>
-                            <option value="300">5 Minutes</option>
-                            <option value="600">10 Minutes</option>
-                        </select>
-                        <br/><br/>
-                        <div class="btn-group">
-                            <button type="button" class="btn btn-default" ng-click="startScan()"
-                                    ng-disabled="running">
-                                <span ng-show="!running">Start</span>
-                                <img class="button-throbber" ng-show="running" src="img/throbber.gif">
-                            </button>
-                            </button>
-                            <button type="button" class="btn btn-default" ng-click="pauseLiveScan()"
-                                    ng-show="scanSettings.live && running && !paused && !captureRunning"
-                                    ng-disabled="!scanSettings.live && !running">Pause
-                            </button>
-                            <button type="button" class="btn btn-default" ng-click="resumeLiveScan()"
-                                    ng-show="scanSettings.live && running && paused && !captureRunning"
-                                    ng-disabled="!scanSettings.live && !running">Resume
-                            </button>
-                            <button type="button" class="btn btn-default" ng-click="stopAttack()"
-                                    ng-show="captureRunning">Stop Attack
-                            </button>
-                            <button type="button" class="btn btn-default"
-                                    data-toggle="modal" data-target="#viewLog"
-                                    ng-show="captureRunning"
-                                    ng-disabled="$root.pmkidLog.length === 0">View Log
-                            </button>
-                            <button type="button" class="btn btn-default" ng-click="stopScan()"
-                                    ng-disabled="!running">Stop
-                            </button>
-                        </div>
-                    </div>
-                    <div class="row">
-                        <br/>
-                        <div class="progress" ng-show="running && scanSettings.scanDuration > 0">
-                            <div class="progress-bar progress-bar-striped active" role="progressbar"
-                                 aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100"
-                                 style="width: {{ percent }}%">{{ percent | roundCeil }}%
-                            </div>
-                            <div class="alert well-sm alert-danger" ng-show="error">{{ error }}</div>
-                        </div>
-                    </div>
+                <div class="input-group">
+                    <span class="input-group-addon">Scans Location</span>
+                    <input class="form-control" ng-model="scanLocation" ng-disabled="running || loading">
+                    <span class="input-group-btn">
+                        <button class="btn btn-default" ng-click="setScanLocation()" ng-disabled="running || loading">Set</button>
+                    </span>
                 </div>
-            </div>
-            <div class="panel-footer" ng-show="!pineAPDRunning">
-                <div class="alert alert-info">
-                    <strong>Notice:</strong> In order to use Recon, PineAP must first be enabled.<br/>
-                    <button class="btn btn-default" ng-click="startPineAP()" ng-disabled="pineAPDStarting">
-                        <span ng-hide="pineAPDStarting">Start PineAP</span>
-                        <img class="button-throbber" ng-show="pineAPDStarting" src="img/throbber.gif">
+                <br/>
+                <div class="input-group">
+                    <span class="input-group-addon">Scan</span>
+                    <select class="form-control" ng-options="scan.date for scan in scans | filter:shouldShowScan track by scan.scan_id" ng-model="selectedScan" ng-disabled="scans == '' || running"></select>
+                    <span class="input-group-btn">
+                        <button class="btn btn-default" ng-click="displayScan();" ng-disabled="running || loading || scans == ''">Load</button>
+                        <button class="btn btn-default" ng-click="removeScan();" ng-disabled="running || loading || scans == ''">Remove</button>
+                    </span>
+                </div>
+                <br/>
+
+                <img ng-show="loadingScan" src="img/throbber.gif"/>
+                <p class="alert well-sm alert-success" ng-show="setLocationSuccess">Succcessfully set scan location.</p>
+                <p class="alert well-sm alert-success" ng-show="removedScan">Succcessfully removed scan.</p>
+                <p class="alert well-sm alert-info" ng-show="scans == '' && !running">There are no scans available. Please run <a href="#!/modules/Recon">Recon</a> at least once.</p>
+                <p class="alert well-sm alert-danger" ng-show="error">{{ error }}</p>
+
+                <div class="btn-group" ng-show="$root.pmkid_captureRunning">
+                    <button type="button" class="btn btn-default" ng-disabled="$root.pmkid_captureRunning">
+                        <img class="button-throbber" src="img/throbber.gif">
+                    </button>
+                    <button type="button" class="btn btn-default" ng-click="$root.pmkid_stopAttack()">
+                        Stop Attack
+                    </button>
+                    <button type="button" class="btn btn-default" data-toggle="modal" data-target="#viewLog"
+                            ng-disabled="$root.pmkid_pmkidLog.length === 0">
+                        View Log
                     </button>
                 </div>
             </div>
@@ -165,18 +130,18 @@
     </div>
 </div>
 
-<div class="row" ng-show="$root.installedDependencies">
+<div class="row" ng-show="$root.pmkid_installedDependencies">
     <div class="col-md-12" ng-controller="PMKIDAttack_ScanResults">
         <div class="panel panel-default">
             <div class="panel-heading">
                 <h3 class="panel-title">
                     Scan Results
-                    <span ng-show="$root.accessPoints.length" class="badge">{{ $root.accessPoints.length }}</span>
+                    <span ng-show="$root.pmkid_accessPoints.length" class="badge">{{ $root.pmkid_accessPoints.length }}</span>
                 </h3>
             </div>
             <div class="panel-body">
                 <div class="table-responsive">
-                    <table class="table table-hover" ng-hide="($root.accessPoints.length == 0)">
+                    <table class="table table-hover" ng-hide="($root.pmkid_accessPoints.length == 0)">
                         <thead>
                         <tr class="default-cursor">
                             <th ng-click="orderByName='ssid'; reverseSort = !reverseSort">SSID <span
@@ -190,13 +155,6 @@
                                     ng-show="orderByName=='encryption'"><span class="caret"
                                                                               ng-show="reverseSort"></span><span
                                     class="caret caret-reversed" ng-show="!reverseSort"></span></span></th>
-                            <th ng-click="orderByName='wps'; reverseSort = !reverseSort">WPS <span
-                                    ng-show="orderByName=='wps'"><span class="caret" ng-show="reverseSort"></span><span
-                                    class="caret caret-reversed" ng-show="!reverseSort"></span></span></th>
-                            <th ng-click="orderByName='channel'; reverseSort = !reverseSort">Channel <span
-                                    ng-show="orderByName=='channel'"><span class="caret"
-                                                                           ng-show="reverseSort"></span><span
-                                    class="caret caret-reversed" ng-show="!reverseSort"></span></span></th>
                             <th ng-click="orderByName='power'; reverseSort = !reverseSort">Signal <span
                                     ng-show="orderByName=='power'"><span class="caret"
                                                                          ng-show="reverseSort"></span><span
@@ -209,7 +167,7 @@
                         </tr>
                         </thead>
                         <tbody>
-                        <tr ng-repeat="accessPoint in $root.accessPoints|orderBy:orderByName:reverseSort"
+                        <tr ng-repeat="accessPoint in $root.pmkid_accessPoints|orderBy:orderByName:reverseSort"
                             ng-show="accessPoint.encryption != 'Open'">
                             <td class="autoselect">
                                 <span class="text-info" ng-hide="accessPoint.ssid"><i>Hidden</i></span>
@@ -221,13 +179,11 @@
                             <td>
                                 {{ accessPoint.encryption }}
                             </td>
-                            <td>{{ (accessPoint.wps == 1) ? "Yes" : "No" }}</td>
-                            <td>{{ (accessPoint.channel == 0) ? "Wi-Fi Direct" : accessPoint.channel }}</td>
                             <td>{{ accessPoint.power }}</td>
                             <td class="autoselect">{{ accessPoint.lastSeen | timesinceepoch }}</td>
                             <td>
-                                <button type="button" ng-click="startAttack(accessPoint.ssid, accessPoint.bssid)"
-                                        ng-disabled="$root.running || $root.captureRunning"
+                                <button type="button" ng-click="$root.pmkid_startAttack(accessPoint.ssid, accessPoint.bssid)"
+                                        ng-disabled="$root.pmkid_captureRunning"
                                         class="btn btn-default btn-xs">Attack
                                 </button>
                             </td>
@@ -235,10 +191,10 @@
                         </tbody>
                     </table>
                 </div>
-                <div ng-if="($root.accessPoints.length === 0) && !running">
+                <div ng-if="($root.pmkid_accessPoints.length === 0) && !running">
                     No scan results.
                 </div>
-                <div ng-if="($root.accessPoints.length === 0) && running">
+                <div ng-if="($root.pmkid_accessPoints.length === 0) && running">
                     <img src="img/throbber.gif">
                 </div>
             </div>
@@ -281,7 +237,7 @@
                 <h4 class="modal-title ng-binding" id="captureModalLabel">View Log</h4>
             </div>
             <div class="modal-body">
-                <pre class="scrollable-pre log-pre ng-binding">{{ $root.pmkidLog }}</pre>
+                <pre class="scrollable-pre log-pre ng-binding">{{ $root.pmkid_pmkidLog }}</pre>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

+ 1 - 1
modules/src/PMKIDAttack/module.info

@@ -6,5 +6,5 @@
         "tetra"
     ],
     "title": "PMKIDAttack",
-    "version": "2.5"
+    "version": "3.0"
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно