返回顶部
扩大
缩小

Zhang_derek

二、驱动

二、驱动

2.1.hello world

1.创建项目

2.删除Driver Files里面的helloworld.inf文件

3.右键属性

Inf2Cat->General->Run Inf2Cat 改成否
Driver Settings->General->Traget OS VERSION和Target Platform改成对一个的平台
C/C++ -->常规->警告等级改为3,将警告视为错误改成否
C/C++ -->代码生成-->Spectre Mitigation改为Disabled

4.helloworld.c

#include <ntifs.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("卸载驱动\r\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	pDriver->DriverUnload = DriverUnload;
	DbgPrint("加载驱动\r\n");
	DbgPrint("注册表路劲:%wZ\r\n",pReg);

	return STATUS_SUCCESS;
}

2.2.驱动基础

1.字符串函数

1.RtiInitString初始化多字节ascii
2.RtiInitUnicodestring初始化宽字符
3.RtlFreeUnicodeString释放uncode字符串
4.RtlStringCbPrintfA格式化输出记得引用#include <ntstrsafe.h
5.RtiCoipareunicodestring字特串比较

2.申请内存

ExAllocatePool   #申请内存
ExFreePool		 #释放内存

3.创建线程

PsCreateSystemThread    #创建线程

2.3.链表

LIST_ENTRY

typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

节点

 struct MYNODE{
	LIST_ENTRY ListEntry;
	int data;
 };

操作

InitializeListHead  初始化链表头 
IsListEmpty			判断链表是否为空 
InsertHeadList		从链表头部插入节点 
InsertTailList		从链表尾部插入节点 
RemoveHeadList		从链表头部删除节点 
RemoveTailList		从链表尾部删除节点

二叉树

#include <ntifs.h>


typedef struct _AAA 
{
	int id;
	int y;
	int x;
}AAA,*PAAA;

RTL_GENERIC_TABLE gTABLE = {0};

RTL_GENERIC_COMPARE_RESULTS NTAPI GenericCmp(
	_In_ struct _RTL_GENERIC_TABLE *Table,
	_In_ PVOID FirstStruct,
	_In_ PVOID SecondStruct
)
{
	PAAA  a1 = (PAAA)FirstStruct;
	PAAA  a2 = (PAAA)SecondStruct;
	if (a1->id == a2->id)
	{
		return GenericEqual;
	}

	if (a1->id > a2->id) return GenericGreaterThan;
	return GenericLessThan;
	
}

PVOID NTAPI GenericAllocate(
	_In_ struct _RTL_GENERIC_TABLE *Table,
	_In_ CLONG ByteSize
)
{
	return ExAllocatePool(NonPagedPool, ByteSize);
}

