ویرگول
ورودثبت نام
سید عمید قائم مقامی
سید عمید قائم مقامیبرنامه نویسی سیستم ویندوز و مهندسی معکوس و علاقه مند به آموزش.
سید عمید قائم مقامی
سید عمید قائم مقامی
خواندن ۳ دقیقه·۱ ماه پیش

درایور نویسی سطح کرنل قسمت دوم(ساخت یک نخ در سطح کرنل و شرط حلقه بینهایت، همراه با کد درایور):

🔹 هنگام Load:

اول درایور لود می‌شود

دوم یک thread کرنل ساخته می‌شود

سوم هر 2 ثانیه پیام چاپ می‌کند

🔹 هنگام Stop:

اول فلگ توقف فعال می‌شود

دوم thread به‌صورت امن خارج می‌شود

سوم سیستم بدون BSOD ادامه می‌دهد

#pragma warning (disable : 4100) #include <ntifs.h> #include <ntddk.h> HANDLE g_ThreadHandle = NULL; BOOLEAN g_StopThread = FALSE; // تابع Thread VOID ThreadRoutine(PVOID Context) { LARGE_INTEGER interval; UNREFERENCED_PARAMETER(Context); while (!g_StopThread) { // تاخیر 2 ثانیه interval.QuadPart = -2 * 10000000; // -2 ثانیه به واحد 100 نانوثانیه KeDelayExecutionThread(KernelMode, FALSE, &interval); DbgPrintEx(0, 0, "Thread woke up after 2 seconds\n"); } PsTerminateSystemThread(STATUS_SUCCESS); } NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriverObject) { DbgPrintEx(0, 0, "Goodbye!\n"); if (g_ThreadHandle) { g_StopThread = TRUE; // صبر برای پایان Thread با ZwWaitForSingleObject ZwWaitForSingleObject(g_ThreadHandle, FALSE, NULL); // بستن handle ZwClose(g_ThreadHandle); g_ThreadHandle = NULL; } return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { UNREFERENCED_PARAMETER(pRegistryPath); pDriverObject->DriverUnload = UnloadDriver; HANDLE threadHandle = NULL; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadRoutine, NULL ); if (NT_SUCCESS(status)) { g_ThreadHandle = threadHandle; DbgPrintEx(0, 0, "Driver loaded successfully!\n"); } else { DbgPrintEx(0, 0, "Failed to create system thread\n"); } return STATUS_SUCCESS; }

توضیح کد:

#pragma warning (disable : 4100) #include <ntifs.h> #include <ntddk.h>

#pragma warning (disable : 4100)

هشدار 4100 مربوط به پارامترهای استفاده‌نشده (Unreferenced parameter) است.
در درایورهای کرنل خیلی وقت‌ها پارامترها استفاده نمی‌شوند، پس این هشدار عمداً خاموش شده است.

ntifs.h و ntddk.h

این دو هدر شامل:

APIهای کرنل ویندوز

تعاریف PDRIVER_OBJECT

توابعی مثل PsCreateSystemThread، KeDelayExecutionThread، DbgPrintEx

هستند.


g_ThreadHandle

هندل thread کرنلی که ساخته می‌شود را نگه می‌دارد تا:

هنگام unload بتوانیم صبر کنیم تا thread تمام شود

بعد هندل را ببندیم

g_StopThread

یک فلگ کنترلی است:

FALSE → thread ادامه می‌دهد

TRUE → thread باید خارج شود

این روش، راه استاندارد و امن برای متوقف کردن thread در کرنل است.


تابع Thread (هسته‌ی اصلی)

VOID ThreadRoutine(PVOID Context)

این تابع کد اجرایی thread کرنل است که توسط PsCreateSystemThread اجرا می‌شود.


متغیر زمان

LARGE_INTEGER interval; UNREFERENCED_PARAMETER(Context);

LARGE_INTEGER برای نگه‌داری زمان delay استفاده می‌شود

Context در این مثال استفاده نشده، بنابراین با UNREFERENCED_PARAMETER هشدارش حذف شده


حلقه‌ی thread

while (!g_StopThread)

این یعنی:

تا وقتی درایور unload نشده

thread فعال باقی می‌ماند


خوابیدن thread (معادل Sleep)

interval.QuadPart = -2 * 10000000; KeDelayExecutionThread(KernelMode, FALSE, &interval);

توضیح خیلی مهم:

واحد زمان = 100 نانوثانیه

10,000,000 = 1 ثانیه

عدد منفی یعنی relative delay

پس این خط یعنی:

«thread فعلی 2 ثانیه در کرنل بخوابد»


چاپ پیام

DbgPrintEx(0, 0, "Thread woke up after 2 seconds\n");

هر 2 ثانیه یک پیام در DebugView / WinDbg چاپ می‌شود.


پایان صحیح thread

PsTerminateSystemThread(STATUS_SUCCESS);

وقتی g_StopThread = TRUE شود:

  • حلقه تمام می‌شود

  • thread به‌صورت تمیز و رسمی خاتمه می‌یابد

❗ این خیلی مهم است، چون thread نباید ناگهانی کشته شود.


تابع UnloadDriver

NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriverObject)

این تابع زمانی اجرا می‌شود که:

sc stop DriverName

را می‌زنیم.


چاپ پیام خروج

DbgPrintEx(0, 0, "Goodbye!\n");

توقف امن thread

if (g_ThreadHandle) { g_StopThread = TRUE;
  • به thread علامت می‌دهیم که خودش خارج شود

  • هیچ force یا kill وجود ندارد → کاملاً امن


صبر تا پایان thread

ZwWaitForSingleObject(g_ThreadHandle, FALSE, NULL);

این خط:

  • صبر می‌کند تا thread واقعاً تمام شود

  • جلوی BSOD و dangling thread را می‌گیرد


آزادسازی منابع

ZwClose(g_ThreadHandle); g_ThreadHandle = NULL;
  • هندل بسته می‌شود

  • اشاره‌گر null می‌شود تا دوباره استفاده نشود


تابع DriverEntry (نقطه ورود درایور)

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)

این تابع:

  • هنگام load شدن درایور اجرا می‌شود

  • مثل main() در برنامه‌های معمولی است


تنظیم Unload

pDriverObject->DriverUnload = UnloadDriver;

اگر این خط نباشد:

  • sc stop کار نمی‌کند

  • درایور unload نمی‌شود


ساخت thread کرنل

NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadRoutine, NULL );

این کار:

  • یک thread سطح کرنل می‌سازد

  • تابع ThreadRoutine را اجرا می‌کند

  • هندل آن را برمی‌گرداند


بررسی موفقیت

if (NT_SUCCESS(status)) { g_ThreadHandle = threadHandle; DbgPrintEx(0, 0, "Driver loaded successfully!\n"); }

اگر thread ساخته شد:

  • هندل ذخیره می‌شود

  • پیام موفقیت چاپ می‌شود

Telegram: @CaKeegan
Gmail : amidgm2020@gmail.com

threadskernelدرایور
۰
۰
سید عمید قائم مقامی
سید عمید قائم مقامی
برنامه نویسی سیستم ویندوز و مهندسی معکوس و علاقه مند به آموزش.
شاید از این پست‌ها خوشتان بیاید