InlineHookInRing0

一、NtCreateFile

0环:

#include <ntifs.h>
 
// 系统调用号
// NtCreateFile 0x25
#define SYSCODE 0x25
 
PVOID g_pHookMemAddr;//InlineHook跳转地址
ULONG g_dwKernelFuncAddr;//内核函数的地址
 
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
	PULONG ServiceTableBase;			// 函数地址表
	PULONG ServiceCounterTableBase;		// SSDT 函数被调用的次数
	ULONG NumberOfService;				// 函数个数
	PULONG ParamTableBase;				// 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
 
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
	KSYSTEM_SERVICE_TABLE ntoskrnl;		// 内核函数
	KSYSTEM_SERVICE_TABLE win32k;		// win32k.sys 函数
	KSYSTEM_SERVICE_TABLE unUsed1;
	KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr);
// HOOK后的执行函数
VOID __stdcall RealFunc();
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	ULONG dwExecFuncAddr;//执行函数地址
 
	DbgPrint("驱动已启动\r\n");
	pDriver->DriverUnload = DriverUnload;
 
	//获取执行函数的地址
	dwExecFuncAddr = (ULONG)RealFunc;
	//修正函数地址
	if (*(PUCHAR)dwExecFuncAddr == 0xe9)
	{
		DbgPrint("执行函数的地址,修正前:0x%.8x\r\n",dwExecFuncAddr);
		dwExecFuncAddr = *(PULONG)(dwExecFuncAddr + 1) - (dwExecFuncAddr + 5);
		DbgPrint("执行函数的地址,修正后:0x%.8x\r\n",dwExecFuncAddr);
	}
	else
	{
		DbgPrint("执行函数的地址,无需修正\r\n");
	}	
 
	//根据系统调用号找到内核函数的地址
	g_dwKernelFuncAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
	DbgPrint("NtCreateFile函数地址:0x%.8x\r\n",g_dwKernelFuncAddr);
 
	//HOOK
	if (!Hook(g_dwKernelFuncAddr,dwExecFuncAddr))
	{
		return STATUS_UNSUCCESSFUL;
	}
 
	return STATUS_SUCCESS;
}
 
// 关闭页保护
VOID PageProtectOff()
{
	__asm
	{
		cli; // 关闭中断
		mov eax, cr0;
		and eax, not 0x10000; // WP位置0
		mov cr0, eax;
	}
}
 
// 开启页保护
VOID PageProtectOn()
{
	__asm
	{
		mov eax, cr0;
		or eax, 0x10000; // WP位置1
		mov cr0, eax;
		sti; // 恢复中断
	}
}
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	//UN-HOOK
	UnHook(g_dwKernelFuncAddr);
 
	//释放内存
	ExFreePool(g_pHookMemAddr);
 
	DbgPrint("驱动已停止\r\n");
}
 
// HOOK过程
// 将dwSrc函数HOOK至Dst函数
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr)
{
	ULONG i;//for循环的参数
	ULONG dwJumpPara;//E9Jmp的参数
	ULONG dwCallPara;//E8Call参数
 
	DbgPrint("\r\nHook\r\n");
 
	//申请内存
	g_pHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
	if (g_pHookMemAddr == NULL)
	{
		DbgPrint("\r\nExAllocatePool失败\r\n");
		return FALSE;
	}
	DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pHookMemAddr);
	RtlFillMemory(g_pHookMemAddr, 0x100, 0x90);
 
	//DbgBreakPoint();
 
	//pushad pushfd
	*((PUCHAR)g_pHookMemAddr + 0) = 0x60;//pushad
	*((PUCHAR)g_pHookMemAddr + 1) = 0x9c;//pushfd
 
	//int 3
	*((PUCHAR)g_pHookMemAddr + 2) = 0x90;//int 3
 
	//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(RealFunc)
	DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
	*((PUCHAR)g_pHookMemAddr + 3) = 0xe8;//call
	dwCallPara = dwDstFuncAddr - ((ULONG)g_pHookMemAddr + 3 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)((ULONG)g_pHookMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
	}
 
	//popfd popad
	*((PUCHAR)g_pHookMemAddr + 8) = 0x9d;//popfd
	*((PUCHAR)g_pHookMemAddr + 9) = 0x61;//popad
 
	//DbgBreakPoint();
 
	//保存内核函数前5字节的数据到申请的内存区域偏移+10处
	DbgPrint("\r\n保存内核函数前5字节的数据到申请的内存空间中\r\n");
	for (i = 0; i < 5; i++)
	{
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
		*((PUCHAR)g_pHookMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
		DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, (ULONG)g_pHookMemAddr + 10 + i, *((PUCHAR)g_pHookMemAddr + 10 + i));
	}
 
	//DbgBreakPoint();
 
	//在申请的内存空间偏移+15处编辑ShellCode:Jump Back To KernelFuncAddr + 5
	DbgPrint("\r\n在申请的内存空间偏移+15处编辑ShellCode:Jump Back To KernelFuncAddr + 5\r\n");
	*((PUCHAR)g_pHookMemAddr + 15) = 0xe9;//jmp
	dwJumpPara = dwSrcFuncAddr + 5 - ((ULONG)g_pHookMemAddr + 15 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)((ULONG)g_pHookMemAddr + 15 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
	}
 
	//DbgBreakPoint();
 
	//修改内核函数前5字节进行InlineHook
	DbgPrint("\r\n修改内核函数前5字节\r\n关闭页保护\r\n");
	PageProtectOff();
	*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
	DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
 
	//跳转至申请的内存区域偏移+0处的Jmp参数
	dwJumpPara = (ULONG)g_pHookMemAddr - (dwSrcFuncAddr + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
	}
	DbgPrint("开启页保护\r\n");
	PageProtectOn();
 
	//披露重要数据
	DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n",dwSrcFuncAddr,g_pHookMemAddr,dwDstFuncAddr);
 
	return TRUE;
}
 
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr)
{
	ULONG i;
	DbgPrint("\r\nUnHook\r\n");

    //关闭页保护
	PageProtectOff();
 
	//将申请的内存区域偏移+10处的前5字节的数据还原到内核函数
	for (i = 0; i < 5; i++)
	{
		DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
		*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)g_pHookMemAddr + 10 + i);
		DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
	}

    //开启页保护
	PageProtectOn();
}
 
