
تحليل المرحلة الثانية من تحدي Z2A-BlackLotus bootkit-rootkit
تحليل BlackLotus للمرحلة الثانية من bootkit-rootkit
قبل أن نخوض في هذا الأمر الإلهي(صدقني إنه شيء إلهي لا يمكن لأحد أن يفعله بدون مشيئة الله(على الأقل هذا رأيي في هذا الأمر))، إليك هاش ملف bootkit
أول الأشياء أولاً، هكذا يبدو النظام السليم
identifier {bootmgr} device partition=\Device\HarddiskVolume9 path \EFI\MICROSOFT\BOOT\BOOTMGFW.EFI description Windows Boot Manager locale en-US inherit {globalsettings} default {current} resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} displayorder {current} toolsdisplayorder {memdiag} timeout 30
``` So how do we set up a breakpoint in order to debug the bootkit? Well that's we we compiled the ovmf image as debug rather than release. If you specifically start qemu with that command you'll have qemu run and debug messages will be logged in a file called debug.log , which looks like this ```identifier {current} device partition=C: path \Windows\system32\winload.efi description Windows 10 locale en-US inherit {bootloadersettings} recoverysequence {3f80ecd2-df10-11ed-bafc-80a84b2564bb} displaymessageoverride Recovery recoveryenabled Yes isolatedcontext Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \Windows resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} nx OptIn bootmenupolicy Standard
الآن في تحليلي، لم أنجح أبدًا في إصابة جهازي، لذا سأستخدم المثال من منشور مدونة الباحث الآسيوي المُشار إليه سابقًا، وهذا هو الشكل الذي يفترض أن يبدو عليه الجهاز المُصاب```
// Windows Boot Manager
// --------------------
// identifier {9dea862c-5cdd-4e70-acc1-f32b344d4795}
// description Windows Boot Manager
// locale en-US
// inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
// bootdebug Yes
// displayorder {57e1b615-0355-11ec-abb0-005056c00008}
// timeout 30
// Windows Boot Loader
// -------------------
// identifier {57e1b615-0355-11ec-abb0-005056c00008}
// device boot
// path \system32\hvloader.efi
// description Hoy la disco se flota
// locale en-US
// inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
// truncatememory 0x10000000
// avoidlowmemory 0x1000
// nointegritychecks Yes
// testsigning Yes
// isolatedcontext Yes
// osdevice boot
// systemroot \
// ems Yes
=============================================================================
=============================================================================
قبل أن نبدأ، كيف يقوم المرء بإعداد البيئة لتحليل وحدة efi على أي حال؟ حسنًا، يعود الفضل إلى @MaverickMusic__ ، فقد أعطاني هذا الرابط أثناء نقاش معه( https://zhuanlan-zhihu-com.translate.goog/p/343293521?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-GB ). لم أتبع الخطوات هناك بالكامل، لذا إليك ما فعلته بالضبط ليكون لدينا بيئة جاهزة للعمل:
-أولاً قمت بتثبيت edk2(https://github.com/tianocore/tianocore.github.io/wiki/Windows-systems)
-ثانياً قمت بتكوين ovmf الخاص بي على وضع debug وليس release(سيساعدنا هذا لاحقاً). إليك الأمر build -a X64 -t VS2019 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc
-ثالثاً كان عليّ تكوين windbg الخاص بي. كيف بحق الجحيم فعلت هذا؟ قمت بتنزيل كل شيء من هذا الرابط(git clone https://github.com/microsoft/WinDbg-Samples). ثم قمت بتجميع ExdiGdbSrv.sln. ثم اتبعت كل شيء من هذا الرابط(https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-up-qemu-kernel-mode-debugging-using-exdi)، بدءاً من حيث ورد Use regsvr32 to register the DLL in an Administrator command prompt. وحتى PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files". أعلم أنه مُحيّر، لكن أرجو الانتظار بصبر لأنني سأقوم بالتأكيد بتسجيل فيديو سأشرح فيه كل خطوة! رائع، إذن الآن بعد أن أصبح لدينا بيئة جاهزة لتصحيح الأخطاء، كيف بحق الجحيم نقوم بتصحيح الكود؟ نبدأ بتشغيل qemu، وفي حالتي قمت بذلك من خلال تنفيذ qemu-system-x86_64.exe -L . -bios OVMF.fd -hdd dos.img -debugcon file:debug.log -global isa-debugcon.iobase=0x402 . بمجرد تشغيل أمر qemu ذهبت فوراً واخترت compat_monitor0 من قائمة view في qemu. يجب أن يبدو هكذا عندما تفعل ذلك.

أيضاً بعد تحديد هذا يجب عليك إدخال gdbserver لبدء نسخة بعيدة من تصحيح أخطاء gdb والتي سنتصل بها مع windbg باستخدام هذا الأمر .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64. رائع، بمجرد اتصالنا بها سيبدو هكذا
رائع! الآن لفهم هذه المخرجات، السطر الوحيد المهم في حالتنا هو EntryPoint=0x000062C9A8C وهو عنوان التحميل المفضَّل عندما نقوم بتشغيل أداة الإقلاع bootkit. تحديدًا بالنسبة لـ bootkit، يتراوح بين 0x62C4A8C أو 0x62C9A8C. الآن يمكننا إعادة تموضع البرنامج في IDA والقيام بعملنا المعتاد :) . استمتع ببقية المدونة!
=============================================================================
مقارنة BinDiff بين winload.efi الأصلي والملف الذي ألقاه BlackLotus
نرى بعض أوجه التشابه ولكن أيضًا بعض الاختلافات، لكن لا شيء مفيد، على أي حال....
=============================================================================
حسنًا، لنبدأ هذه الحفلة.
حسنًا، لنبدأ التشريح. أولًا نرى أن هناك دالة يتم استدعاؤها. حسنًا، ما قصتها؟
حسنًا، دالة أخرى. ليس تمامًا... هل لاحظت شيئًا مألوفًا؟

لا شيء بعد؟؟؟
لا مشكلة، ربما الآن
نفس دالة فك ترميز الأسماء! أهلاً أيها الصديق القديم :)))
حسنًا، لكن ماذا عن return (*(a1 + 88))(v2, &unk_62CEABC, 3i64); ؟ بصراحة، لا أعرف ماذا أقول من منظور ثابت فقط، لذا لنجرب استخدام المصحح لفهمها :))
إذن عندما نفك ترميز السلسلة النصية نحصل على
إذن بعد ذلك عندما نصل إلى تعليمة الاستدعاء
ولا نحصل على أي معلومات.... رائع، لكن لماذا؟ لأننا لا نملك ملف .pdb لنحصل على رموز تصحيح الأخطاء.... حسنًا، على الأقل IDA مفيد هنا. إذن نعرف أن الدالة «grand» تأخذ كمدخل SystemTable->RuntimeServices، وهو من نوع EFI_SYSTEM_TABLE. حسنًا، إذا فحصناها، فهذا A pointer to the EFI Runtime Services Table. . إذا بحثنا في جوجل نجد مجموعة من الوثائق، لكن الوثيقة المهمة هي https://uefi.org/sites/default/files/resources/UEFI\_Spec\_2\_1\_D.pdf . تقول هناك
حسنًا، إذن بنية تحتوي على مجموعة مؤشرات، نعم، لكن دعنا نقترب أكثر.
أولًا، يقوم بفك ترميز VbsPolicyDisable، وإذا بحثنا في جوجل نجد تحليل ESET الذي ينص that this variable is evaluated by the Windows OS loader during boot and if defined, the core VBS features, such as HVCI and Credential Guard will not be initialized. ، إذن أساسًا هذا المتغير مسؤول عن "الأمان" الحالي على مستوى الإقلاع. حسنًا، بعد ذلك لدينا الدالة التي تأخذ هذا المتغير و
وبذلك يمكننا الوصول إلى استنتاج أن هذه يجب أن تكون دالة تغيّر بطريقة ما حالة ذلك المتغير. حسنًا، ما بعض الدوال الممكنة التي قد تفعل ذلك؟ هناك دالة واحدة فقط من هذا القبيل في EFI_SYSTEM_TABLE وهي EFI_SET_VARIABLE SetVariable;
إذن نستنتج أن هذه الدالة ببساطة تأخذ VbsPolicyDisable وتضبطه على``` db 77h ; w .data:0000000180005034 db 59h ; Y .data:0000000180005035 db 3 .data:0000000180005036 db 32h ; 2 .data:0000000180005037 db 4Dh ; M .data:0000000180005038 db 0BDh ; ½ .data:0000000180005039 db 60h ; ` .data:000000018000503A db 28h ; ( .data:000000018000503B db 0F4h ; ô .data:000000018000503C db 0E7h ; ç .data:000000018000503D db 8Fh .data:000000018000503E db 78h ; x .data:000000018000503F db 4Bh ; K.
الآن، هل هناك أي شيء مهم في هذه البايتات؟ حسنًا، نعم. إذا صادف أنك قرأت الجزء الأول من تحليل blacklotus، فستعرف أنني أشرت إلى عمل باحث آسيوي. لقد كان ذلك الباحث لطيفًا بما يكفي ليحلل أيضًا الـ bootkit المُسقَط. يرجى الاطلاع عليه (https://www.cnblogs.com/DirWang/p/17294545.html#autoid-3-2-1). في تحليله، كان لطيفًا بما يكفي وأعطانا تلك المعلومة. يشيرنا إلى https://github.com/Mattiwatti/EfiGuard/blob/master/EfiGuardDxe/PatchWinload.c . هناك نرى سطرًا مشابهًا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/33c755aa460f5bdc338c75f3f5e1322c731123299d59c43dcdf2be3b72d1276c.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/144b057568871a60a32e477ed1ae7e8d7090778a67b7fc24222f0f58fe44afc1.png" alt=""><figcaption></figcaption></figure>
</div>
هل هناك سبب محدد وراء ذلك؟ بصراحة، لا أعرف؛ فهذه أول مرة أحلّل فيها bootkit. من فضلك أخبرني أو أنشئ pr/pull request لتعديل هذا المستند إذا كانت لديك خبرة أكثر مني :) في هذا المجال.
\=============================================================================
حسنًا، بعد ذلك، يحالفنا الحظ، إذ أن الكود الزائف من IDA مشابه للتجميع (assembly).
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/7457c9d8beb807556618728c7aba102109a472ef2f990f35ec344038fafc4cd5.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e11c4b4e4260f7a91e6dc08bcabb7c3ac420dcee346b1bf9dff02835342f7837.png" alt=""><figcaption></figcaption></figure>
</div>
إذن ما أعتقد أنه يحدث هنا هو تهيئة عادية لـ EFI\_SYSTEM\_TABLE، والتي أعتقد أنها تهيئ العملية التي يجب أن تستمر في عملية الإقلاع. ثم لدينا استدعاء الدالة PatchBootManager.
\=============================================================================
PatchBootManager
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/66c49bf5b64655af7e0edfe384ad715912c02fbeea1ac1313e4f65479ab58f80.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7a1dc3ac7c01cbd4cfd9b3ec614c357895210e4f03ae5d58000e6b047f84eb96.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/3fc22a51052c24c9e436ace83a1672ce88bf25fb11103b32d0143fa0ab4d7216.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/22c7869b067f26c6469e4baffcd4226535c47e82d4baaf7fa8e27820915b1580.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/38cf7697523141faa68a59b52abd2a1ca14d0d9053f1e6960052a5093e3a94bb.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/505a3fd02b96bcb823bf108ee03a8a1204827852260c1e8ce3902638237259b3.png" alt=""><figcaption></figcaption></figure>
</div>
ومن الكود الزائف:
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/9c8482f0faa4d4de5f8643acc4276ebbbfc57386e9b00a4057793b5c67b1bf3b.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c44de61b9f089fd8972bcc8567110bc2d58c21e5465a7b4f14fc7beaefee30a3.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/6809c28e881b3626d73a476cd31631891539f6a7b71cf276619f9cd2244d83e9.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c8cd4870cd0488e57cde3448ba01fdd44063f266516d8530731f42e6ccc5be78.png" alt=""><figcaption></figcaption></figure>
</div>
حسنًا، أول استدعاء دالة نراه هو HandleProtocol. إذن ماذا يفعل هذا الكود؟ لحسن الحظ، صادفنا هذا أثناء بحث سريع على جوجل (https://tianocore-docs.github.io/edk2-ModuleWriteGuide/draft/5\_uefi\_drivers/54\_communication\_between\_uefi\_drivers.html) ونرى أنه `يسترجع البروتوكولات`. رائع، لا يوجد شيء يمكنني فهمه حقًا. نعم، فهمتك يا صديقي. إذن هذا ببساطة يسترجع معلومات وطرق الاتصال التي تستخدمها برامج تشغيل UEFI الأخرى. حسنًا، مع مزيد من البحث، نرى أن المعامل الثاني هو
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/703c3f52bd8c3d10eaf046fc801cbc60ca7a62e9162d67a6ba63caf4c9e9038d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/9d41aacaed9c15391beb8b1b62739572bf7f873508938ade770610eec371a17c.png" alt=""><figcaption></figcaption></figure>
</div>
إذا بحثنا عن تلك البايتات المحددة، نصادف هذا:
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f4a8ed3b81486c8481c0f8894175f9d7390ddf62f9974ba025aad9827dea119e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/882b5116cfd08886c3dac510443fb77c9aa31781eb234208ec81fdf313544c29.png" alt=""><figcaption></figcaption></figure>
</div>
إذن، ما الذي يفعله EFI\_LOADED\_IMAGE\_PROTOCOL\_GUID بحق الجحيم؟ نقتبس من (https://uefi.org/specs/UEFI/2.10/09\_Protocols\_EFI\_Loaded\_Image.html) `يمكن استخدامه على أي مقبض صورة (image handle) للحصول على معلومات حول الصورة المُحمّلة.`، وما نوع المعلومات؟ \`\`\`يحدد هذا القسم EFI\_LOADED\_IMAGE\_PROTOCOL و EFI\_LOADED\_IMAGE\_DEVICE\_PATH\_PROTOCOL. على التوالي، يصف هذان البروتوكولان صورة تم تحميلها في الذاكرة ويحددان مسار الجهاز المستخدم عند تحميل صورة PE/COFF عبر خدمة الإقلاع EFI Boot Service LoadImage(). تتضمن هذه الأوصاف المصدر الذي تم تحميل الصورة منه، والموقع الحالي للصورة في الذاكرة، ونوع الذاكرة المخصصة للصورة، والمعاملات التي تم تمريرها إلى الصورة عند استدعائها.\`\`\`\`
إذن في حالتنا، يلتقط معلومات حول الـ bootkit. الآن هناك مشكلة: لا يمكننا حقًا فحص نتيجة الدالة لأنه لا توجد لدينا رموز تصحيح (debug symbols) :/ لكن يمكننا التخمين. وأميل إلى افتراض أن البنية (نتيجة استدعاء الدالة السابق) ستكون في rbx.
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f744ecd9fd4be572a1e2d191b06231559eca2b32aeaa981a399eec7f3ee710.png" alt=""><figcaption></figcaption></figure>
بعد ذلك نستدعي تفكيك السلسلة (demangle string).
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1fdc75d2dc9221250e6d46692770ad5240f7a0d6cda9cc5634749b327fc8c146.png" alt=""><figcaption></figcaption></figure>
وهو ما يعطينا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e073b265ff13675b755ec8413554bec74ab4eae57dd002b25694632eb43cbc8e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3654bb54071386cd020c43ed4a35fae40aec386897a0ca26a27b58b8e1a91c95.png" alt=""><figcaption></figcaption></figure>
</div>
ثم نستدعي
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c433aa63cddd2ecfb5ce0fd57a6774ad35b1c1ed4ee71e7cecb566cc861d2b80.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6834be566cdd81f2410ec7d4ee97936d14a27017a723371eea3046b8590609f4.png" alt=""><figcaption></figcaption></figure>
</div>
\=============================================================================
sub\_180002B14
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/483f2b789c0fa6fe9378ba324f8e349bc72cbb45e540bbc2355ef55acaf1b6b4.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d84d79115facbc0f9ff7afe06d70a18555e7d94bc196f6f9d0ff6b5cfd40408a.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/19e2366fddab99fa3aa4375b8306475ee31d3bf9a3c3737efeeb4d627868404e.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6c808c76821c756eca776cf6290482f6f9829167f539bf31b2ad82b3de0af829.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/ad0d06238e39e4ba1decb2f1305510a8375822b13ae9148d91e267d14762eb3b.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0e45e9ae64c3fbd8a61ffdf60ec2e532529d8cab6cfc7786fa2c91824233d347.png" alt=""><figcaption></figcaption></figure>
</div>
والكود الزائف:
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c14b1eacbe8eef4155c4148b66fa95f93bbd9e6fc81e5ca80f1ddc5b2b9a7a16.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b7c452865661d95b79886a48a455eba663c2e3915e0a81ad16dc7ddd8c2c0189.png" alt=""><figcaption></figcaption></figure>
</div>
حسنًا، حتى جملة if كل شيء واضح بذاته. الآن ماذا عن if؟ نرى مرة أخرى أنه يقوم باستدعاء مع unk\_180005010 كمعاملات، وهي عبارة عن مصفوفة بايتات أيضًا، وبالفحص الدقيق تبدو هكذا
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c3bb66f35a4e559ae793ba590fc0c342bdde1e1c9765e144cb450a809009655d.png" alt=""><figcaption></figcaption></figure>
الآن إذا فحصنا البايتات الأولى مرة أخرى وقمنا ببحث سريع، نصل إلى هذا (https://github.com/theopolis/uefi-firmware-parser/blob/master/uefi\_firmware/guids/efiguids\_ami.py)، وبشكل أكثر دقة هذا `'EFI_DEVICE_PATH_PROTOCOL_GUID': [0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b]`.
إذا عدنا إلى صفحة مواصفات UEFI، نرى أن `يمكن استخدامه على أي مقبض جهاز للحصول على معلومات عامة حول المسار/الموقع المتعلقة بالجهاز الفعلي أو المنطقي.`. رائع، ونرى أيضًا شيئًا مثل `مسار الجهاز يصف موقع الجهاز الذي يكون المقبض مخصصًا له`. حسنًا، وإذا مررنا قليلًا، نرى دالة تسمى \_EFI\_DEVICE\_PATH\_PROTOCOL. حسنًا، للخلاصة، نعلم أن هذا له علاقة بـ EFI\_DEVICE\_PATH\_PROTOCOL\_GUID، لكن الدالة التي لدينا من نوع EFI\_BOOT\_SERVICES. فهل توجد أي دالة في EFI\_BOOT\_SERVICES يمكنها القيام بشيء مثل التعامل مع بروتوكول؟ نعم، توجد. إذا فحصنا https://www.intel.com/content/dam/doc/product-specification/efi-v1-10-specification.pdf القسم 4.4، نرى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/918a0a5184849cbb87454df44c5ffa5e5fa586f223213287f6c7fbe737a0fbc8.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/fab94604327fe596d9eeb68368efcf0afc721ef7bfcdc07a8977392b4309238c.png" alt=""><figcaption></figcaption></figure>
</div>
بتعبير أدق، تحتوي على دالة نعرفها (HandleProtocol). حسنًا
بعد ذلك نرى استدعاء دالة آخر غير معروف لنا هذه المرة. لنرَ ما المعاملات التي يأخذها. إنه يأخذ 2، ثم طول السلسلة الممررة بصيغة Unicode، ومؤشرًا إلى متغير.
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/39e0d1d9baabff8d95da7109294db94f9fc4409a6ede34d37ece9662fb73651d.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e116e90f20a09d48f21a981e7d24c49f7474ea9ac6007b6fa41973300af4e83d.png" alt=""><figcaption></figcaption></figure>
</div>
الآن إذا فحصنا هذا في مصحح أخطاء (debugger)
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f412c3bf83f60da9213f4c29b39350c925a0aa6411c42de52d7fa4530c5bc3fe.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5285bf4d5e52dbbef857e46e8738c3ba6e7f6cda87f9b67a4965b23cc70aba0e.png" alt=""><figcaption></figcaption></figure>
</div>
نرى شيئًا غريبًا: rcx يحتوي على سلسلة تصحيح أخطاء هي AllocatePool، وهذا يأتي بعد استدعاء دالة، لذا نستنتج أن هذا كان على الأرجح استدعاءً لـ AllocatePool. المضحك أنك إذا فحصت المواصفات أيضًا، سترى أن boot\_services يحتوي أيضًا على مؤشر إلى AllocatePool، مما يزيد افتراضنا قوة.
حسنًا، فإذا تمكنا من تخصيص مساحة كافية (الفحص `if >= 0` هو للتحقق مما إذا نجحنا في التخصيص، لأنه إذا كانت EFI\_OUT\_OF\_RESOURCES مُنفَّذة كـ
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/bf08cd5dd33ad9ca16ff4e6a44a4cbfd51cd1f8b0300d9b6b44984c4306fcb6e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c28af9995294473937be13a6094de90cb57a688c83727617ca9f667c2705d7cd.png" alt=""><figcaption></figcaption></figure>
</div>
فمن الآمن فقط أن نفترض
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/3741ef8be2dc989f601d26568907381f1847d29c0bf514add76485b0f0fef4b6.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/cdfc6ccb296659fc8156d4bfba6d777da8b2792e4af56677d0f0d57695932216.png" alt=""><figcaption></figcaption></figure>
</div>
يُستخدم للإشارة إلى نجاح التخصيص)
إحدى الحقائق المثيرة للاهتمام هي أن المخزن المؤقت بعد تخصيصه ليس صفرًا، بل يحتوي على هذه البايتات. إذا كان أي شخص يعرف المزيد عن هذا، فيرجى إنشاء طلب pr لتعديل هذا المستند.
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e4b15da615e07faa4965d864435bf4deec0e01270f9d1ac1134fb5b20ad46892.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b229a700b321040fc8978f4f0f489a058381795c128d27dbcfbcfff5f9ffd3b2.png" alt=""><figcaption></figcaption></figure>
</div>
إذن نعم، على أي حال ننتهي باستدعاء memcpy، وبعد الاستدعاء يصبح المخزن المؤقت هكذا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/28e61d8725687245e9a9dae7e467929ac15d5a81e33178262f0ce886a3c4555c.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/f161ab0441b14d71dbade9fc3acebbd12b1453de5d53b77b09af98c0cf0ac6d6.png" alt=""><figcaption></figcaption></figure>
</div>
ثم نضيف بعض البايتات لجعل المخزن المؤقت يبدو هكذا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/80906384a49ef1d6eaea9667cb962459c27feb8e9deac857491a248be5443a4f.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c703952c72c154d156603c457a00013305c48519ddee808925c32a62499135f.png" alt=""><figcaption></figcaption></figure>
</div>
ثم نستدعي دالة تسمى FileDevicePath\_call والتي تبدو تقريبًا هكذا 
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/66c77ae12715ee6d982ba2cfb769ba6a650f52ce56d7bae54e3bd93686695f02.png" alt=""><figcaption></figcaption></figure>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5f7e06800ec3eecb9559d1592b8a76868038c0cbb64744e5c928b65d189ef183.png" alt=""><figcaption></figcaption></figure>
وتتحول إلى هذا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2b36492bb7dd46a7139c27de61371b59adac5bfbec989bbb542b58d34ce7982d.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/361e2b338c676b99393f7baa48e970ba886894f579065a4468fe113841c0783b.png" alt=""><figcaption></figcaption></figure>
</div>
حسنًا، لكن هذا لا معنى له ما لم يُشرَح، لذا....
أولًا، لدينا تطبيق مخصص لـ strlen ولن نقوم بتشريحه لأنه عديم الفائدة :) لكن هذه هي النتيجة
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/03a0aabe9f7c87f42b7e64bb284d74738ecdc81134136cfec68c70084644c3ea.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/823c30bd0a6a8c1d750ef1dfb0bce5be67a13a96de12e53b3e46b2226a1c2be1.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5dd4684c37f3129c8234cd69574bb6371b4bef72ff7e027199b7900134cdd101.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/118ee749874a6b08d40286821735190f67af45ca8d4573fc94aee3a2cea04af2.png" alt=""><figcaption></figcaption></figure>
</div>
32 حرفًا من len(of(str)+"\x00" ثم آخر 4 بايتات أُضيفت قبل استدعاء الدالة 0x4FF7F
بعد ذلك نستدعي ما استخدمته أيضًا من تدوينة الباحث الآسيوي: PxepDevicePathInstanceCount، وهي ببساطة strlen، لأنها ببساطة تعد كل حرف ولديها عداد. كما نرى هنا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/130931a6676f0519da2b50a9762955b7581e7102434e587236137b216cc62ead.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ce1a6ad93452a8092d2fb71ffd6418df78c32fc8cdf4fb99133924cc9037f12e.png" alt=""><figcaption></figcaption></figure>
</div>
إذن نعم، نرى pop rbx وبعد الاستدعاء نرى rbx=0x48
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4c2eabdd91ec40fc82c100e67579d729def9e74c6bfd000fff287bc9c10b0f38.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/818bb3c8398d4a53c0260d9310d4d192cfa5b65a404348df5516c94fa3d8dcaa.png" alt=""><figcaption></figcaption></figure>
</div>
ثم نستدعي strlen مرة أخرى على نفس السلسلة. أعتقد أن هذا فقط لأنه في السطر التالي تحديدًا، `v6 + v4 * v5;` نقوم بـ v4\*v5، وهو على ما أعتقد طريقة ما للتعامل مع سلاسل Unicode، كما أعتقد.
على أي حال، ثم نخصص ذاكرة مرة أخرى باستخدام gEfiBootServices + 64 الذي صادفناه سابقًا، والذي تحل إلى AllocatePool.
وهنا نرى أيضًا شيئًا جميلًا، وهو
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/26d19e06bd335f1267946a5da2542cf3eb9f2965fab788d0bcf720d7e3c08d37.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/225c92cbe9a5e72214cb279e61ad5fcbaef0a243db835b67fce5ff7ef74e7c86.png" alt=""><figcaption></figcaption></figure>
</div>
حقيقة أن كتلة الذاكرة هنا تحتوي على النمط afafafaf فيها.
إذن ما يحدث بعد ذلك هو أننا نحصل على مخزنين مؤقتين يبدوان هكذا بعد تنفيذ الحلقة الرئيسية
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/35f257d96c752ac436e81778da5f37c28bfcb79fc5614f3ea8e099888cc011c3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b9c706cc28161a6e7274c5cabc895bedc1279728b3ed7c11084cb6cb38dbf9e3.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/52477a3825650e47112a5e619a098c74e7e0de778ebfeda5682e5b49d48f3923.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/762a6dd3897f3b630ce1d0faa371e58ed9b2bce755bb8edd54f958aab7c3b69b.png" alt=""><figcaption></figcaption></figure>
</div>
وبصراحة، نحن مهتمون فقط بالمخزن الأول لأنه ما يتم إرجاعه، لذا يمكننا أن نستنتج أنه ببساطة، كما أعتقد، ينسخ مسار الجهاز وينظف بعض البيانات العشوائية من المخزن المؤقت. :))
الآن بعد أن ننتهي من هذا، نتحقق مما إذا كان مسار الجهاز في حالتنا قد تمت تهيئته بالفعل على ما أعتقد، ونحرر الذاكرة إذا لم يكن كذلك، وإلا نعيد المخزن الأنظف من الدالة المذكورة سابقًا.
قبل أن ننتهي من هذه الدالة، أود أن أشير إلى حقيقة مثيرة أخرى: هكذا يبدو جدول خدمات الإقلاع (boot service table) في الذاكرة :) يبدو وفقًا للمواصفات بالترويسة الابتدائية. ظننت فقط أنه قد يكون من المثير للاهتمام تركه هنا لأي شخص يريد عمل تطوير إضافي ويجد نفسه يعثر على هذه السلسلة BOOTSERVF في تفريغ ذاكرة (dump)، فهذه بالتأكيد جدول خدمات الإقلاع.
\=============================================================================
حسنًا، إذن ماذا يحدث بعد ذلك؟؟؟ نتحقق مما إذا تمكنا من تحديد موقع ملف winload.efi وقمنا بتحميله في الذاكرة. هذا هو الكود الزائف :)
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/b59f211cb997e5ad783cbb6421833c23bea4ef4f7f21743577cd8aba4656ad2f.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a96f7410f6bd6f7e207b76dff36a411f3c17a3f40dcb1a9433d5292b46f775e2.png" alt=""><figcaption></figcaption></figure>
</div>
وهكذا يبدو في الذاكرة
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e3ee7b08fdc84433a08e60c7065c74692fb3a4e26eb81def063b662aa5229558.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/445d40332ba97516eebf129d17c56a38e28688858515d787ebf90a99580daa51.png" alt=""><figcaption></figcaption></figure>
</div>
ما هو rax؟ rax هو مقبض (handle) للصورة :) لا تكن غبيًا مثلي عندما اعتقدت أول مرة أنه منطقة ذاكرة :)
حسنًا، قبل أن نتعمق أكثر، دعني أشرح بسرعة ما هو winload.efi. إذن، `مع تطور أجهزة الكمبيوتر، أصبح إقلاع BIOS التقليدي قديمًا، وبدأت المواجهة الأمنية حول إقلاع UEFI. من المخطط الانسيابي أدناه، يمكننا أن نرى أن MBR و VBR لم يعودا موجودين في UEFI، بل إن UEFI نفسه مسؤول عن تحميل bootmgr، وهو ما يعني أيضًا أكثر أمانًا وأسرع`
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/d2443977ce3d56790e424fd6236d1d0594db283caa9357ed4e6abb9b8b30b8ed.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1259e1f45b2d2bb8edcb12609e057d089f7c1dcf907677973d799049c58bee4a.png" alt=""><figcaption></figcaption></figure>
</div>
إذن كيف يُقلِع جهاز كمبيوتر يعمل بنظام Windows بشكل طبيعي؟ بعد BDS، يكمل كود برنامج UEFI الثابت المخزن في SPI عمله، ثم يقوم مدير إقلاع برنامج UEFI الثابت أولاً بالاستعلام عن متغير UEFI في NVRAM للعثور على ESP، ويعثر على مدير الإقلاع الخاص بنظام التشغيل bootmgfw.efi لاستدعاء دالة الدخول الخاصة به (برنامج تشغيل DXE).
ستستدعي هذه الدالة أولاً الدالة EfiInitCreateInputParametersEx، والتي تُستخدم أساسًا لتحويل معامل EfiEntry إلى تنسيق المعامل المتوقع بواسطة bootmgfw.efi.
ثم يتم استدعاء دالة نقطة الدخول لمدير إقلاع Windows وهي BmMain.
في هذه الدالة، يتم استدعاء BmFwInitializeBootDirectoryPath لتهيئة مسار تطبيق بدء التشغيل (BootDirectory) (\EFI\Microsoft\Boot).
ثم سيقرأ BootMgr بيانات تكوين إقلاع النظام (BCD)، وإذا كانت هناك خيارات إقلاع متعددة، فسيستدعي BmDisplayGetBootMenuStatus لعرض قائمة الإقلاع.
ثم سيستدعي الدالة BmpLaunchBootEntry لبدء التطبيق (winload.efi).
بالطبع، bootmgfw.efi يفعل أكثر من ذلك، بما في ذلك التحقق من سياسة الإقلاع وسلامة الكود وتهيئة مكونات الإقلاع الآمن (Secure Boot)، لذا لن أخوض في التفاصيل.
في المرحلة الأخيرة من مدير إقلاع Windows (BootMgr)، ستحدد الدالة BmpLaunchBootEntry إدخال الإقلاع الصحيح وفقًا لقيمة BCD السابقة. إذا كان تشفير وحدة التخزين الكامل (BitLocker) مفعّلاً، فسيتم فك تشفير قسم النظام أولاً، ومن ثم يمكن نقل التحكم إلى winload.efi.
بعد ذلك، يتم استدعاء الدالة BmTransferExecution، ويتم فحص خيارات بدء التشغيل، ويتم تمرير تدفق التنفيذ إلى الدالة BlImgStartBootApplication.
ثم ستستدعي الدالة BlImgStartBootApplication الدالة ImgFwStartBootApplication، وأخيراً الدالة ImgArchStartBootApplication. داخلها، سيتم تهيئة وضع حماية الذاكرة لـ winload.efi، ثم يتم استدعاء الدالة BlpArchTransferTo64BitApplication، والتي تستدعي الدالة Archpx64TransferTo64BitApplicationAsm وتسلّم التحكم أخيرًا إلى winload.efi.
ستقوم هذه الدالة بتمكين GDT و IDT الجديدين، ثم تسلّم التحكم بالكامل إلى winload.efi. عند هذه النقطة، يُكمل BootMgr مهمته ويبدأ Winload في العمل. - نهاية الاقتباسات المسروقة من موقع صيني يتحدث عن هذا (يرجى مراجعة هذا للمزيد من المحتوى https://bbs.kanxue.com/thread-268267.htm )ومن هناك، يقوم winload.efi بعمله، وهو تحميل Windows والقيام ببعض أعمال العتاد الإضافية قبل أن يسلم التحكم إلى النواة.
الآن بعد هذا الإيجاز، وكما كنا نقول
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/65537ae888c278e8e487029f93d909fb1e4699069699cf1b7d5ad8fa1f9e0d69.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3b00c68a215f4568fca5d672ea6f892fecf9809e671c68795c067d2660fa3f1f.png" alt=""><figcaption></figcaption></figure>
</div>
نواصل التحقق لمعرفة ما إذا كان تحميله في الذاكرة قد نجح، ثم نستدعي دالة اسمها ati\_analysis\_rdtsc\_aia\_cu\_4e1f، التي ينبغي أن تكون مألوفة لك إذا كنت قد قرأت الجزء الأول من هذا التحليل.
الآن من باب المتعة، لنفترض أننا فشلنا في تحليل تلك الدالة وتم اكتشافنا. دعونا نرى كيف تبدو sub\_180002A08.
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4eb3ae379ab937e19e6a699339d992b2a5fd1fcb33202ca67355f62a5b1203b4.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a4b252df16a31b5bf165d2a500ebe3c54ad5dad3c58cf9fe88a8a1da11ed6b63.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/dd594955a663274e25603804c348b516ca22755886b2732ef81dc8e1e0177544.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6fba01328584e8abb254912b81b048e8dcf80bda6d3eadc11573a52a5e84dd15.png" alt=""><figcaption></figcaption></figure>
</div>
نرى مرة أخرى gEfiSystemTable + 64 الذي لا نعرفه في الواقع هذه المرة لأنه من نوع مختلف؛ ليس من نوع bootservices هذه المرة بل من نوع efisystemtable، ثم memcpy ثم ثلاث استدعاءات دوال أخرى لا نعرفها. الآن إذا شغّلنا حتى تبدأ الحلقة
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/20e0db7308860023b613310ea14e0880529a588540d9dabac2218b52dc93cefb.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f498165a4016c19d8d5797517680fc32dea241d343b38fcc613620270d58dd.png" alt=""><figcaption></figcaption></figure>
</div>
وإذا فحصنا المعاملات السابقة لـ memcpy
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/21f546fbfb10a39e0e603186c8c505a3ae0679e8c7bad40f31643022f9ebfbcd.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/2ef8c97938b8f961abf92c03937ca15d5a48cd03eb58a0169891559fad27dde5.png" alt=""><figcaption></figcaption></figure>
</div>
وفحصنا صورة الإخراج الخاصة بـ qemu نحصل على
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e4325617bfda31fb45f7920d0d1d977103fd6b85260e590fc7cfdca1efacb787.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/04e29142b4cf543a6e5b8f55de2c27d1f3f0034707a6d19e2b1ea45b8251e899.png" alt=""><figcaption></figcaption></figure>
</div>
رائع، إذن دعونا نفهم بعضًا من هذا. سأشير مجددًا إلى منشور المدونة البحثية للآسيوي لأنني بصراحة تائه هنا
إذن هو يقول في مدونته إن الدالتين كانتا في الواقع```
ConOut->ClearScreen(ConOut);
ConOut->OutputString(ConOut, String);
حسنًا، لكن ما هو conOut بحق الجحيم؟ حسنًا، يقول أيضًا أن conout من نوع EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL وأنه يتم الحصول عليه عبر ConOut = gEfiSystemTable->ConOut;. حسنًا، ما معنى هذا في الكود؟
حسنًا، لنتعمق أكثر
التعريف
والـ GUID
الآن، أنا الذكي نسيت أن ألتقط هذا فعليًا في مصحح أخطاء، لأنني عندما حللت هذا لأول مرة خلطت بين نوع البيانات efisystemtable و bootservices وظننت أن هذا هو allocatepool في الواقع.
الآن، ماذا تفعل هذه الدوال؟
حسنًا، من المفترض أن يكون ClearScreen واضحًا بذاته، وكذلك OutputString. كيف توصّل الباحث إلى أن هذا المتغير من نوع EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL؟ على الأرجح أنه رأى بايتات الـ GUID في المصحح.
الآن، ماذا عن الدالة الأخيرة؟
حسنًا، في مقالته يقول إن الدالة الأخيرة هي gEfiBootServices->Stall؟ إذن ما الذي تفعله بحق الجحيم؟. من مواصفات UEFI: The Stall() function stalls execution on the processor for at least the requested number of microseconds. Execution of the processor is not yielded for the duration of the stall.
إذن هي في الأساس تجعل معالجنا يتجمد. رائع، لكم من الوقت؟ 0x1C9C380 ثانية. وقت طويل جدًا برأيي. وهي أيضًا موضوعة داخل حلقة لا نهائية، لذا نعم نحن في ورطة :)))
وهكذا يبدو هذا في مصحح الأخطاء
الآن نتابع مع الدالة الرئيسية لدينا
إذا نجحنا في تحميل bootmgfrw.efi (لأن winload.efi هنا هو محمّل الإقلاع الفعلي لويندوز) فإننا نستدعي sub_180002538
============================================================================= sub_180002538
من منظور الرسم البياني
من منظور لغة التجميع
هل بدأ شيء يبدو مألوفًا؟ لا؟ حسنًا، أعطها دقيقة وسيتضح الأمر، وفي هذه الأثناء ألقِ نظرة على منظور الكود الزائف
نرى بعض التحليل لملف exe :) الآن لا أعرف كم سيكون مطابقًا لما في الجزء السابق (الجزء الأول)، لكن لنرَ :)
إذن نقارن نسختنا في الذاكرة من الملف الثنائي (bootmgfrw.efi) مع ترويسة MZ الكلاسيكية (0x5A4D)، كما ترى
حسنًا، بعد ذلك نُجري فحصًا كلاسيكيًا آخر وهو ما إذا كان يمكننا العثور على ترويسة PE
رائع، بعد ذلك نستدعي sub_1800024C4() والتي تبدو هكذا
رائع، ما يحدث هنا هو أننا نحدد مواقع قيم معينة في الذاكرة، وإذا وجدناها نعيدها. يُرجى الرجوع إلى sub_180002538.py.py من أجل المحاكاة.
على أي حال، إليك sub_180002464
إذا نجحنا في تنفيذ sub_1800024C4 فإننا نعود إلى الدالة الأكبر ونتابع بعض الفحوصات الإضافية. حسنًا، لنفهم هذه الأمور
رائع، إذن نقارن أيضًا ما هو موجود في rax+0xe مع 0x64، همم، مثير للاهتمام، لنفحص rax+0xe
هل هناك سبب خاص وراء هذا الفحص تحديدًا؟ بصراحة لا أعرف؟ ربما. إذا كنت تعرف، فيرجى إنشاء pull request وتعديل هذا المستند.
نقوم ببعض الإضافات ثم مقارنة
أريد أن أتوقف هنا لدقيقة وأشير مجددًا إلى المصدر السابق الذي ألهم هذا المقال كلما ضللت الطريق. في مدونته، أعاد تسمية الدالة التي تقارن القيم إلى RtlpImageDirectoryEntryToDataEx، والتي إذا بحثنا عنها لا نجد أي نتائج، لكن هناك شيئًا قريبًا بما يكفي من تسميته وهو RtlImageDirectoryEntryToData، والذي يقوم أساسًا بهذا: Given the base address of a kernel module and the index of an entry in the data directory, RtlImageDirectoryEntryToData() returns the virtual address and the size of the directory entry(https://codemachine.com/articles/top\_ten\_kernel\_apis.html). في حالتنا، وبما أننا داخل تطبيق efi/uefi، يمكننا اعتبار أن القيمة 50 التي نراها هي حجم البايتات/الميجابايت هنا لقسم الجذر في هذه الحالة، وأن ذلك العنوان الموجود في rax هو أحد مدخلات دليلنا.
قبل أن نتابع أكثر، هناك تفصيل مثير للاهتمام آخر يجب شرحه. في بحثه، يحوّل مخرجات RtlImageDirectoryEntryToData إلى هذه البنية``` typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { union { struct { DWORD NameOffset : 31; DWORD NameIsString : 1; }; DWORD Name; WORD Id; }; union { DWORD OffsetToData; struct { DWORD OffsetToDirectory : 31; DWORD DataIsDirectory : 1; }; }; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
الآن، ما هذا بحق الجحيم في هذه البنية؟
حسنًا، إجراء بحث سريع حول تلك البنية يقودنا إلى هنا(http://www.brokenthorn.com/Resources/OSDevPE.html) وهو ما يخبرنا أن `تحليل الموارد أكثر تعقيدًا بعض الشيء من أنواع الدليل الأخرى. وكبقية الأقسام، هناك بنية أساسية IMAGE_RESOURCE_DIRECTORY يمكن الحصول عليها من عضو DataDirectory في الرأس الاختياري: وهكذا دواليك` وأيضًا أن \`\`\`لا تحتوي هذه البنية على الكثير من الحقول المثيرة للاهتمام، باستثناء الحقول الثلاثة الأخيرة.
إذا كنت قد تعاملت مع موارد Win32، فربما تعلم أن الموارد يمكن تحديدها بالمعرف (ID) أو بالاسم. سيتيح لنا عضوان في هذه البنية معرفة عدد هذه الإدخالات، والإجمالي (NumberOfNamedEntries + NumberOfIdEntries)، وهو مفيد في التكرار عبر جميع الإدخالات. كما يمكنك أن تخمن على الأرجح، الإدخالات موجودة في مصفوفة DirectoryEntries. وتتكون DirectoryEntries من مصفوفة من بنى IMAGE\_RESOURCE\_DIRECTORY\_ENTRY، والتي تتبع التنسيق:\`\`\`
إذن بشكل أساسي، هذا الشيء يُستخدم داخليًا لتحليل الأشياء داخليًا، وبالنسبة لنا له معنى في سياق أننا نعمل مع دليل يحتوي على موارد، رائع.
المزيد من فضلك!
إذن التالي
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/137d3d2aebf0db9501f550b09baddf01c3e50bf703ca8d13386a7185a567f19a.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/045c3a8a2bab306f516cdc7e9a59954e3c1ff16efe4189273c50f54b9e84f3e6.png" alt=""><figcaption></figcaption></figure>
</div>
ما يفعله هذا هو في الأساس التكرار على كل مورد من الدليل والتحقق مما إذا كان من نوع string
بصراحة، لا أعرف لماذا قد يفعل ذلك، لذا إذا كنت مخطئًا فآسف، وإذا لم أكن كذلك فتحياتي!
التالي
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/a57c5815ee8b5498fed6d8dde92f48b9fc2bdfd2d4f4e231796ba96e5e28bea9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/bd4513fdf1f8f165fc404b8462d6bc36644de4937e42d560d54f1a5f1c0e8799.png" alt=""><figcaption></figcaption></figure>
</div>
إذن ما يحدث هنا هو أننا نضيف بعض الإزاحات ونصل إلى ما يقوله الباحث الصيني إنه جدول الموارد الثاني، كما ترى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/8f6655fb8117abf8a4d38b5173d51e4bc3ce67b86803c57cce36d47b73cd1e76.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ebdf5a9a749f2cb1b7a656be5f2d99419edfc9cd2a737e15c6845f2c008e3f11.png" alt=""><figcaption></figcaption></figure>
</div>
ثم نكرر نفس العملية للحصول على بعض الإزاحات
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/faa12c96d0b22e6128ef1cdf14110c31cc9ebca89325f28a07fc6a0a064daeba.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/216539eaf48a407a7f691d10cca06679a545471c3e54f25fedb31c38f0c61a66.png" alt=""><figcaption></figcaption></figure>
</div>
ونكرر نفس العملية، وهذه المرة نتحقق من النوع VS\_VERSION\_INFO
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/ac2d2e82085f4ddbc3f5ae1ce35528dd8420924b0298c65db056d0837c3e4b6d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/23788c642b82988c14654e9dac2afd2504cd22846be0487efce96cae4d6fe094.png" alt=""><figcaption></figcaption></figure>
</div>
إذن ما هو VS\_VERSION\_INFO بحق الجحيم؟ حسنًا، تقول مايكروسوفت(https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource) إنه `يعرّف مورد معلومات الإصدار`، وأعتقد أنه ببساطة يحدد إصدار bootmgfrw.ef
وأخيرًا إذا وجدنا VS\_VERSION\_INFO نكرر نفس الخوارزمية
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4f00ecf2c2c9b32b2d25fcbf3c62e9bb45679df1390a085371f5166a70d67933.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/facd25069491b5d7826500e4f2c04cafe213191075012ddb4c1fa9a8bc97c4c5.png" alt=""><figcaption></figcaption></figure>
</div>
هذه المرة مع لمسة، واللمسة هي أننا نُرجع معرّف البناء (build id) :) كما نرى
إذن كخلاصة، ما الذي حدث هنا بحق الجحيم؟ حسنًا، استنادًا إلى الاسم الذي استخدمه الباحث الصيني(GetPeFileVersionInfo\_BuildNumber\_) يمكننا أن نستنتج أننا في الواقع نحصل على رقم البناء الخاص بـ bootload كما يمكن رؤيته من الصورة الأولى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/b28007dda110fc31d53233931ff077ac42fc81146d803b91999069e204020a4d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d19f1311c2ee242ced63da8334db384929ada3acae147009becc0dbf34d2b7fb.png" alt=""><figcaption></figcaption></figure>
</div>
حيث نرى هنا bootload مُحمَّلًا في الذاكرة
في الصورة الثانية نرى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2000f17c51ccc65267b46ac2c1d191bd033b3bc6e6b655973423dbbd8a1fc77e.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c47fe45fe4b422618a400f2c26c28cd33fea9416f2b24086a2c852d08f1614b.png" alt=""><figcaption></figcaption></figure>
</div>
عددًا صحيحًا في rcx يمكن أن يكون إما رقم البناء أو pefileversion
وفي الصورة الثالثة
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/41729b1d4a4701480d64f058f421cd2ad8a8b9b871bf17675fd7b537cec3dd85.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d2b17725eeb9af2336d725be9c556565fba221fd2a3517912c942f411f9ed33b.png" alt=""><figcaption></figcaption></figure>
</div>
ما يمكننا تخمينه أنه رقم البناء حيث سيتم نقل ebx إلى rax :)
كملاحظة أخيرة حول هذه الدالة، يا للهول، هندسة مذهلة
\=============================================================================
الآن إلى التحدي التالي :) استنادًا إلى مخرجات المرحلة السابقة، إما أن نضبط v10 على sub\_180001D80 أو sub\_180001D48، كما نرى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/33581031e03f29b5997d46b708c467bfd49ce58625e99381dd28c109cadae7d3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6647119081cffb664dcca365392271398b2572ee04c24a0456141f33cbaaeecf.png" alt=""><figcaption></figcaption></figure>
</div>
وفي حالتنا v10=sub\_180001D80
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2af043a1449f6bf10e2925f06697438716976d24a1539a61ab42c4301c4a8435.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0769d4dff6e1da51acaf9c5bac3a9a9b4b446aae9d7c593e7e54d865ec13c2ea.png" alt=""><figcaption></figcaption></figure>
</div>
\=============================================================================
ثم نقوم بعمل strcmp بين مدير الإقلاع bootloade ومصفوفة البايتات تلك
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/59164794afc69304133f0a4c008b9e4755671e8d57bd8dc4ea5a2b2e6ae54164.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/03b00f7c18ff7db73dfd5253f02d6966955e38732fa7d1cfb4840366c17355a1.png" alt=""><figcaption></figcaption></figure>
</div>
أريد أن أتوقف هنا لفترة قصيرة، كما قد تكون خمنت، رأيت شيئًا مثيرًا للاهتمام في تدوينة الباحث الصيني. لقد أطلق على مصفوفة البايتات اسم SigImgArchStartBootApplication. إذن ما هو SigImgArchStartBootApplication بحق الجحيم، ولمن ينتمي، ولماذا بحق الجحيم تسمى تلك المصفوفة بهذا الاسم (migos)؟ إذا بحثنا على جوجل (gulugulu) عن SigImgArchStartBootApplication فلن نحصل على شيء. والآن نظرًا للسياق الحالي، نستخدم مدير إقلاع ويندوز، لنفتحه في IDA. نذهب إلى C:\Windows\Boot\EFI، ونفتح الملف في ida ونبحث عن SigImgArchStartBootApplication، لا شيء. نبحث عن ImgArchStartBootApplication فتقابلنا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/1ad42d5236e8ca4da08688fe3d4c72e6b3de01fdce633a1bdaa870de421cdc40.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d6e211aa12b37dfba0244d48516a08703248484c070f8d7ffcf0a28f08e8a833.png" alt=""><figcaption></figcaption></figure>
</div>
إذن ImgArchStartBootApplication .... ماذا يفعل الكلب...!؟ حسنًا، أمم... سأسرق هذا من `@_xeroxz`(تابعه، ما الذي تفعله إذا كنت لا تتابع أعماله؟) إذن بشكل أساسي في مقال له يقول إن `bootmgfw.ImgArchStartBootApplication بين إصدارات ويندوز 2004-1709 يُستدعى لبدء winload.efi` كما نرى أيضًا من صورته(https://guidedhacking.com/threads/hyper-v-hacking-framework-works-on-every-version-of-windows-10-2004-1511-amd-intel.16251/)
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt="1603213912596">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt=""><figcaption></figcaption></figure>
</div>
إذا لم يكن ذلك واضحًا بما فيه الكفاية في مقال() نرى أن `ImgArchStartBootApplication تلتقط اللحظة التي يتم فيها تحميل محمل نظام التشغيل ويندوز (winload.efi) في الذاكرة ولكن لم يتم تنفيذه بعد`(https://rustrepo.com/repo/rusty-bootkit--uefi-bootkit-in-rust)
رائع، إذن ما علاقة strcmp بـ ImgArchStartBootApplication؟ حسنًا، دعنا نلقي نظرة أقرب على ida وسنكشف قريبًا عن الإجابة، إذا بحثنا في كود محمل الإقلاع عن البايتات 41 b8 09 فسنصادف قريبًا الجاني
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/91050c01f95eb88488cbc575c21af7f453228eeb13c665b94d415eecf5682a55.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7239d85f2dc9e220a2eab80f79b5db9705285a17c074f85958c041d122bfaf8e.png" alt=""><figcaption></figcaption></figure>
</div>
وفي حال طابقت بايتات الصورة في الذاكرة الخاصة بـ bootloade مع توقيع البايتات، ننفذ sub\_180002398
وبالتأكيد كما نرى، حددنا النمط، وحصلنا في eax على منطقة الذاكرة حيث توجد البايتات، ثم نتابع بأمان لتشغيل sub\_180002398
\=============================================================================
sub\_180002398
"منظور التجميع"
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5aa624d92161499019e7ce6597bf46853c59ba89d37fec483a8ac7ee168ddbeb.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/afbf940a1eb535d73dce744606cc63c568c2b447c9cf85034c422a8e900859f4.png" alt=""><figcaption></figcaption></figure>
</div>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6468513a220946bbccfab53328c056a620755e1fe94ad3e36d8c8958ed777794.png" alt=""><figcaption></figcaption></figure>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c5c36e7c29f1cdea6f42d55d7605ad3c2044d66397c867c221da6c0bf74f8d6a.png" alt=""><figcaption></figcaption></figure>
"منظور الكود الزائف"
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5b1d8a264dad55f34a0cc958a2f4a26014a31987af5b66754e754589ea085097.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1d3db7165e0f71a3fa76862ba8afb3869f821f59db6fc5a5c5e99d5002ecfba1.png" alt=""><figcaption></figcaption></figure>
</div>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ae65504884fa2881cb50af2f88e846a0ad029c9431ee6296b28993de8f2e4a0d.png" alt=""><figcaption></figcaption></figure>
إذن ماذا يفعل الكلب؟ بصراحة، يقوم ببعض الحسابات وبعض الإضافات والطرح ولا شيء مهم حقًا؟ لماذا؟ لأنه ليس مثيرًا للاهتمام. ما يهمنا هو ما يحدث بعد أن نعود من الدالة. نرى rax
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4eae862955421b2b1629c120bb09970714cf085e9255590d6cfa36a77bbc69e9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/43917bf46096449ad92172baa282fd3e70ec0bec67fec2bbf2a276285d878b52.png" alt=""><figcaption></figcaption></figure>
</div>
حسنًا، رائع، ما زلت لا أفهم. حسنًا، rax = 0x5eec108 والذي يشير إلى 0x48c48b48، حسنًا وماذا؟ لقد كنت مرتبكًا مثلك تمامًا، لذلك عدت مرة أخرى إلى المدونة الصينية. إذن ما يصفه ذلك الباحث أنه يحدث هنا هو هذا: يعود إلى بداية دالة ImgArchStartBootApplication. لكن كيف بحق الجحيم توصّل إلى هذا؟ حسنًا، كما ذكرنا سابقًا rax =\
0x48c48b48 وإذا فحصنا ملف booloadermnfr.efi نرى
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2dbe283fa0b0dd9cf837e79f1f42eaeb6dcd61252e76979c0a4af3cf2f68e8d8.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/624e1927cac5a0011d6fabea0f2ce4740b8dfd14102509656d6e5c0395a9c08d.png" alt=""><figcaption></figcaption></figure>
</div>
وهو بالضبط نفس تسلسل البايتات في 0x5eec108. حسنًا، هذا رائع :)
يُرجى الرجوع إلى sub\_180002398.py لرؤية محاولتي الفاشلة لمحاكاة هذا السلوك :)
\=============================================================================
رائع، ما التالي؟
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/432ad1832fa35743bc5676f7f8362ad9e2043e17387121136a1f6dfe1bdf16f1.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/aab798c5c80621b1c367ea6eecfff0d7caf9ecc368ae2fe2e947538e4f0e2b0c.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f04ebd9c650ddadb5553e4f2c43c72af8a5ccbef372a4dbdc811600e9583b0c9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3411e1620450739ea98f6db634346748487377106547324591b148cefe358df2.png" alt=""><figcaption></figcaption></figure>
</div>
إذن ما يحدث بعد ذلك هو RaiseTPL. حسنًا، ماذا يفعل هذا؟ يرفع أولوية المهمة المنفذة حاليًا ويعيد مستوى الأولوية السابق. في حالتنا سيتم تشغيله بأعلى صلاحيات تنفيذ.
بعد ذلك نستدعي ما أسميته patch\_something والذي يبدو هكذا
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/0a31b0c154406b340e9bb044c4211afd6494bcac6ec197c99a10a6d0effb6a31.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3fcff1b34a5d9af3cdd70e4dac1188abd3edd13e74d11e4f0bba5d667d4f53a1.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c2f9bb8ca36961def04d4a3111a7d4213bb219949d13094b525a1a906ab788f7.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/accdd93e3428b9b03132eafceda3ec5e1cfda742a978f1cd7f2c6bcf1904ceaa.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e0f6c806d296e47269b9908ceab7b90954bbd219d3d9c13462ebee8344f854f3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1ed164077989d04273ae3b40ec6daf7cf9b93ec42d917533b1e9758525231b7b.png" alt=""><figcaption></figcaption></figure>
</div>
إذن من التحليل الساكن يمكننا أن نرى أن هذا ما يُعرف بالربط (hooking). :) إذن بشكل أساسي، يقوم بتصحيح بايتات ImgArchStartBootApplication لتوجيهها إلى sub\_180001D80 ويحفظ الدالة الأصلية لـ ImgArchStartBootApplication في byte\_180015C78
وكما نرى، يتغير إلى sub\_180001D80 بالضبط
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/6c48bf4c9126a9a1466493aed943113cc27b4bbf9f7d68cdd251d0e14303ad8a.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/633d84a62c16dba91229fe6bb73ed0318719fc06f63f7f2a9d19adba0d0e8cfe.png" alt=""><figcaption></figcaption></figure>
</div>
بعد ذلك نعيد تعيين الصلاحيات ومن هناك نسلم التحكم إلى boomgrfw.efi :)
إذن هذا يمثل رسميًا إنجاز النصف الأول من التحليل :) في الجزء التالي سنتعلم كيفية مواصلة تصحيح أخطاء sub\_180001D80 وboomgrfw.efi (في حالتنا winload.efi). لذا يرجى الجلوس بهدوء حتى أتعلم كيفية تجهيز البيئة للجزء الثاني من التحليل
\=============================================================================
الآن بالنسبة للنصف الثاني من التحليل.... كيف نقوم بتصحيح أخطاء boomgrfw.efi؟