Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/0x-unkwn0wn/simterm/llms.txt

Use this file to discover all available pages before exploring further.

Every mission operates against one or more target hosts. A host definition collects everything the engine needs to simulate the kill chain: what services are exposed, what vulnerabilities exist behind them, what the filesystem looks like once the player has a foothold, and what escalation routes lead to root. All of this is declared as data in TargetNode — no Rust required.

TargetNode struct fields

FieldTypeDefaultDescription
hostnamestringrequiredFully-qualified hostname (e.g. web-01.lab.local).
ipstringrequiredIP address shown during recon.
osstringrequiredOS string shown by uname and sysinfo.
servicesService listrequiredExposed services discovered during scanning.
vulnerabilitiesVulnerability listrequiredHidden vulnerabilities. Players never read these directly.
filesystemFsNode list[]Virtual filesystem, accessible in the post-exploitation phase.
accepts_tokenSome("token") or NoneNoneFoothold token accepted by login for a deterministic entry.
local_privescSome(LocalPrivesc) or NoneNoneLocal escalation vector discoverable by enumeration commands.

Service

Services are the enumeration targets discovered after initial scanning. Their name determines which enumeration tools and categories apply.
FieldTypeDescription
portu16Port number.
namestringService name. Controls enumeration category (see table below).
versionstringVersion string shown during enumeration.
requiresSome("token") or NoneIf set, the service can be discovered but cannot be enumerated until the player holds that foothold token.

Service name → enumeration category

Service namesEnumeration category
http, https, http-proxy, http-altWeb
smb, netbios, netbios-ssn, microsoft-dsSMB
sshSSH / login
mysql, pgsql, postgresql, redis, mongodb, mssql, oracleDatabase
everything elseGeneric
Tool affinity follows these categories: web services respond to nikto, gobuster, and sqlmap; SMB to enum4linux; SSH/login to hydra (intentionally noisy); databases to sqlmap; unknown services to probe.

Vulnerability

Vulnerabilities are the actual attack surface. They are always hidden from the player — the player reasons about them through enumeration results and tool output, then attempts to exploit what they have found.
FieldTypeDefaultDescription
idstringrequiredInternal identifier (not shown directly to the player).
namestringrequiredHuman-readable name (shown in enumeration output).
affected_serviceu16requiredPort of the service this vulnerability belongs to. Must exist in services.
difficultyu8requiredExploitation difficulty, 1..=10.
stealth_costu8requiredTrace added to the detection meter when exploiting.
reliabilityReliable or UnstableUnstableWhether exploitation is deterministic once identified.

Reliability

ValueWhen to use
ReliableDeterministic once identified. Use for credentials, no-auth bugs, LFI, SQL injection, and simple bypasses.
UnstableProbabilistic. Use for fragile RCE, deserialization, memory corruption, SSRF, races, and timing-dependent vectors.
When reliability is omitted it defaults to Unstable. Mark early-mission entry vectors Reliable so players aren’t blocked by bad RNG at low detection budgets.

Local privilege escalation

local_privesc models a host-side escalation vector that enumeration tools can discover. Once found, it enables the privesc command as a deterministic route to root — equivalent to having found a privesc_key file in the filesystem.
local_privesc: Some((
    kind: Sudo,
    note: "sudo vim can spawn a root shell via :!/bin/bash",
)),
FieldTypeDescription
kindLocalKindType of escalation vector (see below).
notestringHint shown to the player on discovery.

LocalKind values

ValueDiscovery commandDescription
Sudosudo -lAn abusable sudo rule (GTFOBin).
SuidsuidAn abusable SUID binary.
KernelsysinfoA vulnerable kernel or OS version.
CronlinpeasA root cron job with a writable script.
linpeas discovers all four kinds. The specific commands listed above each find only their own category.

Full TargetNode example

target: (
    hostname: "web-01.lab.local",
    ip: "10.0.0.5",
    os: "Linux 5.x",
    services: [
        (port: 80,  name: "http", version: "nginx 1.20"),
        (port: 22,  name: "ssh",  version: "OpenSSH 8.4"),
        (port: 3306, name: "mysql", version: "MySQL 8.0",
         requires: Some("db-access-token")),
    ],
    vulnerabilities: [
        (
            id: "WEB-LFI",
            name: "Local file inclusion",
            affected_service: 80,
            difficulty: 4,
            stealth_cost: 5,
            reliability: Reliable,
        ),
        (
            id: "SSH-WEAK",
            name: "Weak SSH password",
            affected_service: 22,
            difficulty: 6,
            stealth_cost: 10,
            reliability: Unstable,
        ),
        (
            id: "MYSQL-RCE",
            name: "MySQL RCE via UDF",
            affected_service: 3306,
            difficulty: 7,
            stealth_cost: 8,
            reliability: Unstable,
        ),
    ],
    filesystem: [
        Dir(name: "home", children: [
            Dir(name: "www-data", children: [
                File(
                    name: "notes.txt",
                    content: ["TODO: remove default creds"],
                    loot: Some((
                        skill: 0.05,
                        credential: Some("admin:admin"),
                        note: Some("Found default credentials in notes."),
                    )),
                ),
                File(
                    name: "db_token",
                    content: ["db-access-token"],
                    loot: Some((foothold_token: Some("db-access-token"))),
                ),
            ]),
        ]),
        Dir(name: "root", children: [
            File(
                name: "flag.txt",
                content: ["FLAG{web01_complete}"],
                root: true,
            ),
        ]),
    ],
    accepts_token: None,
    local_privesc: Some((
        kind: Sudo,
        note: "sudo vim can be abused to spawn a shell",
    )),
)
The affected_service port in every Vulnerability must match a port listed in the same host’s services. If it does not, --doctor reports an error and the vulnerability is unreachable during gameplay. Double-check port numbers when copying vulnerability blocks between hosts.

Build docs developers (and LLMs) love