برمجة - شبكات - كمبيوتر - منتديات الفريق العربي للبرمجة: Kernel-mode Programming #2 - برمجة - شبكات - كمبيوتر - منتديات الفريق العربي للبرمجة

اقفز إلى الموضوع

  • (3 صفحات) +
  • 1
  • 2
  • 3
  • لا تستطيع بدء موضوع جديد
  • لا تستطيع الرد على هذا الموضوع

Kernel-mode Programming #2

#1 العضو غير متواجد حاليا   GamingMasteR 

  • مشرف قسم الأسمبلي سابقاً
  • PipPipPipPip
  • المجموعة: اعضاء
  • المشاركات: 1545
  • الإلتحاق: 14-February 07
  • الجنس:ذكر
  • الوسام

  • الدولة :

السمعة: 49
جيد

أيقونة المشاركة  تمت المشاركة 15 February 2009 - 05:54 AM


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


في هذا الدرس سنتعلم كيف نكتب 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 .


صورة مرفقة


لتحميل الدرايفر يلزمنا 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 .

صورة مرفقة



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

الأحد 15/2/2009
GamingMasteR / AT4RE



References :
Microsoft Developer Network

الملفات المرفقة


تم تعديل هذه المشاركة بواسطة GamingMasteR: 15 February 2009 - 07:03 PM

0



#2 العضو غير متواجد حاليا   do_not_forget2008 

  • عضو
  • PipPip
  • المجموعة: اعضاء
  • المشاركات: 121
  • الإلتحاق: 21-May 08
  • الدولة:Kuwait for now but Egypt Forever
  • الدولة :

السمعة: 0
عادي

أيقونة المشاركة  تمت المشاركة 15 February 2009 - 07:16 AM

اوى كده يا معلم
(i mean teacher )
والله عندما بدات القراءة عن الدرايفر سرت على نفس خطواتك باين ان هناك توارد افكار درس رائع انتظر الدرس التالى على احر من الجمر
ولى سؤال ما معنى جرد الدرايفر ثم اننى اذكر ان DRIVER_OBJECT in MSDN is obaque structure how did you find its members

تم تعديل هذه المشاركة بواسطة do_not_forget2008: 15 February 2009 - 07:26 AM

0

#3 العضو غير متواجد حاليا   do_not_forget2008 

  • عضو
  • PipPip
  • المجموعة: اعضاء
  • المشاركات: 121
  • الإلتحاق: 21-May 08
  • الدولة:Kuwait for now but Egypt Forever
  • الدولة :

السمعة: 0
عادي

تمت المشاركة 15 February 2009 - 01:55 PM

لى سؤال اخر معلش اصلى ضعيف فى السى 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
اذا لم تخنى الذاكرة
متاسف لطول الاسئلة ولكنى اريد ان اتعلم :041:
0

#4 العضو غير متواجد حاليا   GamingMasteR 

  • مشرف قسم الأسمبلي سابقاً
  • PipPipPipPip
  • المجموعة: اعضاء
  • المشاركات: 1545
  • الإلتحاق: 14-February 07
  • الجنس:ذكر
  • الوسام

  • الدولة :

السمعة: 49
جيد

تمت المشاركة 15 February 2009 - 04:13 PM

LEFT TO RIGHT
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

#5 العضو غير متواجد حاليا   do_not_forget2008 

  • عضو
  • PipPip
  • المجموعة: اعضاء
  • المشاركات: 121
  • الإلتحاق: 21-May 08
  • الدولة:Kuwait for now but Egypt Forever
  • الدولة :

السمعة: 0
عادي

أيقونة المشاركة  تمت المشاركة 15 February 2009 - 07:29 PM

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

تم تعديل هذه المشاركة بواسطة do_not_forget2008: 15 February 2009 - 07:31 PM

0

#6 العضو غير متواجد حاليا   GamingMasteR 

  • مشرف قسم الأسمبلي سابقاً
  • PipPipPipPip
  • المجموعة: اعضاء
  • المشاركات: 1545
  • الإلتحاق: 14-February 07
  • الجنس:ذكر
  • الوسام

  • الدولة :

السمعة: 49
جيد

تمت المشاركة 15 February 2009 - 07:33 PM

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


جرد == Enumerate .
0



#7 العضو غير متواجد حاليا   do_not_forget2008 

  • عضو
  • PipPip
  • المجموعة: اعضاء
  • المشاركات: 121
  • الإلتحاق: 21-May 08
  • الدولة:Kuwait for now but Egypt Forever
  • الدولة :

السمعة: 0
عادي

تمت المشاركة 16 February 2009 - 01:17 PM

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

تم تعديل هذه المشاركة بواسطة do_not_forget2008: 16 February 2009 - 01:18 PM

0

#8 العضو غير متواجد حاليا   do_not_forget2008 

  • عضو
  • PipPip
  • المجموعة: اعضاء
  • المشاركات: 121
  • الإلتحاق: 21-May 08
  • الدولة:Kuwait for now but Egypt Forever
  • الدولة :

السمعة: 0
عادي

تمت المشاركة 19 February 2009 - 07:27 AM

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

#9 العضو غير متواجد حاليا   GamingMasteR 

  • مشرف قسم الأسمبلي سابقاً
  • PipPipPipPip
  • المجموعة: اعضاء
  • المشاركات: 1545
  • الإلتحاق: 14-February 07
  • الجنس:ذكر
  • الوسام

  • الدولة :

السمعة: 49
جيد

تمت المشاركة 19 February 2009 - 06:59 PM

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

#10 العضو غير متواجد حاليا   الاخير زمانه 

  • عضو مميز
  • PipPipPip
  • المجموعة: اعضاء
  • المشاركات: 893
  • الإلتحاق: 16-April 05
  • الجنس:ذكر
  • الدولة:Iraq
  • الدولة :

السمعة: 7
عادي

تمت المشاركة 21 February 2009 - 06:36 AM

إقتباس

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

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

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

تم تعديل هذه المشاركة بواسطة الاخير زمانه: 21 February 2009 - 03:15 PM

0

  • (3 صفحات) +
  • 1
  • 2
  • 3
  • لا تستطيع بدء موضوع جديد
  • لا تستطيع الرد على هذا الموضوع

1 أعضاء يقرؤون هذا الموضوع
0 أعضاء، 1 زوار و 0 أعضاء مختبؤون





لإفضل مشاهدة للمنتدى إستخدم مستعرض فايرفوكس