二、驅動 2.1.hello world 1.創建項目 2.刪除Driver Files裡面的helloworld.inf文件 3.右鍵屬性 Inf2Cat->General->Run Inf2Cat 改成否 Driver Settings->General->Traget OS VERSION和T ...
2.1.hello world
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;
}
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%
作者:zhang_derek
出處:http://www.cnblogs.com/derek1184405959/
github:https://github.com/derek-zhang123
個性簽名:其實人跟樹一樣,越是嚮往高處的陽光,它的根就越要伸向黑暗的地底。