Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
datadome-vm — नए Datadome VM का रिवर्स इंजीनियरिंग 🔥 | Kitploit
उपकरण/GitHubGitHub/xkiian/datadome-vm
गतिशील विश्लेषण (सैंडबॉक्सिंग)रिवर्स इंजीनियरिंगबाइनरी विश्लेषणलर्निंग और शिक्षाएंटी-बॉटकैप्चा बायपास
GitHubxkiian/datadome-vm

datadome-vm

नए Datadome VM का रिवर्स इंजीनियरिंग 🔥

रिपॉजिटरी देखें
125196 महीने पहलेKitploit द्वारा समीक्षित

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

DataDome VM विश्लेषण

सारांश

यह रिपॉजिटरी DataDome के CAPTCHA/इंटरस्टीशियल फ़्लो में उपयोग किए जाने वाले ब्राउज़र-आंतरिक JavaScript वर्चुअल मशीन (VM) के पहले सार्वजनिक संस्करण का दस्तावेज़ीकरण करती है। इस विश्लेषण में शामिल हैं:

  • बाइटकोड लोडिंग और डिकोडिंग तंत्र
  • VM मेमोरी लेआउट और आर्किटेक्चर
  • एक प्रूफ-ऑफ-कॉन्सेप्ट डिसअसेम्बलर
  • नियंत्रण-प्रवाह विश्लेषण नोट्स

नोट: यह रिपॉजिटरी केवल एक (स्थिर) VM संस्करण को कवर करती है और सुरक्षा अनुसंधान एवं विश्लेषण उद्देश्यों के लिए है। इसमें डायनामिक सॉल्वर या उत्पादन सॉल्वर कार्यान्वयन शामिल नहीं हैं।

पृष्ठभूमि

14 जनवरी, 2026 को DataDome ने अपने क्लाइंट टैग में एक नया VM-आधारित घटक भेजना शुरू किया।

डिओबफ़स्केशन

VM कोड को कैप्चा चैलेंज से निकालकर vm.js (इस रिपॉजिटरी में उपलब्ध) में रखा गया है।

पहला कदम स्क्रिप्ट को डिओबफ़स्केट करना था:

ओबफ़स्केशन सीधा है: प्रत्येक वेरिएबल का मूल्यांकन करें और उसे उसके वास्तविक मान से बदलें। deobf.js में एक डिओबफ़स्केशन स्क्रिप्ट उपलब्ध है।

प्रारंभिक विश्लेषण

डिओबफ़स्केट किए गए कोड (out.js) को DevTools में चलाने पर VM का अपेक्षित आउटपुट दिखाई देता है:

आउटपुट एक JSON ऑब्जेक्ट है जिसमें दो संख्याएँ और एक स्ट्रिंग है। अब वास्तविक VM कार्यान्वयन में गोता लगाते हैं।

बाइटकोड डिकोडिंग

Q.exports फ़ंक्शन की शुरुआत में, हम देख सकते हैं कि बाइटकोड कैसे डिकोड किया जाता है:

  1. इनपुट स्ट्रिंग को बेस64 डिकोड किया जाता है
  2. लंबाई 129,263 की एक सरणी बनाई जाती है
  3. प्रत्येक इंडेक्स को एक विशिष्ट सीमा के विरुद्ध जाँचा जाता है:
    • यदि इंडेक्स सीमा के भीतर आता है, तो मान डिकोड किया जाता है
    • अन्यथा, एक यादृच्छिक संख्या लौटाई जाती है (B() का उपयोग करके, एक स्यूडो-रैंडम नंबर जनरेटर) -> D कुछ यादृच्छिक "शोर" के साथ डिकोड किए गए बाइटकोड को धारण करता है

VM आर्किटेक्चर

नीचे स्क्रॉल करने पर VM एंट्री पॉइंट दिखाई देता है: दो पैरामीटर A (बाइटकोड) और Q (एक खाली शब्दकोश जो त्रुटि प्रबंधन के लिए उपयोग होता है) वाला एक फ़ंक्शन।

मेमोरी लेआउट

इस VM का सबसे दिलचस्प पहलू इसकी आर्किटेक्चर है: सब कुछ एक ही सरणी (A) में रहता है। इस सरणी में शामिल हैं:

  • स्टैक
  • रजिस्टर
  • ऑपकोड
  • बाइटकोड स्वयं
  • इंस्ट्रक्शन पॉइंटर

