skewrun 1.0.1

Kerberos clock skew wrapper for faketime
skewrun-1.0.1 is not a library.

Skewrun

CI Crates.io

skewrun is an Active Directory time discovery toolkit for red teams. It dynamically resolves the Domain Controller's time via network protocols (CLDAP, SMB, NTP, Kerberos, NTLM) and executes commands via libfaketime (LD_PRELOAD), tricking the executed binary into using the exact DC time.

This solves the Kerberos KRB_AP_ERR_SKEW (Clock Skew Too Great) error, allowing you to run tools like Impacket or NetExec from a Linux attack machine whose clock is heavily desynchronized from the target Windows domain, without requiring root privileges to change the system time.

Architecture: Library-First

Starting with v0.9.0, Skewrun is built as a library-first architecture:

  • ad-time: A pure Rust library crate that extracts time from AD protocols stealthily. It can be natively embedded into other Rust implants or tools.
  • skewrun: A CLI binary that orchestrates the ad-time library and wraps target processes with libfaketime.

Installation

# Pre-built static binary (no Rust toolchain required)

wget https://github.com/joaov-botelho/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


# From crates.io

cargo install skewrun


# From source

git clone https://github.com/joaov-botelho/skewrun && cd skewrun && cargo build --release

Note: You must have libfaketime installed on your system (e.g., apt-get install libfaketime).

Usage

# Default behavior (tries CLDAP -> SMB -> NTP)

skewrun 10.10.10.100 -- impacket-getTGT -dc-ip 10.10.10.100 domain.local/user:pass


# Force specific methods

skewrun 10.10.10.100 -m cldap,ntlm,kerberos -- netexec smb 10.10.10.100


# Just print the offset (useful for shell scripting)

skewrun 10.10.10.100 --print-offset


# Offline mode: supply a known offset manually

skewrun --offset "+3.450s" -- impacket-getTGT ...

Using as a library

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(())
}

Each protocol module (kerberos, ntlm, cldap, smb, ntp) is independent and extractable for use in custom red team tooling.

How It Works

Skewrun queries the DC to calculate the exact microsecond offset (DC_Time - Local_Time). It then sets the FAKETIME environment variable and injects libfaketime into the target command using LD_PRELOAD.

FAKETIME limitations (Static Binaries)

LD_PRELOAD relies on intercepting libc dynamically linked calls (like clock_gettime). If you attempt to use skewrun on a statically compiled binary (such as many Go or Rust tools), libfaketime will silently fail to hook the time functions. Skewrun will warn you if it detects you are attempting to run a static binary.

Forensic Noise & Evasion

The goal is to blend in with standard Windows wire traffic and minimize forensic footprint on the DC.

Method Protocol Port OPSEC Notes (EDR/NDR Visibility)
cldap (Default) CLDAP UDP/389 Extremely Stealthy. Universally allowed. Emulates a standard Windows DC Locator Ping (rootDSE). Dilutes the attribute query and randomizes TimeLimits to evade NDRs.
smb (Default) SMB2 TCP/445 Stealthy. Extracts time from the SMB2 NEGOTIATE response. Plausible workstation noise.
ntp (Default) SNTP UDP/123 Standard. Native RFC 4330. Highly expected traffic from any client.
ntlm SMB2 TCP/445 Stealthy. Exploits SMB2 SESSION_SETUP to get an NTLM Type 2 Challenge containing MsvAvTimestamp. Disconnects TCP before Type 3, meaning no Event ID 4625 (Logon Failure) is generated. Emulates Windows 10/11 flags.
kerberos Kerberos TCP/88 Loud. Sends an AS-REQ for a non-existent user. Encodes proper two-component sname, rotates cname (typos like admnistrator), till (10h ± 30min jitter), nonce, and ClientGuid to blend in. Always generates Event 4768/0x6 (pre-authentication failure for unknown principal) which is exported to SIEM regardless of audit policy. May trigger honey-account alerts if the cname matches a configured tripwire.

License

Dual-licensed under MIT or Apache 2.0 at your option.