Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
datadome-vm — هندسة عكسية لـ VM Datadome الجديد 🔥 | Kitploit
أدوات/GitHubGitHub/xkiian/datadome-vm
التحليل الديناميكي (عزل)الهندسة العكسيةتحليل الملفات الثنائيةالتعلم والتعليممكافحة الروبوتاتتجاوز كابتشا
GitHubxkiian/datadome-vm

datadome-vm

هندسة عكسية لـ VM Datadome الجديد 🔥

عرض المستودع
1251910منذ 6 أشهرتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

تحليل DataDome للآلة الافتراضية

ملخص

يُوثّق هذا المستودع أول إصدار عام للآلة الافتراضية (VM) من DataDome التي تعمل داخل المتصفح، والمستخدمة في تدفق الكابتشا/الصفحة الوسيطة. يغطي هذا التحليل ما يلي:

  • آليات تحميل وفك تشفير البايت كود
  • تخطيط الذاكرة ومعمارية الآلة الافتراضية
  • مفكك ترجمة (disassembler) كدليل على المفهوم
  • ملاحظات تحليل تدفق التحكم

ملاحظة: هذا المستودع يغطي إصدارًا واحدًا فقط (ثابتًا) من الآلة الافتراضية وهو مخصص لأغراض البحث الأمني والتحليل. لا يتضمن حلولًا ديناميكية أو تطبيقات حلول إنتاجية.

خلفية

في 14 يناير 2026، بدأت DataDome في تضمين مكون جديد قائم على الآلة الافتراضية في علامة العميل الخاصة بها.

إزالة التعتيم (Deobfuscation)

تم استخراج كود الآلة الافتراضية من تحدي الكابتشا في ملف vm.js (متاح في هذا المستودع).

كانت الخطوة الأولى هي إزالة التعتيم عن السكريبت:

عملية التعتيم واضحة ومباشرة: يتم تقييم كل متغير واستبداله بقيمته الفعلية. يتوفر سكريبت لإزالة التعتيم في deobf.js.

التحليل الأولي

تشغيل الكود بعد إزالة التعتيم (out.js) في أدوات المطور (DevTools) يكشف عن المخرجات المتوقعة للآلة الافتراضية:

المخرجات هي كائن JSON يحتوي على رقمين وسلسلة نصية. الآن دعنا نتعمق في تطبيق الآلة الافتراضية الفعلي.

فك تشفير البايت كود

في بداية دالة Q.exports، نرى كيف يتم فك تشفير البايت كود:

  1. يتم فك تشفير سلسلة الإدخال باستخدام base64
  2. يتم إنشاء مصفوفة بطول 129,263
  3. يتم فحص كل فهرس مقابل نطاق محدد:
    • إذا كان الفهرس يقع ضمن النطاق، يتم فك تشفير القيمة
    • بخلاف ذلك، يتم إرجاع رقم عشوائي (باستخدام B()، وهو مولد أرقام شبه عشوائي) -> D يحمل البايت كود المُفكك مع بعض "الضوضاء" العشوائية

معمارية الآلة الافتراضية

بالتمرير لأسفل نجد نقطة دخول الآلة الافتراضية: دالة ذات معلمتين A (البايت كود) وQ (قاموس فارغ يستخدم لمعالجة الأخطاء).

تخطيط الذاكرة

الجانب الأكثر إثارة للاهتمام في هذه الآلة الافتراضية هو معماريتها: كل شيء يعيش في مصفوفة واحدة (A). تحتوي هذه المصفوفة على:

  • المكدس (Stack)
  • السجلات (Registers)
  • التعليمة البرمجية (Opcodes)
  • البايت كود نفسه
  • مؤشر التعليمات (Instruction Pointer)

هذا التصميم يعكس معمارية الحاسوب الحقيقية مع مناطق ذاكرة متميزة. الخطوة التالية هي تحديد كل إزاحة (offset) لفهم ما يُخزن أين:

root@kitploit:~
var stack_pointer = 4593
var instruction_pointer = 4635
var frame_base_pointer = 4674
var last_result = 4633
var exit_flag = 4656
var current_opcode_handler = 4685
var current_opcode_id = 4675
var stack_offset = 124482
var vm_start = 5258

مع تحديد هذه الإزاحات، تصبح بنية الآلة الافتراضية واضحة.

دوال المساعدة