VOID NTAPI GenericFree(
	_In_ struct _RTL_GENERIC_TABLE *Table,
	_In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer
)
{
	ExFreePool(Buffer);
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	
	AAA aaa = { 1,2,3 };
	AAA aaa1 = { 2,4,5 };
	AAA aaa2 = { 3,6,7 };
	AAA aaa3 = {4,8,9};

	//初始化二叉树
	RtlInitializeGenericTable(&gTABLE, GenericCmp, GenericAllocate, GenericFree, NULL);

	
	BOOLEAN newE = FALSE;
	//插入
	RtlInsertElementGenericTable(&gTABLE, &aaa, sizeof(AAA), &newE);
	RtlInsertElementGenericTable(&gTABLE, &aaa1, sizeof(AAA), &newE);
	RtlInsertElementGenericTable(&gTABLE, &aaa2, sizeof(AAA), &newE);
	RtlInsertElementGenericTable(&gTABLE, &aaa3, sizeof(AAA), &newE);

	AAA node = {3,0,0};

	//查找
	AAA * xxx = RtlLookupElementGenericTable(&gTABLE, &node);

	//获取元素个数
	int number = RtlNumberGenericTableElements(&gTABLE);

	AAA *RestartKey = NULL;
	AAA* xx = 0;

	//判断树是否空
	if (!RtlIsGenericTableEmpty(&gTABLE))
	{
		//遍历
		for (xx = RtlEnumerateGenericTableWithoutSplaying(&gTABLE, &RestartKey);
			xx != NULL;
			xx = RtlEnumerateGenericTableWithoutSplaying(&gTABLE, &RestartKey))
		{
			DbgPrintEx(77, 0, "%x\r\n", xx->id);
		}
	}
	
	//删除
	RtlDeleteElementGenericTable(&gTABLE, &node);

	node.id = 3;
	xxx = RtlLookupElementGenericTable(&gTABLE, &node);

	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

2.4.驱动断链

断链自身

#include <ntifs.h>

typedef struct _KLDR_DATA_TABLE_ENTRY {
	LIST_ENTRY InLoadOrderLinks;
	ULONG exp;
	ULONG un;
	ULONG NonPagedDebugInfo;
	ULONG DllBase;
	ULONG EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	USHORT LoadCount;
	USHORT __Undefined5;
	ULONG  __Undefined6;
	ULONG  CheckSum;
	ULONG  TimeDateStamp;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;


NTKERNELAPI NTSTATUS ObReferenceObjectByName(
	__in PUNICODE_STRING ObjectName,
	__in ULONG Attributes,
	__in_opt PACCESS_STATE AccessState,
	__in_opt ACCESS_MASK DesiredAccess,
	__in POBJECT_TYPE ObjectType,
	__in KPROCESSOR_MODE AccessMode,
	__inout_opt PVOID ParseContext,
	__out PVOID *Object
);

extern POBJECT_TYPE* IoDriverObjectType;

void DriverHide(PWCH objName)
{
	LARGE_INTEGER in = {0};
	in.QuadPart = -10000 * 5000; //等待5s
	KeDelayExecutionThread(KernelMode,FALSE,&in);

	UNICODE_STRING driverName = { 0 };
	RtlInitUnicodeString(&driverName, objName);
	PDRIVER_OBJECT httpDriver = NULL;
	NTSTATUS status = ObReferenceObjectByName(&driverName, FILE_ALL_ACCESS, 0, 0, *IoDriverObjectType, KernelMode, NULL, httpDriver);
	if (NT_SUCCESS(status))
	{
		PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)httpDriver->DriverSection;
		DbgPrintEx(77,0,"[db]: driver name = %wZ\r\n",&ldr->FullDllName);
		RemoveEntryList(&ldr->InLoadOrderLinks);
		httpDriver->DriverInit = NULL;
		httpDriver->DriverSection = NULL;
		ObDereferenceObject(httpDriver);
	}
	return ;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("卸载驱动\r\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	HANDLE hThread = NULL;
	NTSTATUS status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, DriverHide, L"\\driver\\1.duanlian");
	if (NT_SUCCESS(status))
	{
		NtClose(hThread);
	}
    
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
	
}

断链PCHunter32aq.sys

#include <ntifs.h>

//当系统加载一个驱动时,会为这个驱动建立一个_KLDR_DATA_TABLE_ENTRY结构体,
//DRIVER_OBJECT结构体的DriverSection成员指向这个结构体
//所有驱动的结构体通过InLoadOrderLinks成员链接起来
typedef struct _KLDR_DATA_TABLE_ENTRY {
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY exp;
	ULONG un;
	ULONG NonPagedDebugInfo;
	ULONG DllBase;
	ULONG EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	USHORT LoadCount;
	USHORT __Undefined5;
	ULONG  __Undefined6;
	ULONG  CheckSum;
	ULONG  TimeDateStamp;
} KLDR_DATA_TABLE_ENTRY, * PKLDR_DATA_TABLE_ENTRY;

//根据驱动名字得到驱动对象
NTKERNELAPI NTSTATUS ObReferenceObjectByName(
	__in PUNICODE_STRING ObjectName,
	__in ULONG Attributes,
	__in_opt PACCESS_STATE AccessState,// 访问权限可以写0 写0完全访问不受控制FILE_ALL_ACCESS,
	__in_opt ACCESS_MASK DesiredAccess,
	__in POBJECT_TYPE ObjectType,//对象类型
	__in KPROCESSOR_MODE AccessMode, //内核模式 有三种模式 enum 类型
	__inout_opt PVOID ParseContext,
	__out PVOID* Object     //输出对象 我们要得到的驱动对象
);

extern POBJECT_TYPE* IoDriverObjectType;

void DriverHide(PWCH objName)
{
	LARGE_INTEGER in = { 0 };
	in.QuadPart = -10000 * 5000;
	KeDelayExecutionThread(KernelMode, FALSE, &in);  //线程等待5s

	//初始化驱动名字
	UNICODE_STRING driverName = { 0 };
	RtlInitUnicodeString(&driverName, objName);

	//根据驱动名字得到驱动对象
	PDRIVER_OBJECT httpDriver = NULL;  //驱动对象
	NTSTATUS status = ObReferenceObjectByName(&driverName, FILE_ALL_ACCESS, 0, 0, *IoDriverObjectType, KernelMode, NULL, &httpDriver);

	if (NT_SUCCESS(status))
	{
		PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)httpDriver->DriverSection;
		DbgPrintEx(77, 0, "[db]: driver name = %wZ\r\n", &ldr->FullDllName);
		//断链之前把PCHunter32aq的DriverSetion指向随便一个位置,隐藏驱动的信息
		httpDriver->DriverSection = ldr->InLoadOrderLinks.Flink;
		//断链
		RemoveEntryList(&ldr->InLoadOrderLinks);
		httpDriver->DriverInit = NULL;
		//删除引用计数
		ObDereferenceObject(httpDriver);
	}
	return ;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("卸载驱动\r\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	HANDLE hThread = NULL;
	//创建系统线程
	NTSTATUS status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, DriverHide, L"\\driver\\PCHunter32aq");
	if (NT_SUCCESS(status))
	{
		NtClose(hThread);
	}

	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
	
}

2.5.驱动通信

2.5.1.IRP_MJ_DEVICE_CONTROL

驱动main.c

#include <ntifs.h>

#define DEVICE_NAME L"\\Device\\tongxin"//设备名
#define SYM_NAME    L"\\??\\tongxin"

#define CODE_CTR_INDEX 0x800   //为设备定义一个唯一标识功能号
#define TEST CTL_CODE(FILE_DEVICE_UNKNOWN,CODE_CTR_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制代码


NTSTATUS DefDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;//通知R3,派发已成功
	IoCompleteRequest(Irp, 0);//调用方已完成所有I/O请求处理操作,并将给定的 IRP 返回给 I/O 管理器

	return STATUS_SUCCESS;
}


NTSTATUS Dispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
    //返回一个指向IO_STACK_LOCATION结构的指针
	PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
	//DbgBreakPoint();
    //判断类型是不是这个IRP_MJ_DEVICE_CONTROL
	if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
	{

		int size = ioStack->Parameters.DeviceIoControl.InputBufferLength;
		int OutputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;  
		ULONG IoControlCode = ioStack->Parameters.DeviceIoControl.IoControlCode;  //控制码

		switch (IoControlCode)//判断控制代码
		{
		case TEST:
		{
			int* x = (int*)Irp->AssociatedIrp.SystemBuffer;   //获取R3传过来的参数
			int y = 500;
			DbgPrint("[db]:-------%x----------\r\n", *x);
			memcpy(Irp->AssociatedIrp.SystemBuffer,&y,4);     //写数据也是在这个缓冲区
			Irp->IoStatus.Information = OutputBufferLength;
		}
		break;
		}
	}
	Irp->IoStatus.Status = STATUS_SUCCESS;//设置成功
	IoCompleteRequest(Irp, 0);
	return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING symName = { 0 };
	RtlInitUnicodeString(&symName, SYM_NAME);
	IoDeleteSymbolicLink(&symName);               //删除符号链接
	IoDeleteDevice(pDriver->DeviceObject);        //删除设备
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, DEVICE_NAME);   //初始化设备名

	UNICODE_STRING symName = { 0 };
	RtlInitUnicodeString(&symName, SYM_NAME);     //初始化符号名

	PDEVICE_OBJECT pDevice = NULL;

	//创建一个驱动设备使用的设备对象
	NTSTATUS status = IoCreateDevice(
		pDriver,                           //DriverObject,指向调用者的驱动程序对象的指针
		0,                                //指定要为设备对象的设备扩展分配的驱动程序确定的字节数
		&unName,                          // 命名设备对象
		FILE_DEVICE_UNKNOWN,              //指定设备类型的值
		FILE_DEVICE_SECURE_OPEN,         //提供有关驱动程序设备的附加信息
		FALSE,                          //指定设备对象是否代表独占设备
		&pDevice                        //指向变量的指针,该变量接收指向新创建的DEVICE_OBJECT结构的指针
	);


	if (!NT_SUCCESS(status))
	{
		DbgPrint("[db]:%x\r\n", status);
		//DbgPrintEx(77, 0, "");
		return status;
	}

	//设备名和用户的可见名之间创建符号链接
	status = IoCreateSymbolicLink(&symName, &unName);


	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDevice);
		DbgPrint("[db]:%x\r\n", status);
		return status;
	}

	pDevice->Flags &= ~DO_DEVICE_INITIALIZING;  //xp系统才需要干掉这个位,win7以上系统不需要
	pDevice->Flags |= DO_BUFFERED_IO;

	pDriver->MajorFunction[IRP_MJ_CREATE] = DefDispatch;   //设置回调函数
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DefDispatch;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch;

	pDriver->DriverUnload = DriverUnload;
	return status;
}

r3.cpp

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

#define SYM_NAME    "\\\\.\\tongxin"   //符号名

#define CODE_CTR_INDEX 0x800   //为设备定义一个唯一标识功能号
#define TEST CTL_CODE(FILE_DEVICE_UNKNOWN,CODE_CTR_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制代码

int main()
{
	HANDLE hDevice = CreateFileA(
		SYM_NAME,								 //要创建或打开的文件或设备的名称
		GENERIC_READ | GENERIC_WRITE,			//权限
		FILE_SHARE_READ | FILE_SHARE_WRITE,    //请求的文件或设备的共享模式
		NULL, 
		OPEN_EXISTING,                         //对存在或不存在的文件或设备采取的操作。
		FILE_ATTRIBUTE_NORMAL,				  //文件或设备属性和标志,FILE_ATTRIBUTE_NORMAL是文件最常见的默认值。
		NULL
	);

	int x = 100;
	int y = 0;
	DWORD p = 0;

	BOOL  b = DeviceIoControl(
		hDevice,				//要在其上执行操作的设备的句柄
		TEST,				   //操作的控制代码
		&x,					  //指向包含执行操作所需数据的输入缓冲区的指针
		4,                   //输入缓冲区的大小
		&y,                 //指向输出缓冲区的指针
		4,                 //输出缓冲区的大小
		&p,                //一个指向变量的指针
		NULL
	);     


	CloseHandle(hDevice);
	printf("%d\r\n", y);
	system("pause");
	return 0;
}

测试

先运行驱动,然后运行r3程序,可以看到y值改为500

2.5.2.IRP_MJ_READ

驱动main.c

#include <ntifs.h>

#define DEVICE_NAME L"\\Device\\tongxin"
#define SYM_NAME    L"\\??\\tongxin"


