#include "ntddk.h"
#include "hookiat.h"
#pragma comment(lib,"ntdll.lib")
ULONG g_OriginalPsGetCurrentProcessId;
typedef HANDLE (*PSGETCURRENTPROCESSID)();
HANDLE
MyPsGetCurrentProcessId()
{
HANDLE handle;
DbgPrint("HOOK_PsGetCurrentProcessId called!\n");
handle =((PSGETCURRENTPROCESSID)(g_OriginalPsGetCurrentProcessId))();
return handle;
}
PVOID GetModlueBaseAdress(char* ModlueName)
{
ULONG size,index;
PULONG buf;
NTSTATUS status;
PSYSTEM_MODULE_INFORMATION module;
PVOID driverAddress=0;
ZwQuerySystemInformation(SystemModuleInformation,&size, 0, &size);
if(NULL==(buf = (PULONG)ExAllocatePool(PagedPool, size)))
{
DbgPrint("failed alloc memory failed \n");
return 0;
}
status=ZwQuerySystemInformation(SystemModuleInformation,buf, size , 0);
if(!NT_SUCCESS( status ))
{
DbgPrint("failed query\n");
return 0;
}
module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1);
for (index = 0; index < *buf; index++)
if (_stricmp(module[index].ImageName + module[index].ModuleNameOffset, ModlueName) == 0)
{
driverAddress = module[index].Base;
DbgPrint("Module found at:%x\n",driverAddress);
}
ExFreePool(buf);
return driverAddress;
}
//StartHook_And_Unhook是安装钩子和卸载钩子,如果 test==1表示安装,否则表示卸载
VOID StartHook_And_Unhook(IN PCSTR funName, IN unsigned int test)
{
HANDLE hMod;//JK:不指向任何类型的指针
PUCHAR BaseAddress = NULL;//JK:这个变量保存了一个32BTI地址,而这个地址指向了一个内存单元的内容
IMAGE_DOS_HEADER * dosheader;//JK:DOS文件头指针
IMAGE_OPTIONAL_HEADER * opthdr;//JK:结构
PIMAGE_EXPORT_DIRECTORY exports;//JK:用于保存一个IMAGE_EXPORT_DIRECTORY结构地址的指针变量
USHORT index=0 ;
ULONG addr ,i;
PUCHAR pFuncName = NULL;
PULONG pAddressOfFunctions,pAddressOfNames;//这个变量保存了一个32BTI地址,而这个地址指向了四个内存单元的内容
PUSHORT pAddressOfNameOrdinals;//这个变量保存了一个32BTI地址,而这个地址指向了两个内存单元的内容
BaseAddress= GetModlueBaseAdress("ntoskrnl.exe");//JK:获取要HOOK模块的导入表的模块地址
DbgPrint("Map BaseAddress is:%x\n",BaseAddress);
hMod = BaseAddress;
dosheader = (IMAGE_DOS_HEADER *)hMod;//JK:dosheader保存了描述DOS头的结构变量的地址
opthdr =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)hMod+dosheader->e_lfanew+24);//JK:dosheader->e_lfanew会输出PE文件头的位置+24是因为IMAGE_FILE_HEADER结构占20个字节,而加4是因为Signature所占4个字节,这样就指向了IMAGE_OPTIONAL_HEADER的位置
exports = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)dosheader+ opthdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);//JK:exports保存了IMAGE_EXPORT_DIRECTORY结构变量的地址
pAddressOfFunctions=(ULONG*)((BYTE*)hMod+exports->AddressOfFunctions); //JK:获得EAT的入口地址,EAT又双字的数组组成
pAddressOfNames=(ULONG*)((BYTE*)hMod+exports->AddressOfNames);//JK:函数名字符串的地址表,根据这个地址表(由双字的数组组成)可获得函数名称的字符串
pAddressOfNameOrdinals=(USHORT*)((BYTE*)hMod+exports->AddressOfNameOrdinals); //JK:保存用于去pAddressOfFunctions指向的EAT中取函数地址的索引值(这个索引值还与函数名字符串的地址表对应,这样就可通过函数名称返回函数的地址了)
for (i = 0; i < exports->NumberOfNames; i++)
{
index=pAddressOfNameOrdinals[i];
pFuncName = (PUCHAR)( (BYTE*)hMod + pAddressOfNames[i]);
if (_stricmp( (char*)pFuncName,funName) == 0)
{
addr=pAddressOfFunctions[index];//JK:addr变量保存了PsGetCurrentProcessId函数的地址
break;
}
}
if(test==1) {
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
//DbgPrint("PsGetCurrentProcessId is:%x\n",(ULONG)hMod + addr);//JK:输出PsGetCurrentProcessId这个函数的地址,基地址加RVA JK:用addr代替了pAddressOfFunctions[index]
g_OriginalPsGetCurrentProcessId= (ULONG)hMod + pAddressOfFunctions[index] ;//JK:g_OriginalPsGetCurrentProcessId保存了原先PsGetCurrentProcessId的地址
//DbgPrint("g_OriginalPsGetCurrentProcessId is:%x\n",g_OriginalPsGetCurrentProcessId);
pAddressOfFunctions[index] = ( PCHAR )MyPsGetCurrentProcessId - BaseAddress;//求出MyPsGetCurrentProcessId的RVA
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
}
else
{
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
pAddressOfFunctions[index] = ( PCHAR )g_OriginalPsGetCurrentProcessId - BaseAddress;//JK 恢复以前的PsGetCurrentProcessId的地址
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
}
}
VOID Unload(PDRIVER_OBJECT DriverObject)
{
PCSTR myfunName="PsGetCurrentProcessId";
StartHook_And_Unhook(myfunName,0);
DbgPrint("Unload Callled\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING str)
{
PCSTR myfunName="PsGetCurrentProcessId";
StartHook_And_Unhook(myfunName,1);
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)