تبدأ الآلة الافتراضية بمجموعة من دوال المساعدة التي تتعامل مع:

  • قراءة القيم المكتوبة من المكدس
  • نقل البيانات بين المكدس و"السجلات"

تهيئة الآلة الافتراضية

بعد دوال المساعدة، تقوم الآلة الافتراضية بتهيئة القيم الأساسية:

  • جميع المؤشرات (المكدس، التعليمات، قاعدة الإطار)
  • علامة الخروج
  • سجل آخر نتيجة

أسفل التهيئة توجد جميع معالجات التعليمات.

حلقة الموزع (Dispatcher Loop)

الموزع هو الحلقة الرئيسية للآلة الافتراضية والتي تستمر حتى يتم تعيين `exit_flag`:
  • I تمثل التعليمات الحالية
  • P هو الإزاحة الفعلية داخل المصفوفة (مع مراعاة التعتيم)
  • تقوم الحلقة بتعيين التعليمات الحالية إلى current_opcode_handler وتحديث current_opcode_id

تنفيذ التعليمة البرمجية (Opcode Implementation)

كيفية عمل التعليمة البرمجية

إليك مثال أساسي لمعالج تعليمة برمجية:

  1. يجلب قيمة فورية من البايت كود
  2. يسترجع القيمة العليا من المكدس
  3. ينفذ عملية (مثل %= أو ^=)
  4. يستدعي الدالة fetch() في النهاية

تعليمات برمجية مثيرة للاهتمام

التعليمة البرمجية 4919: إنشاء دالة/إغلاق (Closure)

واحدة من أكثر التعليقات البرمجية تعقيدًا هي التي تنشئ الإغلاقات/الدوال:

root@kitploit:~
A[4919] = function () {
    var Q = readUint8();  // عدد الوسائط المتوقعة
    var B = [];
    for (var E = readUint8(), D = 0; D < E; D++) {
        var g = readUint8();
        var a = A[A[frame_base_pointer] + g];
        B.push(a);  // التقاط المتغيرات من النطاق الحالي
    }
    var h = A[instruction_pointer] + 3;  // حفظ عنوان جسم الدالة
    A[A[stack_pointer]++] = function (E) {
        // إعداد إطار مكدس جديد عند الاستدعاء
        var e = A[stack_pointer] - E;
        while (E < Q) {
            A[e + E++] = undefined;  // ملء الوسائط المفقودة بـ undefined
        }
        A[stack_pointer] = e + Q;
        for (var D = 0; D < B.length; D++) {
            var g = B[D];
            A[A[stack_pointer]++] = g;  // دفع المتغيرات الملتقطة
        }
        A[e - 2] = A[frame_base_pointer];  // حفظ مؤشر الإطار القديم
        A[e - 1] = A[instruction_pointer];  // حفظ عنوان العودة
        A[frame_base_pointer] = e;
        A[instruction_pointer] = h;  // القفز إلى جسم الدالة
    };
    fetch();
};

هذه التعليمة البرمجية:

  1. تقرأ عدد الوسائط المتوقعة
  2. تلتقط المتغيرات من النطاق الحالي (إغلاق)
  3. تنشئ دالة تقوم بإعداد إطار مكدس جديد مع اتفاقيات الاستدعاء المناسبة
  4. تتعامل مع الوسائط المفقودة عن طريق ملئها بـ undefined
  5. تحفظ عنوان العودة ومؤشر الإطار للعودة الصحيحة

التعليمة البرمجية 5003: استدعاء دالة ديناميكي

هذه التعليمة البرمجية تنشئ غلافًا لاستدعاءات الدوال التي تتعامل مع كل من الاستدعاءات العادية واستدعاءات المُنشئ (Constructor):

root@kitploit:~
A[5003] = function () {
    var Q = A[--A[stack_pointer]];  // POP الدالة
    var B = A[--A[stack_pointer]];  // POP سياق 'this'

    function E(e) {  // e = عدد الوسائط
        var D = A[stack_pointer];
        var g = A.slice(D - e, D);  // الحصول على الوسائط من المكدس
        if (this instanceof E) {
            // استدعاء المُنشئ (new E(...))
            g.unshift(null);
            var h = Function.prototype.bind.apply(Q, g);
            A[stack_pointer] -= e;
            try {
                a = new h();
            } catch (A) {
                a = A.message;
            }
            A[A[stack_pointer]++] = a;
        } else {
            // استدعاء دالة عادية
            var t;
            try {
                t = Q.apply(B, g);
            } catch (A) {
                t = A.message;
            }
            A[stack_pointer] -= e + 2;
            A[A[stack_pointer]++] = t;
        }
    }

    A[A[stack_pointer]++] = E;
    fetch();
};

