
توليد تواقيع عالمية لأي دالة نظام من جميع إصدارات ويندوز باستخدام Winbindex
التوقيعات الثنائية عبر الإصدارات وإزاحات RVA لوظائف PE في Windows
pe-signgen هي أداة لمهندسي الهندسة العكسية وباحثي الأمن، تقوم تلقائيًا بتوليد:
الفكرة الأساسية هي توفير طريقة منهجية وقوية للوصول إلى الوظائف غير المُصدرة عبر إصدارات Windows 10/11. تعتمد الأداة على:
⚠️ دعم إصدارات Windows
pe-signgenيدعم Windows 10 و Windows 11 فقط. هذا اختيار تصميم متعمد: لا يوفر Winbindex بيانات كاملة للإصدارات الأقدم.
دوال Windows الداخلية غير المُصدرة
توليد توقيعات لوظائف مثل LdrpInitializeTls و RtlpInsertInvertedFunctionTableEntry وغيرها.
أبحاث اختراق الألعاب / مكافحة الغش توليد توقيعات مستقرة تصمد أمام تحديثات الألعاب
البحث الأمني تحديد موقع الإجراءات الحساسة أمنيًا عبر إصدارات Windows
الأتمتة توليد توقيعات وإزاحات قابلة للبرمجة لمجموعات كاملة من واجهات API الداخلية
توفر pe-signgen ثلاث صيغ إخراج متميزة لحالات استخدام مختلفة:
بيانات منظمة للأتمتة والبرمجة النصية والتكامل مع الأدوات الأخرى.```bash pe-signgen --signature ntdll!NtCreateFile -o ntcreatefile.json --output-format json
**هيكل المخرجات:**```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" }
]
}
]
}
ملاحظات:
major و minor من سلسلة البناء عن طريق التقسيم عند أول نقطة ..
مثال: "10240.16384" → major = 10240, minor = 16384.build هي مفتاح سلسلة البناء الأصلي المستخدم داخليًا.تنسيقات ثنائية مضغوطة وجاهزة للتشغيل مُحسَّنة للأنظمة المضمنة والمسح الضوئي منخفض التكلفة.
تتوافق هذه التنسيقات مع التخطيط على القرص المُنفَّذ في write_wsig() و write_woff().
الرقم السحري: WSO\0 (0x57 0x53 0x4F 0x00)
الإصدار الحالي: 1
الغرض: تخزين التواقيع الثنائية مع أقنعة البدل وإصدارات بناء Windows المرتبطة.
┌─────────────────────────────────────┐ │ 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) │ └─────────────────────────────────────┘
**ملاحظات تخطيط هامة (يطابق `write_wsig`)**
* بعد الترويسة، تتم كتابة أسماء DLL والوظائف كبايتات UTF‑8.
* لكل مجموعة توقيع، تتم كتابة بايتات النمط وبايتات القناع، متبوعة بمصفوفة البناء لتلك المجموعة.
* هذه المناطق الخاصة بكل مجموعة **ليست** مجمعة عالميًا حسب النوع: قد تكون الأنماط والأقنعة ومصفوفات البناء متداخلة.
* يقوم المنشئ بالمحاذاة إلى **4 بايتات** قبل كل مصفوفة بناء وقبل جدول المجموعات. قد يؤدي ذلك إلى إدخال حشوة.
* يجب على المستهلكين **دائمًا** اتباع الإزاحات في الترويسة وإدخالات المجموعة؛ **لا** تعتمد على الرسم التخطيطي المفاهيمي للتجانس الفيزيائي.
##### تخطيط الترويسة (36 بايتًا)```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
تمثل كل مجموعة توقيع نمطًا فريدًا ينطبق على إصدار واحد أو أكثر من إصدارات Windows.```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
##### مدخل إصدار البناء (8 بايت)
يحدد كل مدخل بناء إصدارًا محددًا من ويندوز يستخدم هذا التوقيع.```c
typedef struct {
uint32_t major; // e.g. 19041
uint32_t minor; // e.g. 1234
} wsig_build_t; // 8 bytes
major و minor تأتي من تقسيم سلسلة البناء ("A.B" → A, B). لا يتم تخزين سلسلة البناء الأصلية في التنسيق الثنائي؛ إذا كنت بحاجة إليها، احتفظ بها خارجيًا (وهي موجودة في مخرجات JSON).
القناع هو قناع بت حيث يتوافق كل بت مع بايت في نمط التوقيع:
مثال:``` 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)
يتم تخزين و تفسير بايتات القناع (Mask bytes) بترتيب البتات **little-endian** داخل كل بايت (تمامًا كما هو مستخدم في المساعدات C و `parse_signature`):```c
uint8_t bit = (mask_bytes[byte_index >> 3] >> (byte_index & 7)) & 1u;
*_len لتحديد الطول؛ لا تقرأ بعد ذلك.العلامة السحرية: WOF\0 (0x57 0x4F 0x46 0x00)
الإصدار الحالي: 1
الغرض: تخزين عناوين RVA المباشرة وإزاحات الملفات للوظائف عبر إصدارات Windows المختلفة
┌─────────────────────────────────────┐ │ Header (36 bytes) │ ├─────────────────────────────────────┤ │ DLL Name (variable) │ ├─────────────────────────────────────┤ │ Function Name (variable) │ ├─────────────────────────────────────┤ │ Matched Symbol Names (variable) │ ← One UTF‑8 string per entry ├─────────────────────────────────────┤ ← Aligned to 4 bytes │ Entries Table (32 × N bytes) │ └─────────────────────────────────────┘
تفاصيل التخطيط (تطابق `write_woff`):
* بعد عنصر نائب الرأس، تُكتب أسماء DLL والوظائف كبايات UTF‑8.
* لكل بناء، يُكتب اسم الرمز المطابق كسلسلة UTF‑8 (بدون فاصل). تشكل هذه مجموعة سلاسل بسيطة.
* ثم يقوم الكاتب بالمحاذاة إلى 4 بايات ويكتب جدول الإدخالات ذي الحجم الثابت.
* يحتوي كل إدخال على إزاحات (`matched_off`, `matched_len`) تشير إلى مجموعة السلاسل هذه.
##### تخطيط الرأس (36 بايت)```c
// Packed as: "<4sIIIIIIII" (little-endian)