[转](37)0环与3环通信,PspTerminateProcess 关闭进程工具

 

设备对象和3环窗口对象的类比

3环窗口程序中的MSG结构体和窗口对象,与0环的设备对象和IRP结构体的关系有点像:
在这里插入图片描述

我们在开发窗口程序的时候,消息被封装成一个结构体:MSG,在内核开发时,消息被封装成另外一个结构体:IRP(I/O Request Package)。

 

在窗口程序中,能够接收消息的只能是窗口对象。在内核中,能够接收IRP消息的只能是设备对象。

驱动程序原本的目的是用来控制硬件,但我们也可以用驱动做一些安全相关的事情,因为驱动运行在0环。为了控制驱动运行,我们需要在3环向驱动发数据,所以我们需要有一种方法来建立0环到3环的通信。本文介绍常规方式,也就是创建设备对象的方式。

 

1.设备对象

我们在开发窗口程序的时候,消息被封装成一个结构体:MSG,在内核开发时,消息被封装成另外一个结构体:IRP(I/O Request Package).

在窗口程序中,能够接收消息的只能时窗口对象.同样,在内核中,能够接收IRP消息的只能是设备对象.

看来,要实现通信就绕不过设备对象.

2.创建设备对象

通常理解一个设备对象就是指硬件,比如一个鼠标,键盘,但是这个设备对象也可以什么真实物体都不对应,成为一个抽象的存在

//创建设备名称
UNICODE_STRING Devicename;
RtlInitUnicodeString(&Devicename,L"\\Device\\MyDevice");

//创建设备
	status = IoCreateDevice(pdriver, 0, &Devicename, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObj);
	if (status != STATUS_SUCCESS) 
	{
		DbgPrint("创建设备失败! \r\n");
		return status;
	}

3.设置交互数据的方式

pDeviceObj->Flags |= DO_BUFFERED_IO;

  • 缓冲区方式读写(DO_BUFFERED_IO): 操作系统将应用程序提供的缓冲区里的数据复制到内核模式下的地址中.优点:上层线程切换不影响数据读取.缺点:复制过程影响效率
  • 直接方式读写(DO_DIRECT_IO): 操作系统会将用户模式下的缓冲区锁住.然后操作系统将这段缓冲区在内核模式地址再次映射一遍.这样,用户模式的缓冲区和内核模式的缓冲区指向的是同一区域的物理内存,缺点就是要单独占用物理页面
  • 其他方式读写(在调用IoCreateDevice创建设备后对pDevObj->Flags即不设置DO_BUFFERED_IO也不设置DO_DIRECT_IO此时就是其他方式):(不建议,这种方式就是0环直接读写3环)

4.IRP与派遣函数

在这里插入图片描述

注意这个派遣函数是给设备对象调用的,而不是给我们自己调用的,我们只需要提供好派遣函数并注册。

5.IRP的类型

<1> 当应用层通过CreateFile,ReadFile,WriteFile,CloseHandle等函数打开,从设备读取数据,向设备写入数据,关闭设备的时候,会使操作系统产生出IRP_MJ_CREATE,IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_CLOSE等不同的IRP。
<2>其他类型的IRP

IRP类型来源
IRP_MJ_DEVICE_CONTROLDeviceControl函数会产生此IRP(常规方式用的最多,更灵活)
IRP_MJ_POWER在操作系统处理电源消息时,产生此IRP
IRP_MJ_SHUTDOWN关闭系统前会产生此IRP

6.派遣函数在哪里注册呢?

看 驱动函数的最后一项
,这个数组里面保存着不同的消息所对应的不同的派遣函数。

1: kd> dt _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x008 DeviceObject     : Ptr64 _DEVICE_OBJECT
   +0x010 Flags            : Uint4B
   +0x018 DriverStart      : Ptr64 Void//驱动模块所处位置
   +0x020 DriverSize        : Uint4B//大小
   +0x028 DriverSection    : Ptr64 Void//对应一个指针,指向的是LDR_DATA_TABLE_ENTRY,这样的一个链表把所有的内核模块全部圈在了一起.
   +0x030 DriverExtension  : Ptr64 _DRIVER_EXTENSION
   +0x038 DriverName       : _UNICODE_STRING//名称
   +0x048 HardwareDatabase : Ptr64 _UNICODE_STRING
   +0x050 FastIoDispatch   : Ptr64 _FAST_IO_DISPATCH
   +0x058 DriverInit       : Ptr64     long 
   +0x060 DriverStartIo    : Ptr64     void 
   +0x068 DriverUnload     : Ptr64     void 
   +0x070 MajorFunction    : [28] Ptr64     long 

举个例子:IRP_MJ_CREATE