यह डिज़ाइन विशिष्ट मेमोरी क्षेत्रों वाले वास्तविक कंप्यूटर आर्किटेक्चर को दर्शाता है। अगला कदम प्रत्येक ऑफ़सेट को मैप करना है ताकि यह समझा जा सके कि कहाँ क्या संग्रहीत है:

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

इन ऑफ़सेट्स के मैप होने के बाद VM संरचना स्पष्ट हो जाती है।

सहायक फ़ंक्शन

VM सहायक फ़ंक्शनों के एक संग्रह से शुरू होता है जो संभालते हैं:

  • स्टैक से टाइप किए गए मान पढ़ना
  • स्टैक और "रजिस्टरों" के बीच डेटा ले जाना

VM आरंभीकरण

सहायक फ़ंक्शनों के बाद, VM मुख्य मानों को आरंभ करता है:

  • सभी पॉइंटर (स्टैक, इंस्ट्रक्शन, फ्रेम बेस)
  • एग्ज़िट फ्लैग
  • अंतिम परिणाम रजिस्टर

आरंभीकरण के नीचे सभी इंस्ट्रक्शन हैंडलर हैं।

डिस्पैचर लूप

डिस्पैचर मुख्य VM लूप है जो `exit_flag` सेट होने तक चलता है:
  • I वर्तमान इंस्ट्रक्शन को दर्शाता है
  • P सरणी में वास्तविक ऑफ़सेट है (ओबफ़स्केशन को ध्यान में रखते हुए)
  • लूप वर्तमान इंस्ट्रक्शन को current_opcode_handler पर सेट करता है और current_opcode_id को अपडेट करता है

ऑपकोड कार्यान्वयन

ऑपकोड कैसे काम करते हैं

यहाँ एक ऑपकोड हैंडलर का एक मूल उदाहरण है:

  1. बाइटकोड से एक तत्काल मान लाता है
  2. स्टैक से शीर्ष मान प्राप्त करता है
  3. एक संक्रिया करता है (जैसे %= या ^=)
  4. अंत में fetch() फ़ंक्शन को कॉल करता है

दिलचस्प ऑपकोड

ऑपकोड 4919: फ़ंक्शन/क्लोज़र निर्माण

सबसे जटिल ऑपकोडों में से एक क्लोज़र/फ़ंक्शन बनाता है:

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: डायनामिक फ़ंक्शन कॉल

यह ऑपकोड फ़ंक्शन कॉल के लिए एक रैपर बनाता है जो नियमित और कंस्ट्रक्टर दोनों कॉल को संभालता है:

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: ऑब्जेक्ट लिटरल निर्माण

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() कॉल करके समाप्त होता है, जो अगले इंस्ट्रक्शन को तैयार करता है:

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. इंस्ट्रक्शन पॉइंटर को बढ़ाता है
  4. ऑपकोड हैंडलर को खोजता है
  5. current_opcode_handler और current_opcode_id को अपडेट करता है

यह डिस्पैचर तर्क को दर्शाता है, जो VM आर्किटेक्चर के विशिष्ट फ़ेच-डिकोड-एक्ज़ीक्यूट चक्र बनाता है।

डिसअसेम्बलर कार्यान्वयन

विश्लेषण में सहायता के लिए, एक प्रूफ-ऑफ-कॉन्सेप्ट डिसअसेम्बलर (disasm.js) विकसित किया गया था जो VM के बाइटकोड को मानव-पठनीय असेंबली में परिवर्तित करता है।

दृष्टिकोण

डिसअसेम्बलर दो पास में काम करता है:

पास 1: लेबल खोज

पहला पास सभी जंप लक्ष्यों की पहचान करने के लिए बाइटकोड को स्कैन करता है। इसमें शामिल है:

  • आगे और पीछे की जंप (JMP_FWD, JMP_BACK)
  • सशर्त जंप (JZ, JNZ_KEEP, JZ_KEEP)
  • क्लोज़र सीमाएँ (फ़ंक्शन बॉडी और उनके अंत बिंदु)

प्रत्येक लक्ष्य पते को एक लेबल (जैसे L_0042) से चिह्नित किया जाता है ताकि नियंत्रण प्रवाह को आसानी से समझा जा सके।

