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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
BYOVD-DriverKiller — هندسة عكسية واستغلال برامج التشغيل | Kitploit
أدوات/GitHubGitHub/alex3o/byovd-driverkiller
الاستغلالالهندسة العكسيةما بعد الاستغلالتحليل الملفات الثنائيةالتعلم والتعليمالفريق الأحمر
GitHubalex3o/byovd-driverkiller

BYOVD-DriverKiller

هندسة عكسية واستغلال برامج التشغيل

عرض المستودع
831428منذ سنة واحدةتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

BYOVD-DriverKiller

⚠️ تحذير: هذا المشروع تعليمي واستعراضي بشكل صارم. ليس موجّهًا للاستخدام في سياق خبيث. الهدف هو تعلّم منهجية الهندسة العكسية وخطوات استغلال درايفر في نظام ويندوز.


أشرح هنا المنهجية التي اتبعتها لحل التمرين المقترح من طرف d1rk(SaadAhla) https://github.com/SaadAhla، والذي يتمثل في إجراء هندسة عكسية واستغلال على درايفر شرعي وموقّع وغير موجود في قوائم الحظر (HVCI، LOLBIN...). يتوفّر برنامج بلغة C يسمح بإنهاء أي عملية نشطة على النظام عبر هذا الدرايفر الخاص بوضع النواة، وسأفصّل طريقة عمله بعد قليل.

POC-BYOD

📃 الاستخدام: DriverKiller.exe <nom_processus.exe> [-d]

الخيار -d: يسمح بحذف الخدمة والدرايفر من النظام بعد الاستغلال.

يجب تفعيل وضع توقيع الاختبار (testsigning mode) على الجهاز الهدف لأن شهادة الدرايفر منتهية الصلاحية.


الجزء 1 - الهندسة العكسية:

يوفّر التمرين ملفًا بامتداد .sys، مُسمّى بهاش SHA-256 الخاص به. تتمثل الخطوة الأولى في فتح هذا الملف باستخدام IDA.
IDA متاح مجانًا. يكفي الذهاب إلى موقع Hex-Rays لإنشاء ترخيص وتنزيل البرنامج.

نبدأ بسرد جدول عناوين الاستيراد (IAT) الخاص بالدرايفر والبحث عن استدعاء API الذي يهمّنا: ZwTerminateProcess.

screen1-git

عند النقر المزدوج على ZwTerminateProcess، يقوم IDA بإعادة توجيهنا إلى الكود المترجم لهذه الدالة. وباختيار المدخل ثم عرض المراجع المتقاطعة (cross-references)، نحصل على قائمة بدوال الدرايفر التي تستدعيها.

screen2-git

نلاحظ أن الدالة sub_12EF4، عند الإزاحة 1CE، هي التي تستخدم ZwTerminateProcess. بعد النقر المزدوج، يعرض IDA كودها المترجم.

screen11-git

يكشف الكود المُفكَّك عن استدعاءات ZwOpenProcess (الذي يفتح مقبضًا للعملية الهدف) وZwTerminateProcess (الذي ينهي العملية عبر هذا المقبض).