转到定义查看
在这里插入图片描述
IRP_MJ_CREATE消息的值是0,那他的派遣函数就存储在MajorFunction函数数组中对应的的0下标处。

7.派遣函数的格式

//派遣函数的格式:
NTSTATUS MyDispatchFunction(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
    //处理自己的业务...
    
    //设置返回状态
    pIrp->IoStatus.Status = STATUS_SUCCESS;//getlasterror()得到的就是这个值
    pIrp->IoStatus.Information = 0;//返回给3环多少数据,没有填0
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

8.通过IRP_MJ_DEVICE_CONTROL交互数据

应用层调用DeviceControl函数会产生此IRP。

9.几个重要的结构体

IRP

以下是WDK帮助文档原内容:大体意思是IRP结构体包含了用来描述一个I/O请求的完整信息.是一个半透明的结构体:包含文档化的Header 头部分以及在头部后面的不可见的IO_STACK_LOCATION结构体

An IRP is the basic I/O manager structure used to communicate with drivers and to allow drivers to 
communicate with each other. A packet consists of two different parts:

Header, or fixed part of the packet — This is used by the I/O manager to store information about the 
original request, such as the caller's device-independent parameters, the address of the device object 
upon which a file is open, and so on. It is also used by drivers to store information such as the final 

status of the request. 
I/O stack locations — Following the header is a set of I/O stack locations, one per driver in the chain 
of layered drivers for which the request is bound. Each stack location contains the parameters, 
function codes, and context used by the corresponding driver to determine what it is supposed to be   
doing. For more information, see the IO_STACK_LOCATION structure. 

//以下是IRP结构体文档化(可见)部分:Header

0: kd> dt _IRP
ntdll!_IRP
   +0x000 Type             : Int2B //I/O请求类型(IRP_MJ_CREATE等等)
   +0x002 Size             : Uint2B
   +0x008 MdlAddress       : Ptr64 _MDL  //指向用户缓冲区的MDL类型的指针 
   +0x010 Flags            : Uint4B //I/O需要进行的操作类型
   +0x018 AssociatedIrp    : <unnamed-tag> //指向系统缓冲区的指针
   +0x020 ThreadListEntry  : _LIST_ENTRY
   +0x030 IoStatus         : _IO_STATUS_BLOCK //保存IRP状态和信息
   +0x040 RequestorMode    : Char //来自于内核请求还是用户层请求
   +0x041 PendingReturned  : UChar
   +0x042 StackCount       : Char 
   +0x043 CurrentLocation  : Char
   +0x044 Cancel           : UChar //设置取消IRP
   +0x045 CancelIrql       : UChar
   +0x046 ApcEnvironment   : Char
   +0x047 AllocationFlags  : UChar
   +0x048 UserIosb         : Ptr64 _IO_STATUS_BLOCK
   +0x050 UserEvent        : Ptr64 _KEVENT
   +0x058 Overlay          : <unnamed-tag>
   +0x068 CancelRoutine    : Ptr64     void 
   +0x070 UserBuffer       : Ptr64 Void
   +0x078 Tail             : <unnamed-tag>

IO_STACK_LOCATION

0: kd> dt _IO_STACK_LOCATION
ntdll!_IO_STACK_LOCATION
   +0x000 MajorFunction    : UChar  //要被执行的操作
   +0x001 MinorFunction    : UChar  //子功能函数,一些pnp管理器,电源管理器,文件系统驱动和SCSI一类的驱动为了某些功能而设置该成员
   +0x002 Flags            : UChar
   +0x003 Control          : UChar
   +0x008 Parameters       : <unnamed-tag>  //根据主功能函数和子功能的函数值来决定联合体结构
   +0x028 DeviceObject     : Ptr64 _DEVICE_OBJECT
   +0x030 FileObject       : Ptr64 _FILE_OBJECT
   +0x038 CompletionRoutine : Ptr64     long 
   +0x040 Context          : Ptr64 Void

IO_STACK_LOCATION Parameters

union {
        //
        // Parameters for IRP_MJ_CREATE 
        //
        struct {
            PIO_SECURITY_CONTEXT  SecurityContext;
            ULONG  Options;
            USHORT POINTER_ALIGNMENT  FileAttributes;
            USHORT  ShareAccess;
            ULONG POINTER_ALIGNMENT  EaLength;
        } Create;
        //
        // Parameters for IRP_MJ_READ 
        //
        struct {
            ULONG  Length;
            ULONG POINTER_ALIGNMENT  Key;
            LARGE_INTEGER  ByteOffset;
        } Read;
        //
        // Parameters for IRP_MJ_WRITE 
        //
        struct {
            ULONG  Length;
            ULONG POINTER_ALIGNMENT  Key;
            LARGE_INTEGER  ByteOffset;
        } Write;
        //
        // Parameters for IRP_MJ_QUERY_INFORMATION 
        //
        struct {
            ULONG  Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT  FileInformationClass;
        } QueryFile;
        //
        // Parameters for IRP_MJ_SET_INFORMATION 
        //
        struct {
            ULONG  Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT  FileInformationClass;
            PFILE_OBJECT  FileObject;
            union {
                struct {
                    BOOLEAN  ReplaceIfExists;
                    BOOLEAN  AdvanceOnly;
                };
                ULONG  ClusterCount;
                HANDLE  DeleteHandle;
            };
        } SetFile;
        //
        // Parameters for IRP_MJ_QUERY_VOLUME_INFORMATION 
        //
        struct {
            ULONG  Length;
            FS_INFORMATION_CLASS POINTER_ALIGNMENT  FsInformationClass;
        } QueryVolume;
        //
        // Parameters for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            ULONG  OutputBufferLength;
            ULONG POINTER_ALIGNMENT  InputBufferLength;
            ULONG POINTER_ALIGNMENT  IoControlCode;
            PVOID  Type3InputBuffer;
        } DeviceIoControl;
        //
        // Nonsystem service parameters.
        //
        // Parameters for IRP_MN_MOUNT_VOLUME 
        //
        struct {
            PVOID  DoNotUse1;
            PDEVICE_OBJECT  DeviceObject;
        } MountVolume;
        //
        // Parameters for IRP_MN_VERIFY_VOLUME 
        //
        struct {
            PVOID  DoNotUse1;
            PDEVICE_OBJECT  DeviceObject;
        } VerifyVolume;
        //
        // Parameters for Scsi using IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            struct _SCSI_REQUEST_BLOCK  *Srb;
        } Scsi;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS 
        //
        struct {
            DEVICE_RELATION_TYPE  Type;
        } QueryDeviceRelations;
        //
        // Parameters for IRP_MN_QUERY_INTERFACE 
        //
        struct {
            CONST GUID  *InterfaceType;
            USHORT  Size;
            USHORT  Version;
            PINTERFACE  Interface;
            PVOID  InterfaceSpecificData;
        } QueryInterface;
        //
        // Parameters for IRP_MN_QUERY_CAPABILITIES 
        //
        struct {
            PDEVICE_CAPABILITIES  Capabilities;
        } DeviceCapabilities;
        //
        // Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS 
        //
        struct {
            PIO_RESOURCE_REQUIREMENTS_LIST  IoResourceRequirementList;
        } FilterResourceRequirements;
        //
        // Parameters for IRP_MN_READ_CONFIG and IRP_MN_WRITE_CONFIG 
        //
        struct {
            ULONG  WhichSpace;
            PVOID  Buffer;
            ULONG  Offset;
            ULONG  POINTER_ALIGNMENT Length;
        } ReadWriteConfig;
        //
        // Parameters for IRP_MN_SET_LOCK 
        //
        struct {
            BOOLEAN  Lock;
        } SetLock;
        //
        // Parameters for IRP_MN_QUERY_ID 
        //
        struct {
            BUS_QUERY_ID_TYPE  IdType;
        } QueryId;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_TEXT 
        //
        struct {
            DEVICE_TEXT_TYPE  DeviceTextType;
            LCID POINTER_ALIGNMENT  LocaleId;
        } QueryDeviceText;
        //
        // Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION 
        //
        struct {
            BOOLEAN  InPath;
            BOOLEAN  Reserved[3];
            DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
        } UsageNotification;
        //
        // Parameters for IRP_MN_WAIT_WAKE 
        //
        struct {
            SYSTEM_POWER_STATE  PowerState;
        } WaitWake;
        //
        // Parameter for IRP_MN_POWER_SEQUENCE 
        //
        struct {
            PPOWER_SEQUENCE  PowerSequence;
        } PowerSequence;
        //
        // Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER 
        //
        struct {
            ULONG  SystemContext;
            POWER_STATE_TYPE POINTER_ALIGNMENT  Type;
            POWER_STATE POINTER_ALIGNMENT  State;
            POWER_ACTION POINTER_ALIGNMENT  ShutdownType;
        } Power;
        //
        // Parameters for IRP_MN_START_DEVICE 
        //
        struct {
            PCM_RESOURCE_LIST  AllocatedResources;
            PCM_RESOURCE_LIST  AllocatedResourcesTranslated;
        } StartDevice;
        //
        // Parameters for WMI Minor IRPs 
        //
        struct {
            ULONG_PTR  ProviderId;
            PVOID  DataPath;
            ULONG  BufferSize;
            PVOID  Buffer;
        } WMI;
        //
        // Others - driver-specific
        //
        struct {
            PVOID  Argument1;
            PVOID  Argument2;
            PVOID  Argument3;
            PVOID  Argument4;
        } Others;
    } Parameters;

 

 

