
فك تشفير واستخراج صور البرامج الثابتة لنظام FortiOS 8.0.0.
فك تشفير واستخراج صور البرامج الثابتة (firmware) لنظام FortiOS 8.0.0.
يعمل هذا السكربت على توسيع Forticrack الخاص بـ Bishop Fox لدعم صور البرامج الثابتة للإصدار 8.0.0. كما كانت مقالة RandoriSec حول تشفير البرامج الثابتة لـ FortiGate 7.4.7 مفيدة جدًا في هندسة التشفير عكسيًا لنظام FortiOS 8.0.0، إذ يبدو أنه تكرار أحدث لتشفير 7.4.7.
يعمل مع صور FGT و FFW على حد سواء.
تم اختبار هذا على كل من صورتي FGT و FFW بإصدار v8.0.0.F-build0167. قد تتطلب الإصدارات الأخرى إعادة هندسة النواة عكسيًا مرة أخرى للعثور على مقاطع النواة والعناوين الافتراضية الدقيقة للمفتاح العام RSA ومفتاح XOR.
يحاول السكربت اكتشاف ما إذا كان ملف .out يخص FGT أو FFW تلقائيًا بناءً على التسمية. ويمكن أيضًا تحديده كوسيط اختياري في حال الحاجة.
$ python3 forticrack_v8.py
[x] Usage: python3 forticrack_v8.py <.out file> [FGT|FFW]
عرض توضيحي:

الدليل الناتج:

