驅動程序多線程 PsCreateSystemThread


  內核函數PsCreateSystemThread負責創建新線程。該函數可以創建兩種線程,一種是用戶線程,它屬於當前進程中的線程。另一種是系統線程,系統線程不屬於當前用戶進程,而是屬於系統進程,一般PID為4,名字為“System”的進程。

    NTSTATUS 
    PsCreateSystemThread(
      OUT PHANDLE  ThreadHandle, //新創建的線程句柄
      IN ULONG  DesiredAccess, //創建的權限
      IN POBJECT_ATTRIBUTES  ObjectAttributes  OPTIONAL,//線程的屬性,一般設為NULL
      IN HANDLE  ProcessHandle  OPTIONAL,//指定創建用戶線程還是系統線程。如果為NULL,則為系統進程,如果該值是一個進程句柄,則新創建的線程屬於這個指定的進程。DDK提供的NTCurrentProcess可以得到當前進程的句柄。
      OUT PCLIENT_ID  ClientId  OPTIONAL,
      IN PKSTART_ROUTINE  StartRoutine,//新線程的運行地址
      IN PVOID  StartContext //新線程接收的參數
      );

 

  

          在內核模式下創建的線程是無法自動退出的,必須使用PsTerminateSystemThread強制結束線程

 

         通過內核事件KEVENT和內核等待KeWaitForSingleObject來演示事件的創建過程。

   

	KEVENT Event;

	//創建一個同步事件
	KeInitializeEvent(
		&Event,               //要初始化的KEVENT結構對象
		SynchronizationEvent, //事件類型
		FALSE);       

      KeSetEvent(
        &Event, //被激活的事件
        IO_NO_INCREMENT, //被喚醒線程臨時提升線程優先級的增量,傳0
        FALSE); //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject.

  

	KeWaitForSingleObject(
		&Event,      //同步對象的指針,
		Executive,   //等待的原因,一般為Executive
		KernelMode,  //等待模式,一般為KernelMode
		FALSE,       //指明等待是否為“警惕”的,一般為FALSE
		NULL);       //等待時間,如果為NULL,就表示無限期等待,直到同步對象變為激發態
	DbgPrint("ThreadProcedure() Exit\r\n");
	PsTerminateSystemThread(STATUS_SUCCESS);

  

   總結一下代碼流程:

    1.驅動程序KeInitializeEvent創建了一個內核事件

                2.PsCreateSystemThread創建新的系統線程,將創建好的KEVENT結構傳參給新創建的線程。 再調用KeSetEvent事件激活

                3.線程中調用KeWaitForSingleObject等待事件激活狀態(受信),執行后續代碼,最后PsTerminateSystemThread結束線程

 

  源代碼:

 

KEvent.h

 

#pragma once
#include <ntifs.h>
#define DELAY_ONE_MICROSECOND 	(-10)
#define DELAY_ONE_MILLISECOND	(DELAY_ONE_MICROSECOND*1000)





VOID DriverUnload(PDRIVER_OBJECT DriverObject);
VOID KSleep(LONG MilliSecond);
void ThreadProcedure(PVOID ParameterData);

 

 

KEvent.c

#include "KEvent.h"
//http://www.cnblogs.com/dacainiao/p/5923147.html
//同步事件(SynchronizationEvent)
//當事件對象為激發時,如遇到KeWaitForXX等內核函數,事件對象則自動變回未激發態
//通知事件(NotificationEvent)
//當事件對象為激發時,如遇到KeWaitForXX等內核函數,事件對象則不會變回未激發態 
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
	int i = 0;
	NTSTATUS Status = STATUS_SUCCESS;
	HANDLE   ThreadHandle = NULL;
	PDEVICE_OBJECT  DeviceObject = NULL;
	KEVENT Event;

	CLIENT_ID       ClientID = {0};

	DriverObject->DriverUnload = DriverUnload;

	//創建一個同步事件
	KeInitializeEvent(
		&Event,               //要初始化的KEVENT結構對象
		SynchronizationEvent, //事件類型
		FALSE);               //如果為真,初始為激發態


	//創建一個通知事件
	//KeInitializeEvent(&Event, NotificationEvent, 
	//	FALSE);

	


	//創建一個System進程下運行的線程	
	for (i=0;i<2;i++)
	{
		Status = PsCreateSystemThread(
			&ThreadHandle,                     //新創建的線程句柄
			0,                                 //創建的權限
			NULL,                              //線程的屬性,一般設為NULL
			NtCurrentProcess(),                //指定創建用戶線程還是系統線程。如果為NULL,則為系統進程,如果該值是一個進程句柄,則新創建的線程屬於這個指定的進程。DDK的NTCurrentProcess可以得到當前進程的句柄。
			&ClientID,
			(PKSTART_ROUTINE)ThreadProcedure,  //新線程的運行地址
			(PVOID)&Event);                    //新線程接收的參數
	}
	
	
	KSleep(3000);
	KeSetEvent(
		&Event,               //被激活的事件
		IO_NO_INCREMENT,      //被喚醒線程臨時提升線程優先級的增量,傳0
		FALSE);               //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject.


	


	return Status;
}



void ThreadProcedure(PVOID ParameterData)
{
	KEVENT Event = *((PKEVENT)ParameterData);
	NTSTATUS Status;
	KeWaitForSingleObject(
		&Event,      //同步對象的指針,
		Executive,   //等待的原因,一般為Executive
		KernelMode,  //等待模式,一般為KernelMode
		FALSE,       //指明等待是否為“警惕”的,一般為FALSE
		NULL);       //等待時間,如果為NULL,就表示無限期等待,直到同步對象變為激發態
	DbgPrint("ThreadProcedure() Exit\r\n");
	PsTerminateSystemThread(STATUS_SUCCESS);
}

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("DriverUnload()\r\n");
}


VOID KSleep(LONG MilliSecond)
{
	LARGE_INTEGER Interval = {0};
	Interval.QuadPart = DELAY_ONE_MILLISECOND;
	Interval.QuadPart *= MilliSecond;
	KeDelayExecutionThread(KernelMode, 0, &Interval);
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM