GamingMasteR

Kernel-mode Programming #2

23 ردود في هذا الموضوع

السلام عليكم ورحمة الله وبركاته

في هذا الدرس سنتعلم كيف نكتب driver بسيط جداً لا يقوم بشئ تقريباً ، أعتقد أن المتابع حصل على الأدوات التي تم الإشارة إليها في الدرس السابق وهي حزمة الـddk و DbgView و محرر كود .

بعد تنصيب الـDDK ستجد انه يوجد له قائمة في Start->Programs تحت اسم Development Kits ، ما يهمنا هو الملف التالي وهو سطر الأوامر الذي سنعمل منه :

Build Environments -> Windows XP -> Windows XP Free Build Environment

قم بعمل shortcut للملف المذكور في مكان سهل الوصول إليه .

لعمل driver بسيط عن طريق سطر الأوامر هذا لابد من توافر ثلاث أشياء أساسية و هي :

1- makefile : وهو ملف يقوم بعمل إعادة توجيه لملف الـmake file الحقيقي الآتي مع حزمة الـDDK ، يحتوي هذا الملف على هذا السطر فقط :

!INCLUDE $(NTMAKEENV)\makefile.def

لا تقم بتغيير محتوى هذا الملف .

2- sources : وهو الملف المسئول عن عناصر المشروع الأساسية مثل الملفات التي سيتم ترجمتها و ونوع الملف الناتج و اسمه واي خيارات اخرى للمشروع :

TARGETNAME = test_driver هنا نعرف اسم الملف الناتج بأنه "test_driver" .

TARGETTYPE = DRIVER نصرح بان الملف الناتج هو عبارة عن Driver وليس Exe او Dll .

INCLUDES=..\..\inc لتحديد مجلد الـIncludes الخاص بالـDDK .

SOURCES = driver.c هنا نقوم بوضع ملفات السورس التي سيتم ترجمتها بحيث يفصل بين كل ملف وآخر مسافة " " .

حسنا الآن سنقوم بشرح الكود الخاص بالدرايفر ، الدرايفر لا يقوم بفعل أي شئ ، فقط يتم تحميله فيقوم بإرسال جملة للـDebug output لنعرف انه تم تحميله ، أيضا سيتم طباعة جملة أخرى أثناء عمل Unload للدرايفر .

كما نعرف لابد من نقطة بداية للدرايفر لأنه يعتبر PE File ، في برامج الـConsole كنا نعرف نقطة البداية باسم main وفي برامج الـGUI نعرفها باسم WinMain بينما في المكتبات DLL يتم تعريفها باسم DllEntryPoint او DllMain ، في الدرايفرات نعرفها باسم DriverEntry وهو بالشكل التالي :

NTSTATUS 
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);

DriverObject : مؤشر الى DRIVER_OBJECT وهو structure يمثل اي درايفر في النظام و تركيبه كالتالي :

typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
PFAST_IO_DISPATCH FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT, *PDRIVER_OBJECT;

العناصر المهمة :

DeviceObject : وهي مؤشر إلى سلسلة الـdevices التي ترتبط بهذا الدرايفر ، سنتعرف المزيد عنها لاحقاً .

DriverStart : عنوان لـDriverEntry الخاص بالدرايفر .

DriverSize : حجم الدرايفر بعد تحميله في الذاكرة الخاصة بالكرنل .

DriverSection : هذا العنصر غير مصرح به من قبل مايكروسوفت لكنه مهم جداً وسنتكلم عنه أكثر عند الحديث عن طرق جرد الدرايفرز .

DriverName : هو structure يحتوي على اسم الدرايفر ، تركيب الـstructure كالتالي :

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

حيث Buffer تشير إلى النص كـunicode وليس ansi ، ولتكن قاعدة لديك ان كل تعاملنا مع روتينات النظام نستخدم فيها دائما نصوص Unicode ، لاحظ أيضا أن النص ليس بالضرورة Null-Terminated أي انه لابد من الاستعانة بالطول Length أثناء التعامل مع النص كي لا نقع في مشاكل خطيرة .

DriverUnload : وهو عنوان للدالة التي سيتم استدعاؤها أثناء عمل Unload للدرايفر ، لاحظ انك اذا لم يتم بوضع هذا العنصر فانك لن تتمكن من عمل Unload للدرايفر إلى ان تقوم بعمل reset للنظام .

MajorFunction : مصفوفة من عناوين للـdispatch routines الخاصة بالدرايفر وهي مهمة جدا وسنقوم بتفصيل المهم منها عند الحديث عن الـIRP Handling .

RegistryPath : وهو مؤشر الى UNICODE_STRING يحتوي على اسم مفتاح الرجستري الخاص بالدرايفر ، لاحظ أن أي درايفر يتم تحميله لابد من وجود مفتاح رجستري خاص به و يكون عادة تحت هذا المسار :