NTSTATUS DefDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(Irp, 0);

	return STATUS_SUCCESS;
}

NTSTATUS ReadDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
	DbgBreakPoint();
	PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
	LARGE_INTEGER ByteOffset = ioStack->Parameters.Read.ByteOffset;
	int Length = ioStack->Parameters.Read.Length;
	int* xxx = Irp->AssociatedIrp.SystemBuffer;
	*xxx = 100;
	Irp->IoStatus.Information = Length;
	Irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(Irp, 0);
	return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING symName = { 0 };
	RtlInitUnicodeString(&symName, SYM_NAME);
	IoDeleteSymbolicLink(&symName);
	IoDeleteDevice(pDriver->DeviceObject);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, DEVICE_NAME);

	UNICODE_STRING symName = { 0 };
	RtlInitUnicodeString(&symName, SYM_NAME);

	PDEVICE_OBJECT pDevice = NULL;

	NTSTATUS status = IoCreateDevice(pDriver, 0, &unName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);

	if (!NT_SUCCESS(status))
	{
		DbgPrint("[db]:%x\r\n", status);

		return status;
	}

	status = IoCreateSymbolicLink(&symName, &unName);


	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDevice);
		DbgPrint("[db]:%x\r\n", status);
		return status;
	}

	pDevice->Flags &= ~DO_DEVICE_INITIALIZING;
	pDevice->Flags |= DO_BUFFERED_IO;

	pDriver->MajorFunction[IRP_MJ_CREATE] = DefDispatch;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DefDispatch;
	pDriver->MajorFunction[IRP_MJ_READ] = ReadDispatch;

	pDriver->DriverUnload = DriverUnload;
	return status;
}

r3.cpp

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

#define SYM_NAME    "\\\\.\\tongxin"

int main()
{
	HANDLE hDevice = CreateFileA(SYM_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	int x = 500;
	DWORD p = 0;

	ReadFile(hDevice, &x, 4, &p, NULL); 

	CloseHandle(hDevice);
	printf("%d\r\n", x);
	system("pause");
	return 0;
}

测试

先运行驱动,然后运行r3程序,可以看到x值改为500

2.6.通信封装

驱动main.c

#include <ntifs.h>
#include <Windowsx.h>

#define DEVICE_NAME L"\\Device\\tongxinfz"
#define SYM_NAME    L"\\??\\tongxinfz"

#define _COMM_ID	0x12345678//设定一个ID进行对比

typedef struct _CommPackage
{
	ULONG64 id;
	ULONG64 code;
	ULONG64 inData;
	ULONG64 inLen;
	ULONG64 outData;
	ULONG64 outLen;
}CommPackage, * PCommPackage;//自己创建一个包,用于通信

typedef NTSTATUS(NTAPI* CommCallback)(PCommPackage package);//定义了一个结构体指针

CommCallback gCommCallback = NULL;//创建一个新的结构体

typedef struct _Test
{
	int x;
}Test, * PTest;

typedef enum _CMD//枚举
{
	TEST = 0,
}CMD;

VOID DriverDestoryComm(PDRIVER_OBJECT  pDriver)
{
	UNICODE_STRING symName = { 0 };
	RtlInitUnicodeString(&symName, SYM_NAME);
	IoDeleteSymbolicLink(&symName);
	if (pDriver->DeviceObject) IoDeleteDevice(pDriver->DeviceObject);
}//销毁符号链接和设备链接	

NTSTATUS DefDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(Irp, 0);
	return STATUS_SUCCESS;
}

NTSTATUS WriteDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
	DbgBreakPoint();
	PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);//返回一个指向IO_STACK_LOCATION结构的指针
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	int Length = ioStack->Parameters.Write.Length;//要写入的数据长度
	if (Length == sizeof(CommPackage) && gCommCallback)//判断这个包是否存在
	{
		PCommPackage package = Irp->AssociatedIrp.SystemBuffer;
		if (package->id == _COMM_ID)//对比ID是不是一样的
			if (MmIsAddressValid(package)) status = gCommCallback(package);
	}

	Irp->IoStatus.Information = 0;
	Irp->IoStatus.Status = status;//完成写入
	IoCompleteRequest(Irp, 0);
	return status;
}

NTSTATUS NTAPI Dispatch(PCommPackage package)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	switch (package->code)//再来根据编号选择执行不同的指令
	{
	case TEST:
	{
		PTest t = (PTest)package->inData;
		t->x = 200;
		DbgPrintEx(77, 0, "[db]:%d\r\n", t->x);//观察是否成功写入
		status = STATUS_SUCCESS;
	}
	break;
	}

	return status;
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	DriverDestoryComm(pDriver);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
	UNICODE_STRING unName = { 0 };
	UNICODE_STRING symName = { 0 };

	RtlInitUnicodeString(&unName, DEVICE_NAME);
	RtlInitUnicodeString(&symName, SYM_NAME);

	PDEVICE_OBJECT pDevice = NULL;

	NTSTATUS status = IoCreateDevice(pDriver, 0, &unName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);

	if (!NT_SUCCESS(status)) {
		KdPrintEx((77, 0, "[db]:%x\r\n", status));
		return status;
	}

	status = IoCreateSymbolicLink(&symName, &unName);

	if (!NT_SUCCESS(status)) {
		IoDeleteDevice(pDevice);
		KdPrintEx((77, 0, "[db]:%x\r\n", status));
	}

	pDevice->Flags &= ~DO_DEVICE_INITIALIZING;
	pDevice->Flags |= DO_BUFFERED_IO;

	pDriver->MajorFunction[IRP_MJ_CREATE] = DefDispatch;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DefDispatch;
	pDriver->MajorFunction[IRP_MJ_WRITE] = WriteDispatch;//与之前的过程相仿

	if (NT_SUCCESS(status))
	{
		gCommCallback = Dispatch;
	}

	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

