Skip to main content

Overview

The sleep_strat module provides sleep interval calculation with configurable jitter strategies. This helps beacons evade detection by varying their callback timing patterns. Two jitter strategies are available:
  • Uniform: Evenly distributed random jitter
  • Gaussian: Bell-curve distributed jitter (more natural)
Module: evasion.sleep_strat

Functions

get_sleep_fn()

def get_sleep_fn(strategy: str) -> Callable
Return the sleep function matching the given strategy name.

Parameters

strategy
str
required
Jitter strategy name:
  • "uniform": Uniform random distribution
  • "gaussian": Gaussian (normal) distribution

Returns

Callable
Callable[[float, int], float]
Sleep function with signature (base_s: float, jitter_pct: int) -> float

Raises

  • ValueError: If strategy is not “uniform” or “gaussian”

Example

from evasion.sleep_strat import get_sleep_fn
import time

# Get uniform jitter function
sleep_fn = get_sleep_fn('uniform')

# Calculate sleep duration with 20% jitter
base_interval = 30.0  # 30 seconds
jitter = 20  # 20%
duration = sleep_fn(base_interval, jitter)

# Sleep for calculated duration
time.sleep(duration)

# Get gaussian jitter function
sleep_fn = get_sleep_fn('gaussian')
duration = sleep_fn(base_interval, jitter)
time.sleep(duration)

uniform_sleep()

def uniform_sleep(base_s: float, jitter_pct: int) -> float
Return a sleep duration using uniform random jitter within +/- jitter_pct of base.

Parameters

base_s
float
required
Base sleep duration in seconds
jitter_pct
int
required
Jitter percentage (0-100). Applied as +/- range around base.

Returns

float
float
Sleep duration in seconds, uniformly distributed in range:
  • Minimum: base_s * (1 - jitter_pct/100) or MIN_SLEEP_S, whichever is greater
  • Maximum: base_s * (1 + jitter_pct/100)

Example

from evasion.sleep_strat import uniform_sleep

# 30 second base with 20% jitter
# Result will be uniformly distributed between 24-36 seconds
duration = uniform_sleep(30.0, 20)
print(f"Sleep for {duration:.2f} seconds")

# No jitter
duration = uniform_sleep(30.0, 0)
print(f"Sleep for {duration:.2f} seconds")  # Always 30.00

# 50% jitter (wide range)
duration = uniform_sleep(60.0, 50)
print(f"Sleep for {duration:.2f} seconds")  # Between 30-90 seconds

gaussian_sleep()

def gaussian_sleep(base_s: float, jitter_pct: int) -> float
Return a sleep duration using Gaussian jitter with standard deviation derived from jitter_pct.

Parameters

base_s
float
required
Base sleep duration in seconds (mean of distribution)
jitter_pct
int
required
Jitter percentage (0-100). Converted to standard deviation: sigma = base_s * (jitter_pct / 100)

Returns

float
float
Sleep duration in seconds, normally distributed around base_s with standard deviation sigma. Result is clamped to MIN_SLEEP_S minimum.

Example

from evasion.sleep_strat import gaussian_sleep

# 30 second base with 20% jitter
# Standard deviation = 6 seconds
# ~68% of results will be within 24-36 seconds
# ~95% of results will be within 18-42 seconds
duration = gaussian_sleep(30.0, 20)
print(f"Sleep for {duration:.2f} seconds")

# More natural-looking timing variation
for i in range(5):
    duration = gaussian_sleep(45.0, 30)
    print(f"Beacon {i+1}: {duration:.2f}s")

Constants

MIN_SLEEP_S

MIN_SLEEP_S = 1.0
Minimum sleep duration in seconds. All sleep functions clamp their return values to this floor to prevent zero or negative sleep intervals.

Jitter Strategies

Uniform Distribution

Characteristics:
  • Evenly distributed across the entire range
  • All values within range are equally likely
  • Predictable minimum and maximum bounds
Use Cases:
  • When you need guaranteed min/max bounds
  • Testing with predictable ranges
  • Environments where extreme values are acceptable
