RUST-SECURITY
Authorized use only. Offensive reference for systems you own or are explicitly permitted to test. You are responsible for staying within the law.
Rust basics for building security tools. Memory-safe, fast, and compiles to standalone binaries — ideal for offensive and defensive tooling.
WHY RUST FOR SECURITY#
- Memory safety without garbage collector - Compiles to fast native binaries (no runtime needed) - Cross-compilation to Windows/Linux/macOS - No dependency on .NET, Python, or Java on target - Growing ecosystem of security libraries - Tools: YARA-X, RustScan, Feroxbuster, Chainsaw
PROJECT SETUP#
# Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # New project cargo new my_tool cd my_tool # Build and run cargo build # Debug build cargo build --release # Release (optimized) cargo run # Build and run cargo run --release # Release run # Cross-compile rustup target add x86_64-pc-windows-gnu # Windows target cargo build --release --target x86_64-pc-windows-gnu # Strip binary strip target/release/my_tool # Smaller binary
NETWORKING#
# TCP client (Cargo.toml: no extra deps for basic)
use std::net::TcpStream;
use std::io::{Read, Write};
fn main() {
let mut stream = TcpStream::connect("10.10.10.5:80").unwrap();
stream.write_all(b"GET / HTTP/1.1\r\nHost: target\r\n\r\n").unwrap();
let mut buf = [0u8; 4096];
let n = stream.read(&mut buf).unwrap();
println!("{}", String::from_utf8_lossy(&buf[..n]));
}
# TCP server
use std::net::TcpListener;
let listener = TcpListener::bind("0.0.0.0:4444").unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let mut buf = [0u8; 1024];
stream.read(&mut buf).unwrap();
stream.write_all(b"ACK").unwrap();
}
# Port scanner
use std::net::{TcpStream, SocketAddr};
use std::time::Duration;
fn scan_port(host: &str, port: u16) -> bool {
let addr: SocketAddr = format!("{}:{}", host, port).parse().unwrap();
TcpStream::connect_timeout(&addr, Duration::from_millis(500)).is_ok()
}
# Async port scanner (tokio)
# Cargo.toml: tokio = { version = "1", features = ["full"] }
use tokio::net::TcpStream;
use tokio::time::{timeout, Duration};
async fn scan(host: String, port: u16) -> Option<u16> {
let addr = format!("{}:{}", host, port);
match timeout(Duration::from_millis(500), TcpStream::connect(&addr)).await {
Ok(Ok(_)) => Some(port),
_ => None,
}
}
# HTTP client (reqwest)
# Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
let resp = reqwest::blocking::get("http://target.com")?.text()?;
println!("{}", resp);
# Async HTTP
let resp = reqwest::get("http://target.com").await?.text().await?;
USEFUL CRATES (LIBRARIES)#
# Cargo.toml dependencies # Networking tokio # Async runtime reqwest # HTTP client hyper # HTTP server/client rustls # TLS implementation # CLI clap # Argument parsing colored # Terminal colors indicatif # Progress bars # Crypto sha2 # SHA-256/384/512 md-5 # MD5 hashing aes # AES encryption hmac # HMAC ring # Crypto primitives rand # Random number generation # Parsing serde # Serialization (JSON, TOML, etc.) serde_json # JSON parsing regex # Regular expressions nom # Parser combinators (binary parsing) goblin # PE/ELF/Mach-O parsing # System sysinfo # System information winapi # Windows API bindings nix # Unix API bindings # Security specific yara-x # YARA rule engine pcap # Packet capture dns-lookup # DNS resolution
BINARY PARSING (PE/ELF)#
# Cargo.toml: goblin = "0.8"
use goblin::Object;
use std::fs;
let buf = fs::read("binary.exe").unwrap();
match Object::parse(&buf).unwrap() {
Object::PE(pe) => {
println!("PE: {} sections", pe.sections.len());
for section in &pe.sections {
println!(" {}: {:#x}", section.name().unwrap(), section.virtual_address);
}
for import in &pe.imports {
println!(" Import: {} -> {}", import.dll, import.name);
}
}
Object::Elf(elf) => {
println!("ELF: entry {:#x}", elf.entry);
for sym in &elf.syms {
println!(" Symbol: {}", elf.strtab.get_at(sym.st_name).unwrap_or("?"));
}
}
_ => println!("Unknown format"),
}
WINDOWS API (OFFENSIVE)#
# Cargo.toml: windows = { version = "0.58", features = ["Win32_System_Threading", ...] }
use windows::Win32::System::Threading::*;
use windows::Win32::System::Memory::*;
// Process enumeration
unsafe {
let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0).unwrap();
// ... iterate processes
}
// Shellcode injection pattern (authorized testing only)
unsafe {
let h = OpenProcess(PROCESS_ALL_ACCESS, false, pid).unwrap();
let addr = VirtualAllocEx(h, None, shellcode.len(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(h, addr, shellcode.as_ptr() as _, shellcode.len(), None);
CreateRemoteThread(h, None, 0, Some(std::mem::transmute(addr)), None, 0, None);
}
FILE HASHING#
# Cargo.toml: sha2 = "0.10"
use sha2::{Sha256, Digest};
use std::fs;
let data = fs::read("file.exe").unwrap();
let hash = Sha256::digest(&data);
println!("SHA256: {:x}", hash);
ERROR HANDLING#
# Result type (no exceptions in Rust)
fn connect(host: &str) -> Result<String, Box<dyn std::error::Error>> {
let resp = reqwest::blocking::get(host)?.text()?;
Ok(resp)
}
# Using anyhow for easy error handling
# Cargo.toml: anyhow = "1"
use anyhow::Result;
fn main() -> Result<()> {
let data = std::fs::read("file.txt")?;
Ok(())
}
EXISTING RUST SECURITY TOOLS#
RustScan # Fast port scanner Feroxbuster # Web content discovery YARA-X # YARA engine Chainsaw # Windows EVTX analysis ripgrep (rg) # Fast grep (used in log analysis) fd # Fast file finder bat # File viewer (syntax highlighting) sigma-rust # Sigma rule engine
TIPS#
- cargo build --release for production (10-100x faster) - Cross-compile to Windows from Linux with mingw - strip binary to reduce size (~50-70% smaller) - Use tokio for async networking (concurrent scanning) - goblin parses PE/ELF/Mach-O without external deps - clap for professional CLI argument handling - No runtime dependency = easy deployment on targets - Rust binaries are harder to reverse engineer than .NET/Python - Use nom for custom binary protocol parsing - serde_json for parsing API responses and config files