三、0环与3环通信实验

 

更多细节,我打算放在代码里,因为这部分内容都是按照Windows的规则调用API,没什么特别的,有什么不懂查文档即可。

 

驱动代码

 

#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\HbgDev"  //创建设备名称
 //ring3用CreateFile打开设备时,用"\\\\.\\HbgDevLnk"//相当于起的别名
#define SYMBOLICLINK_NAME L"\\??\\HbgDevLnk"

#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

// 函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath);
VOID DriverUnload(PDRIVER_OBJECT pDriver);
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);

// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	NTSTATUS status;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL; // 设备对象指针
	UNICODE_STRING DeviceName; // 设备名,0环用
	UNICODE_STRING SymbolicLinkName; // 符号链接名,3环用
	
	// 创建设备名称
	RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
	// 创建设备
	status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);
	if (status != STATUS_SUCCESS)
	{
		IoDeleteDevice(pDeviceObj);
		DbgPrint("创建设备失败.\n");
		return status;
	}
	DbgPrint("创建设备成功.\n");
	// 设置交互数据的方式
	pDeviceObj->Flags |= DO_BUFFERED_IO;
	// 创建符号链接
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);
	IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	// 设置分发函数
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;
	// 设置卸载函数
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

// 卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING SymbolicLinkName;
	// 删除符号链接,删除设备
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);
	IoDeleteSymbolicLink(&SymbolicLinkName);
	IoDeleteDevice(pDriver->DeviceObject);
	DbgPrint("驱动卸载成功\n");
}

