Volver a actualizaciones
Nuevo releaseJul 22, 2026

skewrun v1.2.0

Protocolos de descubrimiento de tiempo de Active Directory para equipos rojos. Extracción sigilosa a través de Kerberos, SMB, NTLM y CLDAP.

Compartir

Skewrun

CI Crates.io OpenSSF Best Practices OpenSSF Scorecard

skewrun demo

skewrun es un kit de herramientas de descubrimiento de tiempo de Active Directory para equipos rojos. Resuelve dinámicamente la hora del Controlador de Dominio a través de protocolos de red (CLDAP, SMB, NTP, Kerberos, NTLM) y ejecuta comandos mediante libfaketime (LD_PRELOAD), engañando al binario ejecutado para que utilice la hora exacta del DC.

Esto resuelve el error KRB_AP_ERR_SKEW de Kerberos (Desviación de reloj demasiado grande), permitiéndole ejecutar herramientas como Impacket o NetExec desde una máquina de ataque Linux cuyo reloj está fuertemente desincronizado con el dominio Windows de destino, sin necesidad de privilegios de root para cambiar la hora del sistema.

Arquitectura: Primero la biblioteca

A partir de v0.9.0, Skewrun está construido con una arquitectura que prioriza la biblioteca:

  • ad-time: Una crate de biblioteca pura en Rust que extrae el tiempo de los protocolos de AD de forma sigilosa. Puede integrarse de forma nativa en otros implantes o herramientas de Rust.
  • skewrun: Un binario CLI que orquesta la biblioteca ad-time y envuelve procesos objetivo con libfaketime.

Instalación

# Binario estático precompilado (no requiere cadena de herramientas Rust)
wget https://github.com/JVBotelho/skewrun/releases/latest/download/skewrun-x86_64-linux-musl
chmod +x skewrun-x86_64-linux-musl
sudo mv skewrun-x86_64-linux-musl /usr/local/bin/skewrun

# Desde crates.io
cargo install skewrun

# Desde el código fuente
git clone https://github.com/JVBotelho/skewrun && cd skewrun && cargo build --release

Nota: Debe tener libfaketime instalado en su sistema (ej., apt-get install libfaketime).

Uso

# Comportamiento predeterminado (intenta CLDAP -> SMB -> NTP)
skewrun 10.10.10.100 -- impacket-getTGT -dc-ip 10.10.10.100 domain.local/user:pass

# Forzar métodos específicos
skewrun 10.10.10.100 -m cldap,ntlm,kerberos -- netexec smb 10.10.10.100

# Solo imprimir el desplazamiento (útil para scripts de shell)
skewrun 10.10.10.100 --print-offset

# Modo sin conexión: proporcionar un desplazamiento conocido manualmente
skewrun --offset "+3.450s" -- impacket-getTGT ...

# Ajustar la fluctuación entre métodos (predeterminado: sigma=0.4, base=8000ms; sigma=0 desactiva la fluctuación)
skewrun 10.10.10.100 --jitter-sigma 0.2 --jitter-base-ms 5000 -- impacket-getTGT ...

Uso como biblioteca

use ad_time::protocols::cldap::CldapSource;
use ad_time::time_src::TimeSource;
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let src = CldapSource;
    let addr = "10.10.10.100:389".parse()?;
    let offset_us = src.fetch(addr, Duration::from_secs(3))?;
    println!("DC offset: {} µs", offset_us);
    Ok(())
}

Cada módulo de protocolo (kerberos, ntlm, cldap, smb, ntp) es independiente y extraíble para su uso en herramientas de equipo rojo personalizadas.

Cómo funciona

Skewrun consulta al DC para calcular el desplazamiento exacto en microsegundos (Hora_DC - Hora_Local). Luego establece la variable de entorno FAKETIME e inyecta libfaketime en el comando objetivo usando LD_PRELOAD.

Limitaciones de FAKETIME (Binarios estáticos)

LD_PRELOAD depende de interceptar llamadas enlazadas dinámicamente de libc (como clock_gettime). Si intenta usar skewrun en un binario compilado estáticamente (como muchas herramientas Go o Rust), libfaketime fallará silenciosamente al enganchar las funciones de tiempo. Skewrun le advertirá si detecta que está intentando ejecutar un binario estático.

Ruido forense y evasión

El objetivo es mezclarse con el tráfico estándar de red de Windows y minimizar la huella forense en el DC.

Independientemente del método utilizado: cada socket de salida establece TTL=128 y habilita Nagle (TCP_NODELAY=0) antes del handshake TCP, coincidiendo con la huella de la pila de red de un cliente Windows en lugar de los valores predeterminados de Linux (TTL=64, Nagle desactivado) que un observador pasivo (p0f, conn.log de Zeek) marcaría de otro modo. Los retrasos entre métodos utilizan fluctuación log-normal respaldada por CSPRNG (no un rango aleatorio plano) con retroceso exponencial en fallos repetidos, evitando la firma de temporización uniforme que una banda de fluctuación fija deja en los registros de conexión; consulte --jitter-sigma y --jitter-base-ms arriba.

MétodoProtocoloPuertoNotas OPSEC (Visibilidad EDR/NDR)
cldap (Predeterminado)CLDAPUDP/389Extremadamente sigiloso. Universalmente permitido. Envía una consulta de diagnóstico LDAP rootDSE estándar (búsqueda base objectClass=*), coincidiendo con la línea base de ldapsearch, cmdlets de PowerShell AD y herramientas de monitoreo. Diluye la lista de atributos con atributos administrativos comunes y aleatoriza el orden de los atributos por solicitud para romper las firmas NDR estáticas.
smb (Predeterminado)SMB2TCP/445Sigiloso. Extrae la hora de la respuesta SMB2 NEGOTIATE. Negocia SMB 3.1.1 con PREAUTH_INTEGRITY_CAPABILITIES (SHA-512), coincidiendo con el comportamiento de clientes Windows 10/11.
ntp (Predeterminado)SNTPUDP/123Estándar. RFC 4330 nativo. Tráfico altamente esperado de cualquier cliente.
ntlmSMB2TCP/445Sigiloso. Explota SMB2 SESSION_SETUP para obtener un desafío NTLM Tipo 2 que contiene MsvAvTimestamp. Desconecta TCP antes del Tipo 3, lo que significa que no se genera ningún Evento 4625 (Fallo de inicio de sesión). Emula las banderas de Windows 10/11.
kerberosKerberosTCP/88Ruidoso. Envía un AS-REQ para un usuario inexistente. Codifica un sname adecuado de dos componentes, rota cname (errores tipográficos como admnistrator), establece till en la constante fija de Windows 20370913024805Z (no aritmética de reloj local — ver ADR-0002), aleatoriza nonce. Siempre genera Evento 4768/0x6 (fallo de preautenticación para principal desconocido) que se exporta a SIEM independientemente de la política de auditoría. Puede activar alertas de cuentas honeypot si el cname coincide con un tripwire configurado.

Pruebas

cargo test                                            # pruebas unitarias + de propiedades
cargo +nightly fuzz run fuzz_parse_krb_error          # solo Linux/macOS

Todos los analizadores orientados a la red (parse_krb_error, parse_cldap_search_response, parse_ntlm_type2, parse_negotiate_response, parse_ntp_timestamp) se prueban mediante pruebas de propiedades para seguridad ante pánicos usando proptest y se someten a fuzzing en CI. La codificación de enteros BER se verifica para determinar la minimalidad DER y la corrección del signo en todo el rango i32, cubriendo valores de etype negativos según RFC 4120. Los objetivos de fuzzing y el corpus residen en fuzz/.

Licencia

Licenciado dualmente bajo MIT o Apache 2.0 según su elección.

Categorías