r3.cpp

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

HANDLE ghDevice;
#define SYM_NAME    L"\\??\\tongxinfz"
typedef struct _CommPackage
{
	ULONG64 id;
	ULONG64 code;
	ULONG64 inData;
	ULONG64 inLen;
	ULONG64 outData;
	ULONG64 outLen;
}CommPackage, * PCommPackage;
#define _COMM_ID	0x12345678

typedef struct _Test
{
	int x;
}Test, * PTest;

typedef enum _CMD
{
	TEST = 0,
}CMD;

int main()
{

	Test x1 = { 0 };
	x1.x = 100;

	ghDevice = CreateFileW(SYM_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (ghDevice == NULL || ghDevice == INVALID_HANDLE_VALUE)
	{
		ghDevice = NULL;
		return 0;
	}

	CommPackage packag;
	packag.code = TEST;
	packag.inData = (ULONG64)&x1;
	packag.inLen = (ULONG64)4;
	packag.outData = (ULONG64)NULL;
	packag.outLen = (ULONG64)NULL;
	DWORD pro = NULL;
	packag.id = _COMM_ID;//构造结构体

	WriteFile(ghDevice, &packag, sizeof(CommPackage), &pro, NULL);
	printf("%d\r\n", x1.x);
	system("pause");
	return 0;
}

2.7.内存加载

Build.cpp


#include <stdlib.h>
#include <stdio.h>
#include <memory.h>

int main(int argc, char* args[], char** env)
{
	if (argc < 2)
	{
		printf("参数不对\r\n");
		printf("举个例子:build.exe dll路径\r\n");
		return 0;
	}

	char* dllpath = args[1];
	FILE* file = NULL;
	fopen_s(&file, dllpath, "rb");

	if (!file)
	{
		printf("文件不存在\r\n");
		return 0;
	}

	//求文件大小
	fseek(file, 0, SEEK_END);
	unsigned int len = ftell(file);

	//绕回到头部文件流指针
	rewind(file);

	unsigned char* filebuffer = (unsigned char*)malloc(len);
	memset(filebuffer, 0, len);

	fread_s(filebuffer, len, len, 1, file);

	fclose(file);

	//创建一个文件 写入我们的硬编码
	if (argc == 2)
	{
		fopen_s(&file, "dll.h", "wb");
	}
	else
	{
		fopen_s(&file, args[2], "wb");
	}

	if (file == NULL)
	{
		free(filebuffer);
		return 0;
	}

	fputs("#pragma once\n", file);

	fprintf_s(file, "unsigned char sysData[%d] = 	{\n", len);
	fprintf_s(file, "\t");
	for (int i = 0; i < len; i++)
	{
		filebuffer[i] ^= 0xcd;
		filebuffer[i] ^= 0xd8;
		fprintf_s(file, "0x%02X, ", filebuffer[i]);
		if ((i + 1) % 30 == 0)
		{
			fprintf_s(file, "\r\n\t");
		}


	}

	fprintf_s(file, "\r\n};");
	fclose(file);

	free(filebuffer);

	return 0;
}

Test/Main.c

#include <ntifs.h>


VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	DbgPrintEx(77, 0, "----------11111111111111111111111111---------------\r\n");
	//pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

PeLoad/tools.h

#pragma once
#include <ntifs.h>

typedef enum _SYSTEM_INFORMATION_CLASS {
	SystemBasicInformation,
	SystemProcessorInformation,             // obsolete...delete
	SystemPerformanceInformation,
	SystemTimeOfDayInformation,
	SystemPathInformation,
	SystemProcessInformation,
	SystemCallCountInformation,
	SystemDeviceInformation,
	SystemProcessorPerformanceInformation,
	SystemFlagsInformation,
	SystemCallTimeInformation,
	SystemModuleInformation,
	SystemLocksInformation,
	SystemStackTraceInformation,
	SystemPagedPoolInformation,
	SystemNonPagedPoolInformation,
	SystemHandleInformation,
	SystemObjectInformation,
	SystemPageFileInformation,
	SystemVdmInstemulInformation,
	SystemVdmBopInformation,
	SystemFileCacheInformation,
	SystemPoolTagInformation,
	SystemInterruptInformation,
	SystemDpcBehaviorInformation,
	SystemFullMemoryInformation,
	SystemLoadGdiDriverInformation,
	SystemUnloadGdiDriverInformation,
	SystemTimeAdjustmentInformation,
	SystemSummaryMemoryInformation,
	SystemMirrorMemoryInformation,
	SystemPerformanceTraceInformation,
	SystemObsolete0,
	SystemExceptionInformation,
	SystemCrashDumpStateInformation,
	SystemKernelDebuggerInformation,
	SystemContextSwitchInformation,
	SystemRegistryQuotaInformation,
	SystemExtendServiceTableInformation,
	SystemPrioritySeperation,
	SystemVerifierAddDriverInformation,
	SystemVerifierRemoveDriverInformation,
	SystemProcessorIdleInformation,
	SystemLegacyDriverInformation,
	SystemCurrentTimeZoneInformation,
	SystemLookasideInformation,
	SystemTimeSlipNotification,
	SystemSessionCreate,
	SystemSessionDetach,
	SystemSessionInformation,
	SystemRangeStartInformation,
	SystemVerifierInformation,
	SystemVerifierThunkExtend,
	SystemSessionProcessInformation,
	SystemLoadGdiDriverInSystemSpace,
	SystemNumaProcessorMap,
	SystemPrefetcherInformation,
	SystemExtendedProcessInformation,
	SystemRecommendedSharedDataAlignment,
	SystemComPlusPackage,
	SystemNumaAvailableMemory,
	SystemProcessorPowerInformation,
	SystemEmulationBasicInformation,
	SystemEmulationProcessorInformation,
	SystemExtendedHandleInformation,
	SystemLostDelayedWriteInformation,
	SystemBigPoolInformation,
	SystemSessionPoolTagInformation,
	SystemSessionMappedViewInformation,
	SystemHotpatchInformation,
	SystemObjectSecurityMode,
	SystemWatchdogTimerHandler,
	SystemWatchdogTimerInformation,
	SystemLogicalProcessorInformation,
	SystemWow64SharedInformation,
	SystemRegisterFirmwareTableInformationHandler,
	SystemFirmwareTableInformation,
	SystemModuleInformationEx,
	SystemVerifierTriageInformation,
	SystemSuperfetchInformation,
	SystemMemoryListInformation,
	SystemFileCacheInformationEx,
	MaxSystemInfoClass  // MaxSystemInfoClass should always be the last enum
} SYSTEM_INFORMATION_CLASS;

typedef struct _RTL_PROCESS_MODULE_INFORMATION {
	HANDLE Section;                 // Not filled in
	PVOID MappedBase;
	PVOID ImageBase;
	ULONG ImageSize;
	ULONG Flags;
	USHORT LoadOrderIndex;
	USHORT InitOrderIndex;
	USHORT LoadCount;
	USHORT OffsetToFileName;
	UCHAR  FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
	ULONG NumberOfModules;
	RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;


NTSTATUS ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,
	void* SystemInformation, ULONG SystemInformationLength, ULONG* ReturnLength);

PIMAGE_NT_HEADERS RtlImageNtHeader(void* Base);



ULONG_PTR QueryModule(PUCHAR moduleName, ULONG_PTR* moduleSize);

PeLoad/tool.c

#include "tools.h"



ULONG_PTR QueryModule(PUCHAR moduleName, ULONG_PTR* moduleSize)
{
	if (moduleName == NULL) return 0;

	RTL_PROCESS_MODULES rtlMoudles = { 0 };
	PRTL_PROCESS_MODULES SystemMoudles = &rtlMoudles;
	BOOLEAN isAllocate = FALSE;
	//测量长度
	ULONG* retLen = 0;
	NTSTATUS status = ZwQuerySystemInformation(SystemModuleInformation, SystemMoudles, sizeof(RTL_PROCESS_MODULES), &retLen);

	//分配实际长度内存
	if (status == STATUS_INFO_LENGTH_MISMATCH)
	{
		SystemMoudles = ExAllocatePool(PagedPool, retLen + sizeof(RTL_PROCESS_MODULES));
		if (!SystemMoudles) return 0;

		memset(SystemMoudles, 0, retLen + sizeof(RTL_PROCESS_MODULES));

		status = ZwQuerySystemInformation(SystemModuleInformation, SystemMoudles, retLen + sizeof(RTL_PROCESS_MODULES), &retLen);

		if (!NT_SUCCESS(status))
		{
			ExFreePool(SystemMoudles);
			return 0;
		}

		isAllocate = TRUE;
	}

	PUCHAR kernelModuleName = NULL;
	ULONG_PTR moudleBase = 0;

	do
	{


		if (_stricmp(moduleName, "ntoskrnl.exe") == 0 || _stricmp(moduleName, "ntkrnlpa.exe") == 0)
		{
			PRTL_PROCESS_MODULE_INFORMATION moudleInfo = &SystemMoudles->Modules[0];
			moudleBase = moudleInfo->ImageBase;
			if (moduleSize) *moduleSize = moudleInfo->ImageSize;

			break;
		}


		kernelModuleName = ExAllocatePool(PagedPool, strlen(moduleName) + 1);
		memset(kernelModuleName, 0, strlen(moduleName) + 1);
		memcpy(kernelModuleName, moduleName, strlen(moduleName));
		_strupr(kernelModuleName);


		for (int i = 0; i < SystemMoudles->NumberOfModules; i++)
		{
			PRTL_PROCESS_MODULE_INFORMATION moudleInfo = &SystemMoudles->Modules[i];

			PUCHAR pathName = _strupr(moudleInfo->FullPathName);
			DbgPrintEx(77, 0, "baseName = %s,fullPath = %s\r\n",
				moudleInfo->FullPathName + moudleInfo->OffsetToFileName, moudleInfo->FullPathName);


			if (strstr(pathName, kernelModuleName))
			{
				moudleBase = moudleInfo->ImageBase;
				if (moduleSize) *moduleSize = moudleInfo->ImageSize;
				break;
			}

		}

	} while (0);


	if (kernelModuleName)
	{
		ExFreePool(kernelModuleName);
	}

	if (isAllocate)
	{
		ExFreePool(SystemMoudles);
	}

	return moudleBase;
}

PeLoad/Loader.h

#pragma once
#include <ntifs.h>

BOOLEAN UpdataIAT(char* imageBuffer);

BOOLEAN LoadDriver(PUCHAR fileBuffer);

PeLoad/Loader.c

#include "Loader.h"
#include <ntimage.h>
#include "tools.h"



typedef NTSTATUS(NTAPI* DriverEntryProc)(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg);

typedef struct _IMAGE_RELOC
{
	UINT16	Offset : 12;		// 低12位---偏移
	UINT16	Type : 4;			// 高4位---类型
} IMAGE_RELOC, * PIMAGE_RELOC;

PUCHAR FileToImage(char* fileBuffer)
{
	if (!fileBuffer) return NULL;

	PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)fileBuffer;
	PIMAGE_NT_HEADERS pNts = (PIMAGE_NT_HEADERS)(fileBuffer + pDos->e_lfanew);

	//创建imageBuffer
	ULONG sizeofImage = pNts->OptionalHeader.SizeOfImage;
	PUCHAR imageBuffer = ExAllocatePool(NonPagedPool, sizeofImage);
	memset(imageBuffer, 0, sizeofImage);

	//复制PE头
	memcpy(imageBuffer, fileBuffer, pNts->OptionalHeader.SizeOfHeaders);

	ULONG NumberOfSections = pNts->FileHeader.NumberOfSections;

	PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNts);

	//拉伸PE 结构
	for (ULONG i = 0; i < NumberOfSections; i++)
	{
		memcpy(imageBuffer + pSection->VirtualAddress, fileBuffer + pSection->PointerToRawData, pSection->SizeOfRawData);
		pSection++;
	}

	return imageBuffer;
}

//获取到 LoadLibraryExW
ULONG64 ExportTableFuncByName(char* pData, char* funcName)
{
	PIMAGE_DOS_HEADER pHead = (PIMAGE_DOS_HEADER)pData;
	PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pData + pHead->e_lfanew);
	int numberRvaAndSize = pNt->OptionalHeader.NumberOfRvaAndSizes;
	PIMAGE_DATA_DIRECTORY pDir = (PIMAGE_DATA_DIRECTORY)&pNt->OptionalHeader.DataDirectory[0];

	PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(pData + pDir->VirtualAddress);

	ULONG64 funcAddr = 0;
	for (int i = 0; i < pExport->NumberOfNames; i++)
	{
		int* funcAddress = pData + pExport->AddressOfFunctions;
		int* names = pData + pExport->AddressOfNames;
		short* fh = pData + pExport->AddressOfNameOrdinals;
		int index = -1;
		char* name = pData + names[i];

		if (strcmp(name, funcName) == 0)
		{
			index = fh[i];
		}



		if (index != -1)
		{
			funcAddr = pData + funcAddress[index];
			break;
		}


	}

	if (!funcAddr)
	{
		KdPrint(("没有找到函数%s\r\n", funcName));

	}
	else
	{
		KdPrint(("找到函数%s addr %p\r\n", funcName, funcAddr));
	}


	return funcAddr;
}