// 不设置这个函数,则Ring3调用CreateFile会返回1
// IRP_MJ_CREATE 处理函数
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;  //设置返回状态 getlasterror()得到的就是这个值
	pIrp->IoStatus.Information = 0;          //返回给3环多少数据,没有填0
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_CLOSE 处理函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层断开连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_DEVICE_CONTROL 处理函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	// DbgPrint("IrpDeviceControlProc.\n");
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack; //定义一个指向IO_STACK_LOCATION结构体的指针
	ULONG uIoControlCode; 
	PVOID pIoBuffer;
	ULONG uInLength;
	ULONG uOutLength;
	ULONG uRead;
	ULONG uWrite;
	
	// 设置临时变量的值
	uRead = 0;
	uWrite = 0x12345678;
	// 获取IRP数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp); //根据从ring3发来的
	// 获取控制码 
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	// 获取缓冲区地址(输入输出是同一个)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	// Ring3 发送数据的长度
	uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	// Ring0 发送数据的长度
	uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	switch (uIoControlCode)
	{
	case OPER1:
		{
			DbgPrint("IrpDeviceControlProc -> OPER1...\n");
			pIrp->IoStatus.Information = 0;
			status = STATUS_SUCCESS;
			break;
		}
	case OPER2:
		{
			DbgPrint("IrpDeviceControlProc -> OPER2 输入字节数: %d\n", uInLength);
			DbgPrint("IrpDeviceControlProc -> OPER2 输出字节数: %d\n", uOutLength);
			// 读取缓冲区
			memcpy(&uRead,pIoBuffer,4);
			DbgPrint("IrpDeviceControlProc -> OPER2 uRead: %x\n", uRead);
			// 写入缓冲区
			memcpy(pIoBuffer, &uWrite, 4);
			// 设置状态
			pIrp->IoStatus.Information = 2; // 返回两字节
			status = STATUS_SUCCESS;
			break;
		}
	}

	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

 

应用程序代码

 

// IRPTest_R3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <winioctl.h>
#include <stdio.h>

//#define DEVICE_NAME L"\\Device\\HbgDev"
#define SYMBOLICLINK_NAME L"\\\\.\\HbgDevLnk"
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IN_BUFFER_MAXLENGTH 4
#define OUT_BUFFER_MAXLENGTH 4