// HOOK后的执行函数
/*
	KernelFunc(NtCreateFile):
	此时
	{
		esp + 0x00 = NtCreateFile的返回地址
		esp + 0x04 = FileHandle			
		esp + 0x08 = DesiredAccess		
		esp + 0x0c = ObjectAttributes	
		esp + 0x10 = IoStatusBlock		
		esp + 0x14 = AllocationSize		
		esp + 0x18 = FileAttributes		
		esp + 0x1c = ShareAccess		
		esp + 0x20 = CreateDisposition	
		esp + 0x24 = CreateOptions		
		esp + 0x28 = EaBuffer			
		esp + 0x2c = EaLength			
	}
	8056f27c jmp HookMemory
	8056f281 xor eax,eax
	......
	******************************************
	HookMemory:
	pushad
	pushfd
	int 3
	此时
	{
		esp + 0x00 = eflags
		esp + 0x04 = edi
		esp + 0x08 = esi
		esp + 0x0c = ebp
		esp + 0x10 = esp
		esp + 0x14 = ebx
		esp + 0x18 = edx
		esp + 0x1c = ecx
		esp + 0x20 = eax

		esp + 0x24 = NtCreateFile的返回地址				
		esp + 0x28 = FileHandle		
		esp + 0x2c = DesiredAccess	
		esp + 0x30 = ObjectAttributes		
		esp + 0x34 = IoStatusBlock		
		esp + 0x38 = AllocationSize		
		esp + 0x3c = FileAttributes		
		esp + 0x40 = ShareAccess	
		esp + 0x44 = CreateDisposition		
		esp + 0x48 = CreateOptions			
		esp + 0x4c = EaBuffer			
		esp + 0x50 = EaLength			
	}		
	call ExecFunc(RealFunc)
	popfd
	popad
	mov edi,edi
	push ebp
	mov ebp,esp
	jmp nt!NtCreateFile + 0x5(8056f281)
	******************************************
	ExecFunc(RealFunc):
	此时
	{
	esp + 0x00 = ExecFunc(RealFunc)的返回地址

	esp + 0x04 = eflags
	esp + 0x08 = edi
	esp + 0x0c = esi
	esp + 0x10 = ebp
	esp + 0x14 = esp
	esp + 0x18 = ebx
	esp + 0x1c = edx
	esp + 0x20 = ecx
	esp + 0x24 = eax

	esp + 0x28 = NtCreateFile的返回地址
	esp + 0x2c = FileHandle
	esp + 0x30 = DesiredAccess		
	esp + 0x34 = ObjectAttributes		
	esp + 0x38 = IoStatusBlock		
	esp + 0x3c = AllocationSize		
	esp + 0x40 = FileAttributes	
	esp + 0x44 = ShareAccess		
	esp + 0x48 = CreateDisposition			
	esp + 0x4c = CreateOptions			
	esp + 0x50 = EaBuffer
	esp + 0x54 = EaLength			
	}

	push ebp
	此时
	{
	esp + 0x00 = ebp(原)

	esp + 0x04 = ExecFunc(RealFunc)的返回地址

	esp + 0x08 = eflags
	esp + 0x0c = edi
	esp + 0x10 = esi
	esp + 0x14 = ebp
	esp + 0x18 = esp
	esp + 0x1c = ebx
	esp + 0x20 = edx
	esp + 0x24 = ecx
	esp + 0x28 = eax

	esp + 0x2c = NtCreateFile的返回地址
	esp + 0x30 = FileHandle		
	esp + 0x34 = DesiredAccess		
	esp + 0x38 = ObjectAttributes		
	esp + 0x3c = IoStatusBlock		
	esp + 0x40 = AllocationSize	
	esp + 0x44 = FileAttributes		
	esp + 0x48 = ShareAccess			
	esp + 0x4c = CreateDisposition			
	esp + 0x50 = CreateOptions
	esp + 0x54 = EaBuffer
	esp + 0x58 = EaLength
	}

	mov ebp,esp
	此时,esp == ebp
	{
	ebp + 0x00 = ebp(原)

	ebp + 0x04 = ExecFunc(RealFunc)的返回地址

	ebp + 0x08 = eflags
	ebp + 0x0c = edi
	ebp + 0x10 = esi
	ebp + 0x14 = ebp
	ebp + 0x18 = ebp
	ebp + 0x1c = ebx
	ebp + 0x20 = edx
	ebp + 0x24 = ecx
	ebp + 0x28 = eax

	ebp + 0x2c = NtCreateFile的返回地址
	ebp + 0x30 = FileHandle		
	ebp + 0x34 = DesiredAccess		
	ebp + 0x38 = ObjectAttributes		
	ebp + 0x3c = IoStatusBlock		
	ebp + 0x40 = AllocationSize	
	ebp + 0x44 = FileAttributes		
	ebp + 0x48 = ShareAccess			
	ebp + 0x4c = CreateDisposition			
	ebp + 0x50 = CreateOptions
	ebp + 0x54 = EaBuffer
	ebp + 0x58 = EaLength
	}
	sub esp,30h
	cli
	......
*/
VOID __stdcall RealFunc()
{
	ULONG FileHandle;
	ULONG DesiredAccess;
	ULONG ObjectAttributes;
	ULONG IoStatusBlock;
	ULONG AllocationSize;
	ULONG FileAttributes;
	ULONG ShareAccess;
	ULONG CreateDisposition;
	ULONG CreateOptions;
	ULONG EaBuffer;
	ULONG EaLength;	
	ULONG dwRetAddr;
 
	__asm
	{
		cli;

		mov eax,[ebp + 0x04];//当前函数的返回地址
		mov [dwRetAddr],eax;
 
		mov eax,[ebp + 0x30];//NtCreateFile参数01:FileHandle
		mov [FileHandle],eax;
		mov eax,[ebp + 0x34];//NtCreateFile参数02:DesiredAccess
		mov [DesiredAccess],eax;
		mov eax,[ebp + 0x38];//NtCreateFile参数03:ObjectAttributes
		mov [ObjectAttributes],eax;
		mov eax,[ebp + 0x3c];//NtCreateFile参数04:IoStatusBlock
		mov [IoStatusBlock],eax;
		mov eax,[ebp + 0x40];//NtCreateFile参数05:AllocationSize
		mov [AllocationSize],eax;
		mov eax,[ebp + 0x44];//NtCreateFile参数06:FileAttributes
		mov [FileAttributes],eax;
		mov eax,[ebp + 0x48];//NtCreateFile参数07:ShareAccess
		mov [ShareAccess],eax;
		mov eax,[ebp + 0x4c];//NtCreateFile参数08:CreateDisposition
		mov [CreateDisposition],eax;
		mov eax,[ebp + 0x50];//NtCreateFile参数09:CreateOptions
		mov [CreateOptions],eax;
		mov eax,[ebp + 0x54];//NtCreateFile参数10:EaBuffer
		mov [EaBuffer],eax;
		mov eax,[ebp + 0x58];//NtCreateFile参数11:EaLength
		mov [EaLength],eax;
	}
	
	if (ShareAccess == 0xffff)
	{
		__asm pushfd;
 
		DbgPrint("\r\n");
		DbgPrint("NtCreateFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtCreateFile参数02:DesiredAccess:0x%.8x\r\n",DesiredAccess);
		DbgPrint("NtCreateFile参数03:ObjectAttributes:0x%.8x\r\n",ObjectAttributes);
		DbgPrint("NtCreateFile参数04:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtCreateFile参数05:AllocationSize:0x%.8x\r\n",AllocationSize);
		DbgPrint("NtCreateFile参数06:FileAttributes:0x%.8x\r\n",FileAttributes);
		DbgPrint("NtCreateFile参数07:ShareAccess:0x%.8x\r\n",ShareAccess);
		DbgPrint("NtCreateFile参数08:CreateDisposition:0x%.8x\r\n",CreateDisposition);
		DbgPrint("NtCreateFile参数09:CreateOptions:0x%.8x\r\n",CreateOptions);
		DbgPrint("NtCreateFile参数10:EaBuffer:0x%.8x\r\n",EaBuffer);
		DbgPrint("NtCreateFile参数11:EaLength:0x%.8x\r\n",EaLength);	
		//DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);	
 
		__asm popfd;
	}
 
	//验证堆栈
	/*
	if (dwRetAddr == ((ULONG)g_pHookMemAddr + 8))
	{
		DbgPrint("\r\n");
		DbgPrint("NtCreateFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtCreateFile参数02:DesiredAccess:0x%.8x\r\n",DesiredAccess);
		DbgPrint("NtCreateFile参数03:ObjectAttributes:0x%.8x\r\n",ObjectAttributes);
		DbgPrint("NtCreateFile参数04:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtCreateFile参数05:AllocationSize:0x%.8x\r\n",AllocationSize);
		DbgPrint("NtCreateFile参数06:FileAttributes:0x%.8x\r\n",FileAttributes);
		DbgPrint("NtCreateFile参数07:ShareAccess:0x%.8x\r\n",ShareAccess);
		DbgPrint("NtCreateFile参数08:CreateDisposition:0x%.8x\r\n",CreateDisposition);
		DbgPrint("NtCreateFile参数09:CreateOptions:0x%.8x\r\n",CreateOptions);
		DbgPrint("NtCreateFile参数10:EaBuffer:0x%.8x\r\n",EaBuffer);
		DbgPrint("NtCreateFile参数11:EaLength:0x%.8x\r\n",EaLength);	
		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
	}
	*/
 
	__asm sti;
 
	return;
}