BOOLEAN UpdataRelocation(char* imageBuffer)
{
	PIMAGE_NT_HEADERS pNts = RtlImageNtHeader(imageBuffer);
	if (!pNts) return FALSE;

	PIMAGE_DATA_DIRECTORY iRelocation = &pNts->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

	PIMAGE_BASE_RELOCATION pBase = (PIMAGE_BASE_RELOCATION)(imageBuffer + iRelocation->VirtualAddress);

	while (pBase->SizeOfBlock && pBase->VirtualAddress)
	{

		PIMAGE_RELOC RelocationBlock = (PIMAGE_RELOC)((PUCHAR)pBase + sizeof(IMAGE_BASE_RELOCATION));

		UINT32	NumberOfRelocations = (pBase->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);

		for (int i = 0; i < NumberOfRelocations; i++)
		{
			if (RelocationBlock[i].Type == IMAGE_REL_BASED_DIR64)
			{

				// 64 位
				PUINT64	Address = (PUINT64)((PUINT8)imageBuffer + pBase->VirtualAddress + RelocationBlock[i].Offset);
				UINT64	Delta = *Address - pNts->OptionalHeader.ImageBase + (PUINT8)imageBuffer;
				*Address = Delta;
			}
			else if (RelocationBlock[i].Type == IMAGE_REL_BASED_HIGHLOW)
			{

				PUINT32	Address = (PUINT32)((PUINT8)imageBuffer + pBase->VirtualAddress + (RelocationBlock[i].Offset));
				UINT32	Delta = *Address - pNts->OptionalHeader.ImageBase + (PUINT8)imageBuffer;
				*Address = Delta;
			}
		}

		pBase = (PIMAGE_BASE_RELOCATION)((PUCHAR)pBase + pBase->SizeOfBlock);
	}

	return TRUE;

}

