1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::collections::HashMap;
use aho_corasick::{AcAutomaton, Automaton};
use errors::ArmorlibError;
use scan_module::ScanModule;
use scan_object::ScanObject;
use finding::{Finding, Severity};
pub struct StringsScanModule;
fn suspicious_strings() -> HashMap<&'static str, &'static str> {
hashmap!{
"48 8B CD E8 60 FF FF FF 48 FF C3 32 44 1E FF 48 FF CF 88 43 FF" =>
"xor decode loop for <PolishBankRAT_srservice>",
}
}
impl ScanModule for StringsScanModule {
fn scan(&self, scan_object: &ScanObject) -> Result<Vec<Finding>, ArmorlibError> {
let mut findings: Vec<Finding> = Vec::new();
let strings = suspicious_strings();
let aut: AcAutomaton<&str> = strings.keys().cloned().collect();
let hex = scan_object.get_metadata("hex/hex_data")?;
let matches = aut.find(&hex);
for item in matches {
let pattern: &str = aut.pattern(item.pati);
let description: &str = match strings.get(pattern) {
Some(description) => description,
None => {
return Err(ArmorlibError::UnknownProcessingError(String::from(
"matched key not found",
)))
}
};
findings.push(Finding {
title: String::from(description),
description: format!("found suspicious string: {}", pattern),
id: String::from("SUSPICIOUS_STRING"),
severity: Severity::Warn(String::from("may indicate malware"))
})
}
Ok(findings)
}
fn info(&self) -> (&'static str, &'static str) {
("strings", "searches for suspicious byte patterns")
}
fn required_preprocessors(&self) -> Vec<&'static str> {
vec!["hex"]
}
}