int _tmain(int argc, _TCHAR* argv[])
{
	// 获取设备句柄
	HANDLE hDevice = CreateFileW(SYMBOLICLINK_NAME,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	DWORD dwError = GetLastError();
	if (hDevice == INVALID_HANDLE_VALUE)
	{		
		printf("获取设备句柄失败 %d.\n", dwError); // 如果返回1,请在驱动中指定 IRP_MJ_CREATE 处理函数
		getchar();
		return 1;
	}
	else
	{
		printf("获取设备句柄成功.\n");
	}
	// 测试通信
	DWORD dwInBuffer = 0x11111111;
	DWORD dwOutBuffer = 0xFFFFFFFF;
	DWORD dwOut;	
	DeviceIoControl(hDevice,OPER2,&dwInBuffer,IN_BUFFER_MAXLENGTH,&dwOutBuffer,OUT_BUFFER_MAXLENGTH,&dwOut,NULL);
	printf("dwOutBuffer: %08X dwOut: %08X\n", dwOutBuffer, dwOut);
	// 关闭设备
	CloseHandle(hDevice);
	getchar();
	return 0;
}


 

运行结果

 

在这里插入图片描述

 

四、驱动加载程序

 

现在,希望自己编程实现驱动的注册,运行,停止,卸载。

 

给出一个demo,包含一个能完成加法程序的驱动,以及对它进行操作的3环程序。
代码较多,都是API的用法。

 

应用程序代码

 

// 驱动加载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <winioctl.h>
#include <stdio.h> 

// 编写一个简单的驱动,在驱动入口和卸载函数打印一些提示信息
// 这个驱动可以做加法,3环程序可以给他传两个4字节整数,驱动会返回相加的结果
#define DRIVER_NAME L"MathsDriver"
#define DRIVER_PATH L"MathsDriver.sys"
#define DRIVER_LINK L"\\\\.\\MathsDriverLnk"
#define OPERADD CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath)
{
	// 获取驱动完整路径
	WCHAR szDriverFullPath[MAX_PATH] = { 0 };
	GetFullPathNameW(lpszDriverPath,MAX_PATH,szDriverFullPath,NULL);
	//printf("%s\n", szDriverFullPath);
	// 打开服务控制管理器
	SC_HANDLE hServiceMgr = NULL; // SCM管理器句柄	
	hServiceMgr = OpenSCManagerW(NULL,NULL,SC_MANAGER_ALL_ACCESS);
	if (NULL == hServiceMgr)
	{
		printf("OpenSCManagerW 失败, %d\n", GetLastError());
		return FALSE;
	}
	printf("打开服务控制管理器成功.\n");
	// 创建驱动服务
	SC_HANDLE hServiceDDK = NULL; // NT驱动程序服务句柄
	hServiceDDK = CreateServiceW(
		hServiceMgr,
		lpszDriverName,//驱动程序的在注册表中的名字   
		lpszDriverName, // 注册表驱动程序的 DisplayName 值 
		SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
		SERVICE_KERNEL_DRIVER, // 表示加载的服务是驱动程序 
		SERVICE_DEMAND_START,    // 注册表驱动程序的 Start 值    
		SERVICE_ERROR_IGNORE,   // 注册表驱动程序的 ErrorControl 值    
		szDriverFullPath,       // 注册表驱动程序的 ImagePath 值    
		NULL,
		NULL,
		NULL,
		NULL,
		NULL);
	if (NULL == hServiceDDK)
	{
		DWORD dwErr = GetLastError();
		if (dwErr != ERROR_IO_PENDING && dwErr != ERROR_SERVICE_EXISTS)
		{
			printf("创建驱动服务失败, %d\n", dwErr);
			return FALSE;
		}
	}
	printf("创建驱动服务成功.\n");
	// 驱动服务已经创建,打开服务
	hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);
	if (!StartService(hServiceDDK, NULL, NULL))
	{
		DWORD dwErr = GetLastError();
		if (dwErr != ERROR_SERVICE_ALREADY_RUNNING)
		{
			printf("运行驱动服务失败, %d\n", dwErr);
			return FALSE;
		}
	}
	printf("运行驱动服务成功.\n");
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return TRUE;
}

void RunMathDriver()
{
	HANDLE hDevice = CreateFileW(DRIVER_LINK, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("创建设备失败. %d\n", GetLastError());
		return;
	}
	// 加法
	DWORD n1 = 100, n2 = 50;
	BYTE InBuffer[8];
	DWORD OutBuffer;
	memcpy(InBuffer,&n1,4);
	memcpy(InBuffer+4,&n2,4);
	DWORD dwOut;	
	DeviceIoControl(hDevice,OPERADD,InBuffer,8,&OutBuffer,4,&dwOut,NULL);
	printf("%d + %d = %d\n", n1, n2, OutBuffer);
	// 关闭设备
	CloseHandle(hDevice);
}