يوجد بالفعل العديد من المقالات والسكربتات حول فك تشفير fortiOS (مثل تلك المذكورة سابقًا). ومع ذلك، لا ينطبق أي منها على FortiOS 8.0.0، لأن Fortinet عدّلت التشفير مرة أخرى.
تتيح Fortinet تنزيل صور الترقية لكل من FortiFirewall و FortiGate على https://support.fortinet.com/ > Login > Support > VM Images. هذه الصور هي ملفات .out، وهذا هو ما يتوقعه السكربت كمدخل. عند تنفيذه، يقوم بـ 4 عمليات رئيسية:
.out (عمل Bishop Fox)ملف الترقية .out مشفّر بتشفير كتلي مخصص قائم على XOR. قامت Bishop Fox بهندسته عكسيًا ونشرت forticrack مع شرح وافٍ. يستخدم هذا الجزء من السكربت عمليًا نفس الكود من forticrack الأصلي من Bishop Fox، والذي يستخرج المفتاح المطابق ذا الـ 32 بايت ويفك تشفير ملف .out. أقترح قراءة الشرح إذا أردت معرفة المزيد عن ذلك.
الملف الناتج بعد فك التشفير هو صورة برنامج ثابت قياسية من Fortinet. يستخرجها السكربت باستخدام binwalk، منتجًا نظام الملفات التالي:
ext-root
├── boot
│ ├── cert.der
│ └── grub
│ ├── BOOTX64.EFI
│ ├── grub.cfg
│ └── grubx64.efi
├── boot.msg
├── datafs.tar.gz
├── datafs.tar.gz.bak
├── datafs.tar.gz.chk
├── datafs.tar.gz.chk.bak
├── extlinux.conf
├── filechecksum
├── flatkc
├── flatkc.chk
├── flatkc.sig
├── hash_bin.sha256
├── ldlinux.c32
├── ldlinux.sys
├── rootfs.gz
└── rootfs.gz.chk
حيث:
boot/ : دليل يحتوي على ملفات مُحمّل الإقلاع (bootloader)datafs.tar.gz : نظام ملفات البياناتflatkc : نواة لينكس bzImagerootfs.gz : نظام الملفات المشفّرجميع الملفات المثيرة للاهتمام لباحثي الثغرات الأمنية، مثل /sbin/init، مشفّرة داخل rootfs.gz.
rootfs.gz (الجزء الجديد)هذا هو الجزء الجديد الخاص بالإصدار 8.0.0. لمعرفة كيفية عمله، تم استخدام Claude Code بشكل مكثف لهندسة منطق فك التشفير عكسيًا والحصول على العناوين الافتراضية المضمّنة (hardcoded) داخل صورة النواة، بالاستناد إلى مقالة RandoriSec حول FortiGate 7.4.7 كمرجع. من تجربتي، فإن الهندسة العكسية بمساعدة الذكاء الاصطناعي تتألق حقًا عند تحليل أمور التشفير، والتي كانت مهمة شاقة كلاسيكية عندما كانت الهندسة العكسية اليدوية هي الخيار الوحيد.
ملف rootfs.gz مشفّر بتشفير تدفقي مخصص يسمى FORT-RC4. مفتاح فك تشفيره مضمّن داخل توقيع RSA بنمط PKCS#1 مُلحق في نهاية الملف. لفك تشفير هذا التوقيع، يجب استخدام المفتاح العام RSA المطابق، والذي يمكن استرداده من صورة النواة.
بما أن flatkc هو ملف bzImage، يمكن استخراج ELF الخاص بالنواة بسهولة عن طريق تحديد حمولة gzip داخله وفك ضغطها. داخل ELF، على العنوان الافتراضي 0xffffffff8179a1a0، توجد 270 بايت من بيانات DER المشفّرة بـ XOR وتمثل المفتاح العام RSA. مفتاح XOR ذو الـ 32 بايت لفك تشفيرها موجود على العنوان 0xffffffff8179a2c0. فك التشفير هو مجرد decoded[i] = encoded[i] ^ xor_key[i & 0x1f]، والنتيجة تُحلَّل كهيكل DER قياسي من نوع PKCS#1 RSAPublicKey (مفتاح عام RSA-2048).
بعد استرداد المفتاح العام RSA، يتم فك تشفير كتلة التوقيع (آخر 256 بايت من rootfs.gz) عن طريق حساب m = sig^e mod n. النتيجة المكونة من 256 بايت هي رسالة بحشو PKCS#1 v1.5 Type 1 بالتخطيط التالي:
m[0x00] = 0x00
m[0x01] = 0x01
m[0x02..0x9E] = 0xFF (157 padding bytes)
m[0x9F] = 0x00
m[0xA0..0xBF] = SHA256(rootfs.gz[:-256])
m[0xC0..0xDF] = (unused)
m[0xE0..0xFF] = RC4 key (32 bytes)
يتم التحقق من تجزئة SHA-256 مقابل محتوى rootfs.gz كفحص سلامة، والمفتاح RC4 ذو الـ 32 بايت في النهاية هو ما يُستخدم فعليًا لفك تشفير الملف.
بخصوص FORT-RC4، فقد تمت هندسته عكسيًا بالكامل بواسطة Claude بأسلوب vibe-reversed (أي الهندسة العكسية القائمة على الحدس). إليك كيف يعمل:
يحتوي FORT-RC4 على KSA قياسي لكن PRGA معدّل: بدلًا من إنتاج بايت تدفق مفاتيح واحد لكل دورة من خلال بحث واحد في S-box، يقوم بعمليتي بحث إضافيتين باستخدام نسخ مخلوطة بالبتات من
iوj، ويجري عملية XOR بين0xAAومؤشر الخلط، ويجمع قيمتين من S-box لإنتاج البايت النهائي. هناك أيضًا فرق بين FGT و FFW: في FGT، تتم إعادة تعيين كل منiوjإلى 0 بعد KSA وقبل بدء PRGA، بينما في FFW يحتفظjبقيمته من KSA. هذا واضح في نواة FGT على الإزاحة+0x83داخل دالة التشفير كتسلسل البايتات31 c0 31 d2(xor eax,eax; xor edx,edx)، وهو غير موجود في FFW. لهذا السبب يحتاج السكربت إلى معرفة النوع.
كما ذُكر، كانت مقالة RandoriSec حول 7.4.7 مرجعًا مفيدًا، لكن آلية التشفير تغيّرت بما يكفي بحيث لم ينطبق منهجهم مباشرة على 8.0.0، لذا فهذه هي الاختلافات الرئيسية:
.init.data. في 8.0.0، هذا القسم عبارة عن أصفار بالكامل، لذا يُستخدم مخطط XOR بسيط بدلًا من ذلك.rootfs باستخدام AES-CTR. في 8.0.0، يكون التشفير FORT-RC4 (خوارزمية تشفير مخصصة).rsa_parse_pub_key. أما نواة 8.0.0 فهي مجرّدة من الرموز (stripped)، لذا كان لا بد من العثور على العناوين الافتراضية عن طريق هندسة روتين فك التشفير عكسيًا مباشرة.العناوين الافتراضية لكتلة مفتاح RSA متقاربة بين الإصدارين (منزاحة بمقدار 0x3000)، مما ساعد أيضًا أثناء الهندسة العكسية.
الناتج بعد فك التشفير هو ملف gzip حقيقي. بفك ضغطه، يتم الحصول على أرشيف CPIO، وهو تنسيق initrd القياسي لنظام لينكس ويمكن استخراجه بسهولة باستخدام cpio -idmv.