/*
	函数调用过程
	CreateFileA(kernel32) ==> CreateFileW(kernel32) ==> NtCreateFile(ntdll) ==> NtCreateFile(ntoskrnl) ==> IoCreateFile(ntoskrnl)

	kernel32:
	HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
								DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)

	kernel32:
	HANDLE __stdcall CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
								DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)

	ntdll:
	NTSTATUS __stdcall NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, 
									OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes, 
									IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength)
		FileHandle			= dword ptr  04h
		DesiredAccess		= dword ptr  08h
		ObjectAttributes	= dword ptr  0Ch
		IoStatusBlock		= dword ptr  10h
		AllocationSize		= dword ptr  14h
		FileAttributes		= dword ptr  18h
		ShareAccess			= dword ptr  1Ch
		CreateDisposition	= dword ptr  20h
		CreateOptions		= dword ptr  24h
		EaBuffer			= dword ptr  28h
		EaLength			= dword ptr  2Ch

		mov     eax, 25h	//系统调用号
		mov     edx, 7FFE0300h
		call    dword ptr [edx]
		retn    2Ch

	ntoskrnl:
	NTSTATUS __stdcall NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, 
							OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes, 
							IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength)
		FileHandle			= dword ptr  08h
		DesiredAccess		= dword ptr  0Ch
		ObjectAttributes	= dword ptr  10h
		IoStatusBlock		= dword ptr  14h
		AllocationSize		= dword ptr  18h
		FileAttributes		= dword ptr  1Ch
		ShareAccess			= dword ptr  20h
		CreateDisposition	= dword ptr  24h
		CreateOptions		= dword ptr  28h
		EaBuffer			= dword ptr  2Ch
		EaLength			= dword ptr  30h

		8B FF	mov edi, edi
		55		push ebp
		8B EC	mov ebp, esp
		xor     eax, eax
		push    eax					; Options
		push    eax					; InternalParameters
		push    eax					; CreateFileType
		push    dword ptr [ebp+30h] ; EaLength
		push    dword ptr [ebp+2Ch] ; EaBuffer
		push    dword ptr [ebp+28h] ; CreateOptions
		push    dword ptr [ebp+24h] ; Disposition
		push    dword ptr [ebp+20h] ; ShareAccess
		push    dword ptr [ebp+1Ch] ; FileAttributes
		push    dword ptr [ebp+18h] ; AllocationSize
		push    dword ptr [ebp+14h] ; IoStatusBlock
		push    dword ptr [ebp+10h] ; ObjectAttributes
		push    dword ptr [ebp+0Ch] ; DesiredAccess
		push    dword ptr [ebp+08h]	; FileHandle
		call    _IoCreateFile@56	; IoCreateFile(x,x,x,x,x,x,x,x,x,x,x,x,x,x)
		pop     ebp
		retn    2Ch	//11个参数
*/

3环:

#include <WINDOWS.H>
#include <STDIO.H>

#define FILENAME "C:\\Program Files\\PETool 1.0.0.5.exe"
#define FILE_SHARE_OTHER 0xffff

int main()
{
	//获取3环函数地址
	DWORD dwFunc3Addr = (DWORD)CreateFileA;
	printf("CreateFileA的地址为:0x%.8x\n\n",dwFunc3Addr);
 
	//正常测试
	HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
	{
		printf("CreateFileA失败,错误代码:%d\n", GetLastError());
		system("pause");
		return -1;
	}
	printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);
	
	//特殊通信
	/*
	WINBASEAPI HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
										DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
	正常参数
	#define FILE_SHARE_READ			0x00000001  
	#define FILE_SHARE_WRITE		0x00000002  
	#define FILE_SHARE_DELETE		0x00000004
	特殊参数
	#define FILE_SHARE_OTHER		0x0000FFFF
	*/
	hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_OTHER, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	printf("lpFileName:0x%.8x\ndwDesiredAccess:0x%.8x\ndwShareMode:0x%.8x\nlpSecurityAttributes:0x%.8x\ndwCreationDisposition:0x%.8x\ndwFlagsAndAttributes:0x%.8x\nhTemplateFile:0x%.8x\n",
				(DWORD)FILENAME,(DWORD)GENERIC_ALL,(DWORD)FILE_SHARE_OTHER,(DWORD)NULL,(DWORD)OPEN_EXISTING,(DWORD)FILE_ATTRIBUTE_NORMAL,(DWORD)NULL);
 
 
	CloseHandle(hFile);
	system("pause");
	return 0;
}

二、NtReadFile(仅HOOK传入参数)

0环:

#include <ntifs.h>
 
// 系统调用号
// NtCreateFile 0x25
// NtReadFile	0xB7
#define SYSCODE 0xB7
 
PVOID g_pHookMemAddr;//InlineHook跳转地址
ULONG g_dwKernelFuncAddr;//内核函数的地址
PVOID g_pSpyBuffer;//偷换的缓冲区
 
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
	PULONG ServiceTableBase;			// 函数地址表
	PULONG ServiceCounterTableBase;		// SSDT 函数被调用的次数
	ULONG NumberOfService;				// 函数个数
	PULONG ParamTableBase;				// 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
 
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
	KSYSTEM_SERVICE_TABLE ntoskrnl;		// 内核函数
	KSYSTEM_SERVICE_TABLE win32k;		// win32k.sys 函数
	KSYSTEM_SERVICE_TABLE unUsed1;
	KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr);
// HOOK后的执行函数
VOID __stdcall RealFunc();
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	ULONG dwExecFuncAddr;//执行函数地址
 
	DbgPrint("驱动已启动\r\n");
	pDriver->DriverUnload = DriverUnload;
 
	//获取执行函数的地址
	dwExecFuncAddr = (ULONG)RealFunc;
	//修正函数地址
	if (*(PUCHAR)dwExecFuncAddr == 0xe9)
	{
		DbgPrint("执行函数的地址,修正前:0x%.8x\r\n",dwExecFuncAddr);
		dwExecFuncAddr = *(PULONG)(dwExecFuncAddr + 1) - (dwExecFuncAddr + 5);
		DbgPrint("执行函数的地址,修正后:0x%.8x\r\n",dwExecFuncAddr);
	}
	else
	{
		DbgPrint("执行函数的地址,无需修正\r\n");
	}	
 
	//根据系统调用号找到内核函数的地址
	g_dwKernelFuncAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
	DbgPrint("内核函数地址:0x%.8x\r\n",g_dwKernelFuncAddr);
 
	//HOOK
	if (!Hook(g_dwKernelFuncAddr,dwExecFuncAddr))
	{
		return STATUS_UNSUCCESSFUL;
	}
 
	return STATUS_SUCCESS;
}
 
// 关闭页保护
VOID PageProtectOff()
{
	__asm
	{
		cli; // 关闭中断
		mov eax, cr0;
		and eax, not 0x10000; // WP位置0
		mov cr0, eax;
	}
}
 
// 开启页保护
VOID PageProtectOn()
{
	__asm
	{
		mov eax, cr0;
		or eax, 0x10000; // WP位置1
		mov cr0, eax;
		sti; // 恢复中断
	}
}
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	//UN-HOOK
	UnHook(g_dwKernelFuncAddr);
 
	//释放内存
	ExFreePool(g_pHookMemAddr);
 
	DbgPrint("驱动已停止\r\n");
}
 
