
أداة إزالة تشويش ثابتة لشفرة JavaScript البايتية المُجمَّعة في محرك V8، مع التركيز على حمولات JSCeal. توفر عوامل تصفية قائمة على الأنماط، وإعادة تسطيح تدفق التحكم، وإعادة بناء السلاسل النصية، وإعادة تسمية اختيارية للدوال بمساعدة LLM لأغراض التحليل.
هذه الأداة مخصصة لإزالة التعتيم (Deobfuscation) بشكل ثابت من البايت كود المُجمَّع لـ V8 JavaScript والذي تمت حمايته باستخدام javascript-obfuscator.
تعمل الأداة على الكود الزائف (Pseudocode) الناتج عن View8، وليس على كود JavaScript الأصلي. تم تطوير المشروع واختباره على حمولات JSCeal.
المرشحات (Filters) تعتمد على الأنماط (Pattern-driven) وهي مخصصة في المقام الأول لتكون مجموعة أدوات بحثية وتنفيذًا مرجعيًا. الأداة ليست أداة إزالة تعتيم عامة لـ JavaScript، ولا تعيد بناء الكود المصدري الأصلي، ولا تنتج كود JavaScript قابلًا للتشغيل. يبقى ناتجها كودًا زائفًا من View8 مخصصًا للفحص الثابت والبحث والمقارنة وتصدير شجرة الدوال.
pickle الخاص بـ Python. تحميل ملف .pkl خبيث أو غير موثوق يمكن أن ينفذ كودًا. قم بتحميل الملفات المسلسلة التي قمت بإنشائها محليًا باستخدام View8 فقط.requirements.txt؛brotli لسير عمل فك الضغط الجماعي على Linux؛أنشئ بيئة Python معزولة:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
الخلفية (Backend) الخاصة بـ OpenAI في deobf_ai.py تتطلب أيضًا حزمة OpenAI الخاصة بـ Python:
python3 -m pip install openai
خلفية Anthropic تستخدم HTTP API عبر requests. خلفية Ollama تتوقع خادم Ollama يمكن الوصول إليه.
حمولة JSCeal الأصلية app.jsc مضغوطة بـ Brotli. على Linux، يمكن فك ضغطها باستخدام أداة brotli:
brotli -d app.jsc -o app.decompressed.jsc
سير العمل الجماعي تحت scripts/ يقوم بهذه الخطوة باستخدام scripts/unpack_all.sh.
على Windows، أو عندما تكون أداة سطر الأوامر brotli غير متوفرة، يمكن استخدام مساعد Node.js المرفق كبديل. يقوم فقط بفك ضغط الإدخال ولا ينفذه:
node Utils/decompress-jsc.js app.jsc
يكتب:
app.jsc.decompressed.jsc
V8 code cache خاص بإصدار محدد. استخدم مفككًا مبنيًا لنفس إصدار V8 المستخدم في الحمولة.
عينات JSCeal المستخدمة أثناء التطوير كانت مبنية على V8 10.2.154.26. المفككات الافتراضية من بناء V8 غير مرتبط لن تعمل بشكل صحيح.
شجرة المصدر تحتوي على كود المفكك وتصحيحات V8 المطلوبة تحت:
Utils/disasm/v8dasm.cpp
Utils/disasm/patches/
يتم توزيع ثنائي Linux مُجمَّع مسبقًا مع إصدار المشروع، بينما تحتوي شجرة المصدر على الكود المصدري والتصحيحات اللازمة لإعادة بنائه. الوصف التفصيلي متاح على ويكي المشروع. بعد الحصول على أو بناء v8dasm المطابق، قم بتشغيل:
/path/to/v8dasm app.decompressed.jsc > app.jsc.disasm.txt
قم بتغذية الملف المفكك إلى view8.py وأنتج كلاً من المخرجات المسلسلة لمزيد من المعالجة والكود الزائف القابل للقراءة البشرية:
mkdir -p decompiled
python3 View8/view8.py \
--input_format disassembled \
--inp app.jsc.disasm.txt \
--normalize \
--out decompiled/app.dec.txt \
--export_format decompiled serialized
هذا ينتج:
decompiled/app.dec.txt
decompiled/app.dec.pkl
خيار --normalize يجعل معرفات الدوال المولدة قابلة للتكرار عبر عمليات التفكيك وفك الترجمة المتكررة.
هناك مرشحات منفصلة لطبقات التعتيم الفردية. يمكن تطبيقها معًا على مخرجات View8 المسلسلة باستخدام deobf_all.py:
mkdir -p deobfuscated
python3 deobf_all.py \
--inp decompiled/app.dec.pkl \
--out deobfuscated/app.deobf.txt \
--export_format decompiled serialized
مرشح السلاسل النصية الافتراضي هو النمط 2، المستخدم في غالبية حمولات JSCeal التي تم تحليلها. لتحديد مخطط السلاسل الأبسط بشكل صريح، أضف:
--str_deobf 1
المخرجات النموذجية هي:
deobfuscated/app.deobf.txt
deobfuscated/app.deobf.pkl
deobfuscated/app.deobf.txt.strings.txt
decompiled/app.dec.resolved_funcs.csv
ملف CSV للدوال المُحلَّلة هو ذاكرة تخزين مؤقت خاصة بالعينة. عندما يكون غائبًا، تستعيد مرحلة السلاسل النصية تكوين وحدة فك الترميز المطلوبة، وتكتب CSV، وتستمر في إزالة تعتيم السلاسل في نفس التشغيل. التشغيلات اللاحقة تعيد استخدام الذاكرة المؤقتة وتكون عادةً أسرع.
لا تعيد استخدام CSV للدوال المُحلَّلة مع حمولة مفككة مختلفة.
بعد تطبيق جميع مرشحات إزالة التعتيم الهيكلية، يمكن لـ deobf_ai.py اقتراح أسماء تصف سلوك الدوال. يدعم خلفيات Anthropic وOpenAI وOllama.
مرر النموذج بشكل صريح حتى تبقى عمليات التشغيل قابلة للتكرار.
export ANTHROPIC_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend anthropic \
--model '<model-id>' \
--export_format decompiled serialized
export OPENAI_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend openai \
--model '<model-id>' \
--export_format decompiled serialized
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend ollama \
--model '<local-model>' \
--ollama_url http://localhost:11434 \
--export_format decompiled serialized
في الوضع الافتراضي، يبني مُعيد التسمية شجرة استدعاءات مباشرة بدءًا من الدالة المدخلة ويعيد تسمية الدوال التي يتم الوصول إليها عبر الاستدعاءات فقط. أضف --greedy لتضمين جميع مراجع الدوال المرئية، بما في ذلك الاستدعاءات الخلفية والمعالجات المعينة.
ملف CSV ثنائي الأعمدة المُنشأ يعمل كذاكرة تخزين مؤقت ويسمح لاستمرار تشغيل متقطع. حدد ذاكرة تخزين مؤقت موجودة بشكل صريح باستخدام --csv:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--csv deobfuscated/app.deobf.renamed_funcs.greedy.example-model.csv \
--llm_backend anthropic \
--model '<model-id>' \
--greedy \
--export_format decompiled serialized
في الوضع العادي، يتم التعامل مع CSV كذاكرة تخزين مؤقت جزئية محتملة. يتم تطبيق الأسماء المخزنة أولاً، وتتم إزالة الدوال المغطاة بالفعل بواسطة الذاكرة المؤقتة من شجرة الاستدعاءات أو المراجع المحددة، ويتم استدعاء LLM فقط للدوال التي تبقى غير محلولة. إذا كانت CSV تغطي تلك الشجرة بالكامل، فلا حاجة لمفتاح API أو اتصال LLM. إذا كانت تغطي جزءًا فقط من الشجرة، تتم تهيئة الخلفية المحددة وتُضاف التعيينات المُنشأة حديثًا إلى نفس CSV.
استخدم نفس وضع الشجرة الذي استُخدم عند إنشاء CSV. CSV الناتج من تشغيل --greedy يحتاج عادةً إلى --greedy مرة أخرى إذا كان الهدف هو مواصلة ذلك التشغيل بدلاً من إعادة استخدام مجموعة الاستدعاءات المباشرة فقط.
استخدم --apply-csv-only عندما تحتوي CSV بالفعل على التسميات التي تريد تطبيقها، بما في ذلك التعيينات المراجعة أو المحررة أو المستوردة أو المعاد ترسيخها:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--csv renamed_functions.normalized.csv \
--apply-csv-only \
--export_format decompiled serialized
هذا الوضع:
--csv صريحًا؛--func.يتم تجاهل الصفوف التي لا يوجد معرف الدالة الأصلي الخاص بها في الإدخال. يفشل الأمر عندما تحتوي CSV على تعيينات غير قابلة للتطبيق على الملف المحمّل.
استخدم --func مع معرف الدالة الكامل الدقيق لطلب تحليل دلالي مركّز لدالة واحدة بعد إزالة التعتيم:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--func func_example_0x100001234 \
--llm_backend anthropic \
--model '<model-id>'
يتضمن التحليل اسمًا مقترحًا وملخصًا للسلوك والمدخلات وقيمة الإرجاع والآثار الجانبية والمنطق خطوة بخطوة وكودًا زائفًا منقىً وأدلة داعمة وحالات عدم يقين غير محلولة. توفير --csv يضيف أسماء دلالية مخزنة كسياق للمراجع داخل الدالة المحددة دون تعديل المجموعة المحمّلة. استخدم --analysis-out analysis/function.md لحفظ التقرير بصيغة Markdown. تتم طباعة التطابقات التقريبية كاقتراحات فقط؛ يجب أن يطابق معرف الدالة المطلوب تمامًا.
استخدم --help للخيارات التي تتحكم في درجة الحرارة والتجميع ووضع التفكير في Anthropic وحدود الرموز ومسارات CSV المخصصة.
الأسماء المولدة بواسطة LLM هي أدوات مساعدة للتنقل، وليست أدلة. تحقق دائمًا منها مقابل الجسم بعد إزالة التعتيم.
مخرجات JSCeal بعد إزالة التعتيم عادةً ما تكون كبيرة جدًا. قم بتحميل المخرجات المسلسلة مرة أخرى إلى View8 وقسمها إلى أشجار دوال أصغر.
في هذه المرحلة، أضف --scope 0. تم تنفيذ نشر النطاق بالفعل بواسطة أداة إزالة التعتيم، وتكراره قد ينشر القيم بشكل غير صحيح.
شجرة مبنية على علاقات المُعلِن (Declarer):
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/declarers \
--export_format decompiled \
--tree start \
--scope 0
نظرة عامة مضغوطة على الاستدعاءات المباشرة:
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/calls \
--export_format decompiled \
--tree start \
--scope 0 \
--split_mode calls \
--inline_depth 1 \
--split_depth 5
شجرة مراجع أوسع، بما في ذلك الاستدعاءات الخلفية والمعالجات المعينة:
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/references \
--export_format decompiled \
--tree start \
--scope 0 \
--split_mode references \
--inline_depth 1 \
--split_depth 3
قد تستخدم ملفات JSC المختلفة أوضاعًا مختلفة لتعتيم السلاسل النصية.
أبسط وضع تمت ملاحظته يستخدم إزاحة الفهرس ويتم التعامل معه بواسطة deobf_str1.py. وضع JSCeal الأكثر شيوعًا يستخدم Base64 وRC4 وسلاسل مجزأة وفهارس محولة؛ يتم التعامل معه بواسطة deobf_str2.py.
خط الأنابيب الكامل يختار النمط 2 افتراضيًا. يمكن أيضًا تشغيل المرشحات بشكل مستقل للاختبار.
deobf_str2.pyاستخدم --help لعرض جميع الأوضاع والخيارات المتاحة:
python3 deobf_str2.py --help
يمكن بدء تشغيل مباشر لإزالة تعتيم السلاسل باستخدام:
python3 deobf_str2.py \
--inp decompiled/app.dec.pkl \
--out work/app.strings.txt \
--export_format decompiled serialized
أثناء التشغيل، يحدد السكربت دوال وحدة فك ترميز السلاسل، ويحمّل أي تكوينات مخزنة صالحة، ويحل التكوينات المفقودة، ويحفظ CSV الناتج، ويفك ترميز السلاسل. لا حاجة لتشغيل ثانٍ.
عند استخدام deobf_str2.py مباشرة، اسم CSV الافتراضي هو resolved_funcs.csv. حدد مسارًا خاصًا بالعينة باستخدام --csv أو -c:
python3 deobf_str2.py \
--inp decompiled/app.dec.pkl \
--out work/app.strings.txt \
--csv decompiled/app.dec.resolved_funcs.csv \
--export_format decompiled serialized \
--verbosity 1
عند ربط المرشحات الفردية، حافظ على المخرجات المسلسلة بين المراحل حتى تتمكن المراحل اللاحقة من مواصلة العمل على كائنات View8.
deobf_all.py يطبق المراحل التالية بالترتيب:
إعادة تسمية الدوال بمساعدة LLM اختيارية وتُشغَّل بشكل منفصل بعد إزالة التعتيم الهيكلي.
يحتوي المستودع على سير عمل مساعد كامل تحت scripts/. جميع السكربتات محفوظة في دليل واحد وتستمد من نفس التكوين المركزي.
scripts/config.sh مسارات الأدوات ومساحة العمل المشتركة
scripts/copy_payloads.sh جمع ملفات JSCeal app.jsc وتسميتها بـ MD5
scripts/unpack_all.sh فك ضغط Brotli
scripts/disasm_all.sh تفكيك V8 جماعي
scripts/decompile_all.sh فك ترجمة View8 جماعي
scripts/deobfuscate_all.sh إزالة تعتيم جماعية مع سجل مدمج
scripts/run_unattended.sh إزالة تعتيم وتحقق منفصل
scripts/collect_output.sh جمع ذاكرات التخزين المؤقت لوحدات فك الترميز وقوائم السلاسل
يحتوي scripts/config.sh المرفق على مسارات من بيئة مثال:
JSC_DEOBF_ROOT="$HOME/jsc_deobfuscator"
V8DASM="$HOME/code/v8/v8dasm"
قم بتحرير هذا الملف مرة واحدة لتكوين مسار التثبيت ومفكك V8 المطابق وأدلة مساحة العمل والأوامر الخارجية ومسارات السجلات وتخطيط الجمع. مساحة العمل الافتراضية هي الدليل الذي يتم تشغيل سكربت المساعدة منه.
يمكن أيضًا تجاوز كل قيمة عبر متغير بيئة. JSC_HELPER_CONFIG يمكنه تحديد ملف تكوين مختلف.
تشغيل جماعي نموذجي هو:
scripts/copy_payloads.sh
scripts/unpack_all.sh
scripts/disasm_all.sh
scripts/decompile_all.sh
scripts/deobfuscate_all.sh
scripts/collect_output.sh
تحافظ السكربتات على الاصطلاحات المستخدمة لمجموعة JSCeal، بما في ذلك التعامل مع ملفات app.jsc المكتشفة كحمولات مضغوطة بـ Brotli وتسميتها بـ MD5. راجع scripts/README.md قبل تطبيق سير العمل على عينات غير مرتبطة.
لتشغيل جماعي طويل، يطلق scripts/run_unattended.sh إزالة التعتيم باستخدام nohup، ويكتب ملفات سجل وPID وحالة بطوابع زمنية، ويتحقق من كل مخرج مُنشأ بحثًا عن مراجع غير محلولة لدوال وحدة فك ترميز السلاسل المخزنة:
scripts/run_unattended.sh
يمكن توفير العينات المحددة بشكل صريح:
scripts/run_unattended.sh \
decompiled/sample1.dec.pkl \
decompiled/sample2.dec.pkl
View8/ مفكك View8 ومصدّر أشجار الدوال
Utils/decompress-jsc.js بديل فك ضغط Brotli لنظام Windows
Utils/disasm/v8dasm.cpp كود مصدر مفكك V8
Utils/disasm/patches/ تصحيحات V8 المطلوبة بواسطة المفكك
Utils/check_unresolved_decoder_references.py
أداة التحقق من المخرجات المساعدة
deobf_all.py خط أنابيب إزالة التعتيم الافتراضي الكامل
deobf_str1.py مرشح إزاحة فهرس السلاسل البسيط
deobf_str2.py مرشح سلاسل RC4/Base64 مع استعادة الفهرس
deobf_scope2.py نشر النطاق والقواميس
deobf_unflattener.py إزالة تسطيح تدفق التحكم
deobf_replace_ops.py استبدال البروكسي ومغلفات العمليات
deobf_globals.py النشر العام
deobf_inline_temporaries.py تنظيف نهائي متحفظ
deobf_ai.py إعادة تسمية الدوال الاختيارية بمساعدة LLM
scripts/ مساعدات التجميع والتحقق القابلة للتكوين
يمكن تنفيذ كل مرحلة رئيسية بشكل منفصل للاختبار. قم بتشغيل السكربت المحدد مع --help لرؤية واجهته الكاملة:
python3 deobf_str1.py --help
python3 deobf_str2.py --help
python3 deobf_scope2.py --help
python3 deobf_unflattener.py --help
python3 deobf_replace_ops.py --help
python3 deobf_globals.py --help
python3 deobf_inline_temporaries.py --help
javascript-obfuscator ذات الصلة. قد تتطلب المتغيرات الجديدة كاشفات أو تحويلات إضافية.تم اختبار خط الأنابيب ضد الانحدارات (Regression) على مجموعة JSCeal المستخدمة في البحث المصاحب. تشمل فحوصات الإصدار الأساسية:
python3 -m compileall -q .
python3 deobf_all.py --help
python3 deobf_str2.py --help
python3 deobf_ai.py --help
python3 View8/view8.py --help
لكل عينة من المجموعة، تحقق من أن التشغيل:
.pkl و.txt؛سكربت المساعدة غير المراقب يؤتمت التحقق النهائي من مراجع وحدة فك الترميز.
javascript-obfuscator.كود مصدر JSC Deobfuscator المؤلف لهذا المشروع مرخص بموجب
رخصة GNU العامة، الإصدار 2 أو (حسب اختيارك) أي إصدار لاحق
(GPL-2.0-or-later). راجع LICENSE للنص الكامل للترخيص.
حقوق النشر (C) 2026 Aleksandra "Hasherezade" Doniec @ Check Point Research.
الوحدة الفرعية View8 هي مشروع منفصل. المواد المشتقة من طرف ثالث لمفكك
تحت Utils/disasm/ تحتفظ بمصدرها الحالي ولا يُعاد ترخيصها بموجب إشعار حقوق النشر أعلاه.