Skip to content

Latest commit

 

History

15 Commits

Folders and files

Repository files navigation

NPM Version NPM Downloads GitHub License GitHub Issues TypeScript Bundle Size


sigscan-ts

High-performance binary signature scanner and gamedata verifier
Zero runtime dependencies • Hybrid Buffer.indexOf prefix optimization • Fully Type-Safe • Auto relocatable signatures

Get Started » · View Examples

About The Project

Hey! I built this because I was working on a few game server modding tools and got tired of copy-pasting raw C++ signature scanning algorithms or relying on slow, outdated JavaScript libraries.

This is a modern, high-performance binary signature scanner. It runs on Node.js and Bun with no runtime dependencies whatsoever.

Why this package is special

  • Zero runtime dependencies - All dependencies are strictly for development and compilation. Check the package.json for yourself.
  • Hybrid search engine - Rather than scanning byte-by-byte, it parses your signature to find the longest continuous prefix, performs a native C++ indexOf search, and then verifies wildcards around candidates. See the benchmark table below.
  • Extremely forgiving parser - Copy signatures directly from Cheat Engine, IDA Pro, x64dbg, or C-style arrays ({ 0x48, 0x8b, 0xc4, ?? }). It handles spaces, dots, commas, raw hex strings, and escaped sequences out of the box.
  • Built-in CLI & Gamedata Verifier - Scan single signatures or batch-verify entire gamedata.json files (supporting both CounterStrikeSharp and SwiftlyS2 formats) against server binaries in seconds.

Performance

Benchmarked on a 100 MB random buffer with 3 planted signatures (Apple M2 Pro, Bun 1.4).

Pattern type Example Time Memory / iter vs naive loop
No wildcards DE AD BE EF CA FE BA BE ~7.1 ms ~2.1 KB ~18x faster
Wildcards (prefix-opt) DE AD ?? EF CA ?? BA BE ~7.9 ms 0.00 B ~17x faster
Fragmented wildcards ?? AD ?? EF ?? FE ?? BE ~13.5 ms ~35 KB ~10x faster
scan() with fast: true any ~3.8 ms ~1.3 KB ~35x faster
Naive JS loop (baseline) — ~131 ms ~1.8 KB 1x

Run it yourself: bun run bench

(back to top)

Installation

npm install sigscan-ts
pnpm add sigscan-ts
bun add sigscan-ts

(back to top)

Quick example

Here is a quick example of a one-off pattern scan:

import { readFileSync } from "node:fs";
import { scan, PatternScanner } from "sigscan-ts";

const buffer = readFileSync("libserver.so");

// 1. One-off quick scan
const result = scan(buffer, "48 8B C4 ? 53 ?? 90");
if (result.found) {
  console.log(`Found pattern at ${result.offsets.length} locations.`);
  console.log(`Primary offset: 0x${result.offsets[0].toString(16)}`);
  console.log(`Is the signature unique/reliable? ${result.reliable}`);
}

// 2. Reusable scanner (efficient for scanning multiple signatures)
const scanner = new PatternScanner(buffer);
const offsets = scanner.findPattern("55 48 89 E5");
console.log("Offsets found:", offsets);

Multi-pattern scan

Scan many named signatures in one call — useful for gamedata.json verification or any batch scan:

import { readFileSync } from "node:fs";
import { PatternScanner } from "sigscan-ts";

const buffer = readFileSync("server.so");
const scanner = new PatternScanner(buffer);

// returns Record<name, number[]>
const offsets = scanner.findPatterns({
  UTIL_ClientPrintAll: "55 48 89 E5 41 57 4D 89 CF",
  GiveNamedItem:       "55 48 89 E5 41 57 41 56 41 55",
  CCSPlayer_Respawn:   "48 8B 05 ?? ?? ?? ?? 48 85",
});

// returns Record<name, { found, offsets, reliable }>
const results = scanner.scanPatterns({
  UTIL_ClientPrintAll: "55 48 89 E5 41 57 4D 89 CF",
  GiveNamedItem:       "55 48 89 E5 41 57 41 56 41 55",
});

if (results["GiveNamedItem"].reliable) {
  console.log("unique match at", results["GiveNamedItem"].offsets[0].toString(16));
}

Standalone helpers also available: findPatterns(buffer, patterns) and scanPatterns(buffer, patterns).

(back to top)

Profiling & Scan Context

sigscan-ts includes built-in high-resolution timers and async context tracking:

import { startTimer, measure, runWithContext, createScanMetrics, scan } from "sigscan-ts";

// 1. High-resolution timer
const timer = startTimer();
// ... work ...
console.log(`Duration: ${timer.stop().toFixed(2)}ms`);

// 2. Measure wrapper
const { result, durationMs } = measure(() => scan(buffer, "55 48 89 E5"));

// 3. AsyncLocalStorage context (tracks scans, cache hits/misses across call chains)
const metrics = createScanMetrics();
runWithContext({ traceId: "req-123", metrics, logger: console.debug }, () => {
  scan(buffer, "55 48 89 E5");
});
console.log(`Scans: ${metrics.totalScans}, Cache hits: ${metrics.cacheHits}`);

(back to top)

Command Line Interface (CLI)

If you install the package globally or run it via npx, you can use the built-in CLI:

# Scan a binary for a specific signature
sigscan-ts -b libserver.so -p "48 8B C4 ?? 53"

# Fast pattern scan that stops after proving a second match
sigscan-ts -b libserver.so -p "48 8B C4 ?? 53" --fast

# Verify an entire gamedata.json file against binaries
# (Supports folder paths or passing multiple files via multiple -b flags.
# Platform types and libraries are automatically detected!)
sigscan-ts -b /path/to/binaries_dir -g latest-gamedata.json
sigscan-ts -b libserver.so -b server.dll -g latest-gamedata.json

Here is a preview of the batch-verification mode running on both Windows and Linux binaries side-by-side:

sigscan-ts CLI batch-verification output

(back to top)

Supported Pattern Formats

The parser automatically detects and handles almost any copy-pasted pattern style:

  • IDA Pro: "48 8B C4 ?? 53 ? 90"
  • x64dbg: "48.8B.C4.??.53" (Dot-separated)
  • Cheat Engine: "48 8b c4 ?? 53"
  • C-style Array: "{ 0x48, 0x8b, 0xc4, ??, 0x53 }"
  • Escaped Hex: "\x48 \x8B \xC4 ?? \x53"
  • Raw Hex String: "488bc4??53"

(back to top)

For developers

If you want to contribute or build the library locally, please check out the contributing guide.

(back to top)

License

MIT - do whatever you want with it


Credits

Built by K4ryuu

Sponsor this project

Used by

Contributors

Languages