// HOOK过程
// 将dwSrc函数HOOK至Dst函数
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr)
{
	ULONG i;//for循环的参数
	ULONG dwJumpPara;//E9Jmp的参数
	ULONG dwCallPara;//E8Call参数
 
	DbgPrint("\r\nHook\r\n");
 
	//申请内存
	g_pHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
	if (g_pHookMemAddr == NULL)
	{
		DbgPrint("\r\nExAllocatePool失败\r\n");
		return FALSE;
	}
	DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pHookMemAddr);
	RtlFillMemory(g_pHookMemAddr, 0x100, 0x90);
 
	//DbgBreakPoint();
 
	//pushad pushfd
	*((PUCHAR)g_pHookMemAddr + 0) = 0x60;//pushad
	*((PUCHAR)g_pHookMemAddr + 1) = 0x9c;//pushfd
 
	//int 3
	*((PUCHAR)g_pHookMemAddr + 2) = 0x90;//int 3
 
	//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(RealFunc)
	DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
	*((PUCHAR)g_pHookMemAddr + 3) = 0xe8;//call
	dwCallPara = dwDstFuncAddr - ((ULONG)g_pHookMemAddr + 3 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)((ULONG)g_pHookMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
	}
 
	//popfd popad
	*((PUCHAR)g_pHookMemAddr + 8) = 0x9d;//popfd
	*((PUCHAR)g_pHookMemAddr + 9) = 0x61;//popad
 
	//DbgBreakPoint();
 
	//保存内核函数前7字节的数据到申请的内存区域偏移+10处
	DbgPrint("\r\n保存内核函数前5字节的数据到申请的内存空间中\r\n");
	for (i = 0; i < 7; i++)
	{
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
		*((PUCHAR)g_pHookMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
		DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, (ULONG)g_pHookMemAddr + 10 + i, *((PUCHAR)g_pHookMemAddr + 10 + i));
	}
 
	//DbgBreakPoint();
 
	//在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr + 5
	DbgPrint("\r\n在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr + 5\r\n");
	*((PUCHAR)g_pHookMemAddr + 20) = 0xe9;//jmp
	dwJumpPara = dwSrcFuncAddr + 5 - ((ULONG)g_pHookMemAddr + 20 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)((ULONG)g_pHookMemAddr + 20 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
	}
 
	//DbgBreakPoint();
 
	//修改内核函数前7字节进行InlineHook
	DbgPrint("\r\n修改内核函数前7字节\r\n关闭页保护\r\n");
	PageProtectOff();
	*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
	DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
 
	//跳转至申请的内存区域偏移+0处的Jmp参数
	dwJumpPara = (ULONG)g_pHookMemAddr - (dwSrcFuncAddr + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
	}

	//多余处填充nop
	*(PUCHAR)(dwSrcFuncAddr + 5) = 0x90;//nop
	*(PUCHAR)(dwSrcFuncAddr + 6) = 0x90;//nop

	DbgPrint("开启页保护\r\n");
	PageProtectOn();
 
	//披露重要数据
	DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n",dwSrcFuncAddr,g_pHookMemAddr,dwDstFuncAddr);
 
	return TRUE;
}
 
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr)
{
	ULONG i;
	DbgPrint("\r\nUnHook\r\n");

	//关闭页保护
	PageProtectOff();
 
	//将申请的内存区域偏移+10处的前7字节的数据还原到内核函数
	for (i = 0; i < 7; i++)
	{
		DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
		*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)g_pHookMemAddr + 10 + i);
		DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
	}

	ExFreePool(g_pSpyBuffer);

	//开启页保护
	PageProtectOn();
}
 
// HOOK后的执行函数
/*
	NTSTATUS __stdcall NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
									PVOID Buffer, ULONG dwLength, PLARGE_INTEGER ByteOffset, PULONG Key)
	KernelFunc(NtReadFile):
	此时
	{
		esp + 0x00 = NtReadFile的返回地址
		esp + 0x04 = FileHandle
		esp + 0x08 = Event
		esp + 0x0c = ApcRoutine
		esp + 0x10 = ApcContext
		esp + 0x14 = IoStatusBlock
		esp + 0x18 = Buffer
		esp + 0x1c = dwLength
		esp + 0x20 = ByteOffset
		esp + 0x24 = Key
	}
	jmp HookMemory
	nop
	nop
	nop
	call    __SEH_prolog
	......
	******************************************
	HookMemory:
	pushad
	pushfd
	int 3
	此时
	{
		esp + 0x00 = eflags
		esp + 0x04 = edi
		esp + 0x08 = esi
		esp + 0x0c = ebp
		esp + 0x10 = esp
		esp + 0x14 = ebx
		esp + 0x18 = edx
		esp + 0x1c = ecx
		esp + 0x20 = eax

		esp + 0x24 = NtReadFile的返回地址
		esp + 0x28 = FileHandle
		esp + 0x2c = Event
		esp + 0x30 = ApcRoutine
		esp + 0x34 = ApcContext
		esp + 0x38 = IoStatusBlock
		esp + 0x3c = Buffer
		esp + 0x40 = dwLength
		esp + 0x44 = ByteOffset
		esp + 0x48 = Key
	}		
	call ExecFunc(RealFunc)
	popfd
	popad
	push    68h
	push    0041A310h
	jmp nt!NtReadFile + 0x5(805727af)
	******************************************
	ExecFunc(RealFunc):
	此时
	{
	esp + 0x00 = ExecFunc(RealFunc)的返回地址

	esp + 0x04 = eflags
	esp + 0x08 = edi
	esp + 0x0c = esi
	esp + 0x10 = ebp
	esp + 0x14 = esp
	esp + 0x18 = ebx
	esp + 0x1c = edx
	esp + 0x20 = ecx
	esp + 0x24 = eax

	esp + 0x28 = NtReadFile的返回地址
	esp + 0x2c = FileHandle
	esp + 0x30 = Event
	esp + 0x34 = ApcRoutine
	esp + 0x38 = ApcContext
	esp + 0x3c = IoStatusBlock
	esp + 0x40 = Buffer
	esp + 0x44 = dwLength
	esp + 0x48 = ByteOffset
	esp + 0x4c = Key		
	}

	push ebp
	此时
	{
	esp + 0x00 = ebp(原)

	esp + 0x04 = ExecFunc(RealFunc)的返回地址

	esp + 0x08 = eflags
	esp + 0x0c = edi
	esp + 0x10 = esi
	esp + 0x14 = ebp
	esp + 0x18 = esp
	esp + 0x1c = ebx
	esp + 0x20 = edx
	esp + 0x24 = ecx
	esp + 0x28 = eax

	esp + 0x2c = NtReadFile的返回地址
	esp + 0x30 = FileHandle
	esp + 0x34 = Event
	esp + 0x38 = ApcRoutine
	esp + 0x3c = ApcContext
	esp + 0x40 = IoStatusBlock
	esp + 0x44 = Buffer
	esp + 0x48 = dwLength
	esp + 0x4c = ByteOffset
	esp + 0x50 = Key
	}

	mov ebp,esp
	此时,esp == ebp
	{
	ebp + 0x00 = ebp(原)

	ebp + 0x04 = ExecFunc(RealFunc)的返回地址

	ebp + 0x08 = eflags
	ebp + 0x0c = edi
	ebp + 0x10 = esi
	ebp + 0x14 = ebp
	ebp + 0x18 = ebp
	ebp + 0x1c = ebx
	ebp + 0x20 = edx
	ebp + 0x24 = ecx
	ebp + 0x28 = eax

	ebp + 0x2c = NtReadFile的返回地址
	ebp + 0x30 = FileHandle
	ebp + 0x34 = Event
	ebp + 0x38 = ApcRoutine
	ebp + 0x3c = ApcContext
	ebp + 0x40 = IoStatusBlock
	ebp + 0x44 = Buffer
	ebp + 0x48 = dwLength
	ebp + 0x4c = ByteOffset
	ebp + 0x50 = Key
	}
	sub esp,30h
	cli
	......
*/

