二、驱动
2.1.hello world
1.创建项目
2.删除Driver Files里面的helloworld.inf文件
3.右键属性
代码语言:javascript复制Inf2Cat->General->Run Inf2Cat 改成否
Driver Settings->General->Traget OS VERSION和Target Platform改成对一个的平台
C/C -->常规->警告等级改为3,将警告视为错误改成否
C/C -->代码生成-->Spectre Mitigation改为Disabled
4.helloworld.c
代码语言:javascript复制#include <ntifs.h>
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("卸载驱动rn");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
pDriver->DriverUnload = DriverUnload;
DbgPrint("加载驱动rn");
DbgPrint("注册表路劲:%wZrn",pReg);
return STATUS_SUCCESS;
}
2.2.驱动基础
1.字符串函数
代码语言:javascript复制1.RtiInitString初始化多字节ascii
2.RtiInitUnicodestring初始化宽字符
3.RtlFreeUnicodeString释放uncode字符串
4.RtlStringCbPrintfA格式化输出记得引用#include <ntstrsafe.h
5.RtiCoipareunicodestring字特串比较
2.申请内存
代码语言:javascript复制ExAllocatePool #申请内存
ExFreePool #释放内存
3.创建线程
代码语言:javascript复制PsCreateSystemThread #创建线程
2.3.链表
LIST_ENTRY
代码语言:javascript复制typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
节点
代码语言:javascript复制 struct MYNODE{
LIST_ENTRY ListEntry;
int data;
};
操作
代码语言:javascript复制InitializeListHead 初始化链表头
IsListEmpty 判断链表是否为空
InsertHeadList 从链表头部插入节点
InsertTailList 从链表尾部插入节点
RemoveHeadList 从链表头部删除节点
RemoveTailList 从链表尾部删除节点
二叉树
代码语言:javascript复制#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, "%xrn", xx->id);
}
}
//删除
RtlDeleteElementGenericTable(&gTABLE, &node);
node.id = 3;
xxx = RtlLookupElementGenericTable(&gTABLE, &node);
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
2.4.驱动断链
断链自身
代码语言:javascript复制#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 = %wZrn",&ldr->FullDllName);
RemoveEntryList(&ldr->InLoadOrderLinks);
httpDriver->DriverInit = NULL;
httpDriver->DriverSection = NULL;
ObDereferenceObject(httpDriver);
}
return ;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("卸载驱动rn");
}
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
代码语言:javascript复制#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 = %wZrn", &ldr->FullDllName);
//断链之前把PCHunter32aq的DriverSetion指向随便一个位置,隐藏驱动的信息
httpDriver->DriverSection = ldr->InLoadOrderLinks.Flink;
//断链
RemoveEntryList(&ldr->InLoadOrderLinks);
httpDriver->DriverInit = NULL;
//删除引用计数
ObDereferenceObject(httpDriver);
}
return ;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("卸载驱动rn");
}
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
代码语言:javascript复制#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----------rn", *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]:%xrn", status);
//DbgPrintEx(77, 0, "");
return status;
}
//设备名和用户的可见名之间创建符号链接
status = IoCreateSymbolicLink(&symName, &unName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDevice);
DbgPrint("[db]:%xrn", 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
代码语言:javascript复制#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("%drn", y);
system("pause");
return 0;
}
测试
先运行驱动,然后运行r3程序,可以看到y值改为500
2.5.2.IRP_MJ_READ
驱动main.c
代码语言:javascript复制#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]:%xrn", status);
return status;
}
status = IoCreateSymbolicLink(&symName, &unName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDevice);
DbgPrint("[db]:%xrn", 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
代码语言:javascript复制#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("%drn", x);
system("pause");
return 0;
}
测试
先运行驱动,然后运行r3程序,可以看到x值改为500
2.6.通信封装
驱动main.c
代码语言:javascript复制#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]:%drn", 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]:%xrn", status));
return status;
}
status = IoCreateSymbolicLink(&symName, &unName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(pDevice);
KdPrintEx((77, 0, "[db]:%xrn", 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
代码语言:javascript复制#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("%drn", x1.x);
system("pause");
return 0;
}
2.7.内存加载
Build.cpp
代码语言:javascript复制#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
int main(int argc, char* args[], char** env)
{
if (argc < 2)
{
printf("参数不对rn");
printf("举个例子:build.exe dll路径rn");
return 0;
}
char* dllpath = args[1];
FILE* file = NULL;
fopen_s(&file, dllpath, "rb");
if (!file)
{
printf("文件不存在rn");
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 oncen", 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, "0xX, ", filebuffer[i]);
if ((i 1) % 30 == 0)
{
fprintf_s(file, "rnt");
}
}
fprintf_s(file, "rn};");
fclose(file);
free(filebuffer);
return 0;
}
Test/Main.c
代码语言:javascript复制#include <ntifs.h>
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
DbgPrintEx(77, 0, "----------11111111111111111111111111---------------rn");
//pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
PeLoad/tools.h
代码语言:javascript复制#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
代码语言:javascript复制#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 = %srn",
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
代码语言:javascript复制#pragma once
#include <ntifs.h>
BOOLEAN UpdataIAT(char* imageBuffer);
BOOLEAN LoadDriver(PUCHAR fileBuffer);
PeLoad/Loader.c
代码语言:javascript复制#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(("没有找到函数%srn", funcName));
}
else
{
KdPrint(("找到函数%s addr %prn", 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
代码语言:javascript复制#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
代码语言:javascript复制set "projectpath=�%"
cd ../
set "preProjectpath=�%"
cd %projectpath%
set "SignFullPath=%preProjectpath%/Debug/Test.sys"
Build.exe %SignFullPath%