Distribution Example (base=30s, jitter=20%):
Probability

    │ ┌────────────────────────┐
    │ │                        │
    │ │                        │
    └─┴────────────────────────┴───► Time
     24s                      36s

Gaussian Distribution

Characteristics:
  • Bell curve centered on base duration
  • Most values cluster near the base
  • Occasional outliers (rare but possible)
  • More natural-looking timing patterns
Use Cases:
  • Mimicking human behavior
  • More realistic beacon timing
  • When you want occasional variation without constant extremes
Distribution Example (base=30s, jitter=20%):
Probability
    │     ╱‾‾‾╲
    │   ╱       ╲
    │ ╱           ╲
    │╱             ╲___
    └────────────────────────► Time
        24s  30s  36s

Usage Patterns

Basic Beacon Loop

from evasion.sleep_strat import get_sleep_fn
import time

# Configure jitter strategy
sleep_fn = get_sleep_fn('gaussian')
BASE_INTERVAL = 30.0
JITTER_PCT = 20

while True:
    # Perform beacon callback
    beacon()
    
    # Sleep with jitter
    duration = sleep_fn(BASE_INTERVAL, JITTER_PCT)
    time.sleep(duration)

Profile-Based Configuration

from evasion.sleep_strat import get_sleep_fn

PROFILES = {
    'stealth': {
        'strategy': 'gaussian',
        'base': 120.0,  # 2 minutes
        'jitter': 40,    # 40% variance
    },
    'fast': {
        'strategy': 'uniform',
        'base': 10.0,   # 10 seconds
        'jitter': 10,    # 10% variance
    },
    'deterministic': {
        'strategy': 'uniform',
        'base': 30.0,
        'jitter': 0,     # No jitter
    },
}

def get_sleep_duration(profile_name: str) -> float:
    profile = PROFILES[profile_name]
    sleep_fn = get_sleep_fn(profile['strategy'])
    return sleep_fn(profile['base'], profile['jitter'])

# Use stealth profile
duration = get_sleep_duration('stealth')
time.sleep(duration)

Dynamic Jitter Adjustment

from evasion.sleep_strat import gaussian_sleep
import time

BASE_INTERVAL = 30.0

# Start with low jitter
jitter = 10

while True:
    beacon()
    
    # Increase jitter if detection risk rises
    if detect_risk_high():
        jitter = min(50, jitter + 10)
    else:
        jitter = max(10, jitter - 5)
    
    duration = gaussian_sleep(BASE_INTERVAL, jitter)
    time.sleep(duration)

Statistical Properties

Uniform Distribution

  • Mean: base_s
  • Range: [base_s * (1 - jitter_pct/100), base_s * (1 + jitter_pct/100)]
  • Standard Deviation: base_s * jitter_pct / 100 / sqrt(3)base_s * jitter_pct * 0.577 / 100

Gaussian Distribution

  • Mean: base_s
  • Standard Deviation: base_s * jitter_pct / 100
  • 68% within: base_s ± 1σ
  • 95% within: base_s ± 2σ
  • 99.7% within: base_s ± 3σ

Comparison Table

FeatureUniformGaussian
DistributionFlatBell curve
PredictabilityMediumLow
Natural appearanceLowHigh
OutliersNoneRare
Min/Max guaranteesYesNo (clamped at MIN_SLEEP_S)
Best forTesting, fixed boundsProduction, stealth

Error Handling

Invalid Strategy

from evasion.sleep_strat import get_sleep_fn

try:
    sleep_fn = get_sleep_fn('exponential')
except ValueError as e:
    print(e)  # 'unknown jitter strategy "exponential". Valid strategies: uniform, gaussian'

Handling Low Base Intervals

from evasion.sleep_strat import uniform_sleep

# Very low base with high jitter might hit MIN_SLEEP_S floor
base = 2.0
jitter = 60  # ±60%

duration = uniform_sleep(base, jitter)
# Requested range: 0.8s - 3.2s
# Actual result: 1.0s - 3.2s (clamped to MIN_SLEEP_S)
print(f"Duration: {duration:.2f}s")

Build docs developers (and LLMs) love