VOID __stdcall RealFunc()
{
	ULONG FileHandle;
	ULONG Event;
	ULONG ApcRoutine;
	ULONG ApcContext;
	ULONG IoStatusBlock;
	ULONG Buffer;
	ULONG dwLength;
	ULONG ByteOffset;
	ULONG Key;
	ULONG dwRetAddr;

	UCHAR i;
	
 
	__asm
	{
		cli;

		mov eax,[ebp + 0x04];//当前函数的返回地址
		mov [dwRetAddr],eax;
 
		mov eax,[ebp + 0x30];//NtReadFile参数01:FileHandle
		mov [FileHandle],eax;
		mov eax,[ebp + 0x34];//NtReadFile参数02:Event
		mov [Event],eax;
		mov eax,[ebp + 0x38];//NtReadFile参数03:ApcRoutine
		mov [ApcRoutine],eax;
		mov eax,[ebp + 0x3c];//NtReadFile参数04:ApcContext
		mov [ApcContext],eax;
		mov eax,[ebp + 0x40];//NtReadFile参数05:IoStatusBlock
		mov [IoStatusBlock],eax;
		mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
		mov [Buffer],eax;
		mov eax,[ebp + 0x48];//NtReadFile参数07:Length
		mov [dwLength],eax;
		mov eax,[ebp + 0x4c];//NtReadFile参数08:ByteOffset
		mov [ByteOffset],eax;
		mov eax,[ebp + 0x50];//NtReadFile参数09:Key
		mov [Key],eax;
	}

	
	if (dwLength == 0xffffffff)
	{
		__asm pushfd;
		
		DbgPrint("\r\n");
		DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
		DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
		DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
		DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
		DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
		DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);

		__asm popfd;

		//修改缓冲区大小
		dwLength = 0x50;
		
		__asm mov eax,[dwLength];
		__asm mov [ebp + 0x48],eax;

		__asm pushfd;
		DbgPrint("已修改参数07:dwLength的值为0x%.8x\r\n",dwLength);
		__asm popfd;

		//修改缓冲区
		g_pSpyBuffer = ExAllocatePool(PagedPool, dwLength);

	}
	
	/*
	//验证堆栈
	if (dwRetAddr == ((ULONG)g_pHookMemAddr + 8))
	{
		__asm pushfd;

		DbgPrint("\r\n");
		DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
		DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
		DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
		DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
		DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
		DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);

		__asm popfd;
	}
	*/

	__asm sti;
 
	return;
}

/*
	函数调用过程
	ReadFilekernel32) ==> NtReadFile(ntdll) ==> NtReadFile(ntoskrnl)

	kernel32:
	BOOL __stdcall ReadFile(IN HANDLE hFile, OUT LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead, IN LPOVERLAPPED lpOverlapped)

		push    ebx				//Key
		push    ebx				//ByteOffset
		push    [ebp + 0x10]	//Length
		push    [ebp + 0x0c]	//Buffer
		lea     eax, [ebp - 0x28]
		push    eax				//IoStatusBlock
		push    ebx				//ApcContext
		push    ebx				//ApcRoutine
		push    ebx				//Event
		push    edi				//FileHandle
		call    ds:__imp__NtReadFile
		......
		retn    14h	//5个参数

	ntdll:
	NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
									OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)

		mov     eax, 0B7h//系统调用号
		mov     edx, 7FFE0300h
		call    dword ptr [edx]
		retn    24h 

	ntoskrnl:
	NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
									OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)

		6A 68				push    68h
		68 10 A3 41 00		push    0041A310h
		E8 18 E3 F6 FF		call    __SEH_prolog
		33 F6				xor     esi, esi
		......
		retn    24h	//9个参数
*/

3环:

#include <WINDOWS.H>
#include <STDIO.H>

#define FILENAME "C:\\Program Files\\PETool 1.0.0.5.exe"
#define FUNCNAME ReadFile
#define FILE_SHARE_OTHER 0xffff

int main()
{
	//获取3环函数地址
	DWORD dwFunc3Addr = (DWORD)FUNCNAME;
	printf("函数的地址为:0x%.8x\n\n",dwFunc3Addr);
 
	//CreateFileA
	HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
	{
		printf("CreateFileA失败,错误代码:%d\n", GetLastError());
		system("pause");
		return -1;
	}
	printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);

	//ReadFile
	DWORD dwNumber = 0;
	DWORD dwLength = 0xffffffff;
	LPVOID lpBuffer = malloc(0x100);
	printf("\nReadFile,数据地址:0x%.8x\n", lpBuffer);
	memset(lpBuffer, 0, 0x100);

	BOOL bRet = ReadFile(hFile, lpBuffer, dwLength, &dwNumber, NULL);
	/*
	if (!bRet)
	{
		printf("\nReadFile,错误代码:%d\n", GetLastError());
		CloseHandle(hFile);
		system("pause");
		return -1;
	}
	*/
	printf("ReadFile成功,已读取:0x%x个字节,数据地址:0x%.8x\n", dwNumber, lpBuffer);

	__asm mov eax,eax;

	CloseHandle(hFile);
	system("pause");
	return 0;
}

三、NtReadFile(HOOK传入、传出参数)

0环:

#include <ntifs.h>
 
// 系统调用号
// NtReadFile	0xB7
#define SYSCODE 0xB7
#define BUFFERSIZE 0x50
 
PVOID g_pBgnHookMemAddr;//函数开始处InlineHook跳转地址
PVOID g_pEndHookMemAddr;//函数结尾处InlineHook跳转地址
ULONG g_dwKernelFuncBgnAddr;//内核函数开始处的地址
ULONG g_dwKernelFuncEndAddr;//内核函数结尾处的地址
ULONG g_dwInByte;//HOOK传入参数时修改的字节数
ULONG g_dwOutByte;//HOOK传出参数时修改的字节数
ULONG g_dwFlag;//暗号
ULONG g_Buffer;//3环的缓冲区,用于修改
PUCHAR g_pszProcessName;//3环进程名
 
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
	PULONG	ServiceTableBase;			// 函数地址表
	PULONG	ServiceCounterTableBase;	// SSDT 函数被调用的次数
	ULONG	NumberOfService;			// 函数个数
	PULONG	ParamTableBase;				// 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
 
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
	KSYSTEM_SERVICE_TABLE ntoskrnl;		// 内核函数
	KSYSTEM_SERVICE_TABLE win32k;		// win32k.sys 函数
	KSYSTEM_SERVICE_TABLE unUsed1;
	KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwJmpMemAddr, ULONG dwDstFuncAddr, ULONG dwByteSize);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr, ULONG dwByteSize);
