能力值:
( LV2,RANK:10 )
|
-
-
2 楼
//NtOpenProcess用到的全局变量[为了方便堆栈平衡的处理使用全局变量]
PEPROCESS processEPROCESS = NULL; //保存访问者的EPROCESS
ANSI_STRING p_str1,p_str2; //保存进程名称
BYTE *ObOpenObjectByPointerAddress = NULL; //ObOpenObjectByPointer的地址
BYTE *p_TpHookAddress = NULL; //TP的HOOK函数地址
BYTE *p_ReturnAddress = NULL; //返回到的地址
BYTE *p_MyHookAddress = NULL; //我们的HOOK函数在哪写入
#define DNF_EXE "DNF.exe" //要检索的进程名
//////////////////////////////////////////////////////////////////////
// 名称: Nakd_NtOpenProcess
// 功能: My_RecoveryHook_NtOpenProcess的中继函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
static NAKED VOID Nakd_NtOpenProcess()
{
//获得调用者的EPROCESS,每个进程都有一个 EPROCESS 结构,里面保存着进程的各种信息,
//和相关结构的指针。EPROCESS 结构位于系统地址空间,所以访问这个结构需要有ring0的权限
processEPROCESS = IoGetCurrentProcess();
//将调用者的进程名保存到str1中
RtlInitAnsiString(&p_str1,(char*)processEPROCESS+0x174);
//将我们要比对的进程名放入str2
RtlInitAnsiString(&p_str2,DNF_EXE);
if (RtlCompareString(&p_str1,&p_str2,TRUE) == 0)
{
//说明是DNF进程访问了这里
__asm
{
push dword ptr [ebp-38h]//这个是HOOK之前的代码
push dword ptr [ebp-24h]
push p_ReturnAddress
mov eax,p_TpHookAddress
jmp eax
}
}
else
{
__asm
{
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
push p_ReturnAddress
mov eax,ObOpenObjectByPointerAddress
jmp eax
}
}
}
//保存5字节代码的结构
#pragma pack(1)
typedef struct _TOP5CODE
{
UCHAR instruction; //指令
ULONG address; //地址
}TOP5CODE,*PTOP5CODE;
#pragma pack( )
//////////////////////////////////////////////////////////////////////
// 名称: My_RecoveryHook_NtOpenProcess
// 功能: 解除游戏保护对NtOpenProcess的HOOK
// 参数:
// 返回: 状态
//////////////////////////////////////////////////////////////////////
NTSTATUS My_RecoveryHook_NtOpenProcess()
{
BYTE *NtOpenProcessAddress = NULL; //NtOpenProcess的地址
BYTE *p = NULL; //临时
TOP5CODE *top5code = NULL; //保存5字节内容
BYTE JmpAddress[6] = {0xE9,0,0,0,0,0x90};//0XE9 表示 JMP, 0X90 表示NOP
KIRQL Irql;
//获取NtOpenProcess的地址
NtOpenProcessAddress = (BYTE*)MyGetFunAddress(L"NtOpenProcess");
DbgPrint( "NtOpenProcessAddress Addr: %x\n", NtOpenProcessAddress);
if (NtOpenProcessAddress == NULL)
{
KdPrint(("NtOpenProcess地址获取失败\n"));
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
//获取ObOpenObjectByPointer的地址
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
if (ObOpenObjectByPointerAddress == NULL)
{
KdPrint(("ObOpenObjectByPointer地址获取失败\n"));
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
//将p指向NtOpenProcess函数开始处
p = NtOpenProcessAddress;
//用一个无限循环来判断给定的特征码来确定被HOOK位置
while (1)
{
if ((*(p-7) == 0x50) &&
(*(p-0xE) == 0x56) &&
(*(p+0xd) == 0x50) &&
(*(p+0x16) == 0x3b) &&
(*(p+0x17) == 0xce) &&
(*p == 0xE8) &&
(*(p+5) == 0x8b) &&
(*(p+6) == 0xf8))
{
KdPrint(("%0X \n",(ULONG)p));
break;
}
//推动指针向前走
p++;
}
//将top5code指向 p 的当前处,E8= CALL ,后面4个字节是地址
//用以取出 call [地址] 这5字节里面的地址
top5code = (TOP5CODE*)p;
p_TpHookAddress = (BYTE*)((ULONG)p+5+top5code->address);//DNF修改的call跳转地址
//找到我们写入自定义函数的地址
p_MyHookAddress = p-6;//放我们自己钩子的地方,前面两条指令占6位
//保存调用ObOpenObjectByPointer函数以后的返回地址
p_ReturnAddress = p+5;//CALL ObOpenObjectByPointer后面指令的地址
//将一条JMP Nakd_NtOpenProcess写入到数组中
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenProcess - ((ULONG)p_MyHookAddress+5);
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(p_MyHookAddress,JmpAddress,6);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
代码贴上看看啊
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
是不是 这几行代码有检测啊 你改别的地方试试啊
|
能力值:
( LV4,RANK:50 )
|
-
-
6 楼
为啥不直接HOOK ObOpenObjectByPointer
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
我也遇到这样的问题,现在一直没解决
|
|
|