BOOLEAN UpdataIAT(char* imageBuffer)
{
	if (!imageBuffer) return FALSE;

	PIMAGE_NT_HEADERS pNts = RtlImageNtHeader(imageBuffer);
	if (!pNts) return FALSE;

	PIMAGE_DATA_DIRECTORY pimportDir = &pNts->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	PIMAGE_IMPORT_DESCRIPTOR import = (PIMAGE_IMPORT_DESCRIPTOR)(imageBuffer + pimportDir->VirtualAddress);

	BOOLEAN isSuccess = TRUE;

	for (; import->Name; import++)
	{
		PUCHAR libName = (imageBuffer + import->Name);
		ULONG_PTR base = QueryModule(libName, NULL);
		if (!base)
		{
			isSuccess = FALSE;
			break;
		}

		PIMAGE_THUNK_DATA pThuckName = (PIMAGE_THUNK_DATA)(imageBuffer + import->OriginalFirstThunk);
		PIMAGE_THUNK_DATA pThuckFunc = (PIMAGE_THUNK_DATA)(imageBuffer + import->FirstThunk);

		for (; pThuckName->u1.ForwarderString; ++pThuckName, ++pThuckFunc)
		{
			PIMAGE_IMPORT_BY_NAME FuncName = (PIMAGE_IMPORT_BY_NAME)(imageBuffer + pThuckName->u1.AddressOfData);

			ULONG_PTR func = ExportTableFuncByName((char*)base, FuncName->Name);
			if (func)
			{
				pThuckFunc->u1.Function = (ULONG_PTR)func;
			}
			else
			{
				isSuccess = FALSE;
				break;
			}
		}

		if (!isSuccess) break;

	}

	return isSuccess;
}

VOID UpdateCookie(char* imageBuffer)
{
	//DbgBreakPoint();
	if (!imageBuffer) return FALSE;

	PIMAGE_NT_HEADERS pNts = RtlImageNtHeader(imageBuffer);
	if (!pNts) return FALSE;

	PIMAGE_DATA_DIRECTORY pConfigDir = &pNts->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];

	PIMAGE_LOAD_CONFIG_DIRECTORY config = (PIMAGE_LOAD_CONFIG_DIRECTORY)(pConfigDir->VirtualAddress + imageBuffer);

	*(PULONG)(config->SecurityCookie) += 10;

}

BOOLEAN LoadDriver(PUCHAR fileBuffer)
{
	PUCHAR imageBase = FileToImage(fileBuffer);
	if (!imageBase) return FALSE;

	BOOLEAN isSuccess = FALSE;

	do
	{
		isSuccess = UpdataRelocation(imageBase);
		if (!isSuccess) break;

		isSuccess = UpdataIAT(imageBase);
		if (!isSuccess) break;

		//修复cookie
		UpdateCookie(imageBase);

		//call 入口点
		PIMAGE_NT_HEADERS pNts = RtlImageNtHeader(imageBase);

		ULONG_PTR entry = pNts->OptionalHeader.AddressOfEntryPoint;
		DriverEntryProc EntryPointFunc = (DriverEntryProc)(imageBase + entry);
		NTSTATUS status = EntryPointFunc(NULL, NULL);
		if (!NT_SUCCESS(status))
		{
			isSuccess = FALSE;
			break;
		}


		//清空PE头
		memset(imageBase, 0, PAGE_SIZE);

	} while (0);



	if (!isSuccess)
	{
		ExFreePool(imageBase);

	}

	return isSuccess;
}

PeLoad/DriverMain.c

#include <ntifs.h>
#include "tools.h"
#include "Loader.h"
#include "dll.h"

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	ULONG dwImageSize = sizeof(sysData);
	unsigned char* pMemory = (unsigned char*)ExAllocatePool(NonPagedPool, dwImageSize);
	memcpy(pMemory, sysData, dwImageSize);
	for (ULONG i = 0; i < dwImageSize; i++)
	{
		pMemory[i] ^= 0xDE;
		pMemory[i] ^= 0x73;
	}
	QueryModule(" ", NULL);
	DbgBreakPoint();
	LoadDriver(pMemory);
	ExFreePool(pMemory);
	pDriver->DriverUnload = DriverUnload;
	return STATUS_UNSUCCESSFUL;
}

encode.bat

set "projectpath=%cd%"
cd ../
set "preProjectpath=%cd%"
cd %projectpath%
set "SignFullPath=%preProjectpath%/Debug/Test.sys"
Build.exe %SignFullPath%

posted on 2022-08-10 01:22  zhang_derek  阅读(415)  评论(0编辑  收藏  举报

导航