// 修改传入参数
VOID __stdcall ChangeInPara();
// 修改传出参数
VOID __stdcall ChangeOutPara();
// 查找目标进程CR3
ULONG FindCr3();
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	ULONG dwExecFuncAddr_In;//修改传入参数的函数地址
	ULONG dwExecFuncAddr_Out;//修改传出参数的函数地址
	g_dwFlag = 0;//暗号初始化:0为未HOOK,1为已HOOK
	g_pszProcessName = (PUCHAR)"InlineHook.exe";

	DbgPrint("驱动已启动\r\n");
	pDriver->DriverUnload = DriverUnload;
	//******************************************修改传入参数******************************************
 
	//获取执行函数(ChangeIn)的地址
	dwExecFuncAddr_In = (ULONG)ChangeInPara;
	//修正地址
	if (*(PUCHAR)dwExecFuncAddr_In == 0xe9)
	{
		DbgPrint("执行函数(ChangeIn)的地址,修正前:0x%.8x\r\n",dwExecFuncAddr_In);
		dwExecFuncAddr_In = *(PULONG)(dwExecFuncAddr_In + 1) - (dwExecFuncAddr_In + 5);
		DbgPrint("执行函数(ChangeIn)的地址,修正后:0x%.8x\r\n",dwExecFuncAddr_In);
	}
	else
	{
		DbgPrint("执行函数(ChangeIn)的地址,无需修正\r\n");
	}	
 
	//根据系统调用号找到内核函数开始处的地址
	g_dwKernelFuncBgnAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
	DbgPrint("内核函数开始处地址:0x%.8x\r\n",g_dwKernelFuncBgnAddr);
 
	//申请内存
	g_pBgnHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
	if (g_pBgnHookMemAddr == NULL)
	{
		DbgPrint("\r\nExAllocatePool失败\r\n");
		return FALSE;
	}
	DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pBgnHookMemAddr);
	RtlFillMemory(g_pBgnHookMemAddr, 0x100, 0x90);

	//开始HOOK
	/*
	6A 68				push    68h
	68 10 A3 41 00		push    0041A310h
	共7个字节
	*/
	g_dwInByte = 7;

	if (!Hook(g_dwKernelFuncBgnAddr, (ULONG)g_pBgnHookMemAddr, dwExecFuncAddr_In, g_dwInByte))
	{
		return STATUS_UNSUCCESSFUL;
	}

	//******************************************修改传出参数******************************************

	//获取执行函数(ChangeOut)的地址
	dwExecFuncAddr_Out = (ULONG)ChangeOutPara;
	//修正地址
	if (*(PUCHAR)dwExecFuncAddr_Out == 0xe9)
	{
		DbgPrint("\r\n执行函数(ChangeOut)的地址,修正前:0x%.8x\r\n",dwExecFuncAddr_Out);
		dwExecFuncAddr_Out = *(PULONG)(dwExecFuncAddr_Out + 1) - (dwExecFuncAddr_Out + 5);
		DbgPrint("执行函数(ChangeOut)的地址,修正后:0x%.8x\r\n",dwExecFuncAddr_Out);
	}
	else
	{
		DbgPrint("\r\n执行函数(ChangeOut)的地址,无需修正\r\n");
	}

	//申请内存
	g_pEndHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
	if (g_pEndHookMemAddr == NULL)
	{
		DbgPrint("\r\nExAllocatePool失败\r\n");
		return FALSE;
	}
	DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pEndHookMemAddr);
	RtlFillMemory(g_pEndHookMemAddr, 0x100, 0x90);

	/*
	805727aa	6A 68		push 68h
	......
	80572d2f	C2 24 00	retn 24h
	80572d32	cc			int     3
	80572d33	cc			int     3
	80572d34	cc			int     3
	80572d35	cc			int     3
	80572d36	cc			int     3
	80572d37	cc			int     3
	共3个字节,可修改5个字节
	*/
	g_dwOutByte = 5;

	//根据偏移,计算出HOOK传出参数的位置
	//80572d2f - 805727aa = 0x585;
	g_dwKernelFuncEndAddr = g_dwKernelFuncBgnAddr + 0x585;//不可直接使用IDA的偏移,RVA之故
	DbgPrint("内核函数结尾处地址:0x%.8x\r\n",g_dwKernelFuncEndAddr);

	//开始HOOK
	if (!Hook(g_dwKernelFuncEndAddr, (ULONG)g_pEndHookMemAddr, dwExecFuncAddr_Out, g_dwOutByte))
	{
		return STATUS_UNSUCCESSFUL;
	}
 
	return STATUS_SUCCESS;
}
 
// 关闭页保护
VOID PageProtectOff()
{
	__asm
	{
		cli; // 关闭中断
		mov eax, cr0;
		and eax, not 0x10000; // WP位置0
		mov cr0, eax;
	}
}
 
// 开启页保护
VOID PageProtectOn()
{
	__asm
	{
		mov eax, cr0;
		or eax, 0x10000; // WP位置1
		mov cr0, eax;
		sti; // 恢复中断
	}
}
 
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	//DbgBreakPoint();

	//UN-HOOK
	UnHook((ULONG)g_pBgnHookMemAddr, g_dwKernelFuncBgnAddr, g_dwInByte);
	UnHook((ULONG)g_pEndHookMemAddr, g_dwKernelFuncEndAddr, g_dwOutByte);
 
	//释放内存
	ExFreePool(g_pBgnHookMemAddr);
	ExFreePool(g_pEndHookMemAddr);
 
	DbgPrint("驱动已停止\r\n");
}
 
// HOOK过程
// 将函数自Src处跳转至JmpMem处后Call至Dst函数,ShellCode占ByteSize个字节
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwJmpMemAddr, ULONG dwDstFuncAddr, ULONG dwByteSize)
{
	ULONG i;//for循环的参数
	ULONG dwJumpPara;//E9Jmp的参数
	ULONG dwCallPara;//E8Call参数
 
	DbgPrint("\r\nHook\r\n");

	//DbgBreakPoint();
 
	//pushad pushfd
	*((PUCHAR)dwJmpMemAddr + 0) = 0x60;//pushad
	*((PUCHAR)dwJmpMemAddr + 1) = 0x9c;//pushfd
 
	//int 3
	*((PUCHAR)dwJmpMemAddr + 2) = 0x90;//int 3
 
	//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(ChangeInPara)
	DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
	*((PUCHAR)dwJmpMemAddr + 3) = 0xe8;//call
	dwCallPara = dwDstFuncAddr - ((ULONG)dwJmpMemAddr + 3 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)(dwJmpMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
	}
 
	//popfd popad
	*((PUCHAR)dwJmpMemAddr + 8) = 0x9d;//popfd
	*((PUCHAR)dwJmpMemAddr + 9) = 0x61;//popad
 
	//DbgBreakPoint();
 
	//保存内核函数前dwByteSize字节的数据到申请的内存区域偏移+10处
	DbgPrint("\r\n保存内核函数前dwByteSize字节的数据到申请的内存空间中\r\n");
	for (i = 0; i < dwByteSize; i++)
	{
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
		*((PUCHAR)dwJmpMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
		DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwJmpMemAddr + 10 + i, *((PUCHAR)dwJmpMemAddr + 10 + i));
	}
 
	//DbgBreakPoint();
 
	//在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr
	DbgPrint("\r\n在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr\r\n");
	*((PUCHAR)dwJmpMemAddr + 20) = 0xe9;//jmp
	dwJumpPara = dwSrcFuncAddr + 5 - (dwJmpMemAddr + 20 + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)(dwJmpMemAddr + 20 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
	}
 
	//DbgBreakPoint();
 
	//修改内核函数前dwByteSize字节进行InlineHook
	DbgPrint("\r\n修改内核函数前%d字节\r\n关闭页保护\r\n",dwByteSize);
	PageProtectOff();
	*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
	DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
 
	//跳转至申请的内存区域偏移+0处的Jmp参数
	dwJumpPara = (ULONG)dwJmpMemAddr - (dwSrcFuncAddr + 5);
	for (i = 1; i < 5; i++)
	{
		*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
		DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
	}
 
	//内核函数多余处填充nop
	for (i = 5; i < dwByteSize; i++)
	{
		*(PUCHAR)(dwSrcFuncAddr + i) = 0x90;//nop
	}
 
	DbgPrint("开启页保护\r\n");
	PageProtectOn();
 
	//披露重要数据
	DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n共修改%d个字节\r\n",dwSrcFuncAddr,dwJmpMemAddr,dwDstFuncAddr,dwByteSize);

	return TRUE;
}
 
// UN_HOOK
// 将SrcAddr区域dwByteSize的数据还原至DstAddr处
VOID UnHook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr, ULONG dwByteSize)
{
	ULONG i;
	DbgPrint("\r\nUnHook\r\n");
 
	//关闭页保护
	PageProtectOff();
 
	//将申请的内存区域偏移+10处的前dwByteSize字节的数据还原到内核函数
	for (i = 0; i < dwByteSize; i++)
	{
		DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwDstFuncAddr + i, *(PUCHAR)(dwDstFuncAddr + i));
		*(PUCHAR)(dwDstFuncAddr + i) = *(PUCHAR)(dwSrcFuncAddr + 10 + i);
		DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwDstFuncAddr + i, *(PUCHAR)(dwDstFuncAddr + i));
	}
 
	//开启页保护
	PageProtectOn();
}
 
// HOOK后的执行函数
/*
	NTSTATUS __stdcall NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
									PVOID Buffer, ULONG dwLength, PLARGE_INTEGER ByteOffset, PULONG Key)
	KernelFunc(NtReadFile):
	此时
	{
		esp + 0x00 = NtReadFile的返回地址
		esp + 0x04 = FileHandle
		esp + 0x08 = Event
		esp + 0x0c = ApcRoutine
		esp + 0x10 = ApcContext
		esp + 0x14 = IoStatusBlock
		esp + 0x18 = Buffer
		esp + 0x1c = dwLength
		esp + 0x20 = ByteOffset
		esp + 0x24 = Key
	}
	jmp HookMemory
	nop
	nop
	nop
	call    __SEH_prolog
	......
	******************************************
	HookMemory:
	pushad
	pushfd
	int 3
	此时
	{
		esp + 0x00 = eflags
		esp + 0x04 = edi
		esp + 0x08 = esi
		esp + 0x0c = ebp
		esp + 0x10 = esp
		esp + 0x14 = ebx
		esp + 0x18 = edx
		esp + 0x1c = ecx
		esp + 0x20 = eax
		esp + 0x24 = NtReadFile的返回地址
		esp + 0x28 = FileHandle
		esp + 0x2c = Event
		esp + 0x30 = ApcRoutine
		esp + 0x34 = ApcContext
		esp + 0x38 = IoStatusBlock
		esp + 0x3c = Buffer
		esp + 0x40 = dwLength
		esp + 0x44 = ByteOffset
		esp + 0x48 = Key
	}		
	call ExecFunc(ChangeInPara)
	popfd
	popad
	push    68h
	push    0041A310h
	jmp nt!NtReadFile + 0x5(805727af)
	******************************************
	ExecFunc(ChangeInPara):
	此时
	{
	esp + 0x00 = ExecFunc(ChangeInPara)的返回地址
	esp + 0x04 = eflags
	esp + 0x08 = edi
	esp + 0x0c = esi
	esp + 0x10 = ebp
	esp + 0x14 = esp
	esp + 0x18 = ebx
	esp + 0x1c = edx
	esp + 0x20 = ecx
	esp + 0x24 = eax
	esp + 0x28 = NtReadFile的返回地址
	esp + 0x2c = FileHandle
	esp + 0x30 = Event
	esp + 0x34 = ApcRoutine
	esp + 0x38 = ApcContext
	esp + 0x3c = IoStatusBlock
	esp + 0x40 = Buffer
	esp + 0x44 = dwLength
	esp + 0x48 = ByteOffset
	esp + 0x4c = Key		
	}
	push ebp
	此时
	{
	esp + 0x00 = ebp(原)
	esp + 0x04 = ExecFunc(ChangeInPara)的返回地址
	esp + 0x08 = eflags
	esp + 0x0c = edi
	esp + 0x10 = esi
	esp + 0x14 = ebp
	esp + 0x18 = esp
	esp + 0x1c = ebx
	esp + 0x20 = edx
	esp + 0x24 = ecx
	esp + 0x28 = eax
	esp + 0x2c = NtReadFile的返回地址
	esp + 0x30 = FileHandle
	esp + 0x34 = Event
	esp + 0x38 = ApcRoutine
	esp + 0x3c = ApcContext
	esp + 0x40 = IoStatusBlock
	esp + 0x44 = Buffer
	esp + 0x48 = dwLength
	esp + 0x4c = ByteOffset
	esp + 0x50 = Key
	}
	mov ebp,esp
	此时,esp == ebp
	{
	ebp + 0x00 = ebp(原)
	ebp + 0x04 = ExecFunc(ChangeInPara)的返回地址
	ebp + 0x08 = eflags
	ebp + 0x0c = edi
	ebp + 0x10 = esi
	ebp + 0x14 = ebp
	ebp + 0x18 = esp
	ebp + 0x1c = ebx
	ebp + 0x20 = edx
	ebp + 0x24 = ecx
	ebp + 0x28 = eax
	ebp + 0x2c = NtReadFile的返回地址
	ebp + 0x30 = FileHandle
	ebp + 0x34 = Event
	ebp + 0x38 = ApcRoutine
	ebp + 0x3c = ApcContext
	ebp + 0x40 = IoStatusBlock
	ebp + 0x44 = Buffer
	ebp + 0x48 = dwLength
	ebp + 0x4c = ByteOffset
	ebp + 0x50 = Key
	}
	sub esp,30h
	cli
	......
*/
 
// 修改传入参数
VOID __stdcall ChangeInPara()
{
	ULONG FileHandle;
	ULONG Event;
	ULONG ApcRoutine;
	ULONG ApcContext;
	ULONG IoStatusBlock;
	ULONG Buffer;
	ULONG dwLength;
	ULONG ByteOffset;
	ULONG Key;
	ULONG dwRetAddr;	
 
	__asm
	{
		cli;
 
		mov eax,[ebp + 0x04];//当前函数的返回地址
		mov [dwRetAddr],eax;
 
		mov eax,[ebp + 0x30];//NtReadFile参数01:FileHandle
		mov [FileHandle],eax;
		mov eax,[ebp + 0x34];//NtReadFile参数02:Event
		mov [Event],eax;
		mov eax,[ebp + 0x38];//NtReadFile参数03:ApcRoutine
		mov [ApcRoutine],eax;
		mov eax,[ebp + 0x3c];//NtReadFile参数04:ApcContext
		mov [ApcContext],eax;
		mov eax,[ebp + 0x40];//NtReadFile参数05:IoStatusBlock
		mov [IoStatusBlock],eax;
		mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
		mov [Buffer],eax;
		mov eax,[ebp + 0x48];//NtReadFile参数07:Length
		mov [dwLength],eax;
		mov eax,[ebp + 0x4c];//NtReadFile参数08:ByteOffset
		mov [ByteOffset],eax;
		mov eax,[ebp + 0x50];//NtReadFile参数09:Key
		mov [Key],eax;
	}

	if (dwLength == 0xffffffff)
	{
		__asm pushfd;
		
		DbgPrint("\r\nChangeInPara\r\n");
		DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
		DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
		DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
		DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
		//保存目标进程的3环缓冲区,防止后期变更
		g_Buffer = Buffer;
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
		DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
		DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
 
		__asm popfd;
 
		//修改堆栈中的传入参数:缓冲区大小
		dwLength = BUFFERSIZE;
		
		__asm mov eax,[dwLength];
		__asm mov [ebp + 0x48],eax;
 
		__asm pushfd;
		DbgPrint("已修改参数07:dwLength的值为0x%.8x\r\n",dwLength);
		__asm popfd;

		//修改暗号为已HOOK
		g_dwFlag = 1;
	}
	
	/*
	//验证堆栈
	if (dwRetAddr == ((ULONG)g_pBgnHookMemAddr + 8))
	{
		__asm pushfd;
		DbgPrint("\r\n");
		DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
		DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
		DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
		DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
		DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
		DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
		DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
		DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
		__asm popfd;
	}
	*/
 
	__asm sti;
 
	return;
}
 
/*
	函数调用过程
	ReadFilekernel32) ==> NtReadFile(ntdll) ==> NtReadFile(ntoskrnl)
	kernel32:
	BOOL __stdcall ReadFile(IN HANDLE hFile, OUT LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead, IN LPOVERLAPPED lpOverlapped)
		push    ebx				//Key
		push    ebx				//ByteOffset
		push    [ebp + 0x10]	//Length
		push    [ebp + 0x0c]	//Buffer
		lea     eax, [ebp - 0x28]
		push    eax				//IoStatusBlock
		push    ebx				//ApcContext
		push    ebx				//ApcRoutine
		push    ebx				//Event
		push    edi				//FileHandle
		call    ds:__imp__NtReadFile
		......
		retn    14h	//5个参数
	ntdll:
	NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
									OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
		mov     eax, 0B7h//系统调用号
		mov     edx, 7FFE0300h
		call    dword ptr [edx]
		retn    24h 
	ntoskrnl:
	NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
									OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
		6A 68				push    68h
		68 10 A3 41 00		push    0041A310h
		E8 18 E3 F6 FF		call    __SEH_prolog
		33 F6				xor     esi, esi
		......
		retn    24h	//9个参数
*/

// HOOK传出参数后的执行函数
VOID __stdcall ChangeOutPara()
{
	ULONG i;
	ULONG dwRetAddr;
	ULONG Buffer;//内核函数传出参数
	ULONG dwLength;//内核函数传入参数
	PVOID pTempBuffer;//临时缓冲区,用于转存

	//当前进程CR3
	ULONG dwMyCr3;
	//目标进程CR3
	ULONG dwTargetCr3;

	__asm
	{
		cli;

		mov eax,[ebp + 0x04];//当前函数的返回地址
		mov [dwRetAddr],eax;

		mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
		mov [Buffer],eax;
		mov eax,[ebp + 0x48];//NtReadFile参数07:Length
		mov [dwLength],eax;

		sti;
	}

	/*
	//当前进程的CR3
	__asm cli;
	__asm mov eax,cr3;
	__asm mov [dwMyCr3],eax;
	__asm sti;
	//DbgPrint("当前进程的CR3:0x%x\r\n",dwMyCr3);
	*/

	/*
	//验证堆栈
	if (dwRetAddr == ((ULONG)g_pEndHookMemAddr + 8))
	{
		//DbgBreakPoint();

		__asm pushfd;
		DbgPrint("\r\n");

		DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);

		DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
		__asm popfd;
	}
	*/

	//判断暗号
	if (g_dwFlag == 1 && Buffer == g_Buffer)
	{
		DbgPrint("\r\nChangeOutPara\r\n");

		/*
		DbgPrint("当前进程的CR3:0x%x\r\n",dwMyCr3);
		//目标进程的CR3
		dwTargetCr3 = FindCr3();
		*/

		__asm pushfd;
		DbgPrint("\r\nNtReadFile参数06:Buffer:0x%.8x\r\n",g_Buffer);
		DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
		__asm popfd;
		
		//创建临时缓冲区
		pTempBuffer = ExAllocatePool(NonPagedPool, 0x100);
		if (pTempBuffer == NULL)
		{
			__asm pushfd;
			DbgPrint("ExAllocatePool失败\r\n");
			__asm popfd;
			return;
		}
		__asm pushfd;
		DbgPrint("ExAllocatePool成功,高2G缓冲区的内存地址:0x%.8x\r\n",(ULONG)pTempBuffer);
		__asm popfd;

		//填充数据
		for (i = 0; i < 100; i++)
		{
			*(PUCHAR)((ULONG)pTempBuffer + i) = i;
		}
		
		//DbgBreakPoint();

		/*
		//跨进程写入数据(误,并未跨进程,EIP走到此处,与目标进程为统一进程)
		__asm cli;

		//1.将当前进程的CR3修改为3环程序的CR3
		__asm mov eax,[dwTargetCr3];
		__asm mov cr3,eax;	
		*/

		//2.将高2G内存空间的数据转存至低2G空间(3环程序)的缓冲区
		RtlCopyMemory((PVOID)g_Buffer, pTempBuffer, BUFFERSIZE);

		/*
		//3.恢复当前进程的CR3
		__asm mov eax,[dwMyCr3];
		__asm mov cr3,eax;
		__asm sti;
		*/

		ExFreePool(pTempBuffer);
		
		/*
		//修改堆栈中的传出参数:Buffer(无意义)
		__asm mov eax,[g_pSpyBuffer];
		__asm mov [ebp + 0x44],eax;
		*/

		__asm pushfd;
		DbgPrint("已修改参数06:Buffer的内容\r\n");
		__asm popfd;

		//恢复初始值
		g_dwFlag = 0;
	}

	//__asm sti;

	return;
}

// 查找目标进程CR3
ULONG FindCr3()
{
	PEPROCESS pEprocess;
	PUCHAR pszProcessName;
	PLIST_ENTRY pList;
	PLIST_ENTRY pListNext;
	ULONG dwCR3;

	DbgPrint("\r\nFindCr3\r\n");

	//获取当前进程结构体_EPROCESS的地址
	__asm
	{
		pushad;
		pushfd;

		//CurrentThread: Ptr32 _KTHREAD
		mov eax,fs:[0x124];
		//ThreadsProcess: Ptr32 _EPROCESS
		mov eax,[eax + 0x220];
		mov pEprocess,eax;

		popfd;
		popad;
	}

	pList = (PLIST_ENTRY)((ULONG)pEprocess + 0x88);
	pszProcessName = (PUCHAR)((ULONG)pEprocess + 0x174);
	DbgPrint("当前进程名:%s\r\n",pszProcessName);
	if (!strcmp(pszProcessName,g_pszProcessName))
	{
		//_EPROCESS._KPROCESS.DirectoryTableBase : [2] Uint4B
		dwCR3 = *(PULONG)((ULONG)pEprocess + 0x18);
		DbgPrint("已找到进程%s,CR3:0x%x\r\n",pszProcessName,dwCR3);
		return dwCR3;
	}

	pListNext = pList->Flink;
	//遍历所有进程
	DbgPrint("\r\n开始遍历进程\r\n");
	do 
	{
		pEprocess = (PEPROCESS)(*(PULONG)pListNext - 0x88);
		pszProcessName = (PUCHAR)((ULONG)pEprocess + 0x174);
		DbgPrint("进程名:%s\r\n",pszProcessName);

		if (!strcmp(pszProcessName,g_pszProcessName))
		{
			//_EPROCESS._KPROCESS.DirectoryTableBase : [2] Uint4B
			dwCR3 = *(PULONG)((ULONG)pEprocess + 0x18);
			DbgPrint("已找到进程%s,CR3:0x%x\r\n",pszProcessName,dwCR3);
			return dwCR3;
		}

		pListNext = (PLIST_ENTRY)((ULONG)pEprocess + 0x88);

	} while (pListNext->Flink != pList);

	DbgPrint("进程遍历结束,未找到指定的进程\r\n");
	return 0;
}

3环:

#include <WINDOWS.H>
#include <STDIO.H>
 
#define FILENAME "C:\\Program Files\\PETool.exe"
#define FUNCNAME ReadFile
#define FILE_SHARE_OTHER 0xffff
 
int main()
{
	//获取3环函数地址
	DWORD dwFunc3Addr = (DWORD)FUNCNAME;
	printf("函数的地址为:0x%.8x\n\n",dwFunc3Addr);
 
	//CreateFileA
	HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
	{
		printf("CreateFileA失败,错误代码:%d\n", GetLastError());
		system("pause");
		return -1;
	}
	printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);
 
	//ReadFile
	DWORD dwNumber = 0;
	DWORD dwLength = 0xffffffff;
	LPVOID lpBuffer = malloc(0x100);
	printf("\nReadFile,数据地址:0x%.8x\n", lpBuffer);
	memset(lpBuffer, 0, 0x100);
 
	BOOL bRet = ReadFile(hFile, lpBuffer, dwLength, &dwNumber, NULL);
	/*
	if (!bRet)
	{
		printf("\nReadFile,错误代码:%d\n", GetLastError());
		CloseHandle(hFile);
		system("pause");
		return -1;
	}
	*/
	//通过查看传出参数dwNumber的值,验证传入参数dwLength是否已被修改

	printf("ReadFile成功,已读取:0x%x个字节,数据地址:0x%.8x\n", dwNumber, lpBuffer);
	Sleep(1000);
	getchar();

	//读取缓冲区,验证传出参数的lpBuffer的内容是否被替换
	for (int i = 0; i < 0x50; i++)
	{
		printf("0x%.2x\t",*(PUCHAR)((DWORD)lpBuffer + i));
	}
	printf("\n");
 
	__asm mov eax,eax;
	
	system("pause");
	CloseHandle(hFile);
	free(lpBuffer);

	return 0;
}

似乎达到了目的,如有错误之处,请留言指出,谢谢!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值