Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

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

datadome-vm

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

عرض المستودع
1251961منذ 7 أشهرتمت المراجعة من قبل 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) لفهم ما يُخزن أين:

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)

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

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):

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)

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();
};
تنزيل الأداة