void UnLoadDriver(PCWSTR lpszDriverName)
{
	SC_HANDLE hServiceMgr = OpenSCManagerW(0,0,SC_MANAGER_ALL_ACCESS);    //打开SCM管理器  
	SC_HANDLE hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);
	SERVICE_STATUS SvrStatus;
	ControlService(hServiceDDK,SERVICE_CONTROL_STOP,&SvrStatus);
	DeleteService(hServiceDDK);
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	if (!LoadDriver(DRIVER_NAME, DRIVER_PATH))
	{
		printf("加载驱动失败.\n");
		getchar();
		return 1;
	}
	RunMathDriver();
	UnLoadDriver(DRIVER_NAME);
	getchar();
	return 0;
}


 

驱动代码

 

注意,驱动项目名应和三环中定义的 DRIVER_NAME 一致。

 

#include <ntddk.h>

// 编写一个简单的驱动,在驱动入口和卸载函数打印一些提示信息
// 这个驱动可以做加法,3环程序可以给他传两个4字节整数,驱动会返回相加的结果
#define DEVICE_NAME L"\\Device\\MathsDriverDev"
#define DRIVER_LINK L"\\??\\MathsDriverLnk"
#define OPERADD CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

// 函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath);
VOID DriverUnload(PDRIVER_OBJECT pDriver);
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);

// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	NTSTATUS status;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL; // 设备对象指针
	UNICODE_STRING DeviceName; // 设备名,0环用
	UNICODE_STRING SymbolicLinkName; // 符号链接名,3环用

	// 创建设备名称
	RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
	// 创建设备
	status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);
	if (status != STATUS_SUCCESS)
	{
		IoDeleteDevice(pDeviceObj);
		DbgPrint("创建设备失败.\n");
		return status;
	}
	DbgPrint("创建设备成功.\n");
	// 设置交互数据的方式
	pDeviceObj->Flags |= DO_BUFFERED_IO;
	// 创建符号链接
	RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);
	IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	// 设置分发函数
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;
	// 设置卸载函数
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

// 卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING SymbolicLinkName;
	// 删除符号链接,删除设备
	RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);
	IoDeleteSymbolicLink(&SymbolicLinkName);
	IoDeleteDevice(pDriver->DeviceObject);
	DbgPrint("驱动卸载成功\n");
}

// 不设置这个函数,则Ring3调用CreateFile会返回1
// IRP_MJ_CREATE 处理函数
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_CLOSE 处理函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层断开连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_DEVICE_CONTROL 处理函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	// DbgPrint("IrpDeviceControlProc.\n");
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack;
	ULONG uIoControlCode;
	PVOID pIoBuffer;
	ULONG uInLength;
	ULONG uOutLength;
	ULONG uRead1;
	ULONG uRead2;
	ULONG uWrite;

	// 设置临时变量的值
	uRead1 = uRead2 = 0;
	uWrite = 0x12345678;
	// 获取IRP数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	// 获取控制码
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	// 获取缓冲区地址(输入输出是同一个)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	// Ring3 发送数据的长度
	uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	// Ring0 发送数据的长度
	uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	switch (uIoControlCode)
	{
	case OPERADD:
		{
			// 读取缓冲区
			memcpy(&uRead1,pIoBuffer,4);
			memcpy(&uRead2,(PUCHAR)pIoBuffer+4,4);			
			uWrite = uRead1 + uRead2;
			// 写入缓冲区
			memcpy(pIoBuffer, &uWrite, 4);
			// 设置状态
			pIrp->IoStatus.Information = 4;
			status = STATUS_SUCCESS;
			break;
		}
	}

	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

 

运行结果

 

在这里插入图片描述

 

五、进程终结工具(基于 PspTerminateProcess)

 

关于未导出函数 PspTerminateProcess,可以看上一篇博客:《内核空间与内核模块》

 

编写一个3环程序,可以将任意一个进程的名字传递给0环的驱动程序,如果这个进程存在,驱动程序将该进程终结.

 

将要求中的传递进程名改成传递PID,这样会省事很多。另外,如果工具可以以一个单文件的形式存在,即不带sys文件,那么看起来会高级不少,然而我现在无法完成该需求,如果你知道怎么做,请在评论中留言。

 

这个项目和第四大点的demo非常像,3环部分,只需将传递两个4字节加数改成传递一个4字节PID,并且修改一下宏定义中,驱动项目的名字即可。

 

3环代码

 

// 驱动加载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <winioctl.h>
#include <stdio.h> 

