# Skewrun
[](https://github.com/joaov-botelho/skewrun/actions/workflows/ci.yml)
[](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.
| **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.