二、驅動

来源:https://www.cnblogs.com/derek1184405959/archive/2022/08/10/16570808.html
-Advertisement-
Play Games

二、驅動 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

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%
作者:zhang_derek 出處:http://www.cnblogs.com/derek1184405959/ github:https://github.com/derek-zhang123
個性簽名:其實人跟樹一樣,越是嚮往高處的陽光,它的根就越要伸向黑暗的地底。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前兩天一個鄰居發出了靈魂質問:“為什麼我買的180平和你的169平看上去一樣大?” “因為咱倆的套內面積都是138平......” 我們去看房子,比較不同樓盤的價格,看的都是單價,可這個單價,卻是用(總價 ÷ 建築面積)計算的。而我們實際買到手裡的,是套內面積。 套內面積 = 使用面積+牆體厚度+陽 ...
  • 線程本地存儲 · 語雀 (yuque.com) 線程本地存儲提供了線程記憶體儲變數的能力,這些變數是線程私有的。 線程本地存儲一般用在跨類、跨方法的傳遞一些值。 線程本地存儲也是解決特定場景下線程安全問題的思路之一(每個線程都訪問本線程自己的變數)。 Java 語言提供了線程本地存儲,ThreadLo ...
  • 在大部分涉及到資料庫操作的項目裡面,事務控制、事務處理都是一個無法迴避的問題。這裡我們一起探討下關於事務控制相關的一些內容。 ...
  • 來源: blog.csdn.net/fumitzuki/article/details/81630048 volatile關鍵字是由JVM提供的最輕量級同步機制。與被濫用的synchronized不同,我們並不習慣使用它。想要正確且完全的理解它並不容易。 Part1Java記憶體模型 Java記憶體模型 ...
  • 多商戶商城系統,也稱為B2B2C(BBC)平臺電商模式多商家商城系統。可以快速幫助企業搭建類似拼多多/京東/天貓/淘寶的綜合商城。 多商戶商城系統支持商家入駐加盟,同時滿足平臺自營、旗艦店等多種經營方式。平臺可以通過收取商家入駐費,訂單交易服務費,提現手續費,簡訊通道費等多手段方式,實現整體盈利。 ...
  • [演算法1-排序](.NET源碼學習)& LINQ & Lambda 說起排序演算法,在日常實際開發中我們基本不在意這些事情,有API不用不是沒事找事嘛。但必要的基礎還是需要瞭解掌握。 排序的目的是為了讓無序的數據,變得“有序”。此處的有序指的是,滿足當前使用需求的順序,除了自帶的API,我們還可以自定 ...
  • 作為一個沒有系統學習過依賴註入的開發者而言,如果直接在一個使用依賴註入的框架下進行開發,往往對於依賴註入的存在是沒有明顯的察覺,通過代碼追根溯源你都會看不出對象是從哪裡創建的。但這並不影響你進行開發的工作,你可以參照現有代碼的使用形式,將需要使用的對象加入到構造函數的參數列表上,你就可以使用對象,調 ...
  • PDF/X-1a是一種PDF文件規範標準,在製作、使用PDF以及印刷時所需要遵循的技術條件,屬於PDF/X-1標準下的一個子標準。 PDF/X-1標準有由CGATS於1999年制定的PDF/X-1:1999,由ISO於2001年制的PDF/X-1:2001、PDF/X-1a:2001以及PDF/X- ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...