\Registry\Machine\System\CurrentControlSet\Services\Xxx

حيث Xxx هو اسم الدرايفر .

DriverEntry لابد أن نقوم فيها بإرجاع NTSTATUS تحدد فشل العملية من نجاحها ، في Win32 API كنا دائما نجد ان معظم الدوال تقوم بإرجاع إما true للدلالة على نجاح العملية او false للدلالة على فشلها ، في Kernel-mode لا يتم التعامل بهذا الشكل ولكن عن طريق الـNTSTATUS والتي تسمح لنا بعدد كبير من النواتج لدقة أفضل ، ويمكن تقسيم الـNTSTATUS إلى مجموعتين أساسيتين :

SUCCESS : وتأخذ القيم الموجبة من 0 الى 0x7FFFFFFF .

ERROR : وتأخذ القيم السالبة من 0xC0000000 الى 0xFFFFFFFF .

يمكنك الإطلاع على قيم NTSTATUS في ملف ntstatus.h الموجود بالـDDK .

في DriverEntry إذا قمنا بإرجاع قيمة تدل على ERROR فانه سيتم عمل Unload تلقائيا للدرايفر ، في حالتنا سنقوم بإرجاع قيمة STATUS_SUCCESS لتدل على نجاح العملية .

اذن الكود الخاص بالـDriverEntry سيكون بالشكل التالي :

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPathName
)
{
DbgPrint("Test Driver :: DriverEntry");
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
};

في الكود السابق الدالة DbgPrint تقوم بعمل format للنص (اعتبرها كـprintf) ثم إرساله إلى الـDebug output والذي يمكننا مراقبته عن طريق DbgView ، قمنا أيضا بتحديد الدالة Unload ليتم استدعائها أثناء عمل Unloading للدرايفر .

الدالة Unload تأخذ دائما الشكل التالي :

VOID 
Unload(
IN PDRIVER_OBJECT DriverObject
);

حيث DriverObject هو مؤشر للدرايفر الذي سيتم عمل Unload له وهو نفسه الذي يتم تمريره في DriverEntry ، اذن دالة Unload الخاصة بنا تكون بالشكل التالي :

VOID
Unload(
IN PDRIVER_OBJECT DriverObject
)
{
DbgPrint("Test Driver :: Unload");
};

حسنا هكذا انتهينا من شرح الكود ، نأتي الآن لعملية الترجمة :)

في حالتي هذه فإن المشروع موجود في المجلد C:\driver ، قم بفتح سطر الاوامر الخاص بالـddk :

Start->Programs->Development Kit->Windows DDK->Build Environments->Windows XP->Windows XP Free Build Environment

انتقل إلى مجلد المشروع ثم أعطي الأمر build ، ستجد في المجلد الناتج ملفات الـobject/sys/pdb .

post-101943-1234666200_thumb.jpg

لتحميل الدرايفر يلزمنا loader ، طبعا في البرامج الحقيقية سنقوم بكتابة الـloader بأنفسنا لكن في حالتنا هذه وللتسهيل يمكن الاستعانة بأي لودر عام مثل الخاص بـOSR (ستجده بالمرفقات) ، قم بتشغيل الـLoader ثم اختر ملف الدرايفر test_driver.sys واترك الباقي كما هو ، هناك خطوتين لتحميل الدرايفر وخطوتين لإنهائه ، قم أولا بتشغيل DbgView كي نلتقط الـDebug Output ثم :

1- Register Service : هذه العملية لا تقوم بتحميل الدرايفر ولكنها تضع المفاتيح اللازمة لبدأ الدرايفر في الرجستري + إعلام الـService Manager به .

2- Start Service : هنا نقوم فعليا بتحميل الدرايفر وبالتالي يتم استدعاء DriverEntry و ظهور رسالة الـDebug Output في DbgView كما اتفق.

3- Stop Service : هنا يتم عمل Unload للدرايفر واستدعاء الدالة Unload وظهور الرسالة الخاصة بها أيضا في DbgView أيضاً.

4- Unregister Service : يتم هنا إزالة القيم الخاصة بالدرايفر من الرجستري والـService Manager .

post-101943-1234666309_thumb.jpg

في الدرس القادم سنتعلم بعض المفاهيم المهمة قبل أن نتمكن من التعمق في الموضوع !

الأحد 15/2/2009

GamingMasteR / AT4RE

References :

Microsoft Developer Network

Kernel_mode_programming__2_Files.rar

تم تعديل بواسطه GamingMasteR
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اوى كده يا معلم

(i mean teacher )

والله عندما بدات القراءة عن الدرايفر سرت على نفس خطواتك باين ان هناك توارد افكار درس رائع انتظر الدرس التالى على احر من الجمر