#define DRIVER_NAME L"HbgProcessKillerDriver"
#define DRIVER_PATH L"HbgProcessKillerDriver.sys"
#define DRIVER_LINK L"\\\\.\\HbgProcessKillerDriverLnk"
#define OPERKILLPID CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath)
{
	// 获取驱动完整路径
	WCHAR szDriverFullPath[MAX_PATH] = { 0 };
	GetFullPathNameW(lpszDriverPath,MAX_PATH,szDriverFullPath,NULL);
	//printf("%s\n", szDriverFullPath);
	// 打开服务控制管理器
	SC_HANDLE hServiceMgr = NULL; // SCM管理器句柄	
	hServiceMgr = OpenSCManagerW(NULL,NULL,SC_MANAGER_ALL_ACCESS);
	if (NULL == hServiceMgr)
	{
		printf("OpenSCManagerW 失败, %d\n", GetLastError());
		return FALSE;
	}
	printf("打开服务控制管理器成功.\n");
	// 创建驱动服务
	SC_HANDLE hServiceDDK = NULL; // NT驱动程序服务句柄
	hServiceDDK = CreateServiceW(
		hServiceMgr,
		lpszDriverName,
		lpszDriverName,
		SERVICE_ALL_ACCESS,
		SERVICE_KERNEL_DRIVER,
		SERVICE_DEMAND_START,
		SERVICE_ERROR_IGNORE,
		szDriverFullPath,
		NULL,
		NULL,
		NULL,
		NULL,
		NULL);
	if (NULL == hServiceDDK)
	{
		DWORD dwErr = GetLastError();
		if (dwErr != ERROR_IO_PENDING && dwErr != ERROR_SERVICE_EXISTS)
		{
			printf("创建驱动服务失败, %d\n", dwErr);
			return FALSE;
		}
	}
	printf("创建驱动服务成功.\n");
	// 驱动服务已经创建,打开服务
	hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);
	if (!StartService(hServiceDDK, NULL, NULL))
	{
		DWORD dwErr = GetLastError();
		if (dwErr != ERROR_SERVICE_ALREADY_RUNNING)
		{
			printf("运行驱动服务失败, %d\n", dwErr);
			return FALSE;
		}
	}
	printf("运行驱动服务成功.\n");
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return TRUE;
}

void TransferPID()
{
	HANDLE hDevice = CreateFileW(DRIVER_LINK, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("创建设备失败. %d\n", GetLastError());
		return;
	}
	DWORD InBuffer;
	DWORD OutBuffer;	
	DWORD dwOut;
	printf("请输入你要干掉的进程PID:");
	scanf("%d", &InBuffer);
	DeviceIoControl(hDevice,OPERKILLPID,&InBuffer,4,&OutBuffer,4,&dwOut,NULL);	
	// 关闭设备
	CloseHandle(hDevice);
}

void UnLoadDriver(PCWSTR lpszDriverName)
{
	SC_HANDLE hServiceMgr = OpenSCManagerW(0,0,SC_MANAGER_ALL_ACCESS);
	SC_HANDLE hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);
	SERVICE_STATUS SvrStatus;
	ControlService(hServiceDDK,SERVICE_CONTROL_STOP,&SvrStatus);
	DeleteService(hServiceDDK);
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	if (!LoadDriver(DRIVER_NAME, DRIVER_PATH))
	{
		printf("加载驱动失败.\n");
		getchar();
		return 1;
	}
	TransferPID();
	UnLoadDriver(DRIVER_NAME);
	getchar();
	getchar();
	return 0;
}


 

驱动代码

 

#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\HbgProcessKillerDriverDev"
#define DRIVER_LINK L"\\??\\HbgProcessKillerDriverLnk"
#define OPERKILLPID CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

// 结构声明
typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	UINT32 SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	UINT32 Flags;
	UINT16 LoadCount;
	UINT16 TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	UINT32 CheckSum;
	UINT32 TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

// 全局变量
PDRIVER_OBJECT g_pDriver;

// 函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath);
VOID DriverUnload(PDRIVER_OBJECT pDriver);
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);
VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PUINT32 uKrnlImageSize);
PVOID MemorySearch(PVOID bytecode, UINT32 bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress);
void KillPid(ULONG uPid, PDRIVER_OBJECT driver);

// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	NTSTATUS status;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL; // 设备对象指针
	UNICODE_STRING DeviceName; // 设备名,0环用
	UNICODE_STRING SymbolicLinkName; // 符号链接名,3环用

	g_pDriver = pDriver;

	// 创建设备名称
	RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
	// 创建设备
	status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);
	if (status != STATUS_SUCCESS)
	{
		IoDeleteDevice(pDeviceObj);
		DbgPrint("创建设备失败.\n");
		return status;
	}
	DbgPrint("创建设备成功.\n");
	// 设置交互数据的方式
	pDeviceObj->Flags |= DO_BUFFERED_IO;
	// 创建符号链接
	RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);
	IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	// 设置分发函数
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;
	// 设置卸载函数
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

// 卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING SymbolicLinkName;
	// 删除符号链接,删除设备
	RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);
	IoDeleteSymbolicLink(&SymbolicLinkName);
	IoDeleteDevice(pDriver->DeviceObject);
	DbgPrint("驱动卸载成功\n");
}

