Files
CyberSecurityUP-SysWhispers4/scripts/update_syscall_table.py
T
CyberSecurityUP 562c115e6c Initial release: SysWhispers4 — advanced Windows syscall stub generator
- 5 SSN resolution methods: Static, FreshyCalls, Hell's Gate, Halo's Gate, Tartarus' Gate
- 4 invocation methods: Embedded (direct), Indirect, Randomized (RDTSC entropy), Egg hunt
- Architecture support: x64, x86, WoW64, ARM64 (SVC #0 / w8)
- Compiler support: MSVC (MASM ml64.exe), MinGW (GAS inline asm), Clang
- XOR SSN encryption at rest (randomized key per generation)
- ETW user-mode bypass (ntdll!EtwEventWrite patch)
- Call-stack spoofing trampoline (ntdll return address)
- PEB-walk ntdll resolution (no Win32 API calls)
- EAT parsing with DJB2 compile-time hashes (no string comparisons)
- Fix: rdtsc clobbers rdx (arg2) in randomized stub — save rdx→r11 before rdtsc
- 48 NT functions across 5 presets (common, injection, evasion, token, all)
- j00ru syscall table update script (26 Windows builds Win7–Win11 24H2)
- Comprehensive README with SW1/SW2/SW3/SW4 feature comparison matrix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:07:23 -03:00

213 lines
6.9 KiB
Python

#!/usr/bin/env python3
"""
SysWhispers4 — Syscall Table Updater
Fetches the latest NT syscall numbers from j00ru/windows-syscalls and
updates data/syscalls_nt_x64.json and data/syscalls_nt_x86.json.
Usage:
python scripts/update_syscall_table.py
python scripts/update_syscall_table.py --arch x86
python scripts/update_syscall_table.py --arch x64,x86
python scripts/update_syscall_table.py --out custom_table.json
Requirements:
pip install requests (or: python -m pip install requests)
"""
from __future__ import annotations
import argparse
import csv
import io
import json
import sys
from pathlib import Path
from typing import Dict, Optional
from urllib.request import urlopen, Request
from urllib.error import URLError
# ---------------------------------------------------------------------------
# j00ru table URLs (raw CSV from GitHub)
# ---------------------------------------------------------------------------
JORU_BASE = "https://raw.githubusercontent.com/j00ru/windows-syscalls/master"
CSV_URLS = {
"x64": f"{JORU_BASE}/x64/csv/nt.csv",
"x86": f"{JORU_BASE}/x86/csv/nt.csv",
}
# Windows build number → human-readable label
BUILD_LABELS: Dict[str, str] = {
"5.1.2600.0": "Windows XP RTM",
"5.1.2600.2180": "Windows XP SP2",
"5.2.3790.0": "Windows Server 2003 RTM",
"5.2.3790.1830": "Windows Server 2003 SP1",
"5.2.3790.3959": "Windows Server 2003 SP2",
"6.0.6000.16386":"Windows Vista RTM",
"6.0.6001.18000":"Windows Vista SP1",
"6.0.6002.18005":"Windows Vista SP2",
"6.1.7600.16385":"Windows 7 RTM",
"6.1.7601.17514":"Windows 7 SP1",
"6.2.9200.16384":"Windows 8 RTM",
"6.3.9600.16384":"Windows 8.1 RTM",
"10.0.10240.16384":"Windows 10 1507",
"10.0.10586.0": "Windows 10 1511",
"10.0.14393.0": "Windows 10 1607",
"10.0.15063.0": "Windows 10 1703",
"10.0.16299.15": "Windows 10 1709",
"10.0.17134.1": "Windows 10 1803",
"10.0.17763.1": "Windows 10 1809",
"10.0.18362.1": "Windows 10 1903",
"10.0.18363.418":"Windows 10 1909",
"10.0.19041.1": "Windows 10 2004",
"10.0.19042.1": "Windows 10 20H2",
"10.0.19043.1": "Windows 10 21H1",
"10.0.19044.1": "Windows 10 21H2",
"10.0.19045.1": "Windows 10 22H2",
"10.0.20348.1": "Windows Server 2022",
"10.0.22000.1": "Windows 11 21H2",
"10.0.22621.1": "Windows 11 22H2",
"10.0.22631.1": "Windows 11 23H2",
"10.0.26100.1": "Windows 11 24H2 / Server 2025",
}
def _version_to_build(ver_str: str) -> Optional[str]:
"""
Convert 'major.minor.build.revision' to the short build number key
used in our JSON (e.g. '10.0.19041.1''19041').
Falls back to full string for older versions.
"""
parts = ver_str.split(".")
if len(parts) >= 3:
major = int(parts[0])
build = int(parts[2])
if major >= 10:
return str(build)
# For Vista/7/8: use minor.build
return f"{parts[1]}.{parts[2]}"
return ver_str
def fetch_csv(url: str) -> str:
print(f" [~] Fetching: {url}")
req = Request(url, headers={"User-Agent": "SysWhispers4/1.0"})
try:
with urlopen(req, timeout=30) as resp:
return resp.read().decode("utf-8")
except URLError as e:
print(f" [!] Failed to fetch {url}: {e}")
sys.exit(1)
def parse_joru_csv(csv_text: str) -> dict:
"""
Parse j00ru's CSV into our JSON format:
{ "FunctionName": { "build_number": ssn_int, ... }, ... }
"""
reader = csv.reader(io.StringIO(csv_text))
rows = list(reader)
if not rows:
return {}
# First row: "Function", "version1", "version2", ...
header = rows[0]
func_col = 0
version_cols = range(1, len(header))
result: dict = {
"_comment": "NT syscall numbers — generated by SysWhispers4/scripts/update_syscall_table.py",
"_source": "https://github.com/j00ru/windows-syscalls",
"_format": "FunctionName -> { build_number -> decimal_ssn }",
"_windows_builds": {},
}
# Build the build-label map
for col in version_cols:
ver = header[col].strip()
build_key = _version_to_build(ver)
if build_key:
label = BUILD_LABELS.get(ver, ver)
result["_windows_builds"][build_key] = label
for row in rows[1:]:
if not row or len(row) < 2:
continue
func_name = row[func_col].strip()
if not func_name:
continue
func_entry: dict = {}
for col in version_cols:
if col >= len(row):
break
cell = row[col].strip()
if not cell or cell.lower() in ("", "n/a", "-", "null"):
continue
try:
ssn = int(cell, 16) if cell.startswith("0x") else int(cell)
except ValueError:
continue
ver = header[col].strip()
build_key = _version_to_build(ver)
if build_key:
func_entry[build_key] = ssn
if func_entry:
result[func_name] = func_entry
return result
def main() -> None:
parser = argparse.ArgumentParser(
description="Update SysWhispers4 syscall tables from j00ru/windows-syscalls",
)
parser.add_argument(
"--arch",
default="x64",
help="Comma-separated architectures to fetch: x64, x86 (default: x64)",
)
parser.add_argument(
"--out",
default=None,
help="Custom output path (overrides the default data/ location)",
)
parser.add_argument(
"--functions",
default=None,
help="Comma-separated list of functions to keep (default: all Nt* functions)",
)
args = parser.parse_args()
data_dir = Path(__file__).parent.parent / "data"
archs = [a.strip() for a in args.arch.split(",")]
filter_funcs = set(f.strip() for f in args.functions.split(",")) if args.functions else None
for arch in archs:
if arch not in CSV_URLS:
print(f" [!] Unknown arch '{arch}'. Available: {list(CSV_URLS)}")
continue
csv_text = fetch_csv(CSV_URLS[arch])
table = parse_joru_csv(csv_text)
# Filter to Nt* functions only (NT namespace) + keep metadata
filtered = {k: v for k, v in table.items()
if k.startswith("_") or k.startswith("Nt")}
# Further filter if user specified specific functions
if filter_funcs:
filtered = {k: v for k, v in filtered.items()
if k.startswith("_") or k in filter_funcs}
out_path = Path(args.out) if args.out else data_dir / f"syscalls_nt_{arch}.json"
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(json.dumps(filtered, indent=2, sort_keys=False), encoding="utf-8")
n_funcs = sum(1 for k in filtered if not k.startswith("_"))
print(f" [+] Written {n_funcs} functions ({arch}) → {out_path}")
print(" [+] Syscall table update complete.")
if __name__ == "__main__":
main()