skewrun 1.0.1

Kerberos clock skew wrapper for faketime
# Skewrun


[![CI](https://github.com/joaov-botelho/skewrun/actions/workflows/ci.yml/badge.svg)](https://github.com/joaov-botelho/skewrun/actions/workflows/ci.yml)
[![Crates.io](https://img.shields.io/crates/v/skewrun.svg)](https://crates.io/crates/skewrun)

`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


```bash
# 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


```bash
# 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


```rust
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](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) at your option.