Skip to content

Commit c4f8d12

Browse files
committed
feat: integrate YARA signature-based detection
1 parent 14e8aab commit c4f8d12

5 files changed

Lines changed: 208 additions & 3 deletions

File tree

.github/workflows/rust.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
with:
2323
components: rustfmt
2424

25+
- name: Install System Dependencies
26+
run: sudo apt-get update && sudo apt-get install -y clang libclang-dev
27+
2528
- name: Check formatting
2629
run: cargo fmt --check
2730

Cargo.lock

Lines changed: 152 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ sha2 = "0.10"
1313
goblin = "0.9"
1414
regex = "1"
1515
chrono = "0.4"
16+
yara = { version = "0.31.0", features = ["vendored"] }

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ WORKDIR /usr/src/entrors
77
# Copy the source code into the container
88
COPY . .
99

10+
# Install dependencies required for YARA (clang, libclang)
11+
RUN apt-get update && apt-get install -y clang libclang-dev
12+
1013
# Build the project in release mode
1114
RUN cargo build --release
1215

src/main.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct AnalysisReport {
6464
suspicious_apis: Vec<String>,
6565
strings_found: Vec<String>,
6666
mitre_techniques: Vec<String>,
67+
yara_matches: Vec<String>,
6768
}
6869

6970
#[derive(Debug, Serialize, Clone)]
@@ -190,6 +191,7 @@ fn main() {
190191
"T1129".to_string(),
191192
"T1082".to_string(),
192193
],
194+
yara_matches: scan_with_yara(&file_data),
193195
};
194196

195197
// Sezgisel Kurallar
@@ -249,6 +251,9 @@ fn calculate_risk_score(report: &mut AnalysisReport) {
249251
score += 15;
250252
}
251253

254+
// YARA matches: +25 each
255+
score += (report.yara_matches.len() as u32) * 25;
256+
252257
report.risk_score = score.min(100);
253258
report.risk_level = match report.risk_score {
254259
0..=30 => "LOW",
@@ -285,6 +290,37 @@ fn extract_strings(data: &[u8]) -> Vec<String> {
285290
matches
286291
}
287292

293+
fn scan_with_yara(data: &[u8]) -> Vec<String> {
294+
let mut matches = Vec::new();
295+
if let Ok(mut compiler) = yara::Compiler::new() {
296+
let rule = r#"
297+
rule UPX_Packed {
298+
strings:
299+
$upx1 = "UPX0"
300+
$upx2 = "UPX1"
301+
condition:
302+
$upx1 and $upx2
303+
}
304+
rule Suspicious_MZ {
305+
strings:
306+
$mz = "MZ"
307+
condition:
308+
$mz at 0
309+
}
310+
"#;
311+
if let Ok(compiler) = compiler.add_rules_str(rule) {
312+
if let Ok(rules) = compiler.compile_rules() {
313+
if let Ok(results) = rules.scan_mem(data, 10) {
314+
for m in results {
315+
matches.push(m.identifier.to_string());
316+
}
317+
}
318+
}
319+
}
320+
}
321+
matches
322+
}
323+
288324
fn generate_html_report(report: &AnalysisReport) -> String {
289325
let color = match report.risk_level.as_str() {
290326
"LOW" => "#28a745",
@@ -323,6 +359,7 @@ fn generate_html_report(report: &AnalysisReport) -> String {
323359
<h3>Tespit Edilen Şüpheli API ve Stringler</h3>
324360
<p><b>APIler:</b> {}</p>
325361
<p><b>Stringler:</b> {}</p>
362+
<p><b>YARA Tespiti:</b> {}</p>
326363
</div>
327364
</body></html>"#,
328365
color,
@@ -333,7 +370,12 @@ fn generate_html_report(report: &AnalysisReport) -> String {
333370
report.risk_score,
334371
sections_html,
335372
report.suspicious_apis.join(", "),
336-
report.strings_found.join(", ")
373+
report.strings_found.join(", "),
374+
if report.yara_matches.is_empty() {
375+
"Bulunamadı".to_string()
376+
} else {
377+
report.yara_matches.join(", ")
378+
}
337379
)
338380
}
339381

@@ -363,6 +405,9 @@ fn render_terminal_report(report: &AnalysisReport) {
363405
if !report.suspicious_apis.is_empty() {
364406
println!(" [!] Şüpheli APIler: {:?}", report.suspicious_apis);
365407
}
408+
if !report.yara_matches.is_empty() {
409+
println!(" [!] YARA Eşleşmeleri: {:?}", report.yara_matches);
410+
}
366411
}
367412

368413
// ─────────────────────────────────────────────────────────────
@@ -516,9 +561,10 @@ mod tests {
516561
suspicious_apis: vec!["VirtualAlloc".into()],
517562
strings_found: vec!["http".into()],
518563
mitre_techniques: vec![],
564+
yara_matches: vec!["UPX_Packed".into()],
519565
};
520566
calculate_risk_score(&mut report);
521-
assert_eq!(report.risk_score, 20 + 10 + 15); // Packed(20) + API(10) + String(15) = 45
522-
assert_eq!(report.risk_level, "MEDIUM");
567+
assert_eq!(report.risk_score, 20 + 10 + 15 + 25); // Packed(20) + API(10) + String(15) + YARA(25) = 70
568+
assert_eq!(report.risk_level, "HIGH");
523569
}
524570
}

0 commit comments

Comments
 (0)