ولى سؤال ما معنى جرد الدرايفر ثم اننى اذكر ان DRIVER_OBJECT in MSDN is obaque structure how did you find its members

تم تعديل بواسطه do_not_forget2008
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

لى سؤال اخر معلش اصلى ضعيف فى السى DriverObject->DriverUnload = Unload;

هذا السطر هو pointer to function that takes pointer to driver object and return NTSTATUS and we could write like this

DriverObject->DriverUnload =& Unload;

as we assgin the address to the pointer

فى دالة الغاء تحميل الدرايفر من الذاكرة هى عبارة عن مؤشر الى دالة التى تاخذ مؤشر من نوع درايفر اوبجيكت وترجع متغير من نوع LONG

اى اننى استطيع وضع علامة اند لكى اخصص عنوان الدالة التى يتم استدعائها وقت استدعاء نظام التشغيل دالة الغاء التحميل من الذاكرة اظن ان هذا نوع من callback function

اذا لم تخنى الذاكرة

متاسف لطول الاسئلة ولكنى اريد ان اتعلم :resentful:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

A driver object is partially opaque. Driver writers must know about certain members of a driver object to initialize a driver and to unload it if the driver is unloadable.

بالنسبة للجزء الثاني من الاستفسار فالمترجم يعتبر التعبيرين في هذه الحالة واحد .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

فالمترجم يعتبر التعبيرين في هذه الحالة واحد<br /><br />لم افهم معنى العبارة

ثم يا اخى لم تجب عن سؤال جرد الدرايفر

تم تعديل بواسطه do_not_forget2008
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

DriverObject->DriverUnload = Unload;
DriverObject->DriverUnload = &Unload;

جرد == Enumerate .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

فين بقية الاعضاء؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟ :blush:

تم تعديل بواسطه do_not_forget2008
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اخى GM متى ياتى الدرس القادم ؟؟؟؟ :clapping:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الأسبوع القادم ان شاء الله .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
الأسبوع القادم ان شاء الله .

بالانتظار اخي.

GM ممكن تعيد رفع الملفات؟

تم تعديل بواسطه الاخير زمانه
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

صراحة الموضوع جذبني , (مع أني لم افهم 60 % منه) و لكني إن شاء الله من المتابعين للموضوع.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بعد السلام عليكم وتحية لكل اعضاء المنتدى الكرام وتحية خاصة لGM صاحب هذه السلسلة الجميلة اخى الدرس تـأخر هذه المرة وانا بجد محتاج الجرعة والا سوف يضعونى فى مستشفى الامراض العقلية وفى ايدى كتاب عن الDrivers وبقول GM GM Gm :wacko: :blink:وديت الدرايفر وين يا جى ام ما رأيك اخى الفاضل فى ان نناقش Kernel Modules على التوازى هنا او فى منتدى اللينكس هذه مجرد فكرة

تم تعديل بواسطه do_not_forget2008
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ممكن اعرف ماذا تعنى ب فيبى درايفر؟؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

Visual Basic 6 Driver !!!!

:) يعني صارت الring4 تسوي درايفرات :D

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

هو اساسا فى حاجة اسمها ring 4 يا ولد عيب كده :evil:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

أنا أسمي الفيجول بيسك ring4 لإنها تسبب لي مشاكل لا يعلمها إلا ربك :D

ومن ناحية برمجية , الring4 أظنه يطلق على برامج ال.Net وframework آخر لا أذكر إسمه ,

ولكن تبقى عندي الفيجول محدودة :P يعني رنج داخل رنج :D

منتظرين الأستاذ GM :) الله يقويه ويجعل وقته وعمله في ميزان حسناته , دمتم بود ,

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

يبدو ان الاخ GM لم يجد ما يريده من المتابعين لدروسه فتركنا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم

الدرس جميل جدا اخي GM فهمت منه 70 %

ارجو ان تكمل هده السلسلة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

درس رائع يا GM وبانتظار البقية..

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

نريد البقية اخي GM جازاك الله خيرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم

اشكر الاخ العزيز gm على هذا الشرح الجميل

وللمزيد من الشرح عن برمجة برامج قيادة الاجهزة احبائي في الله عليكم بزيارة هذه السلسلة التعريفية البسيطة واليكم الروابط :

المقدمة 1

http://www.codeproje.../driverdev.aspx

الجزء 2

http://www.codeproje...driverdev2.aspx

الجزء 3

http://www.codeproje...driverdev3.aspx

الجزء 4

http://www.codeproje...verdev4asp.aspx

الجزء 5

http://www.codeproje...verdev5asp.aspx

الجزء 6

http://www.codeproje...verdev6asp.aspx

والسلام عليكم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .