Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Shelter — Ofuscación de suspensión basada en ROP para evadir escáneres de memoria | Kitploit
Herramientas/GitHubGitHub/kudaes/shelter
Frameworks de ExploitsForensia de MemoriaRed Teaming
GitHubkudaes/shelter

Shelter

Ofuscación de suspensión basada en ROP para evadir escáneres de memoria

Ver Repositorio
3904815hace 1 añoRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Shelter

Shelter es una técnica de ofuscación de suspensión completamente armada que permite cifrar por completo tu payload en memoria haciendo un uso extensivo de ROP.

Este crate viene con las siguientes características:

  • Cifrado AES-128.
  • Capacidad de cifrar el PE completo.
  • Eliminación del permiso de ejecución durante el tiempo de suspensión.
  • Sin uso de APC/HWBP/Timers, uso exclusivo de ROP para lograr la ofuscación.
  • Uso de Unwinder para lograr el spoofing de la pila de llamadas antes de ejecutar la cadena ROP.
  • Diferentes métodos de ejecución para adaptarse a diversas circunstancias.
  • Otras consideraciones OPSEC: DInvoke_rs, llamadas indirectas al sistema, cifrado de literales de cadena, etc.

Contenido

  • Uso
  • Ejemplos
    • fluctuate
    • fluctuate_from_address
    • fluctuate_from_pattern
  • Pruebas del módulo
  • TO-DO

Uso

Importa este crate en tu proyecto añadiendo la siguiente línea a tu cargo.toml:

[dependencies]
shelter = "=0.1.2"

Luego, compila tu proyecto en modo --release.

La funcionalidad principal de este crate se ha envuelto en tres funciones:

  • fluctuate() permite cifrar tanto la región de memoria actual como todo el PE. Esta función requiere que los bytes MZ del PE estén presentes para recuperar dinámicamente su dirección base.
  • fluctuate_from_address() cifra completamente el PE. Esta función espera como parámetro de entrada la dirección base del PE.
  • fluctuate_from_pattern() también cifra completamente el PE. Esta función espera como parámetro de entrada un conjunto personalizado de dos bytes para usar y determinar la dirección base del PE. Estos bytes mágicos personalizados reemplazan el patrón MZ clásico.

Siempre que se cifra todo el PE, las protecciones de memoria de las secciones originales se almacenan en el heap para restaurarlas posteriormente.

Shelter utiliza NtWaitForSingleObject para dormir. Además de indicar cuántos segundos quieres dormir, también puedes pasar un handle de evento y señalarlo en cualquier momento para regresar antes de que expire el tiempo de espera (usando SetEvent por ejemplo). Ten en cuenta que si tu payload completo está cifrado (que es la idea principal, supongo), necesitarás una forma alternativa de señalizar el evento en caso de que hayas dormido indefinidamente.

Ejemplos

fluctuate

La función espera los siguientes parámetros:

  • Un valor booleano que indica si cifrar todo el PE o solo la región de memoria actual. Pasar true requiere que los bytes MZ estén presentes en memoria.
  • El número de segundos que el programa dormirá. Si se deja como None, el tiempo de espera será infinito, lo que significa que la ejecución no regresará hasta que se señalice el evento pasado a NtWaitForSingleObject.
  • Un handle de evento para pasar a NtWaitForSingleObject. Este parámetro puede ser None. El programa se bloqueará si configuras este parámetro y el tiempo de espera ambos a None.
let time_to_sleep = Some(10); // Sleep for 10 seconds
let _ = shelter::fluctuate(false, time_to_sleep, None); // Encrypt only the current memory region
let time_to_sleep = Some(10); // Sleep for 10 seconds
let _ = shelter::fluctuate(true, time_to_sleep, None); // Encrypt the whole PE
pub type CreateEventW = unsafe extern "system" fn (*const SECURITY_ATTRIBUTES, i32, i32, *const u16) -> HANDLE;

let k32 = dinvoke_rs::dinvoke::get_module_base_address("kernel32.dll"); 
let create_event: CreateEventW;
let event_handle: Option<HANDLE>;
dinvoke_rs::dinvoke::dynamic_invoke!(k32,"CreateEventW",create_event,event_handle,ptr::null_mut(),0,0,ptr::null());
let time_to_sleep = None; // Sleep indefinitely
let _ = shelter::fluctuate(true, time_to_sleep, event_handle); // Encrypt the whole PE until the event is signaled

fluctuate_from_address

La función espera los siguientes parámetros:

  • El número de segundos que el programa dormirá. Si se deja como None, el tiempo de espera será infinito, lo que significa que la ejecución no regresará hasta que se señalice el evento pasado a NtWaitForSingleObject.
  • Un handle de evento para pasar a NtWaitForSingleObject. Este parámetro puede ser None. El programa se bloqueará si configuras este parámetro y el tiempo de espera ambos a None.
  • La dirección base desde la cual se mapea el PE.

Una forma de usar esta función sería mapear manualmente nuestro payload con Dinvoke_rs. De esta manera, el loader puede enviar al payload su propia dirección base, para que el payload pueda usarla para ofuscarse cuando sea necesario. Así, el loader puede eliminar de forma segura los encabezados del PE para lograr un cierto nivel de sigilo.

Ejemplo de loader:

let payload: Vec<u8> = your_download_function();
let mut m = dinvoke_rs::manualmap::manually_map_module(payload.as_ptr(), true).unwrap();
println!("The dll is loaded at base address 0x{:x}", m.1);
let dll_exported_function = dinvoke::get_function_address(m.1, "run");

let run: unsafe extern "Rust" fn (usize) = std::mem::transmute(dll_exported_function);
run(m.1 as usize);

Ejemplo de payload:

#[no_mangle]
fn run(base_address: usize)
{
	...
	let time_to_sleep = Some(10); // Sleep for 10 seconds
	let _ = shelter::fluctuate_from_address(time_to_sleep, None, base_address); // Encrypt the entire PE from this specific base address
	...
}

fluctuate_from_pattern

La función espera los siguientes parámetros:

  • El número de segundos que el programa dormirá. Si se deja como None, el tiempo de espera será infinito, lo que significa que la ejecución no regresará hasta que se señalice el evento pasado a NtWaitForSingleObject.
  • Un handle de evento para pasar a NtWaitForSingleObject. Este parámetro puede ser None. El programa se bloqueará si configuras este parámetro y el tiempo de espera ambos a None.
  • Un array [u8;2] que contiene bytes mágicos personalizados para buscar y así obtener la dirección base del PE.

El propósito de crear esta función es permitir que el loader elimine el encabezado del PE y otras firmas, incluidos los clásicos bytes MZ. De esta manera, esos bytes pueden ser reemplazados por un patrón personalizado que Shelter buscará para recuperar la dirección base del PE.

let time_to_sleep = Some(10); // Sleep for 10 seconds
let pattern = [0x29,0x07];
let _ = shelter::fluctuate_from_pattern(time_to_sleep, None, pattern); // Encrypt the whole PE using custom pattern as magic bytes

Pruebas del módulo

Para probar la implementación de la técnica, se ha utilizado principalmente PE-sieve. Por defecto, PE-sieve busca implants dentro de regiones de memoria ejecutables, lo que significa que incluso ofuscando exclusivamente la región de memoria actual (.text) es suficiente para evitar detecciones:

Ofuscación de la región de memoria actual. Ofuscación de la región de memoria actual (Process Hacker).

Nota que, dado que estamos usando Unwinder, la pila de llamadas es falseada y por lo tanto la bandera /threads tampoco detecta la dll mapeada.

Descargar herramienta