cleanup
This commit is contained in:
parent
f1e1d9ec90
commit
61db822921
@ -1,10 +0,0 @@
|
||||
use anyhow::{Context, Result};
|
||||
use std::fs;
|
||||
|
||||
// Read signatures file
|
||||
pub fn read_signatures(path: &str) -> Result<Vec<String>> {
|
||||
// Read path
|
||||
let content = fs::read_to_string(path)
|
||||
.with_context(|| format!("Could not read signatures file {}", path))?;
|
||||
Ok(content.lines().map(String::from).collect())
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use rand::Rng;
|
||||
use regex::Regex;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use rand::Rng;
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Payload {
|
||||
@ -23,16 +22,14 @@ pub fn parse_signatures(file_path: &str) -> Result<Vec<Signature>> {
|
||||
for (index, line) in reader.lines().enumerate() {
|
||||
let line = line.context("Failed to read line from signatures file")?;
|
||||
if line.trim().is_empty() {
|
||||
continue; // Skip empty lines
|
||||
continue;
|
||||
}
|
||||
|
||||
let payload = if line.contains('(') && line.contains(')') {
|
||||
Payload::Regex(line)
|
||||
} else {
|
||||
Payload::Raw(
|
||||
unescape_string(&line)
|
||||
.with_context(|| format!("Invalid payload on line {}", index + 1))?,
|
||||
)
|
||||
Payload::Raw(unescape_string(&line)
|
||||
.with_context(|| format!("Invalid payload on line {}", index + 1))?)
|
||||
};
|
||||
|
||||
signatures.push(Signature { payload });
|
||||
@ -53,13 +50,12 @@ fn unescape_string(s: &str) -> Result<Vec<u8>> {
|
||||
if c == '\\' {
|
||||
match chars.next() {
|
||||
Some('x') => {
|
||||
let hex = chars
|
||||
.next()
|
||||
.and_then(|c1| chars.next().map(|c2| format!("{}{}", c1, c2)))
|
||||
.unwrap_or_else(|| {
|
||||
let hex = chars.next().and_then(|c1| {
|
||||
chars.next().map(|c2| format!("{}{}", c1, c2))
|
||||
}).unwrap_or_else(|| {
|
||||
result.push(b'\\');
|
||||
result.push(b'x');
|
||||
return String::new();
|
||||
String::new()
|
||||
});
|
||||
if !hex.is_empty() {
|
||||
if let Ok(byte) = u8::from_str_radix(&hex, 16) {
|
||||
@ -70,7 +66,7 @@ fn unescape_string(s: &str) -> Result<Vec<u8>> {
|
||||
result.extend(hex.bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Some('0') => result.push(0),
|
||||
Some('n') => result.push(b'\n'),
|
||||
Some('r') => result.push(b'\r'),
|
||||
@ -94,7 +90,6 @@ pub fn generate_payload(signature: &Signature) -> Vec<u8> {
|
||||
}
|
||||
|
||||
fn generate_regex_match(regex_str: &str) -> Vec<u8> {
|
||||
// Simplified regex matching that doesn't rely on the regex crate
|
||||
let mut result = String::new();
|
||||
let mut chars = regex_str.chars().peekable();
|
||||
|
||||
@ -106,10 +101,7 @@ fn generate_regex_match(regex_str: &str) -> Vec<u8> {
|
||||
'd' => result.push(rand::thread_rng().gen_range(b'0'..=b'9') as char),
|
||||
'w' => result.push(rand::thread_rng().gen_range(b'a'..=b'z') as char),
|
||||
'x' => {
|
||||
// Handle \x hex escapes
|
||||
let hex = chars
|
||||
.next()
|
||||
.and_then(|c1| chars.next().map(|c2| format!("{}{}", c1, c2)))
|
||||
let hex = chars.next().and_then(|c1| chars.next().map(|c2| format!("{}{}", c1, c2)))
|
||||
.unwrap_or_else(|| "00".to_string());
|
||||
if let Ok(byte) = u8::from_str_radix(&hex, 16) {
|
||||
result.push(byte as char);
|
||||
@ -118,39 +110,25 @@ fn generate_regex_match(regex_str: &str) -> Vec<u8> {
|
||||
_ => result.push(next_char),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'[' => {
|
||||
let mut class = String::new();
|
||||
while let Some(class_char) = chars.next() {
|
||||
if class_char == ']' {
|
||||
break;
|
||||
}
|
||||
for class_char in chars.by_ref() {
|
||||
if class_char == ']' { break; }
|
||||
class.push(class_char);
|
||||
}
|
||||
if !class.is_empty() {
|
||||
result.push(
|
||||
class
|
||||
.chars()
|
||||
.nth(rand::thread_rng().gen_range(0..class.len()))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
result.push(class.chars().nth(rand::thread_rng().gen_range(0..class.len())).unwrap());
|
||||
}
|
||||
},
|
||||
'(' => {
|
||||
// Skip capturing groups
|
||||
let mut depth = 1;
|
||||
while let Some(group_char) = chars.next() {
|
||||
if group_char == '(' {
|
||||
depth += 1;
|
||||
}
|
||||
if group_char == ')' {
|
||||
depth -= 1;
|
||||
}
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for group_char in chars.by_ref() {
|
||||
if group_char == '(' { depth += 1; }
|
||||
if group_char == ')' { depth -= 1; }
|
||||
if depth == 0 { break; }
|
||||
}
|
||||
},
|
||||
'+' | '*' => {
|
||||
if let Some(last_char) = result.chars().last() {
|
||||
let repeat = rand::thread_rng().gen_range(0..5);
|
||||
@ -158,7 +136,7 @@ fn generate_regex_match(regex_str: &str) -> Vec<u8> {
|
||||
result.push(last_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'.' => result.push(rand::thread_rng().gen_range(b'!'..=b'~') as char),
|
||||
_ => result.push(c),
|
||||
}
|
||||
@ -187,9 +165,6 @@ mod tests {
|
||||
assert_eq!(unescape_string(r"\0\r\n\t").unwrap(), b"\0\r\n\t");
|
||||
assert_eq!(unescape_string(r"Incomplete\").unwrap(), b"Incomplete\\");
|
||||
assert_eq!(unescape_string(r"Incomplete\x").unwrap(), b"Incomplete\\x");
|
||||
assert_eq!(
|
||||
unescape_string(r"Incomplete\x4").unwrap(),
|
||||
b"Incomplete\\x4"
|
||||
);
|
||||
assert_eq!(unescape_string(r"Incomplete\x4").unwrap(), b"Incomplete\\x4");
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,10 @@ use tokio::net::TcpListener;
|
||||
use tracing::{debug, error, info, Level};
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
mod handler;
|
||||
|
||||
use cli::Cli;
|
||||
use handler::{generate_payload, parse_signatures, Signature};
|
||||
use handler::{generate_payload, parse_signatures};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
|
Loading…
Reference in New Issue
Block a user