از این به بعد بشتر تمرکز پستهام رو روی کرنل و درایور نویسی و ساختار درون اون میگذارم .
تصمیم داشتم بیشتر درمورد ساختار درون کرنل ویندوز توضیح بدم اما دیدم بیشتر موجب سردرگمی میشه برای همین تصمیم گرفتم با ارائه مثال ، در وقت مناسب ساختار هارو بیشتر توضیح بدم .

اولین پست ررو با یک مثال خیلی خیلی ساده توضیح میدم که خواننده ها بیشتر با روش کامپایل و اجرا و دیدن خروجی درایور آشنا بشن .

typedef struct _DRIVER_OBJECT {
  PDEVICE_OBJECT     DeviceObject;
  PDRIVER_EXTENSION  DriverExtension;
  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;

پیش از این درمورد ماهیت درایور توضیح دادم پس اگر مایل به دونستن آن هستید به پستهای قبلی بخش kernel مراجعه کنید .

بیشتر درایور ها رو میتونید در قسمت

c:\windows\system32\drivers

در ویندوز مشاهده کنید.

یکی از دستوراتی که از آن برای چک کردن نصب بودن یا نبودن درایور در cmd استفاده میکنیم دستور

driverquery

است . که لیست درایور های نصب شده در سیستم را به ما نشان میدهد.

پیشنیاز هایی که برای شروه کار لازم هست .

  1. نصب یک ماشین مجازی با ویندوز 32 بیت(برای درایور نویسی نباید از سیستم 64 بیت استفاده کرد دلیل اون رو قبلا در قسمت "درایور چیست" توضیح دادم) (من بر روی ویندوز 7 آموزش هارو تهیه میکنم).
  2. دانلود بسته wdk 7.1 از این مسیر (با حجم 620 مگابایت)
  3. نصب ویژوال استدیو(من از نسخه 2012 استفاده میکنم)
  4. دانلود و نصب برنامه OSRLoader برای نصب درایور (با api ویندوز ها نیز میتوان نصب کرد که در پست های بعد توضیح میدم)
  5. دانلود و نصب برنامه DbgView برای مشاهده خروجی های کرنل .
  6. نصب یک ادیتور (ترجیحا ++Notepad)
  7. و از همه مهم تر آشنایی کامل به زبان c


قبل شروع کار توصیه میشه پست مربوط به "درایور چیست" را حتما مطالعه کنید .

فایل ها در انتها پشت هم آورده شده اند.


فایل makefile : این فایل باید بدون پسوند باشد.

فایل sources : این فایل باید بدون پسوند باشد. در این فایل اطلاعات لازم برای بیلدر قرار دارد.

  1. TARGETNAME نام درایور شما موقع ایجاد توسط build است

  2. TARGETPATH پوشه ای که درایور داخلش قرار می گیرد.

  3. TARGETTYPE نوع فایلی که قرار است ایجاد شود که اینجا DRIVER است

  4. INCLUDES و LIBS به ابزار build می گوید کجا دنبال هدرها و کتابخانه های مورد نیاز بگردد

  5. SOURCES: نام فایل سورس ما اینجا قرار می گیرد اگر بیشتر از یک فایل باشد باید نامها با فاصله از هم جدا شوند.

فایل اصلی درایور(hello.c):این فایل شامل کد های درایور ما میباشد. در ویندوز اینترپوینت درایور ها نامی بجز main دارد یعنی اینترپوینت درایور ها DriverEntry نامیده میشود که از نوع NTSTATUS  میباشد (یکی از دیتا تایپهای مایکروسافت است و داخل فایل ntstatus.h تعریف شده) این تابع دارای دو آرگمان است . اولی از جنس _DRIVER_OBJECT است که دارای متغیر های دیگر است(که در ابتدا پست معرفی شد و توضیح آن ها در پست های بعد انشالاه) ولی در این سورس ما داده DriverUnload آن را مقدار دهی کردیم (که باعث میشود زمان آن لدو شدن ما پیغامی رو از سمت کرنل دریافت کنیم) . در صورتی که این تابع را تعریف نکنیم ، درایور ما پس از لود شدن دیگر آنلود نمیشود .

آرگمان دوم از جنس PUNICODE_STRING است که حاوی آدرس رجستریی است که درایور ما در آن ثبت شده.

از تابع DbgPrint برای فرستادن پیغام به بافر دیباگ استفاده میشود.


بیلد کردن فایل :

تمام فایل ها را در یک فولدر(hello) قرار داده و در یک مسیر قرار میدهیم (کاراکتر اسپیس در مسیر وجود نداشته باشد) .سپس در منوی استارت به قسمت Windows Driver Kits میرویم و سپس به قسمت WDK 7600.16385.1 سپس به قسمت Build Environments رفته بعد از آن قسمت windows 7 رفته سپس x86 Free Build Environment را اجرا کرده .
در کنسول باز شده با دستور cd به آدرس فولدر سورس ها میرویم. سپس برای بیلد کردن آن دستیر زیر را وارد میکنیم ( :) )

C:\...\hello>build /gcZ

پارامتر z باعث سرعت بخشیدن به روند کامپایل میشود و دو پارامتر دیگر باعث رنگی کردن خروجی .

درایور در همان فولدر ، فولدر زیر را میسازد و درایور را در آنجا قرار میدهد.

objfre_win7_x86

برای رجیستر و استارد درایور از OsrLoader استفاده میشه

مسیر OsrLoader مورد نظر

OsrLoader\kit\WNET\i386\FRE

قبل از ران کردن درایور DbgView را با دسترسی ادمین اجرا کنید و در منو ، در بالای پنجره قسمت کپچر را انتخاب کرده و سپس تیک کپچر کرنل و قسمت پایینی آن را نیز فعال کنید تا بتوانید خروجی های کرنلی خود را در آن ببینید (؟!)

سورس:

فایل makefile : یک فایل تکست بسازدی و سورس زیر را در آن وارد کرده و سپس سیو کرده . و پسوند آن را پاک کنید(با نام makefile )

!INCLUDE $(NTMAKEENV)\makefile.def

فایل sources : یک فایل تکست بسازید و سورس زیر را در آن وارد کرده و سپس سیو کرده . و پسوند آن را پاک کنید(با نام sources )

TARGETNAME = hello
TARGETPATH = obj
TARGETTYPE = DRIVER

INCLUDES = %BUILD%\inc
LIBS = %BUILD%\lib

SOURCES = hello.c

فایل اصلی درایور(hello.c):

#include <ntddk.h>

VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Driver Unloaded.\n");
return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
 IN PUNICODE_STRING regPath)
{
DbgPrint("Hello World!.\n");
pDriverObject->DriverUnload = Unload;

return STATUS_SUCCESS;
}