هذه التعليمة البرمجية:

  1. تسحب الدالة والسياق من المكدس
  2. تنشئ غلافًا يمكن استدعاؤه مع وسائط
  3. تكتشف ما إذا كان الاستدعاء استدعاء منشئ (new) أم استدعاء عادي
  4. تطبق الدالة مع السياق المناسب ومعالجة الأخطاء
  5. تدفع النتيجة مرة أخرى إلى المكدس

التعليمة البرمجية 4961: بناء كائنات حرفية (Object Literal Construction)

root@kitploit:~
A[4961] = function () {
    var Q = {};
    for (var E = readUint16(), e = 0; e < E; e++) {
        var D = A[--A[stack_pointer]];  // POP أول
        var g = A[--A[stack_pointer]];  // POP ثاني
        Q[D] = g;
    }
    A[A[stack_pointer]++] = Q;
    fetch();
};

هذه التعليمة البرمجية تبني كائنات حرفية عن طريق:

  1. قراءة عدد أزواج الخصائص من البايت كود
  2. سحب الأزواج من المكدس (أول سحب يصبح المفتاح)
  3. بناء كائن: object[firstPop] = secondPop
  4. دفع الكائن الناتج إلى المكدس

دالة الجلب (Fetch Function)

تختتم كل تعليمة باستدعاء fetch()، التي تُعد التعليمية التالية:

root@kitploit:~
function fetch() {
    var Q = A[instruction_pointer];
    var B = A[vm_start + Q];
    A[instruction_pointer] = Q + 1;
    var E = A[4783 + B];
    A[current_opcode_handler] = E;
    A[current_opcode_id] = B;
}

هذه الدالة:

  1. تقرأ مؤشر التعليمات
  2. تجلب التعليمة البرمجية التالية من البايت كود
  3. تزيد مؤشر التعليمات بمقدار 1
  4. تبحث عن معالج التعليمة البرمجية
  5. تحديث current_opcode_handler و current_opcode_id

هذا يعكس منطق الموزع، مما يُنشئ دورة جلب-فك-تنفيذ (fetch-decode-execute) النمطية في معماريات الآلات الافتراضية.

تنفيذ مفكك الترجمة (Disassembler Implementation)

لتسهيل التحليل، تم تطوير مفكك ترجمة كدليل على المفهوم (disasm.js) لتحويل البايت كود للآلة الافتراضية إلى لغة تجميع قابلة للقراءة البشرية.

النهج

يعمل مفكك الترجمة في مسارين:

المسار 1: اكتشاف العلامات (Labels)

يمسح المسار الأول البايت كود لتحديد جميع أهداف القفزات. يشمل ذلك:

  • القفزات الأمامية والخلفية (JMP_FWD، JMP_BACK)
  • القفزات الشرطية (JZ، JNZ_KEEP، JZ_KEEP)
  • حدود الإغلاقات (جسم الدوال ونقاط نهايتها)

يتم تمييز كل عنوان هدف بعلامة (مثل L_0042) لتسهيل تتبع تدفق التحكم.

المسار 2: فك التجميع (Disassembly)

يحول المسار الثاني كل تعليمة إلى مخرجات شبيهة بلغة التجميع:

root@kitploit:~
000042:  fa 00 0a           PUSH_IMM 10
000045:  19 00 19           PUSH_REG 25
000048:  eb                 ADD

يتضمن كل سطر:

  • العنوان: إزاحة ست عشرية في البايت كود
  • البايتات الخام: البايتات الفعلية المكونة للتعليمة (مفيدة للتحقق) وتبدو رائعة جدًا
  • التعليمة البرمجية: اسم اختصاري للتعليمة
  • الوسائط: المعاملات المُفككة (أرقام السجلات، القيم الفورية، أهداف القفزات)

فك تشفير القيم (Value Decoding)

أحد الجوانب الأكثر تعقيدًا هو فك تشفير القيم الفورية المضمنة في البايت كود. تستخدم الآلة الافتراضية علامات نوعية (type markers) للإشارة إلى كيفية تفسير البايتات التالية:

