
Universelle Signaturgenerierung für jede Systemfunktion aus allen Windows-Builds unter Verwendung von Winbindex
Binäre Signaturen und RVA-Offsets für Windows-PE-Funktionen über verschiedene Versionen hinweg
pe-signgen ist ein Werkzeug für Reverse Engineers und Sicherheitsforscher, das automatisch generiert:
Die Kernidee besteht darin, einen systematischen, robusten Weg zum Zugriff auf nicht exportierte Funktionen über Windows 10/11-Builds hinweg zu bieten. Es nutzt:
⚠️ Windows-Versionsunterstützung
pe-signgenunterstützt nur Windows 10 und Windows 11. Dies ist eine bewusste Designentscheidung: Winbindex bietet keine vollständigen Daten für ältere Versionen.
Nicht exportierte Windows-Interna
Signaturen für Funktionen wie LdrpInitializeTls, RtlpInsertInvertedFunctionTableEntry, usw. generieren.
Game-Hacking / Anti-Cheat-Forschung Stabile Signaturen generieren, die Spielupdates überstehen
Sicherheitsforschung Sicherheitskritische Routinen über Windows-Builds hinweg lokalisieren
Automatisierung Skriptfähige Signatur- und Offset-Generierung für ganze Sätze interner APIs
pe-signgen bietet drei verschiedene Ausgabeformate für unterschiedliche Anwendungsfälle:
Strukturierte Daten für Automatisierung, Skripterstellung und Integration mit anderen Werkzeugen.```bash pe-signgen --signature ntdll!NtCreateFile -o ntcreatefile.json --output-format json
**Ausgabestruktur:**```json
{
"dll_name": "ntdll",
"function_name": "NtCreateFile",
"architecture": "x64",
"generated": "2024-12-11T15:30:00.123456",
"total_builds": 1247,
"unique_signatures": 3,
"signature_groups": [
{
"matched_symbol": "NtCreateFile",
"signature": "4C 8B DC 49 89 5B 08 49 89 6B 10 49 89 73 18 ...",
"length": 48,
"build_count": 845,
"versions": [
{ "major": 10240, "minor": 16384, "build": "10240.16384" },
{ "major": 10586, "minor": 0, "build": "10586.0" }
]
}
]
}
Notes:
major und minor werden aus dem Build-String abgeleitet, indem am ersten . geteilt wird.
Beispiel: "10240.16384" → major = 10240, minor = 16384.build ist der originale Build-String-Schlüssel, der intern verwendet wird.Kompakte, laufzeitbereite Binärformate, optimiert für eingebettete Systeme und Scans mit geringem Overhead.
Diese entsprechen dem On-Disk-Layout, das in write_wsig() und write_woff() implementiert ist.
Magie: WSO\0 (0x57 0x53 0x4F 0x00)
Aktuelle Version: 1
Zweck: Speicherung von Binärsignaturen mit Wildcard-Masken und zugehörigen Windows-Build-Versionen
┌─────────────────────────────────────┐ │ Header (36 bytes) │ ├─────────────────────────────────────┤ │ DLL Name (variable) │ ├─────────────────────────────────────┤ │ Function Name (variable) │ ├─────────────────────────────────────┤ │ Signature / Mask / Build blobs │ ← Arbitrary order, see notes ├─────────────────────────────────────┤ ← Aligned to 4 bytes │ Groups Table (24 × N bytes) │ └─────────────────────────────────────┘
**Wichtige Layout-Anmerkungen (entspricht `write_wsig`)**
* Nach dem Header werden die DLL- und Funktionsnamen als UTF‑8-Bytes geschrieben.
* Für jede Signaturgruppe werden die Pattern-Bytes und Mask-Bytes geschrieben, gefolgt vom Build-Array für diese Gruppe.
* Diese gruppenspezifischen Bereiche sind **nicht** global nach Typ gruppiert: Patterns, Masken und Build-Arrays können gemischt sein.
* Der Builder richtet sich vor jedem Build-Array und vor der Gruppentabelle auf **4 Bytes** aus. Dies kann Padding einführen.
* Konsumenten müssen **immer** den Offsets im Header und den Gruppeneinträgen folgen; verlassen Sie sich **nicht** auf das konzeptionelle Diagramm für die physische Kontiguität.
##### Header-Layout (36 Bytes)```c
// Packed as: "<4sIIIIIIII" (little-endian)
typedef struct {
char magic[4]; // "WSO\0" (WSIG_MAGIC)
uint32_t version; // FORMAT_VERSION (currently 1)
uint32_t arch; // Architecture code (1=x64, 2=ARM64, 3=WoW64)
uint32_t dll_off; // Offset to DLL name string
uint32_t dll_len; // Length of DLL name in bytes
uint32_t func_off; // Offset to function name string
uint32_t func_len; // Length of function name in bytes
uint32_t group_count;// Number of signature groups
uint32_t groups_off; // Offset to groups table
} wsig_header_t; // 36 bytes
Jede Signaturgruppe repräsentiert ein eindeutiges Muster, das auf eine oder mehrere Windows-Builds zutrifft.```c // Packed as: "<IIIIII" (little-endian)
typedef struct { uint32_t sig_off; // Offset to signature pattern bytes uint32_t sig_len; // Length of signature pattern (in bytes) uint32_t mask_off; // Offset to wildcard mask bytes uint32_t mask_len; // Length of wildcard mask (≈ ceil(sig_len/8)) uint32_t builds_off; // Offset to build version array uint32_t build_cnt; // Number of builds using this signature } wsig_group_t; // 24 bytes
##### Build Version Entry (8 bytes)
Jeder Build-Eintrag identifiziert eine bestimmte Windows-Version, die diese Signatur verwendet.```c
typedef struct {
uint32_t major; // e.g. 19041
uint32_t minor; // e.g. 1234
} wsig_build_t; // 8 bytes
major und minor stammen aus der Aufteilung des Build-Strings ("A.B" → A, B). Der ursprüngliche Build-String wird nicht im Binärformat gespeichert; wenn Sie ihn benötigen, behalten Sie ihn extern (er ist in der JSON-Ausgabe vorhanden).
Die Maske ist eine Bitmaske, wobei jedes Bit einem Byte im Signaturmuster entspricht:
Beispiel:``` Signature: 4C 8B DC 49 89 ?? 08 49 Mask bits: 1 1 1 1 1 0 1 1 (MSB first within each byte) Mask byte: 0xBF (binary: 10111111)
Masken-Bytes werden in **Little-Endian-Bit-Reihenfolge** innerhalb jedes Bytes gespeichert und interpretiert (genau wie in den C-Helfern und `parse_signature` verwendet):```c
uint8_t bit = (mask_bytes[byte_index >> 3] >> (byte_index & 7)) & 1u;
*_len, um die Länge zu bestimmen; lesen Sie nicht darüber hinaus.Magic: WOF\0 (0x57 0x4F 0x46 0x00)
Aktuelle Version: 1
Zweck: Speichert direkte RVA- und Datei-Offsets für Funktionen über Windows-Builds hinweg