Skip to content

Commit 22c29d4

Browse files
authored
Merge pull request #9 from parv68/SIEM
Siem
2 parents bbcc345 + d4b69b4 commit 22c29d4

25 files changed

Lines changed: 1245 additions & 0 deletions

examples/01_simple_detect.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
fn main() {
2+
let inputs = [
3+
"5d41402abc4b2a76b9719d911017c592",
4+
"SGVsbG8gV29ybGQ=",
5+
"The quick brown fox jumps over the lazy dog",
6+
];
7+
8+
for input in inputs {
9+
println!("Input: {:?}", input);
10+
11+
if let Some(hash) = cryptotrace::core::hashing::detect_hash(input) {
12+
println!(" Hash: {} (confidence {:.2})", hash.algorithm, hash.confidence);
13+
}
14+
if let Some(enc) = cryptotrace::core::encoding::detect_encoding(input) {
15+
println!(" Encoding: {} (confidence {:.2})", enc.encoding_type, enc.confidence);
16+
}
17+
18+
let (entropy, _freq) = cryptotrace::core::entropy::shannon_entropy(input.as_bytes());
19+
println!(" Entropy: {:.2}", entropy);
20+
println!();
21+
}
22+
}

examples/02_scan_file.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::env;
2+
use std::fs;
3+
4+
fn main() {
5+
let args: Vec<String> = env::args().collect();
6+
let path = if args.len() > 1 { &args[1] } else { "Cargo.toml" };
7+
8+
let data = fs::read(path).expect("Failed to read file");
9+
10+
match cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
11+
Ok(result) => {
12+
println!("File: {}", path);
13+
println!("Algorithm: {}", result.algorithm.unwrap_or_else(|| "<none>".into()));
14+
println!("Encoding: {}", result.detected_type);
15+
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
16+
println!("Entropy: {:.2}", entropy);
17+
println!("Confidence: {:.2}", result.confidence);
18+
println!("Risk: {:?}", result.risk_level);
19+
if !result.weakness_cve.is_empty() {
20+
println!("CVEs: {:?}", result.weakness_cve);
21+
}
22+
}
23+
Err(e) => eprintln!("Error: {}", e),
24+
}
25+
}

examples/03_batch_folder.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::env;
2+
use std::fs;
3+
4+
fn main() {
5+
let args: Vec<String> = env::args().collect();
6+
let dir = if args.len() > 1 { &args[1] } else { "." };
7+
let max_size: u64 = std::env::var("MAX_FILE_SIZE").ok().and_then(|s| s.parse().ok()).unwrap_or(10_485_760);
8+
9+
for entry in fs::read_dir(dir).unwrap().flatten() {
10+
let path = entry.path();
11+
if !path.is_file() { continue; }
12+
13+
let _meta = match fs::metadata(&path) {
14+
Ok(m) if m.len() <= max_size => m,
15+
_ => continue,
16+
};
17+
18+
let data = match fs::read(&path) {
19+
Ok(d) => d,
20+
Err(_) => continue,
21+
};
22+
23+
match cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
24+
Ok(result) => {
25+
let algo = result.algorithm.unwrap_or_else(|| "-".into());
26+
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
27+
println!("{}\t{}\t{}\t{:.2}\t{:.2}",
28+
path.display(), algo, result.detected_type, entropy, result.confidence);
29+
}
30+
Err(e) => eprintln!("Error scanning {}: {}", path.display(), e),
31+
}
32+
}
33+
}

examples/04_compare_inputs.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::io::Read;
2+
use std::path::Path;
3+
4+
fn main() {
5+
let test_data = b"Hello World this is a test string with some data to analyze";
6+
7+
// Method 1: Raw bytes
8+
println!("=== Raw bytes ===");
9+
let r1 = cryptotrace::analyzers::file::analyze_bytes(test_data, cryptotrace::types::SourceType::Binary).unwrap();
10+
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r1.algorithm, r1.detected_type, r1.entropy, r1.confidence);
11+
12+
// Method 2: File
13+
println!("=== From file ===");
14+
let r2 = cryptotrace::analyzers::file::analyze_file(Path::new("Cargo.toml")).unwrap();
15+
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r2.algorithm, r2.detected_type, r2.entropy, r2.confidence);
16+
17+
// Method 3: Stdin (if piped)
18+
println!("=== Stdin (pipe data or skip) ===");
19+
let mut buf = Vec::new();
20+
if std::io::stdin().read_to_end(&mut buf).is_ok() && !buf.is_empty() {
21+
let r3 = cryptotrace::analyzers::file::analyze_bytes(&buf, cryptotrace::types::SourceType::Binary).unwrap();
22+
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r3.algorithm, r3.detected_type, r3.entropy, r3.confidence);
23+
} else {
24+
println!(" (no stdin data)");
25+
}
26+
}

examples/05_csv_export.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use std::env;
2+
use std::fs;
3+
4+
fn main() {
5+
let args: Vec<String> = env::args().collect();
6+
let dir = args.get(1).map(|s| s.as_str()).unwrap_or(".");
7+
let out = args.get(2).map(|s| s.as_str()).unwrap_or("scan_report.csv");
8+
9+
let mut wtr = csv::Writer::from_path(out).expect("Failed to create CSV");
10+
wtr.write_record(["path", "algorithm", "detected_type", "entropy", "confidence", "risk_level"])
11+
.unwrap();
12+
13+
for entry in fs::read_dir(dir).unwrap().flatten() {
14+
let path = entry.path();
15+
if !path.is_file() { continue; }
16+
let data = match fs::read(&path) {
17+
Ok(d) if d.len() <= 10_485_760 => d,
18+
_ => continue,
19+
};
20+
if let Ok(r) = cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
21+
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
22+
wtr.write_record([
23+
path.to_string_lossy().as_ref(),
24+
r.algorithm.as_deref().unwrap_or("-"),
25+
&r.detected_type,
26+
&format!("{:.4}", entropy),
27+
&format!("{:.4}", r.confidence),
28+
&format!("{:?}", r.risk_level),
29+
]).ok();
30+
}
31+
}
32+
wtr.flush().ok();
33+
println!("Report written to {}", out);
34+
}

examples/06_recursive_decode.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use std::io::{Read, Write};
2+
3+
fn main() {
4+
let plaintext = b"Secret configuration: API_KEY=sk-abc123 SECRET=xyz789";
5+
6+
// Gzip then base64 encode
7+
let mut compressed = Vec::new();
8+
{
9+
let mut encoder = flate2::write::GzEncoder::new(&mut compressed, flate2::Compression::default());
10+
encoder.write_all(plaintext).unwrap();
11+
encoder.finish().unwrap();
12+
}
13+
14+
use base64::Engine;
15+
let b64_payload = base64::engine::general_purpose::STANDARD.encode(&compressed);
16+
17+
println!("Encoded payload (first 80 chars): {:?}", &b64_payload[..80.min(b64_payload.len())]);
18+
19+
// Decode layer by layer
20+
let mut current = b64_payload.as_bytes().to_vec();
21+
for layer in 1..=5 {
22+
let s = String::from_utf8_lossy(&current);
23+
24+
if let Some(enc) = cryptotrace::core::encoding::detect_encoding(&s) {
25+
println!("Layer {}: detected encoding = {} (conf={:.2})", layer, enc.encoding_type, enc.confidence);
26+
27+
match enc.encoding_type.as_str() {
28+
"Base64" => {
29+
if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(s.trim()) {
30+
current = decoded;
31+
continue;
32+
}
33+
}
34+
_ => { break; }
35+
}
36+
}
37+
38+
if cryptotrace::core::compression::detect_compression(&current).is_some() {
39+
let mut decompressed = Vec::new();
40+
let mut d = flate2::read::GzDecoder::new(std::io::Cursor::new(&current));
41+
if d.read_to_end(&mut decompressed).is_ok() && !decompressed.is_empty() {
42+
println!("Layer {}: gzip decompressed ({} bytes)", layer, decompressed.len());
43+
current = decompressed;
44+
continue;
45+
}
46+
}
47+
break;
48+
}
49+
50+
println!("Final decoded text: {:?}", String::from_utf8_lossy(&current));
51+
}

