Windows Driver (Part 1)

Introduction to Windows Drivers

ال Drivers هي عبارة عن برامج تعمل كوسيط بين نظام التشغيل والاجهزة المتصلة. عند تركيب hardware جديد على الجهاز مثل GPU نظام التشغيل يبحث عادةً عن Drivers المناسب ويثبتها تلقائيًا. يتم تشغيل Drivers في Kernel Mode وهذا يسمح لها الحصول على تحكم كامل على الجهاز.

User Mode & Kernel Mode

Environment Configuration

قامت Microsoft بتقديم policy جديدة بأسم Driver Signing لنظام Windows 10 والأصدارات الحديثة للمحافظة على نظام التشغيل من البرامج الخبيثة. هذه ال Policy تجبر الشركات على توقيع (Sign) ال drivers الخاصة بهم لكي تتمكن من العمل في Kernel Mode. يمكن تحويل النظام الى Test Mode لتخطي Policy. شغل CMD بصلاحيات Administrator ونفذ الأوامر التالية لتفعيل Test Mode و Kernel Debugging:

circle-info

The last command will generate a key, which we will use in WinDBG, make sure to save it, and do not reboot until your WinDBG is ready

شغل WinDBG في الجهاز الثاني ودخل Port Number و Key في File > Kernel Debug > NET

WinDBG setup

أذا سويت restart للجهاز الأول رح تشوف شي مشابه للصورة هذه:

WinDBG Kernel Debugging
circle-info

You can load Symbols by adding this in "File" -> "Symbol File Path": SRV*C:\symcache*http://msdl.microsoft.com/download/symbols Then run the .reload command

Creating Our First Driver

نعرف Prototype او ال Parameters الي ياخذهم DriverEntry:

circle-info

DriverEntry is similar to the main function in C

طالما نقدر نسوي debug لل driver عن طريق WinDBG نقدر نطبع رسالة عن طريق ()DbgPrint :

من اهم الأشياء الي لازم تصير اذا رح نسوي unload لل driver هو free our resources عشان ما يكون في اي Memory leaks. رح نسوي function يسوي هذه العملية لنا بس اول شي خلونا نحجز مكان في Memory:

اذا صارت عملية unload ال DriverUnload رح ينادي DriverFree function ومحتواها بسيط فقط بتسوي

:free the allocated memory

لازم ننشئ service حتى نقدر نشغل ال Driver:

اول ما يشتغل ال Driver وتوقفه رح تقدر تشوف كل شي في WinDBG:

IRP Major Function Codes

ال IRP هو اختصار ل I/O Request Packet كل IRP يكون فيها MajorFunction code (IRP_MJ_XXX) والي تساعد driver يعرف ايش العملية لتلبية طلب I/O Request. كل Driver لازم يوفر dispatch routines لل Major Function الي يدعمها هذه بعض ال Major Function:

Major function codes

رح نستخدم IRP_MJ_CREATE و IRP_MJ_CLOSE حتى نقدر نفتح و نغلق ال Device:

كل Driver لازم يكون له Device Object و Symlink حتى نقدر نتواصل مع Driver من ال User Mode. نقدر نسوي هذه العملية عن طريق IoCreateDevice و IoCreateSymbolicLink :

رح نستخدم IOCTLsarrow-up-right عشان يقدر ال client يحدد اي function ال driver رح يستخدم. تقدر في نفس project تنشئ header file عشان نعرف IOCTL. واجهة عدة مشاكل في تعريفهم لكن هذه articlearrow-up-right ساعدتني.

ننشئ function جديد وضيفته يستخرج ال IOCTL من Client:

رح نستخدم IRP_MJ_DEVICE_CONTROL الي رح يتحكم في I/O control requests :

ال Client Code رح يكون بسيط, كل الي رح نسويه هو فتح handle لل Driver عن طريق CreateFilearrow-up-right. وبعدها رح نستخدم DeviceIoControlarrow-up-right والي رح ينادي IRP_MJ_DEVICE_CONTROL:

Executing Client Code
WinDBG POV

Send and Receive Data

اخر حاجة رح اشرحها هو كيف نقدر نرسل بيانات ونستلمها من ال Driver وطبعاً هذا كله يتم من خلال DeviceIoControlarrow-up-right . في البداية رح نسوي two structures واحد خاص بال Client Input والثاني بال Results/Response:

الان رح نخلي ال Driver يستلم البيانات و يرجعها لل Client. أضفت checks عشان نتفادى BSOD:

طيب من ناحية ال Client Code رح نستخدم نفس ال header file لأن فيه ال Structure الي نحتاجه. بس الي علينا اننا نعرف متغير فيه البيانات الي رح ترسل ومتغير يستلم الأجابة:

Final results

References

Last updated

Was this helpful?