पास 2: डिसअसेम्बली

दूसरा पास प्रत्येक इंस्ट्रक्शन को असेंबली-जैसे आउटपुट में परिवर्तित करता है:

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

प्रत्येक पंक्ति में शामिल है:

  • पता: बाइटकोड में हेक्साडेसिमल ऑफ़सेट
  • कच्चे बाइट्स: इंस्ट्रक्शन बनाने वाले वास्तविक बाइट्स (सत्यापन के लिए उपयोगी)
  • ऑपकोड: इंस्ट्रक्शन का निमोनिक नाम
  • तर्क: डिकोड किए गए ऑपरेंड (रजिस्टर संख्याएँ, तत्काल मान, जंप लक्ष्य)

मान डिकोडिंग

अधिक जटिल पहलुओं में से एक बाइटकोड में एम्बेडेड तत्काल मानों को डिकोड करना है। VM यह इंगित करने के लिए टाइप मार्कर का उपयोग करता है कि निम्नलिखित बाइट्स की व्याख्या कैसे करें:

सरल प्रकार (कोई अतिरिक्त डेटा नहीं):

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

छोटे पूर्णांक (0-127): उच्च बिट सेट के साथ एन्कोडेड

  • 0x85 → 5 (0x80 | 5)

स्ट्रिंग्स: XOR-एन्कोडेड और नल-टर्मिनेटेड

  • ASCII स्ट्रिंग्स: मार्कर 0x67, XOR कुंजी 183 से शुरू होती है
  • UTF-8 स्ट्रिंग्स: मार्कर 0x27, XOR कुंजी 46 से शुरू होती है

संख्यात्मक प्रकार:

  • 8-बिट साइन्ड: 0x6F + 1 बाइट
  • 16-बिट साइन्ड: 0x61 + 2 बाइट्स (बिग-एंडियन)
  • 24-बिट साइन्ड: 0x65 + 3 बाइट्स (बिग-एंडियन)
  • 32-बिट साइन्ड: 0x54 + 4 बाइट्स (बिग-एंडियन)
  • IEEE 754 डबल: 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:~
Format: CLOSURE locals, capture_count, [capture_indices...], skip_offset

स्किप ऑफ़सेट फ़ंक्शन बॉडी से आगे इंगित करता है, जिससे VM रैखिक निष्पादन के दौरान फ़ंक्शन परिभाषा को छोड़ सकता है।

PUSH_MULTI_IMM (ऑपकोड 96): एक साथ कई मान पुश करता है

root@kitploit:~
Format: 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 ऑपकोड के माध्यम से फ़ंक्शन सीमाओं की पहचान करना
  • देखना कि कौन से मान पुश और हेरफेर किए जा रहे हैं
  • वास्तविक VM कार्यान्वयन के साथ क्रॉस-रेफरेंस करना

नोट्स

मैं VM के मामले में अभी भी काफी नया हूँ, इसलिए हर चीज़ को संदेह की दृष्टि से लें। कोड को दस्तावेज़ित करने और इस रीडमी के कुछ हिस्सों को लिखने में AI का उपयोग किया गया है (क्योंकि डॉक्स लिखना दर्दनाक है)।

अस्वीकरण

यह पूरी तरह से शैक्षिक/सुरक्षा अनुसंधान उद्देश्यों के लिए है। इसमें कोई सॉल्वर या बाइपास शामिल नहीं है – बस यह दस्तावेज़ित करना कि VM कैसे काम करता है क्योंकि यह वास्तव में दिलचस्प है।

DataDome: यदि आप इसे पढ़ रहे हैं, नमस्ते!!! यह सिर्फ मैं एक छात्रवृत्ति पाने की कोशिश कर रहा हूँ 🙏। कृपया मुझ पर मुकदमा न करें, मैं बहुत गरीब हूँ। यदि आपको इस रेपो से कोई समस्या है, तो बस मुझे बताएं और हम इस पर बात कर सकते हैं :)

उन लोगों के लिए खेद है जिन्होंने सोचा कि मैं VM के अंदर के बारे में बात करूंगा… ऐसा नहीं होने वाला है

मुझे DM करके DataDome API मत मांगिए, मैं आपकी मदद नहीं करूंगा।

टूल डाउनलोड करें