Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/undo-ransomware/ransomware_detection.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias <ilovemilk@wusa.io>2020-04-14 18:37:55 +0300
committerMatthias <ilovemilk@wusa.io>2020-04-14 18:37:55 +0300
commite81db910b3b8201c55e88fea69a3d8220d2067f0 (patch)
tree3135da2787a254fe00fb724ea7bee74b745d6a09
parent6f3f5d1cc6a020615ebc2f2bd2489a8f72de6eaa (diff)
add detection logic
-rw-r--r--lib/AppInfo/Application.php2
-rw-r--r--lib/Controller/FileOperationController.php1
-rw-r--r--lib/Service/DetectionService.php49
-rw-r--r--src/components/ProtectionStatus.vue3
-rw-r--r--src/views/Recover.vue98
5 files changed, 117 insertions, 36 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index f90b0f5..5bdad38 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -88,9 +88,11 @@ class Application extends App
$container->registerService('DetectionService', function ($c) {
return new DetectionService(
+ $c->query(ILogger::class),
$c->query('FileOperationService'),
$c->query('DetectionDeserializer'),
$c->query('OCP\IConfig'),
+ $c->query(Classifier::class),
$c->query('ServerContainer')->getUserSession()->getUser()->getUID()
);
});
diff --git a/lib/Controller/FileOperationController.php b/lib/Controller/FileOperationController.php
index ce1ef86..d09268e 100644
--- a/lib/Controller/FileOperationController.php
+++ b/lib/Controller/FileOperationController.php
@@ -69,6 +69,7 @@ class FileOperationController extends Controller
* @param ILogger $logger
* @param Folder $userFolder
* @param FileOperationService $service
+ * @param Classifier $classifier
* @param string $userId
*/
public function __construct(
diff --git a/lib/Service/DetectionService.php b/lib/Service/DetectionService.php
index 503066a..125761b 100644
--- a/lib/Service/DetectionService.php
+++ b/lib/Service/DetectionService.php
@@ -23,10 +23,16 @@ namespace OCA\RansomwareDetection\Service;
use OCA\RansomwareDetection\AppInfo\Application;
use OCA\RansomwareDetection\Model\Detection;
use OCA\RansomwareDetection\Model\DetectionDeserializer;
+use OCA\RansomwareDetection\Classifier;
+use OCA\RansomwareDetection\Analyzer\SequenceAnalyzer;
use OCP\IConfig;
+use OCP\ILogger;
class DetectionService {
+ /** @var ILogger */
+ protected $logger;
+
/** @var FileOperationService */
protected $service;
@@ -36,30 +42,65 @@ class DetectionService {
/** @var IConfig */
protected $config;
+ /** @var Classifier */
+ protected $classifier;
+
/** @var string */
protected $userId;
/**
- * @param FileOperationService $service
- * @param IConfig $config
- * @param string $userId
+ * @param ILogger $logger
+ * @param FileOperationService $service
+ * @param IConfig $config
+ * @param Classifier $classifier
+ * @param SequenceAnalyzer $sequenceAnalyzer
+ * @param string $userId
*/
public function __construct(
+ ILogger $logger,
FileOperationService $service,
DetectionDeserializer $deserializer,
IConfig $config,
+ Classifier $classifier,
+ SequenceAnalyzer $sequenceAnalyzer,
$userId
)
{
+ $this->logger = $logger;
$this->service = $service;
$this->deserializer = $deserializer;
$this->config = $config;
+ $this->classifier = $classifier;
+ $this->sequenceAnalyzer = $sequenceAnalyzer;
$this->userId = $userId;
}
public function getDetections() {
+ $files = $this->service->findAll();
+
+ $sequences = array();
$detectionObjects = array();
- //array_push($detectionObjects, new Detection(1, array()));
+
+ // Classify files and put together the sequences.
+ foreach ($files as $file) {
+ $this->classifier->classifyFile($file);
+ $sequences[$file->getSequence()][] = $file;
+ }
+
+ foreach ($sequences as $id => $sequence) {
+ if (sizeof($sequence) >= $this->config->getAppValue(Application::APP_ID, 'minimum_sequence_length', 0)) {
+ usort($sequence, function ($a, $b) {
+ return $b->getId() - $a->getId();
+ });
+ $result = $this->sequenceAnalyzer->analyze($id, $sequence);
+ $this->logger->debug('detection: suspicion score of sequence ' . $id . ' is ' . $result->getSuspicionScore() . '.', array('app' => Application::APP_ID));
+ if ($result->getSuspicionScore() >= 0.5) {
+ $detection = new Detection($id, $sequence);
+ array_push($detectionObjects, $detection);
+ }
+ }
+ }
+
return $detectionObjects;
}
diff --git a/src/components/ProtectionStatus.vue b/src/components/ProtectionStatus.vue
index 0a07e0b..f2dfc34 100644
--- a/src/components/ProtectionStatus.vue
+++ b/src/components/ProtectionStatus.vue
@@ -69,13 +69,14 @@ export default {
span {
vertical-align: middle;
}
+ padding: 0px 10px 0px 30px;
}
width: 100%;
height: 100%;
box-shadow: none;
color: #fff;
- padding: 0px 10px 0px 30px;
+ padding: 0px 10px 0px 10px;
&.good {
background-color: #18b977;
}
diff --git a/src/views/Recover.vue b/src/views/Recover.vue
index 07a99b7..0c57bc4 100644
--- a/src/views/Recover.vue
+++ b/src/views/Recover.vue
@@ -6,12 +6,14 @@
</div>
<div class="page">
<div class="notification-wrapper">
- <Notification text="Test Notification" @on-close="visible = false" :visible="visible"></Notification>
+ <Notification :text.sync="notificationText" @on-close="closeNotification" :visible.sync="visible"></Notification>
</div>
<Header header="Recover">
- <RecoverAction v-if="detected" id="recover" label="Recover" v-on:recover="onRecover" primary></RecoverAction>
+ <RecoverAction id="recover" label="Recover selected files" v-on:recover="onRecover" primary></RecoverAction>
</Header>
- <FileOperationsTable v-if="detected" id="ransomware-table" :data="fileOperations" v-on:table-state-changed="tableStateChanged"></FileOperationsTable>
+ <div id="tables" v-if="detected">
+ <FileOperationsTable v-for="(detection, index) in detections" :key="index" class="ransomware-table" :data="detection.fileOperations" v-on:table-state-changed="tableStateChanged"></FileOperationsTable>
+ </div>
<span id="message" v-if="!detected">
<iron-icon icon="verified-user"></iron-icon>
Nothing found. You are safe.
@@ -41,24 +43,45 @@ export default {
RecoverAction,
Notification
},
- props: {
- visible: {
- type: Boolean, default: false
- }
- },
data() {
return {
detected: 0,
- fileOperations: [],
- page: 0
+ detections: [],
+ page: 0,
+ visible: false,
+ notificationText: ""
};
},
mounted() {
this.page = 0;
this.fetchDetectionStatus();
- this.fetchData();
+ this.fetchDetections();
},
methods: {
+ closeNotification() {
+ this.visible = false
+ },
+ notice(text) {
+ this.notificationText = text;
+ this.visible = true;
+
+ },
+ buildNotification(deleted, recovered) {
+ var notificationText = "";
+ if (deleted > 0 && recovered > 0) {
+ notificationText = deleted + " files deleted, " + recovered + " files recovered from backup."
+ }
+ if (recovered > 0 && deleted == 0) {
+ notificationText = deleted + " files recovered from backup."
+ }
+ if (deleted > 0 && recovered == 0) {
+ notificationText = deleted + " files deleted."
+ }
+ if (deleted == 0 && recovered == 0) {
+ notificationText = "No files deleted or recovered."
+ }
+ this.notice(notificationText);
+ },
fetchDetectionStatus() {
this.$axios({
method: 'GET',
@@ -76,42 +99,53 @@ export default {
tableStateChanged() {
this.page = 1;
},
- fetchData() {
+ fetchDetections() {
this.$axios({
method: 'GET',
- url: this.fileOperationsUrl
+ url: this.detectionsUrl
})
.then(json => {
- this.fileOperations = json.data;
+ this.detections = json.data;
})
.catch( error => { console.error(error); });
},
onRecover() {
+ var itemsToRecover = [];
const items = document.querySelector('#ransomware-table').items;
const selected = document.querySelector('#ransomware-table').selectedItems;
for (var i = 0; i < selected.length; i++) {
- this.recover(selected[i].id);
- }
+ itemsToRecover.push(selected[i].id);
+ }
+ this.recover(itemsToRecover);
},
- remove(id) {
- for (var i = 0; i < this.fileOperations.length; i++) {
- if (this.fileOperations[i].id === id) {
- this.fileOperations.splice(i, 1);
+ remove(ids) {
+ ids.forEach(id => {
+ for (var i = 0; i < this.fileOperations.length; i++) {
+ if (this.fileOperations[i].id === id) {
+ this.fileOperations.splice(i, 1);
+ }
}
- }
+ });
},
- async recover(id) {
+ async recover(ids) {
await this.$axios({
method: 'PUT',
- url: this.recoverUrl + '/' + id + '/recover'
+ url: this.recoverUrl + '/recover',
+ data: {
+ ids: ids
+ }
})
.then(response => {
switch(response.status) {
- case 204:
- this.remove(id);
+ case 200:
+ this.buildNotification(response.data.deleted, response.data.recovered);
+ if(response.data.filesRecovered.length > 0)
+ this.remove(response.data.filesRecovered);
break;
default:
- console.log(response);
+ this.buildNotification(response.data.deleted, response.data.recovered);
+ if(response.data.filesRecovered.length > 0)
+ this.remove(response.data.filesRecovered);
break;
}
})
@@ -125,7 +159,7 @@ export default {
return OC.generateUrl('/apps/ransomware_detection/api/v1/detection');
},
recoverUrl() {
- return OC.generateUrl('/apps/ransomware_detection/api/v1/file-operation')
+ return OC.generateUrl('/apps/ransomware_detection/api/v1/file-operations')
},
fileOperationsUrl() {
return OC.generateUrl('/apps/ransomware_detection/api/v1/file-operation')
@@ -134,12 +168,14 @@ export default {
}
</script>
-<style scoped>
- #ransomware-table {
- height: calc(100% - 50px);
+<style lang="scss" scoped>
+ #tables {
+ .ransomware-table {
+ //height: calc(100% - 50px);
+ }
}
#recover {
- background-color: green;
+ background-color: grey;
color: #fff;
}
#message {