hook_导出表eat

#include <ntifs.h>
#include <ntimage.h>
typedef VOID(__stdcall *KEATTACHPROCESS)(IN PRKPROCESS Process);
KEATTACHPROCESS OldKeAttachProcess;
UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process);
#define SystemModuleInformation 11
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef struct _SYSTEM_MODULE_INFORMATION  // 系统模块信息
{
	ULONG  Reserved[2];
	ULONG  Base;
	ULONG  Size;
	ULONG  Flags;
	USHORT Index;
	USHORT Unknown;
	USHORT LoadCount;
	USHORT ModuleNameOffset;
	CHAR   ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _tagSysModuleList {          //模块链结构
	ULONG ulCount;
	SYSTEM_MODULE_INFORMATION smi[1];
} MODULES, *PMODULES;
NTSTATUS __stdcall ZwQuerySystemInformation(
	ULONG_PTR SystemInformationClass,
	PVOID SystemInformation,
	ULONG SystemInformationLength,
	PULONG ReturnLength
	);
VOID WPOFF()
{
	__asm
	{
		cli
			mov eax, cr0
			and eax, not 10000h
			mov cr0, eax
	}
}
VOID WPON()
{
	__asm
	{
		mov eax, cr0
			or eax, 10000h
			mov cr0, eax
			sti
	}
}
//作业:把驱动的卸载历程的代码补充,在卸载的时候,恢复EAThook

BOOLEAN GetKernelModuleInfo(ULONG *ulSysModuleBase, ULONG *ulSize)
{
	NTSTATUS status;
	ULONG NeededSize, i;
	PMODULES pModuleList;
	BOOLEAN bRet = FALSE;
	pModuleList = NULL;
	__try
	{
		status = ZwQuerySystemInformation(
			SystemModuleInformation,
			NULL,
			0,
			&NeededSize);
		if (status != STATUS_INFO_LENGTH_MISMATCH)
		{
			return bRet;
		}
		pModuleList = (PMODULES)ExAllocatePool(NonPagedPool, NeededSize);
		if (pModuleList)
		{
			status = ZwQuerySystemInformation(
				SystemModuleInformation,
				pModuleList,
				NeededSize,
				&NeededSize);

			if (NT_SUCCESS(status))
			{
				__try
				{
					//ntoskrnl.exe总是第一个加载
					*ulSysModuleBase = pModuleList->smi[0].Base;
					*ulSize = pModuleList->smi[0].Size;
					bRet = TRUE;

				}
				__except (EXCEPTION_EXECUTE_HANDLER){

				}
			}
			ExFreePool(pModuleList);
			pModuleList = NULL;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		KdPrint(("%08x\r\n", GetExceptionCode()));
	}
	if (pModuleList)
		ExFreePool(pModuleList);

	return bRet;
}
//我们的过滤函数的声明,要跟微软原始函数一样
VOID __stdcall NewKeAttachProcess(IN PRKPROCESS Process)
{
	//我们进行效验,看看传进来的进程对象,是否可以有效
	if (Process && MmIsAddressValid(Process))
	{
		//我们对当前的执行级别进行判断
		if (KeGetCurrentIrql() == PASSIVE_LEVEL){
			//打印出来,是谁在附加谁
			DbgPrint("%s attach to %s\r\n", PsGetProcessImageFileName(PsGetCurrentProcess()), PsGetProcessImageFileName(Process));
		}
	}
	 OldKeAttachProcess(Process);
	 return;
}
BOOLEAN EATTableHook(PVOID ulModuleBase, char *psz_func_name, ULONG_PTR ulong_new_func)
{
	//变量的声明
	PIMAGE_DOS_HEADER pDosHeader;
	PIMAGE_NT_HEADERS NtDllHeader;
	IMAGE_OPTIONAL_HEADER opthdr;
	ULONG_PTR* arrayOfFunctionAddresses;
	ULONG_PTR* arrayOfFunctionNames;
	WORD* arrayOfFunctionOrdinals;
	ULONG_PTR functionOrdinal;
	ULONG_PTR Base, x;
	IMAGE_EXPORT_DIRECTORY *pExportTable;
	char *functionName;
	//try可以捕获一些简单的异常,
	__try
	{
		//获得dos的文件头结构体
		pDosHeader = (PIMAGE_DOS_HEADER)ulModuleBase;
		if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		{
			DbgPrint("IMAGE_DOS_SIGNATURE failed\r\n");
			return FALSE;
		}
		//获得NT 文件头的结构体
		NtDllHeader = (PIMAGE_NT_HEADERS)(ULONG_PTR)((ULONG_PTR)pDosHeader + pDosHeader->e_lfanew);
		if (NtDllHeader->Signature != IMAGE_NT_SIGNATURE)
		{
			DbgPrint("IMAGE_NT_SIGNATURE failed\r\n");
			return FALSE;
		}
		//获得可选镜像头部结构
		opthdr = NtDllHeader->OptionalHeader;
		//获得导出表地址
		pExportTable = (IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)ulModuleBase + opthdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //得到导出表
		//获得相对地址
		arrayOfFunctionAddresses = (ULONG_PTR*)((ULONG_PTR)ulModuleBase + pExportTable->AddressOfFunctions);  //地址表
		arrayOfFunctionNames = (ULONG_PTR*)((BYTE*)ulModuleBase + pExportTable->AddressOfNames);         //函数名表
		arrayOfFunctionOrdinals = (WORD*)((BYTE*)ulModuleBase + pExportTable->AddressOfNameOrdinals);
		//我们在这里获得导出表的起始地址
		Base = pExportTable->Base;
		//我们用一个结构,循环的打印,也就是列举
		for (x = 0; x < pExportTable->NumberOfFunctions; x++) //在整个导出表里扫描
		{
			//得到函数名 = 内核模块的起始地址 + 相对地址
			functionName = (char*)((BYTE*)ulModuleBase + arrayOfFunctionNames[x]);
			functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1;

			//对比,是否是我们要hook的函数
			if (_stricmp(psz_func_name, functionName) == 0)
			{
				//我们要保存原始函数,
				//为什么要保存:因为在你的过滤函数里面,还要调用原始函数
				(PUCHAR)OldKeAttachProcess = (PUCHAR)ulModuleBase + arrayOfFunctionAddresses[functionOrdinal];
				//禁止写保存
				WPOFF();
				//根据我们的计算公司:  EAT表的[index] = 你的新函数 - 你要hook的模块的起始地址;
				//通过这个计算公司,我们就完成了我们的eat hook
				arrayOfFunctionAddresses[functionOrdinal] = (PCHAR)ulong_new_func - (PCHAR)ulModuleBase; //ntos的基址(起始地址)
				//恢复写保护
				WPON();
				DbgPrint("%s:0x%08X\r\n", functionName, OldKeAttachProcess);
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER){
	}
	return FALSE;
}
BOOLEAN EATTableUnHook(PVOID ulModuleBase, char *psz_func_name, ULONG_PTR ulong_new_func)
{
	//变量的声明
	PIMAGE_DOS_HEADER pDosHeader;
	PIMAGE_NT_HEADERS NtDllHeader;
	IMAGE_OPTIONAL_HEADER opthdr;
	ULONG_PTR* arrayOfFunctionAddresses;
	ULONG_PTR* arrayOfFunctionNames;
	WORD* arrayOfFunctionOrdinals;
	ULONG_PTR functionOrdinal;
	ULONG_PTR Base, x;
	IMAGE_EXPORT_DIRECTORY *pExportTable;
	char *functionName;
	//try可以捕获一些简单的异常,
	__try
	{
		//获得dos的文件头结构体
		pDosHeader = (PIMAGE_DOS_HEADER)ulModuleBase;
		if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		{
			DbgPrint("IMAGE_DOS_SIGNATURE failed\r\n");
			return FALSE;
		}
		//获得NT 文件头的结构体
		NtDllHeader = (PIMAGE_NT_HEADERS)(ULONG_PTR)((ULONG_PTR)pDosHeader + pDosHeader->e_lfanew);
		if (NtDllHeader->Signature != IMAGE_NT_SIGNATURE)
		{
			DbgPrint("IMAGE_NT_SIGNATURE failed\r\n");
			return FALSE;
		}
		//获得可选镜像头部结构
		opthdr = NtDllHeader->OptionalHeader;
		//获得导出表地址
		pExportTable = (IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)ulModuleBase + opthdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //得到导出表
		//获得相对地址
		arrayOfFunctionAddresses = (ULONG_PTR*)((ULONG_PTR)ulModuleBase + pExportTable->AddressOfFunctions);  //地址表
		arrayOfFunctionNames = (ULONG_PTR*)((BYTE*)ulModuleBase + pExportTable->AddressOfNames);         //函数名表
		arrayOfFunctionOrdinals = (WORD*)((BYTE*)ulModuleBase + pExportTable->AddressOfNameOrdinals);
		//我们在这里获得导出表的起始地址
		Base = pExportTable->Base;
		//我们用一个结构,循环的打印,也就是列举
		for (x = 0; x < pExportTable->NumberOfFunctions; x++) //在整个导出表里扫描
		{
			//得到函数名 = 内核模块的起始地址 + 相对地址
			functionName = (char*)((BYTE*)ulModuleBase + arrayOfFunctionNames[x]);
			functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1;

			//对比,是否是我们要hook的函数
			if (_stricmp(psz_func_name, functionName) == 0)
			{
				//我们要保存原始函数,
				//为什么要保存:因为在你的过滤函数里面,还要调用原始函数
				//(PUCHAR)OldKeAttachProcess = (PUCHAR)ulModuleBase + arrayOfFunctionAddresses[functionOrdinal];
				//禁止写保存
				WPOFF();
				//根据我们的计算公司:  EAT表的[index] = 你的新函数 - 你要hook的模块的起始地址;
				//通过这个计算公司,我们就完成了我们的eat hook
				arrayOfFunctionAddresses[functionOrdinal] = (PCHAR)OldKeAttachProcess - (PCHAR)ulModuleBase; //ntos的基址(起始地址)
				//恢复写保护
				WPON();
				//DbgPrint("%s:0x%08X\r\n", functionName, OldKeAttachProcess);
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER){
	}
	return FALSE;
}
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	ULONG_PTR ulong_kernel_base;
	ULONG_PTR ulong_kernel_size;
	if (GetKernelModuleInfo(&ulong_kernel_base, &ulong_kernel_size))
	{
		//开始hook,第一个参数就是内核模块的起始地址,就是我们要eat hook的函数名,就是我们的新过滤函数
		EATTableUnHook((PVOID)ulong_kernel_base, "KeAttachProcess", (ULONG_PTR)NewKeAttachProcess);
	}

	DbgPrint("卸载完成!\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	//声明两个变量,一个是内核模块的地址,一个是大小 ULONG_PTR 是编译器自动识别,如果是32位驱动,就是ULONG,如果是64位驱动,就是ULONG_PTR
	ULONG_PTR ulong_kernel_base;
	ULONG_PTR ulong_kernel_size;
	//就是驱动的卸载历程
	DriverObject->DriverUnload = DriverUnload;
	//keattachprocess,是在ntoskrnl.exe 这个内核导出
	if (GetKernelModuleInfo(&ulong_kernel_base, &ulong_kernel_size))
	{
		//开始hook,第一个参数就是内核模块的起始地址,就是我们要eat hook的函数名,就是我们的新过滤函数
		EATTableHook((PVOID)ulong_kernel_base, "KeAttachProcess", (ULONG_PTR)NewKeAttachProcess);
	}
	return STATUS_SUCCESS;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值