من خلال الاطلاع على توثيق ZwOpenProcess (https://learn.microsoft.com/fr-fr/windows-hardware/drivers/ddi/ntddk/nf-ntddk-zwopenprocess)، نلاحظ أن المعامل ClientID يشير إلى مؤشر يحدد PID العملية المستهدفة.

في السطر أعلاه، تتم تهيئة ClientId.UniqueProcess بالمتغير v22. هذا الأخير يُعرَّف مباشرةً بالأعلى:

v22 = (void )((_QWORD *)i + 10);

لفهم هذا الإسناد، يجب تحديد المتغير i والحقل +10.

screen3-git

أعلى هذه الدالة، نلاحظ استدعاءً لـ ZwQuerySystemInformation مع المعامل SYSTEM_PROCESS_INFORMATION. نفهم أيضًا أن i هو عداد التكرار على مداخل هذه البنية مع المتغير v6.

وفقًا لتوثيق ZwQuerySystemInformation: (https://learn.microsoft.com/en-us/windows/win32/sysinfo/zwquerysysteminformation)، تُرجع هذه الدالة مصفوفة تحتوي على مدخل لكل عملية نشطة على النظام.

البنية SYSTEM_PROCESS_INFORMATION موصوفة هنا: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    BYTE Reserved1[48];
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    PVOID Reserved2;
    ULONG HandleCount;
    ULONG SessionId;
    PVOID Reserved3;
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG Reserved4;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    PVOID Reserved5;
    SIZE_T QuotaPagedPoolUsage;
    PVOID Reserved6;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION;

تذكير: أحجام بعض الأنواع في ويندوز x64

  • ULONG = 4 بايت
  • USHORT = 2 بايت
  • HANDLE = 8 بايت
  • PWSTR = 8 بايت
  • KPRIORITY (typedef من LONG) = 4 بايت
  • UNICODE_STRING = 16 بايت لأن بنيتها كالتالي:
  typedef struct _UNICODE_STRING {
    USHORT Length;        -> 2      
    USHORT MaximumLength; -> + 2 = 4
    PWSTR  Buffer;        -> + 8 = 12 (12 n'est pas un multiple de 8 donc padding de 4 ajouté en amont de Buffer) = 16
} UNICODE_STRING;

حساب إزاحة UniqueProcessId:

    ULONG NextEntryOffset;        -> 4
    ULONG NumberOfThreads;        -> + 4 = 8
    BYTE Reserved1[48];           -> + 48 = 56
    UNICODE_STRING ImageName;     -> + 16 = 72
    KPRIORITY BasePriority;       -> + 4 = 76 (76 n'est pas un multiple de 8 donc padding de 4 ajouté) = 80
    HANDLE UniqueProcessId;       -> + 8 = 88

إذن العضو UniqueProcessId يقع عند الإزاحة 0x50 (80 بالنظام العشري).

بالنظر إلى إسناد متغيرنا v22، نجد أن i يُحوَّل إلى مؤشر من نوع QWORD (8 بايت)

v22 = (void )((_QWORD *)i + 10);
إذن v22 يقابل عنوان i + 10 * 8 = 80 بايت. هذا المتغير يحتوي بالفعل على PID المسترجَع من بنية SYSTEM_PROCESS_INFORMATION.

لمعرفة أي PID سيتم تمريره إلى ZwTerminateProcess، يجب تحليل الشرط المحيط بهذا الإسناد.

screen4-git

نلاحظ أنه يتم أولاً استرجاع اسم صورة العملية:

v9 = (wchar_t )((_QWORD *)i + 8);
لأن v9 = عنوان i + 8 × 8 = 64 بايت. وهذا يقابل الحقل Buffer للعضو ImageName، حيث يقع هذا العضو عند الإزاحة 56 + 2 (USHORT) + 2 (USHORT) + 4 (padding) = 64

بناءً على المعالجات والحلقات البرمجية أدناه، يمكننا افتراض أنه تتم مقارنة بين اسم العملية المُمرَّر كوسيط (a2) والعمليات النشطة على النظام v9/String.

sub_1C078(String, v9, (int)v13);
v17 = strupr(a2);
v18 = strupr(String);

إذن، من المفترض أن يحتوي الوسيط a2 على اسم العملية التي سيتم إنهاؤها عبر ZwTerminateProcess. نلاحظ أن a2 هو معامل للدالة sub_12EF4. للمضي قدمًا، يجب فحص مراجع هذه الدالة (أعدت تسميتها إلى ZwTerminateProcessCaller من أجل قراءة أوضح).

screen5-git

نلاحظ أن الدالة ZwTerminateProcessCaller تُستدعى بواسطة الدالة sub_13624 عند الإزاحة 61A.

screen6-git

قبل تحليل هذا الكود المُفكَّك، سأبحث عن مراجع الدالة sub_13624 (أعدت تسميتها إلى ZwTerminateProcessCallerCaller) للتأكد من أن هذا الكود يُستخدم فعلًا بعد استدعاء API لـ DeviceIoControl من وضع المستخدم (UserMode).

screen§-git

نلاحظ أن ZwTerminateProcessCallerCaller تُستدعى بواسطة الدالة sub_14130 (أعدت تسميتها إلى ZwTerminateProcessCallerCallerCaller ...ولحسن حظنا، إنها الأخيرة قبل نقطة الدخول 😅).

تنزيل الأداة