Skip to content

Commit

Permalink
Revert "Merge pull request #146 from vipyrsec/better-match-info"
Browse files Browse the repository at this point in the history
This reverts commit 137cff6, reversing
changes made to 3abfcbe.
  • Loading branch information
jonathan-d-zhang committed Aug 27, 2024
1 parent 8ae0890 commit a746271
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 349 deletions.
211 changes: 1 addition & 210 deletions src/client/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use serde::Serialize;
use serde::{self, Deserialize};
use std::collections::HashMap;
use std::fmt::Display;
use std::path::PathBuf;
use yara::{Compiler, Metadata, Rule, Rules, YrString};
use yara::{Compiler, Rules};

pub type ScanResult = Result<SubmitJobResultsSuccess, SubmitJobResultsError>;

Expand Down Expand Up @@ -37,145 +36,6 @@ pub struct SubmitJobResultsSuccess {

/// The commit hash of the ruleset used to produce these results.
pub commit: String,

pub distributions: Vec<DistributionScanResult>,
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct DistributionScanResult {
pub download_url: String,
pub files: Vec<FileScanResult>,
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct FileScanResult {
pub path: PathBuf,
pub matches: Vec<RuleMatch>,
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct RuleMatch {
pub identifier: String,
pub patterns: Vec<PatternMatch>,
pub metadata: HashMap<String, MetadataValue>,
}

/// Owned version of [`yara::MetadataValue`]
#[derive(Debug, PartialEq, Eq, Serialize)]
#[serde(untagged)]
pub enum MetadataValue {
Integer(i64),
String(String),
Boolean(bool),
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct PatternMatch {
pub identifier: String,
pub matches: Vec<Match>,
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct Match {
pub range: Range,
pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct Range {
pub start: usize,
pub end: usize,
}

impl DistributionScanResult {
pub fn new(download_url: String, files: Vec<FileScanResult>) -> Self {
let filtered = files
.into_iter()
.filter(|file| !file.matches.is_empty())
.collect();

Self {
download_url,
files: filtered,
}
}
}

impl FileScanResult {
pub fn new(path: PathBuf, matches: Vec<Rule>) -> Self {
Self {
path,
matches: matches.into_iter().map(RuleMatch::from).collect(),
}
}

/// Returns the total score of all matched rules.
pub fn calculate_score(&self) -> i64 {
self.matches.iter().map(RuleMatch::score).sum()
}
}

impl From<Rule<'_>> for RuleMatch {
fn from(rule: Rule) -> Self {
Self {
identifier: rule.identifier.to_string(),
patterns: rule
.strings
.into_iter()
.filter(|yr_string| !yr_string.matches.is_empty())
.map(PatternMatch::from)
.collect(),
metadata: Self::map_from_metadata(rule.metadatas),
}
}
}

impl RuleMatch {
pub fn score(&self) -> i64 {
if let Some(&MetadataValue::Integer(score)) = self.metadata.get("weight") {
score
} else {
0
}
}

fn map_from_metadata(metadata: Vec<Metadata>) -> HashMap<String, MetadataValue> {
let mut out = HashMap::new();

for val in metadata {
let metadata_value = match val.value {
yara::MetadataValue::Integer(i) => MetadataValue::Integer(i),
yara::MetadataValue::String(s) => MetadataValue::String(s.to_string()),
yara::MetadataValue::Boolean(b) => MetadataValue::Boolean(b),
};
out.insert(val.identifier.to_string(), metadata_value);
}

out
}
}

impl From<YrString<'_>> for PatternMatch {
fn from(yr_string: YrString) -> Self {
Self {
identifier: yr_string.identifier.to_string(),
matches: yr_string.matches.into_iter().map(Match::from).collect(),
}
}
}

impl From<yara::Match> for Match {
fn from(match_: yara::Match) -> Self {
Self {
range: Range {
start: match_.offset,

// Fish assures me that we cannot have zero length matches, so this should never underflow
end: match_.offset + match_.data.len() - 1,
},
data: match_.data,
}
}
}

#[derive(Debug, Serialize)]
Expand Down Expand Up @@ -242,72 +102,3 @@ pub struct AuthBody<'a> {
pub username: &'a str,
pub password: &'a str,
}

#[cfg(test)]
mod tests {
use crate::client::DistributionScanResult;
use crate::test::make_file_scan_result;

#[test]
fn test_serialize_distribution_scan_result() {
let fsrs = vec![
make_file_scan_result("file1", &[("rule1", 5), ("rule2", 7)]),
make_file_scan_result("file2", &[("rule5", 100), ("rule3", 1)]),
];

let distro = DistributionScanResult::new("https://example.com".into(), fsrs);

let actual = serde_json::to_value(&distro).unwrap();
let expected = serde_json::json!({
"download_url": "https://example.com",
"files": [
{
"path": "file1",
"matches": [
{
"identifier": "rule1",
"patterns": [],
"metadata": {
"weight": 5,
}
},
{
"identifier": "rule2",
"patterns": [],
"metadata": {
"weight": 7,
}
}
]
},
{
"path": "file2",
"matches": [
{
"identifier": "rule5",
"patterns": [],
"metadata": {
"weight": 100,
}
},
{
"identifier": "rule3",
"patterns": [],
"metadata": {
"weight": 1,
}
}
]
}
]
});

assert_eq!(expected, actual);
}

#[test]
fn test_file_score() {
let fsr = make_file_scan_result("ayo", &[("rule1", 5), ("rule2", 7)]);
assert_eq!(fsr.calculate_score(), 12);
}
}
22 changes: 22 additions & 0 deletions src/exts.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use yara::{MetadataValue, Rule};

use crate::scanner::RuleScore;

pub trait RuleExt<'a> {
/// Get the value of a metadata by key. `None` if that key/value pair doesn't exist
fn get_metadata_value(&'a self, key: &str) -> Option<&'a MetadataValue>;

/// Get the weight of this rule. `0` if no weight is defined.
fn get_rule_weight(&'a self) -> i64;

/// Get a vector over the `filetype` metadata value. An empty Vec if not defined.
fn get_filetypes(&'a self) -> Vec<&'a str>;
}
Expand All @@ -23,4 +28,21 @@ impl RuleExt<'_> for Rule<'_> {
Vec::new()
}
}

fn get_rule_weight(&self) -> i64 {
if let Some(MetadataValue::Integer(integer)) = self.get_metadata_value("weight") {
*integer
} else {
0
}
}
}

impl From<Rule<'_>> for RuleScore {
fn from(rule: Rule) -> Self {
Self {
name: rule.identifier.to_owned(),
score: rule.get_rule_weight(),
}
}
}
3 changes: 0 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ mod exts;
mod scanner;
mod utils;

#[cfg(test)]
mod test;

use std::time::Duration;

use client::DragonflyClient;
Expand Down
Loading

0 comments on commit a746271

Please sign in to comment.