// 不设置这个函数,则Ring3调用CreateFile会返回1
// IRP_MJ_CREATE 处理函数
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_CLOSE 处理函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层断开连接设备.\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_DEVICE_CONTROL 处理函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	// DbgPrint("IrpDeviceControlProc.\n");
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack;
	ULONG uIoControlCode;
	PVOID pIoBuffer;
	ULONG uInLength;
	ULONG uOutLength;
	ULONG uPid; // 要关闭的进程号
	ULONG uRet; // PspTerminateProcess 返回值返回给3环

	// 设置临时变量的值
	uPid = uRet = 0;
	// 获取IRP数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	// 获取控制码
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	// 获取缓冲区地址(输入输出是同一个)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	// Ring3 发送数据的长度
	uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	// Ring0 发送数据的长度
	uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	switch (uIoControlCode)
	{
	case OPERKILLPID:
		{
			// 读取缓冲区
			memcpy(&uPid,pIoBuffer,4);
			// 调用 PspTerminateProcess
			KillPid(uPid,g_pDriver);
			// 写入缓冲区
			memcpy(pIoBuffer, &uRet, 4);
			// 设置状态
			pIrp->IoStatus.Information = 4;
			status = STATUS_SUCCESS;
			break;
		}
	}

	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// 获取内核基址,大小
VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PUINT32 uKrnlImageSize)
{
	PLDR_DATA_TABLE_ENTRY pLdteHead; // 内核模块链表头
	PLDR_DATA_TABLE_ENTRY pLdteCur; // 遍历指针
	UNICODE_STRING usKrnlBaseDllName; // 内核模块名

	RtlInitUnicodeString(&usKrnlBaseDllName,L"ntoskrnl.exe");
	pLdteHead = (PLDR_DATA_TABLE_ENTRY)driver->DriverSection;
	pLdteCur = pLdteHead;
	do 
	{
		PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
		//DbgPrint("DllBase: %p, SizeOfImage: %08X %wZ\n", pLdteCur->DllBase, pLdteCur->SizeOfImage, &(pLdteCur->FullDllName));
		if (RtlCompareUnicodeString(&pLdteCur->BaseDllName, &usKrnlBaseDllName, TRUE) == 0)
		{
			*pKrnlBase = pLdteCur->DllBase;
			*uKrnlImageSize = pLdteCur->SizeOfImage;
			return;
		}
		pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink;
	} while (pLdteHead != pLdteCur);
	return;
}

// 特征码搜索
PVOID MemorySearch(PVOID bytecode, UINT32 bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress)
{
	PVOID pCur = pBeginAddress;
	while (pCur != pEndAddress)
	{
		if (RtlCompareMemory(bytecode,pCur,bytecodeLen) == bytecodeLen)
		{
			return pCur;
		}
		((UINT32)pCur)++;
	}
	return 0;
}

// 杀进程
void KillPid(ULONG uPid, PDRIVER_OBJECT driver)
{
	typedef NTSTATUS (*_PspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode);
	_PspTerminateProcess PspTerminateProcess;
	UINT32 bytecode[] = {
		0x0124a164, 0x758b0000, 0x44703b08, 0x0db80775,
		0xebc00000, 0xbe8d575a, 0x00000248, 0x200147f6,
		0x868d1274, 0x00000174
	};
	PVOID pKrnlBase; // 内核基址
	UINT32 uKrnlImageSize; // 内核大小
	PEPROCESS pEprocess; // 要关闭的进程的EPROCESS

	// 获取内核模块基址和大小
	GetKernelBase(driver, &pKrnlBase, &uKrnlImageSize);
	//DbgPrint("内核基址: %p,大小: %X\n", pKrnlBase, uKrnlImageSize);
	// 获取 PspTerminateProcess 函数地址
	PspTerminateProcess = (_PspTerminateProcess)((UINT32)MemorySearch( \
		bytecode,sizeof(bytecode),pKrnlBase,(PVOID)((UINT32)pKrnlBase+uKrnlImageSize)) - 6);
	//DbgPrint("PspTerminateProcess: %p\n", PspTerminateProcess);
	// 根据PID获取EPROCESS
	PsLookupProcessByProcessId((HANDLE)uPid,&pEprocess);
	// 调用 PspTerminateProcess 关闭进程
	PspTerminateProcess(pEprocess, 0);
}

 

关进程前
在这里插入图片描述

 

关进程后

 

在这里插入图片描述


---------------------
作者:hambaga
来源:CSDN
原文:https://blog.csdn.net/Kwansy/article/details/109170129
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值