examples/07_sandbox_crash_test.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Build worker binary first: cargo build --bin cryptotrace-worker
2+
3+
fn main() {
4+
let config = cryptotrace::sanitization::sandbox::SandboxConfig {
5+
enabled: true,
6+
timeout_seconds: 5,
7+
max_memory_mb: 256,
8+
max_concurrent: 2,
9+
worker_path: None,
10+
};
11+
let sandbox = cryptotrace::sanitization::sandbox::Sandbox::new(config);
12+
13+
let test_data = b"5d41402abc4b2a76b9719d911017c592";
14+
match sandbox.run_worker("detect", test_data) {
15+
Ok(output) => {
16+
println!("Sandbox worker succeeded ({} bytes)", output.len());
17+
if let Ok(text) = String::from_utf8(output) {
18+
println!("Output: {}", text);
19+
}
20+
}
21+
Err(e) => {
22+
println!("Sandbox worker failed (expected if no worker binary): {}", e);
23+
println!("Falling back to in-process analysis...");
24+
match cryptotrace::analyzers::file::analyze_bytes(test_data, cryptotrace::types::SourceType::Binary) {
25+
Ok(r) => println!("In-process result: algo={:?} ent={}", r.algorithm, r.entropy),
26+
Err(e2) => eprintln!("Fallback also failed: {}", e2),
27+
}
28+
}
29+
}
30+
31+
let tight = cryptotrace::sanitization::sandbox::SandboxConfig {
32+
enabled: true,
33+
timeout_seconds: 1,
34+
worker_path: None,
35+
..Default::default()
36+
};
37+
let tight_sandbox = cryptotrace::sanitization::sandbox::Sandbox::new(tight);
38+
let large_input = vec![b'A'; 1_000_000];
39+
match tight_sandbox.run_worker("detect", &large_input) {
40+
Ok(_) => println!("Tight timeout: worker finished in time"),
41+
Err(e) => println!("Tight timeout: worker timed out as expected: {}", e),
42+
}
43+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use cryptotrace::core::calibration::{generate_synthetic_dataset, train, predict_proba, signal_contributions, save_model, load_model};
2+
use cryptotrace::types::SignalBreakdown;
3+
4+
fn main() {
5+
println!("Generating synthetic training data...");
6+
7+
let dataset = generate_synthetic_dataset(250);
8+
println!(" {} samples generated", dataset.len());
9+
10+
let model = train(&dataset, 0.01, 1000, 0.001);
11+
println!("Model trained: intercept={:.4}, weights={:?}", model.intercept, model.weights);
12+
println!("Dataset size: {}", model.dataset_size);
13+
14+
let test_signals = SignalBreakdown {
15+
entropy: 0.85,
16+
block_alignment: 0.72,
17+
magic_bytes: 0.65,
18+
length_pattern: 0.91,
19+
charset_purity: Some(0.48),
20+
byte_distribution: None,
21+
window_variance: Some(0.73),
22+
};
23+
let prob = predict_proba(&model, &test_signals);
24+
println!("\nPrediction for high-entropy sample: {:.4}", prob);
25+
26+
let contribs = signal_contributions(&model, &test_signals);
27+
println!("\nSignal contributions:");
28+
for sc in &contribs {
29+
println!(" {:20} {:>8} {:.4}", sc.signal_name, if sc.coefficient > 0.0 { "+" } else { "-" }, sc.contribution);
30+
}
31+
32+
save_model(&model, "calibration_example.json").ok();
33+
if let Ok(loaded) = load_model("calibration_example.json") {
34+
println!("\nModel save/load roundtrip: OK (weights={:?})", loaded.weights);
35+
}
36+
std::fs::remove_file("calibration_example.json").ok();
37+
}

examples/09_sliding_entropy.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use std::fs;
2+
3+
fn main() {
4+
let args: Vec<String> = std::env::args().collect();
5+
let path = if args.len() > 1 { &args[1] } else { "Cargo.toml" };
6+
let data = fs::read(path).expect("Failed to read file");
7+
8+
println!("File: {} ({} bytes)", path, data.len());
9+
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
10+
println!("Global Shannon entropy: {:.2} bits/byte", entropy);
11+
12+
let sw = cryptotrace::core::sliding_entropy::sliding_window_entropy(&data, Some(4096), None, Some(7.5));
13+
14+
if sw.window_scores.is_empty() {
15+
println!("File too small for any window");
16+
return;
17+
}
18+
19+
let avg: f64 = sw.window_scores.iter().sum::<f64>() / sw.window_scores.len() as f64;
20+
let max_score = sw.window_scores.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
21+
let min_score = sw.window_scores.iter().cloned().fold(f64::INFINITY, f64::min);
22+
23+
println!("Windows analyzed: {}", sw.window_scores.len());
24+
println!("Avg window entropy: {:.2}", avg);
25+
println!("Max window entropy: {:.2}", max_score);
26+
println!("Min window entropy: {:.2}", min_score);
27+
println!("Max window entropy (struct): {:.2}", sw.max_window_entropy);
28+
println!("Entropy variance: {:.2}", sw.entropy_variance);
29+
30+
let hot_count = sw.window_scores.iter().filter(|&&s| s > 7.5).count();
31+
if hot_count > 0 {
32+
println!("\nHigh-entropy regions (>7.5 bits/byte):");
33+
println!(" {} windows above threshold", hot_count);
34+
for region in sw.embedded_regions.iter().take(10) {
35+
println!(" offset {}-{}", region.start, region.end);
36+
}
37+
if sw.embedded_regions.len() > 10 {
38+
println!(" ... and {} more", sw.embedded_regions.len() - 10);
39+
}
40+
}
41+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#[tokio::main]
2+
async fn main() {
3+
let sample_hash = "d41d8cd98f00b204e9800998ecf8427e";
4+
5+
println!("Step 1: Hash identification");
6+
if let Some(h) = cryptotrace::core::hashing::detect_hash(sample_hash) {
7+
println!(" Algorithm: {} (confidence {:.2})", h.algorithm, h.confidence);
8+
}
9+
10+
println!("\nStep 2: CVE lookup");
11+
let cve_map = cryptotrace::intelligence::risk::build_cve_map(
12+
"signatures/cve_map.yaml",
13+
"cve-db.json",
14+
);
15+
if let Some(cves) = cve_map.get("MD5") {
16+
println!(" Known CVEs for MD5: {:?}", cves);
17+
}
18+
19+
println!("\nStep 3: Threat intel scan");
20+
let config = cryptotrace::intelligence::threat_intel::ThreatIntelConfig {
21+
vt_api_key: None,
22+
yara_rules_path: None,
23+
enable_scan: true,
24+
};
25+
26+
let reports = cryptotrace::intelligence::threat_intel::composite_threat_scan(
27+
sample_hash,
28+
&[],
29+
&config,
30+
).await.unwrap_or_default();
31+
println!(" Threat reports: {}", reports.len());
32+
for report in &reports {
33+
println!(" Source: {} | Positives: {}/{} | Malicious: {}",
34+
report.source, report.positives, report.total_scanners, report.malicious);
35+
}
36+
37+
let malicious = reports.iter().any(|r| r.malicious);
38+
let max_positives = reports.iter().map(|r| r.positives).max().unwrap_or(0);
39+
let risk = if malicious {
40+
"Critical"
41+
} else if max_positives > 5 {
42+
"High"
43+
} else if max_positives > 2 {
44+
"Medium"
45+
} else {
46+
"Low"
47+
};
48+
println!("\nStep 4: Composite risk assessment");
49+
println!(" Final risk level: {}", risk);
50+
}

0 commit comments

Comments
 (0)