{"id":34593374,"url":"https://github.com/forentfraps/pe-signgen","last_synced_at":"2025-12-24T11:01:30.277Z","repository":{"id":328237701,"uuid":"1114762160","full_name":"forentfraps/pe-signgen","owner":"forentfraps","description":"Universal signature generation for any system function from all Windows Builds using Winbindex","archived":false,"fork":false,"pushed_at":"2025-12-11T21:59:37.000Z","size":141,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-13T01:54:11.697Z","etag":null,"topics":["binary","malware-analysis","microsoft","msdn","pattern","pdb","pe-exe","reverse-engineering","signature","signature-generation","windows","x64","x86"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/pe-signgen/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/forentfraps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-11T21:09:27.000Z","updated_at":"2025-12-12T12:38:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/forentfraps/pe-signgen","commit_stats":null,"previous_names":["forentfraps/pe-signgen"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/forentfraps/pe-signgen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forentfraps%2Fpe-signgen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forentfraps%2Fpe-signgen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forentfraps%2Fpe-signgen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forentfraps%2Fpe-signgen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/forentfraps","download_url":"https://codeload.github.com/forentfraps/pe-signgen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forentfraps%2Fpe-signgen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28001440,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-24T02:00:07.193Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary","malware-analysis","microsoft","msdn","pattern","pdb","pe-exe","reverse-engineering","signature","signature-generation","windows","x64","x86"],"created_at":"2025-12-24T11:01:11.807Z","updated_at":"2025-12-24T11:01:30.271Z","avatar_url":"https://github.com/forentfraps.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pe-signgen\n\n**Cross-version binary signatures and RVA offsets for Windows PE functions**\n\n---\n\n## Overview\n\n`pe-signgen` is a tool for reverse engineers and security researchers that automatically generates:\n\n* **Binary signatures** (byte patterns with wildcards) for **unexported and exported** functions\n* **RVA and file offsets** for locating functions directly in binaries\n* **Cross-build signatures** that work across many Windows versions\n* **Multiple output formats** optimized for different use cases\n* Support for **x64, ARM64, and WoW64** architectures\n\nThe **core idea** is to provide a **systematic, robust way to access unexported functions** across Windows 10/11 builds. It leverages:\n\n* [Winbindex](https://github.com/m417z/winbindex) for Windows build metadata\n* Microsoft's public symbol servers for PDBs\n* Local caching for reproducible, offline-friendly workflows\n\n\u003e ⚠️ **Windows version support**\n\u003e `pe-signgen` supports **Windows 10 and Windows 11 only**.\n\u003e This is a deliberate design choice: Winbindex does not provide complete data for older versions.\n\n---\n\n## Use Cases\n\n* **Unexported Windows internals**\n  Generate signatures for functions like `LdrpInitializeTls`, `RtlpInsertInvertedFunctionTableEntry`, etc.\n\n* **Game hacking / anti-cheat research**\n  Generate stable signatures that survive game updates\n\n* **Security research**\n  Locate security-critical routines across Windows builds\n\n* **Automation**\n  Scriptable signature and offset generation for entire sets of internal APIs\n\n---\n\n## Output Formats\n\n`pe-signgen` provides three distinct output formats for different use cases:\n\n### 1. **JSON Format**\n\nStructured data for automation, scripting, and integration with other tools.\n\n```bash\npe-signgen --signature ntdll!NtCreateFile -o ntcreatefile.json --output-format json\n```\n\n**Output structure:**\n\n```json\n{\n  \"dll_name\": \"ntdll\",\n  \"function_name\": \"NtCreateFile\",\n  \"architecture\": \"x64\",\n  \"generated\": \"2024-12-11T15:30:00.123456\",\n  \"total_builds\": 1247,\n  \"unique_signatures\": 3,\n  \"signature_groups\": [\n    {\n      \"matched_symbol\": \"NtCreateFile\",\n      \"signature\": \"4C 8B DC 49 89 5B 08 49 89 6B 10 49 89 73 18 ...\",\n      \"length\": 48,\n      \"build_count\": 845,\n      \"versions\": [\n        { \"major\": 10240, \"minor\": 16384, \"build\": \"10240.16384\" },\n        { \"major\": 10586, \"minor\": 0, \"build\": \"10586.0\" }\n      ]\n    }\n  ]\n}\n```\n\nNotes:\n\n* `major` and `minor` are derived from the build string by splitting at the first `.`.\n  Example: `\"10240.16384\" → major = 10240, minor = 16384`.\n* `build` is the original build string key used internally.\n\n---\n\n### 2. **Binary Format** (WSIG/WOFF)\n\nCompact, runtime-ready binary formats optimized for embedded systems and low-overhead scanning.\n\nThese match the on-disk layout implemented in `write_wsig()` and `write_woff()`.\n\n---\n\n#### WSIG Format (Windows Signature)\n\n**Magic:** `WSO\\0` (0x57 0x53 0x4F 0x00)\n**Current Version:** 1\n**Purpose:** Store binary signatures with wildcard masks and associated Windows build versions\n\n##### File Structure (conceptual)\n\n```\n┌─────────────────────────────────────┐\n│         Header (36 bytes)           │\n├─────────────────────────────────────┤\n│      DLL Name (variable)            │\n├─────────────────────────────────────┤\n│    Function Name (variable)         │\n├─────────────────────────────────────┤\n│   Signature / Mask / Build blobs    │ ← Arbitrary order, see notes\n├─────────────────────────────────────┤ ← Aligned to 4 bytes\n│   Groups Table (24 × N bytes)       │\n└─────────────────────────────────────┘\n```\n\n**Important layout notes (matches `write_wsig`)**\n\n* After the header, the DLL and function names are written as UTF‑8 bytes.\n* For each signature group, the pattern bytes and mask bytes are written, followed by the build array for that group.\n* These per-group regions are **not** grouped globally by type: patterns, masks, and build arrays may be interleaved.\n* The builder aligns to **4 bytes** before each build array and before the groups table. This can introduce padding.\n* Consumers must **always** follow the offsets in the header and group entries; do **not** rely on the conceptual diagram for physical contiguity.\n\n##### Header Layout (36 bytes)\n\n```c\n// Packed as: \"\u003c4sIIIIIIII\" (little-endian)\n\ntypedef struct {\n    char     magic[4];   // \"WSO\\0\" (WSIG_MAGIC)\n    uint32_t version;    // FORMAT_VERSION (currently 1)\n    uint32_t arch;       // Architecture code (1=x64, 2=ARM64, 3=WoW64)\n    uint32_t dll_off;    // Offset to DLL name string\n    uint32_t dll_len;    // Length of DLL name in bytes\n    uint32_t func_off;   // Offset to function name string\n    uint32_t func_len;   // Length of function name in bytes\n    uint32_t group_count;// Number of signature groups\n    uint32_t groups_off; // Offset to groups table\n} wsig_header_t; // 36 bytes\n```\n\n##### Group Entry (24 bytes)\n\nEach signature group represents a unique pattern that applies to one or more Windows builds.\n\n```c\n// Packed as: \"\u003cIIIIII\" (little-endian)\n\ntypedef struct {\n    uint32_t sig_off;    // Offset to signature pattern bytes\n    uint32_t sig_len;    // Length of signature pattern (in bytes)\n    uint32_t mask_off;   // Offset to wildcard mask bytes\n    uint32_t mask_len;   // Length of wildcard mask (≈ ceil(sig_len/8))\n    uint32_t builds_off; // Offset to build version array\n    uint32_t build_cnt;  // Number of builds using this signature\n} wsig_group_t; // 24 bytes\n```\n\n##### Build Version Entry (8 bytes)\n\nEach build entry identifies a specific Windows version that uses this signature.\n\n```c\ntypedef struct {\n    uint32_t major; // e.g. 19041\n    uint32_t minor; // e.g. 1234\n} wsig_build_t; // 8 bytes\n```\n\n`major` and `minor` come from splitting the build string (`\"A.B\" → A, B`). The original build string is not stored in the binary format; if you need it, keep it externally (it is present in the JSON output).\n\n##### Wildcard Mask Format\n\nThe mask is a **bitmask** where each bit corresponds to a byte in the signature pattern:\n\n* **Bit = 1:** Byte must match exactly (fixed byte)\n* **Bit = 0:** Byte is wildcarded (ignore this byte during matching)\n\n**Example:**\n\n```\nSignature: 4C 8B DC 49 89 ?? 08 49\nMask bits: 1  1  1  1  1  0  1  1  (MSB first within each byte)\nMask byte: 0xBF (binary: 10111111)\n```\n\nMask bytes are stored and interpreted in **little-endian bit order** within each byte (exactly as used in the C helpers and `parse_signature`):\n\n```c\nuint8_t bit = (mask_bytes[byte_index \u003e\u003e 3] \u003e\u003e (byte_index \u0026 7)) \u0026 1u;\n```\n\n##### String Storage\n\n* DLL and function names are stored as **UTF‑8**, **without null terminators**.\n* Use `*_len` to determine the length; do **not** read past that.\n* There are no alignment requirements for the strings themselves.\n* Additional data regions (build arrays and the groups table) are aligned to 4‑byte boundaries; treat any padding as opaque.\n\n---\n\n#### WOFF Format (Windows Offset)\n\n**Magic:** `WOF\\0` (0x57 0x4F 0x46 0x00)\n**Current Version:** 1\n**Purpose:** Store direct RVA and file offsets for functions across Windows builds\n\n##### File Structure\n\n```\n┌─────────────────────────────────────┐\n│         Header (36 bytes)           │\n├─────────────────────────────────────┤\n│      DLL Name (variable)            │\n├─────────────────────────────────────┤\n│    Function Name (variable)         │\n├─────────────────────────────────────┤\n│ Matched Symbol Names (variable)     │ ← One UTF‑8 string per entry\n├─────────────────────────────────────┤ ← Aligned to 4 bytes\n│   Entries Table (32 × N bytes)      │\n└─────────────────────────────────────┘\n```\n\nLayout details (matches `write_woff`):\n\n* After the header placeholder, the DLL and function names are written as UTF‑8 bytes.\n* For each build, the matched symbol name is written as a UTF‑8 string (no terminator). These form a simple string pool.\n* The writer then aligns to 4 bytes and writes the fixed-size entries table.\n* Each entry contains offsets (`matched_off`, `matched_len`) pointing into this string pool.\n\n##### Header Layout (36 bytes)\n\n```c\n// Packed as: \"\u003c4sIIIIIIII\" (little-endian)\n\ntypedef struct {\n    char     magic[4];   // \"WOF\\0\" (WOFF_MAGIC)\n    uint32_t version;    // FORMAT_VERSION (currently 1)\n    uint32_t arch;       // Architecture code (1=x64, 2=ARM64, 3=WoW64)\n    uint32_t dll_off;    // Offset to DLL name string\n    uint32_t dll_len;    // Length of DLL name in bytes\n    uint32_t func_off;   // Offset to function name string\n    uint32_t func_len;   // Length of function name in bytes\n    uint32_t entry_cnt;  // Number of offset entries\n    uint32_t entries_off;// Offset to entries table\n} woff_header_t; // 36 bytes\n```\n\n##### Offset Entry (32 bytes)\n\nEach entry maps a Windows build to the function's location in that build.\n\n```c\n// Packed as: \"\u003cIIQQII\" (little-endian)\n\ntypedef struct {\n    uint32_t major;       // Windows major version (e.g., 19041)\n    uint32_t minor;       // Windows minor version (e.g., 1234)\n    uint64_t rva;         // Relative Virtual Address in the DLL\n    uint64_t file_offset; // Raw file offset in the DLL on disk\n    uint32_t matched_off; // Offset to matched symbol name string\n    uint32_t matched_len; // Length of matched symbol name\n} woff_entry_t; // 32 bytes\n```\n\n##### Usage Notes\n\n* **RVA** is the memory offset when the DLL is loaded at its preferred base.\n* **File offset** is the raw position in the PE file on disk.\n* **Matched symbol** may differ from the requested function (e.g., forwarded exports).\n  The string is stored once in the string pool; `matched_off`/`matched_len` reference it.\n* Entries are **sorted by build version** (`major`, then `minor`) for efficient lookup.\n\n---\n\n#### Architecture Codes\n\nBoth binary formats use the same architecture encoding (via `ARCH_CODE_MAP`):\n\n| Code | Architecture | Description                  |\n| ---- | ------------ | ---------------------------- |\n| 1    | x64          | 64-bit AMD64/Intel64         |\n| 2    | ARM64        | 64-bit ARM (AArch64)         |\n| 3    | WoW64        | 32-bit x86 on 64-bit Windows |\n\nUnknown architecture strings default to `1` (x64) internally; the CLI restricts values to the supported set.\n\n---\n\n### 3. **C Header Format**\n\nReady-to-compile C headers with type-safe structures and data arrays.\n\n`pe-signgen` can emit two *kinds* of C headers:\n\n* **WSIG headers** – for signature and mask data (from `write_wsig_header`).\n* **WOFF headers** – for direct RVA/file-offset tables (from `write_woff_header`).\n\nThe `--output-format cheader` option selects C headers; combining it with `--offsets` switches between WSIG and WOFF variants.\n\n#### WSIG C Header\n\n```bash\npe-signgen --signature ntdll!RtlpInitializeThreadActivationContextStack \\\n  -o rtlp_init_actx.h --output-format cheader\n```\n\n**Generated header structure (simplified, matches `write_wsig_header`):**\n\n```c\n/* Auto-generated WSIG header for ntdll ! RtlpInitializeThreadActivationContextStack ! x64. */\n#ifndef WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H\n#define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H\n\n#include \u003cstdint.h\u003e\n#include \u003cstddef.h\u003e\n\n#define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_DLL_NAME  \"ntdll\"\n#define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_FUNCTION_NAME \"RtlpInitializeThreadActivationContextStack\"\n#define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ARCH \"x64\"\n\n/* Per-version build identifier. */\ntypedef struct {\n    uint32_t major;\n    uint32_t minor;\n} WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t;\n\n/* Signature group entry. */\ntypedef struct {\n    const uint8_t *pattern;\n    const uint8_t *mask;\n    uint32_t length;\n    uint32_t build_count;\n    const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t *versions;\n} WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t;\n\n/* One pattern/mask/versions triple per group. */\nstatic const uint8_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern[] = { /* ... */ };\nstatic const uint8_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_mask[]    = { /* ... */ };\nstatic const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t\n    WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions[] = {\n        { 10240u, 16384u }, /* 10240.16384 */\n        /* ... */\n    };\n\nstatic const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t\n    WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS[] = {\n        {\n            WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern,\n            WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_mask,\n            (uint32_t)(sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern) /\n                       sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern[0])),\n            (uint32_t)(sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions) /\n                       sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions[0])),\n            WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions\n        }, /* group 0 (RtlpInitializeThreadActivationContextStack) */\n        /* ... */\n};\n\nstatic const size_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUP_COUNT =\n    sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS) /\n    sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS[0]);\n\n#endif /* WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H */\n```\n\n**Integration example (corrected to match the generated types):**\n\n```c\n#include \"rtlp_init_actx.h\"\n\nstatic inline int match_byte(uint8_t want, uint8_t got,\n                             const uint8_t *mbits, uint32_t i) {\n    uint8_t bit = (mbits[i \u003e\u003e 3] \u003e\u003e (i \u0026 7)) \u0026 1u;\n    return bit ? (want == got) : 1;\n}\n\nstatic const uint8_t *\nfind_signature(const uint8_t *base, size_t size,\n               const uint8_t *pattern,\n               const uint8_t *mbits,\n               uint32_t sig_len) {\n    if (!base || !pattern || !mbits || sig_len == 0)\n        return NULL;\n    if (size \u003c sig_len)\n        return NULL;\n\n    // Find first non-wildcard byte as anchor\n    uint32_t anchor = sig_len;\n    for (uint32_t i = 0; i \u003c sig_len; ++i) {\n        if ((mbits[i \u003e\u003e 3] \u003e\u003e (i \u0026 7)) \u0026 1u) {\n            anchor = i;\n            break;\n        }\n    }\n    if (anchor == sig_len)\n        return base; // all wildcards\n\n    const uint8_t anchor_val = pattern[anchor];\n    const size_t last_pos = size - (size_t)sig_len;\n\n    for (size_t pos = 0; pos \u003c= last_pos; ++pos) {\n        if (base[pos + anchor] != anchor_val)\n            continue;\n\n        uint32_t i = 0;\n        for (; i \u003c sig_len; ++i) {\n            if (!match_byte(pattern[i], base[pos + i], mbits, i))\n                break;\n        }\n        if (i == sig_len)\n            return base + pos;\n    }\n    return NULL;\n}\n\nstatic void\nfetch_signature(uint32_t major, uint32_t minor,\n                const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *groups,\n                size_t group_len,\n                const uint8_t **signature_dest,\n                const uint8_t **mask_dest,\n                uint32_t *signature_len_dest) {\n    *signature_dest = NULL;\n    *mask_dest = NULL;\n    *signature_len_dest = 0;\n\n    const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *closest = NULL;\n    uint32_t best_distance = 0xFFFFFFFFu;\n\n    for (size_t gi = 0; gi \u003c group_len; ++gi) {\n        const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *g = \u0026groups[gi];\n        for (uint32_t vi = 0; vi \u003c g-\u003ebuild_count; ++vi) {\n            uint32_t m = g-\u003eversions[vi].major;\n            uint32_t n = g-\u003eversions[vi].minor;\n\n            uint32_t distance = (m \u003e major ? m - major : major - m) * 10000u +\n                                (n \u003e minor ? n - minor : minor - n);\n\n            if (distance \u003c best_distance) {\n                best_distance = distance;\n                closest = g;\n            }\n\n            if (m == major \u0026\u0026 n == minor) {\n                *signature_dest = g-\u003epattern;\n                *mask_dest = g-\u003emask;\n                *signature_len_dest = g-\u003elength;\n                return;\n            }\n        }\n    }\n\n    if (closest) {\n        *signature_dest = closest-\u003epattern;\n        *mask_dest = closest-\u003emask;\n        *signature_len_dest = closest-\u003elength;\n    }\n}\n```\n\nYou can then wire this into your own loader-specific code (e.g. using `GetModuleHandleA`, walking PE sections, etc.). The header intentionally only provides data; helper functions are up to the consumer.\n\n#### WOFF C Header\n\nFor offset-only use cases, `write_woff_header` emits a small header describing a sorted table of `(major, minor, rva, file_offset)` entries.\n\n**Layout (matches `write_woff_header`):**\n\n```c\n/* Auto-generated WOFF header for ntdll ! RtlpInitializeThreadActivationContextStack ! x64. */\n#ifndef WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H\n#define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H\n\n#include \u003cstdint.h\u003e\n#include \u003cstddef.h\u003e\n\n#define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_DLL_NAME  \"ntdll\"\n#define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_FUNCTION_NAME \"RtlpInitializeThreadActivationContextStack\"\n#define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ARCH \"x64\"\n\n/* Per-build offset entry. */\ntypedef struct {\n    uint32_t major;\n    uint32_t minor;\n    uint64_t rva;\n    uint64_t file_offset;\n} WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_entry_t;\n\nstatic const WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_entry_t\n    WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES[] = {\n        { 10240u, 16384u, 0x5B195ULL, 0x5A595ULL }, /* 10240.16384 (RtlpInitializeThreadActivationContextStack) */\n        /* ... (sorted by major, then minor) ... */\n};\n\nstatic const size_t WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRY_COUNT =\n    sizeof(WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES) /\n    sizeof(WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES[0]);\n\n#endif /* WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H */\n```\n\nThis is useful when you trust the offsets themselves and do not need pattern-matching.\n\n---\n\n## Installation\n\n### Prerequisites\n\n* Python 3.8+\n* Git\n* Internet connection (first run)\n* ~10GB disk space for full cache\n\n### Install from Pip\n\n```bash\npip install pe-signgen\n```\n\n### Install from Source\n\n```bash\ngit clone https://github.com/forentfraps/pe-signgen.git\ncd pe-signgen\npip install -r requirements.txt\npip install -e .\n```\n\n---\n\n## Quick Start\n\n### Generate a Signature\n\n```bash\npe-signgen --signature ntdll!LdrLoadDll\n```\n\n### Generate Offsets\n\n```bash\npe-signgen --signature kernel32!CreateFileW --offsets\n```\n\n### Save as JSON\n\n```bash\npe-signgen --signature ntdll!NtCreateFile -o out.json --output-format json\n```\n\n---\n\n## Command-Line Options\n\n### Basic Syntax\n\n```bash\npe-signgen --signature DLL!FUNCTION [OPTIONS]\n```\n\n### Architecture\n\n```bash\n--arch x64   # default\n--arch arm64\n--arch wow64\n```\n\n### Version Filtering\n\n```bash\n--os-version win10       # Only Windows 10\n--os-version win11       # Only Windows 11\n--min-version 10.0       # Minimum version\n--max-version 11.0       # Maximum version\n```\n\n### Signature Length Control\n\n```bash\n--min-length 32          # Minimum signature length\n--max-length 64          # Maximum signature length\n```\n\n### Output Options\n\n```bash\n-o, --output PATH        # Output file path\n--output-format FORMAT   # json | binary | cheader\n--offsets                # Generate offsets instead of signatures\n```\n\n### Performance\n\n```bash\n--workers 16             # Parallel workers (default: CPU count)\n--no-cache               # Disable caching\n--no-git-update          # Skip Winbindex updates\n```\n\n### Verbosity\n\n```bash\n--verbose                # Detailed output\n--quiet                  # Minimal output\n--no-progress            # Disable progress bars\n```\n\n---\n\n## Caching\n\n### Cache Layout\n\n```text\n~/.cache/pe-signgen/\n│\n├── dlls/           # Downloaded DLLs\n├── pdbs/           # Downloaded PDBs\n├── signatures/     # Generated signatures\n└── winbindex_data/ # Winbindex metadata\n```\n\n### Cache Control\n\n```bash\n# Disable cache for fresh generation\npe-signgen --signature ntdll!NtCreateFile --no-cache\n\n# Clear cache\nrm -rf ~/.cache/pe-signgen\n\n# Custom cache location\nexport PE_SIGNGEN_CACHE=/custom/path\npe-signgen --signature ntdll!NtCreateFile\n```\n\n---\n\n## Performance\n\n**Example performance (12-core CPU, 100 Mbps):**\n\n| Operation                         | Time        |\n| --------------------------------- | ----------- |\n| First run (no cache)              | 5–10 min    |\n| Cached run                        | \u003c 1 sec     |\n| Per-build analysis                | 0.1–0.5 sec |\n| Full run (1000 builds, 8 workers) | 2–4 min     |\n\n**Resource requirements:**\n\n* **Disk:** ~10 GB for full DLL/PDB cache\n* **Memory:** ~500 MB peak usage\n* **Network:** Several GB on first run\n\n---\n\n## Known Limitations\n\n* **Windows version coverage:** Only Windows **10 and 11** (Winbindex limitation)\n* **Build availability:** Not every Win10/11 build exists in Winbindex\n\n---\n\n## Development\n\n```bash\ngit clone https://github.com/forentfraps/pe-signgen.git\ncd pe-signgen\npip install -e \".[dev]\"\n\n# Code formatting\nblack pe_signgen/\n\n# Type checking\nmypy pe_signgen/\n```\n\n---\n\n## License\n\nMIT License – see [LICENSE](LICENSE).\n\n---\n\n## Credits\n\n* **Winbindex** – Windows build metadata by [@m417z](https://github.com/m417z)\n* **pefile** – PE parsing library\n* **winpdb-rs** – PDB parsing Python bindings\n\nInspired by the need for robust, automated signature generation for internal Windows APIs.\n\n---\n\n## Contributing\n\nContributions welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Submit a pull request\n\n---\n\n## Support\n\n* **Issues:** [GitHub Issues](https://github.com/forentfraps/pe-signgen/issues)\n* **Discussions:** [GitHub Discussions](https://github.com/forentfraps/pe-signgen/discussions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforentfraps%2Fpe-signgen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fforentfraps%2Fpe-signgen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforentfraps%2Fpe-signgen/lists"}