الأنواع البسيطة (بدون بيانات إضافية):

  • 0x28 → true
  • 0x7D → false
  • 0x4C → null
  • 0x3D → undefined

الأعداد الصحيحة الصغيرة (0-127): مشفرة مع تعيين البت الأعلى

  • 0x85 → 5 (0x80 | 5)

السلاسل النصية: مشفرة باستخدام XOR ومنتهية بـ null

  • سلاسل ASCII: علامة 0x67، مفتاح XOR يبدأ من 183
  • سلاسل UTF-8: علامة 0x27، مفتاح XOR يبدأ من 46

الأنواع الرقمية:

  • 8-bit signed: 0x6F + 1 بايت
  • 16-bit signed: 0x61 + 2 بايت (big-endian)
  • 24-bit signed: 0x65 + 3 بايت (big-endian)
  • 32-bit signed: 0x54 + 4 بايت (big-endian)
  • IEEE 754 double: 0x05 + 8 بايت

تشفير XOR للسلاسل النصية واضح ومباشر لكنه يمنع الفحص العرضي:

root@kitploit:~
let str = '';
let xorKey = 183;  // مفتاح ابتدائي لسلاسل ASCII
let ch;
while ((ch = readByte() ^ (xorKey++ & 0xFF)) !== 0) {
    str += String.fromCharCode(ch);
}

تعليمات برمجية خاصة

تتطلب بعض التعليقات البرمجية معالجة مخصصة:

CLOSURE (التعليمة 136): ينشئ دوال/إغلاقات مع متغيرات ملتقطة

root@kitploit:~
التنسيق: CLOSURE locals, capture_count, [capture_indices...], skip_offset

يشير إزاحة التخطي إلى ما بعد جسم الدالة، مما يسمح للآلة الافتراضية بتخطي تعريف الدالة أثناء التنفيذ الخطي.

PUSH_MULTI_IMM (التعليمة 96): يدفع قيمًا متعددة دفعة واحدة

root@kitploit:~
التنسيق: PUSH_MULTI_IMM count, val1, val2, ...

الاستخدام

root@kitploit:~
# فك التجميع من ملف
node disasm.js bytecode.txt

مثال على المخرجات

root@kitploit:~
; DataDome VM Disassembly
; Bytecode size: 5428 bytes
; VM Constants: VM_START=5258, OPCODE_BASE=4783

000000:  88 01 00 04        CLOSURE locals=1, captures=[0, 4], body=L_0006, end=L_0a3f
L_0006:
000006:  fa 67 ...          PUSH_IMM "window"
00001f:  2b                 PUSH_WINDOW
000020:  02                 SET
000021:  fa 67 ...          PUSH_IMM "navigator"
00003a:  19 00 00           PUSH_REG 0
00003d:  fa 67 ...          PUSH_IMM "navigator"
000056:  ee                 GET
000057:  02                 SET
...

هذا التنسيق للمخرجات يجعل من الممكن:

  • تتبع تدفق التنفيذ باتباع علامات القفز
  • تحديد حدود الدوال عبر تعليمات CLOSURE
  • رؤية القيم التي يتم دفعها ومعالجتها بالضبط
  • الربط مع تطبيق الآلة الافتراضية الفعلي

ملاحظات

لا زلت جديدًا نسبيًا في عالم الآلات الافتراضية، لذا خذ كل شيء بحذر. تم استخدام الذكاء الاصطناعي للمساعدة في توثيق الكود وكتابة أجزاء من هذا الملف (لأن كتابة الوثائق أمر مؤلم).

إخلاء مسؤولية

هذا لأغراض تعليمية/بحثية أمنية بحتة. لا يتضمن أي حلول أو تجاوزات - فقط توثيق لكيفية عمل الآلة الافتراضية لأنه مثير للاهتمام حقًا.

DataDome: إذا كنت تقرأ هذا، مرحبًا!!! هذا مجرد محاولة مني للحصول على منحة دراسية 🙏. من فضلك لا تقاضني، أنا مفلس جدًا. إذا كان لديك أي مشكلة مع هذا المستودع، فقط أخبرني ويمكننا التحدث عنها :)

آسف للأشخاص الذين ظنوا أنني سأتحدث عن داخل الآلة الافتراضية... هذا لن يحدث

لا تراسلني خاص وتطلب واجهة برمجة تطبيقات DataDome، لن أساعدك

تنزيل الأداة