#include <ntddk.h>
#define dprintf DbgPrint
#include <windef.h>
#include "debugport.h"
#define DNF_EXE "DNF.exe" //要检索的进程名
ULONG addr_DbgkpQueueMessage;
ULONG addr_DbgkpSetProcessDebugObject;
VOID Reg_DbgkpQueueMessage();
VOID Reg_DbgkpSetProcessDebugObject();
BYTE MovEaxAddress3[7] = {0x8b,0xff,0x55,0x8b,0xec,0x83,0xec}; //b8f4289ab7
//BYTE b_byte[]={0x8B,0xFF,0x55,0x8B,0xEC,0x81,0xEC};
BYTE MovEaxAddress2[7] = {0x8b,0xff,0x55,0x8b,0xec,0x81,0xec}; //b8f4289ab7
//BYTE b_byte[]={0x8B,0xFF,0x55,0x8B,0xEC,0x83,0xEC};
typedef struct _ServiceDescriptorTable {
PVOID ServiceTableBase; //System Service Dispatch Table 的基地址
PVOID ServiceCounterTable;
//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。
unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。
PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表
}*PServiceDescriptorTable;
extern PServiceDescriptorTable KeServiceDescriptorTable;
BYTE *NtReadVirtualMemoryAddress = NULL; //NtReadVirtualMemory的地址
BYTE *NtWriteVirtualMemoryAddress = NULL; //NtWriteVirtualMemory的地址
BYTE * KiAttachProcessAddress=NULL;
BYTE MovEaxAddress[5] = {0xB8,0,0,0,0}; //b8f4289ab7
//BYTE MovEaxAddress1[5] = {0xB8,f4,28,9a,b7}; //b8f4289ab7
BYTE JmpEax[2] = {0xff,0xe0};
BYTE MovEaxAddress1[5]={0xB8,0,0,0,0};
BYTE MovEax[6]={0,0,0,0,0,0};
BYTE MovEaxThread[6]={0,0,0,0,0,0};
BYTE MovEaxRW[2]={0,0};
BYTE MovEaxR[5]={0,0,0,0,0};
BYTE MovEaxW[5]={0,0,0,0,0};
BYTE Mov1[2]={0,0};//保存清零时的原来数据,以便卸载驱动用
BYTE Mov2[2]={0,0};//保存清零时的原来数据,以便卸载驱动用
BYTE Mov3[2]={0,0};//保存清零时的原来数据,以便卸载驱动用
BYTE Mov4[2]={0,0};//保存清零时的原来数据,以便卸载驱动用
KIRQL Irql;
ULONG MyGetFunAddress(IN PCWSTR FunctionName);
ULONG myGetCurrentAddress(IN ULONG index);
NTSTATUS unhook();
NTSTATUS unhook1();
NTSTATUS unhook2();
NTSTATUS unhook3();
NTSTATUS unhook4();
NTSTATUS unhook5();
NTSTATUS unhookT();
VOID WPOFF();
VOID WPON();
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函数在哪写入
//////////////////////////////////////////////////////////////////////
// 名称: My_DbgkpSetProcessDebugObject
// 功能: 解除游戏保护对_My_DbgkpSetProcessDebugObject和DbgkpQueueMessage函数的HOOK(DNF)
// 参数:
// 返回: 状态
//////////////////////////////////////////////////////////////////////
void My_DbgkpSetProcessDebugObject()
{
Reg_DbgkpQueueMessage();
Reg_DbgkpSetProcessDebugObject();
}
//////////////////////////////////////////////////////////////////////
// 名称: Nakd_KiAttachProcess
// 功能: My_RecoveryHook_KiAttachProcess的中继函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
_declspec (naked) NTSTATUS Nakd_KiAttachProcess()
{
__asm
{
mov edi,edi
push ebp
mov ebp,esp
push ebx
push esi
mov eax,KiAttachProcessAddress //注意这个是全局变量 BYTE*
add eax,7
jmp eax
}
}
//////////////////////////////////////////////////////////////////////
// 名称: RecoveryHook_KiAttachProcess
// 功能: 解除游戏保护对_KiAttachProcess函数的HOOK(DNF)
// 参数:
// 返回: 状态
//////////////////////////////////////////////////////////////////////
NTSTATUS My_RecoveryHook_KiAttachProcess()
{
BYTE *KeAttachProcessAddress = NULL; //KeAttachProcess函数地址
BYTE *p;
KIRQL Irql;
//特征码
BYTE Signature1 = 0x56, //p-1 ok
Signature2 = 0x57, //p-2 ok
Signature3 = 0x5F, //p+5 ok
Signature4 = 0x5E, //p+6 ok
Signature5 = 0xE8; //p第一个字节 ok
//获得KeAttachProcess地址,然后通过特征码找到
//KiAttachProcess的地址
KeAttachProcessAddress = (BYTE*)MyGetFunAddress(L"KeAttachProcess");
if (KeAttachProcessAddress == NULL)
{
KdPrint(("KeAttachProcess地址获取失败\n"));
return 0;
}
//将p指向KeAttachProcess函数开始处
p = KeAttachProcessAddress;
while (1)
{
if ((*(p-1) == Signature1) &&
(*(p-2) == Signature2) &&
(*(p+5) == Signature3) &&
(*(p+6) == Signature4) &&
(*p == Signature5))
{
//定位成功后取地址
KiAttachProcessAddress = (PBYTE)(*(PULONG)(p+1)+(ULONG)(p+5));
*(ULONG *)(MovEaxAddress1+1)=*(ULONG *)(KiAttachProcessAddress+1);
KdPrint(("KiAttachProcessAddress地址%x\n",KiAttachProcessAddress));
KdPrint(("Nakd_KiAttachProcess地址%x\n",Nakd_KiAttachProcess));
KdPrint(("*(p-1)的特征码%x\n",*(p-1)));
KdPrint(("*p的特征码%x\n",*p));
KdPrint(("MovEaxAddress1[0]%0x \n",MovEaxAddress1[0]));
KdPrint(("MovEaxAddress1[1]%0x \n",MovEaxAddress1[1]));
KdPrint(("MovEaxAddress1[2]%0x \n",MovEaxAddress1[2]));
KdPrint(("MovEaxAddress1[3]%0x \n",MovEaxAddress1[3]));
KdPrint(("MovEaxAddress1[4]%0x \n",MovEaxAddress1[4]));
break;
}
//推动指针
p++;
}
//计算中继函数地址
*(ULONG *)(MovEaxAddress+1)=(ULONG)Nakd_KiAttachProcess;
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(KiAttachProcessAddress,MovEaxAddress,5);
RtlCopyMemory(KiAttachProcessAddress+5,JmpEax,2);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
// 名称: Nakd_NtOpenProcess
// 功能: My_RecoveryHook_NtOpenProcess的中继函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
_declspec (naked) NTSTATUS Nakd_NtOpenProcess()
{
//获得调用者的EPROCESS
processEPROCESS = IoGetCurrentProcess();
//将调用者的进程名保存到str1中
RtlInitAnsiString(&p_str1,(PCSZ)(ULONG)processEPROCESS+0x174);
//将我们要比对的进程名放入str2
RtlInitAnsiString(&p_str2,DNF_EXE);
if (RtlCompareString(&p_str1,&p_str2,TRUE) == 0)
{
//说明是DNF进程访问了这里
KdPrint(("DNF.exe的DebugPort地址为 %x",(ULONG)processEPROCESS+0xbc));
__asm
{
push dword ptr [ebp-38h]
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
}
}
}
//////////////////////////////////////////////////////////////////////
// 名称: 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};
//获取NtOpenProcess的地址
NtOpenProcessAddress = (BYTE*)MyGetFunAddress(L"NtOpenProcess");
if (NtOpenProcessAddress == NULL)
{
KdPrint(("NtOpenProcess地址获取失败\n"));
return 0;//FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
//获取ObOpenObjectByPointer的地址
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
if (ObOpenObjectByPointerAddress == NULL)
{
KdPrint(("ObOpenObjectByPointer地址获取失败\n"));
return 0;//FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
//将p指向NtOpenProcess函数开始处
p = NtOpenProcessAddress;
//用一个无限循环来判断给定的特征码来确定被HOOK位置
while (1)
{
if ((*(p-7) == 0x50) && //ok
(*(p-0xE) == 0x56) &&//ok
(*(p+0xd) == 0x50) &&//ok
(*(p+0x16) == 0x3b) &&//ok
(*(p+0x17) == 0xce) &&//ok
(*p == 0xE8) &&//ok
(*(p+5) == 0x8b) &&//ok
(*(p+6) == 0xf8))//ok
{
KdPrint(("%0X \n",(ULONG)p));
break;
}
//推动指针向前走
p++;
}
//将top5code指向 p 的当前处
//用以取出 call [地址] 这5字节里面的地址
//top5code = (TOP5CODE*)p;
p_TpHookAddress = (PBYTE)(*(PULONG)(p+1)+(ULONG)(p+5));
KdPrint(("p_TpHookAddress应该跳转的地址 %0X \n",(ULONG)p_TpHookAddress));
//80580a6f e92c0d4c77 jmp f7a417a0
//找到我们写入自定义函数的地址
p_MyHookAddress = p-6;
*(BYTE *)MovEax=*(BYTE *)p_MyHookAddress;
*(BYTE *)(MovEax+1)=*(BYTE *)(p_MyHookAddress+1);
*(BYTE *)(MovEax+2)=*(BYTE *)(p_MyHookAddress+2);
*(BYTE *)(MovEax+3)=*(BYTE *)(p_MyHookAddress+3);
*(BYTE *)(MovEax+4)=*(BYTE *)(p_MyHookAddress+4);
*(BYTE *)(MovEax+5)=*(BYTE *)(p_MyHookAddress+5);
KdPrint(("MovEax%X \n",(ULONG)MovEax));
KdPrint(("p_MyHookAddress%0X \n",(ULONG)p_MyHookAddress));
//保存调用ObOpenObjectByPointer函数以后的返回地址
p_ReturnAddress = p+5;
KdPrint(("p_ReturnAddress%0X \n",(ULONG)p_ReturnAddress));
KdPrint(("Nakd_NtOpenProcess%0X \n",(ULONG)Nakd_NtOpenProcess));
//将一条JMP Nakd_NtOpenProcess写入到数组中
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenProcess - ((ULONG)p_MyHookAddress+5);
KdPrint(("JmpAddress[0]%0x \n",JmpAddress[0]));
KdPrint(("JmpAddress[1]%0x \n",JmpAddress[1]));
KdPrint(("JmpAddress[2]%0x \n",JmpAddress[2]));
KdPrint(("JmpAddress[3]%0x \n",JmpAddress[3]));
KdPrint(("JmpAddress[4]%0x \n",JmpAddress[4]));
KdPrint(("JmpAddress[5]%0x \n",JmpAddress[5]));
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(p_MyHookAddress,JmpAddress,6);
KdPrint(("p_MyHookAddress_hook后的地址%0X \n",*(ULONG *)(p_MyHookAddress)));
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
// NtOpenThread用到的全局变量[为了方便堆栈平衡的处理使用全局变量]
PEPROCESS processEPROCESS_2 = NULL; //保存访问者的EPROCESS
ANSI_STRING p_str1_2,p_str2_2; //保存进程名称
BYTE *ObOpenObjectByPointerAddress_2 = NULL; //ObOpenObjectByPointer的地址
BYTE *p_TpHookAddress_2 = NULL; //TP的HOOK函数地址
BYTE *p_ReturnAddress_2 = NULL; //返回到的地址
BYTE *p_MyHookAddress_2 = NULL; //我们的HOOK函数在哪写入
//////////////////////////////////////////////////////////////////////
// 名称: Nakd_ NtOpenThread
// 功能: My_RecoveryHook_ NtOpenThread的中继函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
_declspec (naked) NTSTATUS Nakd_NtOpenThread()
{
//获得调用者的EPROCESS
processEPROCESS_2 = IoGetCurrentProcess();
//将调用者的进程名保存到str1_2中
RtlInitAnsiString(&p_str1_2,(PCSZ)(ULONG)processEPROCESS_2+0x174);
//将我们要比对的进程名放入str2_2
RtlInitAnsiString(&p_str2_2,DNF_EXE);
if (RtlCompareString(&p_str1_2,&p_str2_2,TRUE) == 0)
{
//说明是DNF进程访问了这里
__asm
{
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
push p_ReturnAddress_2
mov eax,p_TpHookAddress_2
jmp eax
}
}
else
__asm
{
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
push p_ReturnAddress_2
mov eax,ObOpenObjectByPointerAddress_2
jmp eax
}
}
//////////////////////////////////////////////////////////////////////
// 名称: My_RecoveryHook_ NtOpenThread
// 功能: 解除游戏保护对NtOpenThread的HOOK
// 参数:
// 返回: 状态
//////////////////////////////////////////////////////////////////////
NTSTATUS My_RecoveryHook_NtOpenThread()
{
BYTE * NtOpenThreadAddress = NULL; // NtOpenThread的地址
BYTE *p= NULL; //临时
BYTE JmpAddress[6] = {0xE9,0,0,0,0,0x90};
//获取NtOpenThread的地址
NtOpenThreadAddress = (BYTE*)MyGetFunAddress(L"NtOpenThread");
if (NtOpenThreadAddress == NULL)
{
KdPrint(("NtOpenThread地址获取失败\n"));
return 0;
}
//获取ObOpenObjectByPointer_2的地址
ObOpenObjectByPointerAddress_2 = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
if (ObOpenObjectByPointerAddress_2 == NULL)
{
KdPrint(("ObOpenObjectByPointer地址获取失败\n"));
return 0;
}
//将p指向NtOpenThread函数开始处
p= NtOpenThreadAddress;
//用一个无限循环来判断给定的特征码来确定被HOOK位置
while (1)
{
if ((*(p-7) == 0x50) && //ok
(*(p-0xE) == 0x56) &&//ok
(*(p+0xd) == 0x50) &&//ok
(*(p+0x1b) == 0x3b) &&
(*(p+0x1c) == 0xfe) &&
(*p == 0xE8) &&//ok
(*(p+5) == 0x8b) &&//ok
(*(p+6) == 0xf8))//ok
{
KdPrint(("p%0X \n",(ULONG)p));
break;
}
//推动指针向前走
p++;
}
//将top5code_2指向 p_2 的当前处
//用以取出 call [地址] 这5字节里面的地址
//top5code_2 = (TOP5CODE_2 *)p_2;
p_TpHookAddress_2 = (PBYTE)(*(PULONG)(p+1)+(ULONG)(p+5));
KdPrint(("p_TpHookAddress_2应该跳转的地址 %0X \n",(ULONG)p_TpHookAddress_2));
//找到我们写入自定义函数的地址
p_MyHookAddress_2 = p-6;
*(BYTE *)MovEaxThread=*(BYTE *)p_MyHookAddress_2;
*(BYTE *)(MovEaxThread+1)=*(BYTE *)(p_MyHookAddress_2+1);
*(BYTE *)(MovEaxThread+2)=*(BYTE *)(p_MyHookAddress_2+2);
*(BYTE *)(MovEaxThread+3)=*(BYTE *)(p_MyHookAddress_2+3);
*(BYTE *)(MovEaxThread+4)=*(BYTE *)(p_MyHookAddress_2+4);
*(BYTE *)(MovEaxThread+5)=*(BYTE *)(p_MyHookAddress_2+5);
KdPrint(("MovEaxThread!!!!!!!!!!!!!!!!!%X \n",(ULONG)MovEaxThread));
//保存调用ObOpenObjectByPointer函数以后的返回地址
p_ReturnAddress_2 = p+5;
KdPrint((" p_MyHookAddress_2 %0X \n",(ULONG) p_MyHookAddress_2));
KdPrint((" p_ReturnAddress_2 %0X \n",(ULONG)p_ReturnAddress_2));
//将一条JMP Nakd_ NtOpenThread写入到数组中
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenThread - ((ULONG)p_MyHookAddress_2+5);
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(p_MyHookAddress_2,JmpAddress,6);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
// 名称: My_RecoveryHook_NtReadAndWriteMemory
// 功能: 解除游戏保护对NtReadVirtualMemory和
// NtWriteVirtualMemory的HOOK
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
NTSTATUS My_RecoveryHook_NtReadAndWriteMemory()
{
BYTE Push1Ch[2] = {0x6a,0x1c}; //0~2字节
BYTE PushAdd[5] = {0x68,0xd8,0x6f,0x4f,0x80}; //NtReadVirtualMemory[物理机]
BYTE PushAdd2[5] = {0x68,0xf0,0x6f,0x4f,0x80}; //NtWriteVirtualMemory[物理机]
KIRQL Irql;
//从SSDT表中获取NtReadVirtualMemory函数地址
NtReadVirtualMemoryAddress = (BYTE*)myGetCurrentAddress(0xBA);
if (NtReadVirtualMemoryAddress == NULL)
{
KdPrint(("NtReadVirtualMemory函数地址获取失败! \n"));
return 0;//FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
//*(BYTE *)MovEax=*(BYTE *)p_MyHookAddress;
*(BYTE *)MovEaxRW=*(BYTE *)NtReadVirtualMemoryAddress;
*(BYTE *)(MovEaxRW+1)=*(BYTE *)(NtReadVirtualMemoryAddress+1);
*(BYTE *)MovEaxR=*(BYTE *)(NtReadVirtualMemoryAddress+2);
*(BYTE *)(MovEaxR+1)=*(BYTE *)(NtReadVirtualMemoryAddress+3);
*(BYTE *)(MovEaxR+2)=*(BYTE *)(NtReadVirtualMemoryAddress+4);
*(BYTE *)(MovEaxR+3)=*(BYTE *)(NtReadVirtualMemoryAddress+5);
*(BYTE *)(MovEaxR+4)=*(BYTE *)(NtReadVirtualMemoryAddress+6);
//从SSDT表中获取NtWriteVirtualMemory函数地址
NtWriteVirtualMemoryAddress = (BYTE*)myGetCurrentAddress(0x115);
if (NtWriteVirtualMemoryAddress == NULL)
{
KdPrint(("NtWriteVirtualMemory函数地址获取失败! \n"));
return 0;//FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
*(BYTE *)MovEaxW=*(BYTE *)(NtWriteVirtualMemoryAddress+2);
*(BYTE *)(MovEaxW+1)=*(BYTE *)(NtWriteVirtualMemoryAddress+3);
*(BYTE *)(MovEaxW+2)=*(BYTE *)(NtWriteVirtualMemoryAddress+4);
*(BYTE *)(MovEaxW+3)=*(BYTE *)(NtWriteVirtualMemoryAddress+5);
*(BYTE *)(MovEaxW+4)=*(BYTE *)(NtWriteVirtualMemoryAddress+6);
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(NtReadVirtualMemoryAddress,Push1Ch,2);
RtlCopyMemory(NtReadVirtualMemoryAddress+2,PushAdd,5);
RtlCopyMemory(NtWriteVirtualMemoryAddress,Push1Ch,2);
RtlCopyMemory(NtWriteVirtualMemoryAddress+2,PushAdd2,5);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
ULONG uNtSetContextThreadAddress;
ULONG uNtGetContextThreadAddress;
ULONG TenNtSetContextThread, TenNtGetContextThread;
//////////////////////////////////////////////////////////////////////
// 名称: _MyNtGetThreadContext
// 功能: 两个SSDT HOOK伪造函数的中继函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
_declspec (naked) NTSTATUS Nakd_NtGetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
__asm
{
jmp dword ptr[TenNtGetContextThread]
}
}
_declspec (naked) NTSTATUS Nakd_NtSetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
__asm
{
jmp dword ptr[TenNtSetContextThread]
}
}
//////////////////////////////////////////////////////////////////////
// 名称: MyNtGetThreadContext && MyNtSetThreadContext
// 功能: NtGetThreadContext与NtSetThreadContext函数被SSDT HOOK的伪造函数
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
UCHAR* PsGetProcessImageFileName( IN PEPROCESS Process );
NTSTATUS MyNtGetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
if ( _stricmp((const char*)PsGetProcessImageFileName(PsGetCurrentProcess()),DNF_EXE) )
{
return Nakd_NtGetThreadContext(hThread, pContext);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS MyNtSetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
if ( _stricmp((const char*)PsGetProcessImageFileName(PsGetCurrentProcess()),DNF_EXE) )
{
return Nakd_NtSetThreadContext(hThread, pContext);
}
//DbgPrint("Dr7:%08X\n", pContext->Dr7);
if ( pContext->Dr7 == 0x101 )
{
return Nakd_NtSetThreadContext(hThread, pContext);
}
return STATUS_UNSUCCESSFUL;
}
//////////////////////////////////////////////////////////////////////
// 名称: My_Recovery_HardwareBreakpoint
// 功能: 通过对set与get进行SSDT HOOK来恢复硬件断点
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
NTSTATUS My_Recovery_HardwareBreakpoint()
{
KIRQL Irql;
//获取地址
uNtSetContextThreadAddress = (ULONG)KeServiceDescriptorTable->ServiceTableBase+0xD5 * 4;
uNtGetContextThreadAddress = (ULONG)KeServiceDescriptorTable->ServiceTableBase+0x55 * 4;
TenNtSetContextThread = *(ULONG*)uNtSetContextThreadAddress;
TenNtGetContextThread = *(ULONG*)uNtGetContextThreadAddress;
KdPrint(("Set地址:%0X\n",TenNtSetContextThread));
KdPrint(("Get地址:%0X\n",TenNtGetContextThread));
KdPrint(("Process:%0X \n",(ULONG)p_MyHookAddress));
//KdPrint(("Thread:%0X \n",(ULONG)t_MyHookAddress));
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//完成SSDT HOOK
*(ULONG*)uNtGetContextThreadAddress = (ULONG)MyNtGetThreadContext;
*(ULONG*)uNtSetContextThreadAddress = (ULONG)MyNtSetThreadContext;
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_UNSUCCESSFUL;
}
//////////////////////////////////////////////////////////////////////
// 名称: MyEnumKernelModule
// 功能: 枚举内核模块
// 参数: str:内核模块名称
// moduleadd:该模块地址[传出]
// modulesie:该模块大小[传出]
// 返回:
//////////////////////////////////////////////////////////////////////
//BOOLEAN tlgstst= FALSE; //如果找到了指定模块则设置为TRUE
ULONG size, index;
PVOID GetDriverBaseAdress(IN CHAR* str)
{
NTSTATUS status;
ULONG index;
PULONG buf;
PSYSTEM_MODULE_INFORMATION module;
PVOID driverAddress = 0;
char *sysname[256];
char *hljname[256];
ANSI_STRING ModuleName1,ModuleName2;
//BOOLEAN tlgstst= FALSE;
ZwQuerySystemInformation(SystemModuleInformation, &size, 0, &size);
if (NULL == (buf = (PULONG)ExAllocatePool(PagedPool, size)))
{
DbgPrint("failed alloc memory failed_1 \n");
return 0;
}
status = ZwQuerySystemInformation(SystemModuleInformation, buf, size, 0);
if (!NT_SUCCESS(status))
{
DbgPrint("failed query_2\n");
return 0;
}
module = (PSYSTEM_MODULE_INFORMATION)((PULONG)buf + 1);
RtlInitAnsiString(&ModuleName1,str);
for (index = 0; index < *buf; index++)
{
// driverAddress = module[index].Base;
// DbgPrint("Module found at:%x\n", driverAddress);
sysname[index] = module[index].ImageName + module[index].ModuleNameOffset;
//DbgPrint("Module found at:%s\n", sysname[index]);
//hljname[index] = module[index].ImageName;
//DbgPrint("imagename found at:%s\n", hljname[index]);
RtlInitAnsiString(&ModuleName2,sysname[index]);
if (RtlCompareString(&ModuleName1,&ModuleName2,TRUE) == 0)
{
sysname[index] = module[index].ImageName + module[index].ModuleNameOffset;
DbgPrint("Module found at:%s\n", sysname[index]);
driverAddress = module[index].Base;
DbgPrint("Module found at:%x\n", driverAddress);
//tlgstst = TRUE;
break;
}
}
ExFreePool(buf);
return driverAddress;
}
//////////////////////////////////////////////////////////////////////
// 名称: My_Recovery_Debugport
// 功能: 恢复游戏对debugport的清零操作
// 参数:
// 返回:
//////////////////////////////////////////////////////////////////////
BYTE *sd1 = NULL,*sd2 = NULL,*pd = NULL;
BYTE rreett[2] = {0x8b,0xff},rreett1[2] = {0xe9,0x40};
BYTE *p1,*p2,*p3,*p4;
NTSTATUS My_Recovery_Debugport()
{
NTSTATUS stats;
ULONG ModuleSize,ModuleAddress,i,number = 0;
BYTE *p;
KIRQL Irql;
BYTE C390[2] = {0xc3,0x90},C391[3]={0xc2,0x08,0x00};
//获取指定的内核模块地址和字节数
ModuleAddress = (ULONG)GetDriverBaseAdress("tesSafe.sys");
if (ModuleAddress == 0)
{
return 0;//FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
}
KdPrint(("Address:%0X Sie:%d \n",ModuleAddress,size));
//将P指向内核模块开始处
p1 = (BYTE*)ModuleAddress + 0x2124;//2123
p2 = (BYTE*)ModuleAddress + 0x585e;//5855
p3 = (BYTE*)ModuleAddress + 0x2080;//别人给的,只有这个没确定!
p4 = (BYTE*)ModuleAddress + 0x3926;//监控
KdPrint(("p1:%0X \n",(ULONG)p1));
KdPrint(("p2:%0X \n",(ULONG)p2));
KdPrint(("p3:%0X \n",(ULONG)p3));
KdPrint(("p4:%0X \n",(ULONG)p4));
//干掉3个SD
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(p4,C390,2);//这个是监控
RtlCopyMemory(p1,C390,2);
RtlCopyMemory(p2,C390,2);
RtlCopyMemory(p3,C390,2);
//RtlCopyMemory(p3,C391,3);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
NTSTATUS unhookT()
{
WPOFF(); //清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(KiAttachProcessAddress,MovEaxAddress1,5);//1
RtlCopyMemory(KiAttachProcessAddress+5,JmpEax,2);
RtlCopyMemory(p_MyHookAddress,MovEax,6);//2
RtlCopyMemory(p_MyHookAddress_2,MovEaxThread,6);//3
RtlCopyMemory(NtReadVirtualMemoryAddress,MovEaxRW,2);//4
RtlCopyMemory(NtReadVirtualMemoryAddress+2,MovEaxR,5);
RtlCopyMemory(NtWriteVirtualMemoryAddress,MovEaxRW,2);
RtlCopyMemory(NtWriteVirtualMemoryAddress+2,MovEaxW,5);
*(ULONG*)uNtGetContextThreadAddress = TenNtGetContextThread;//5
*(ULONG*)uNtSetContextThreadAddress = TenNtSetContextThread;
RtlCopyMemory(p1,rreett,2);//6
RtlCopyMemory(p2,rreett,2);
RtlCopyMemory(p3,rreett1,2);
RtlCopyMemory(p4,rreett,2);
//恢复Irql
KeLowerIrql(Irql);
WPON(); //恢复CR0
return STATUS_SUCCESS;
}
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
unhookT();
KdPrint(("驱动卸载成功\n"));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING pRegistryString)
{
DriverObject->DriverUnload = OnUnload;
My_DbgkpSetProcessDebugObject();
My_RecoveryHook_KiAttachProcess();
My_RecoveryHook_NtOpenProcess();
My_RecoveryHook_NtOpenThread();
My_RecoveryHook_NtReadAndWriteMemory();
My_Recovery_HardwareBreakpoint();
My_Recovery_Debugport();
KdPrint(("驱动加载成功\n"));
return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
// 名称: MyGetFunAddress
// 功能: 获取函数地址
// 参数: 函数名称字符串指针
// 返回: 函数地址
//////////////////////////////////////////////////////////////////////
ULONG MyGetFunAddress( IN PCWSTR FunctionName)
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
//////////////////////////////////////////////////////////////////////
// 名称: myGetCurrentAddress
// 功能: 获取SSDT表中指定函数的当前地址
// 参数: index:指定函数在表中的索引号
// 返回: 刂?
//////////////////////////////////////////////////////////////////////
ULONG myGetCurrentAddress(IN ULONG index)
{
ULONG SSDT_Cur_Addr;
__asm
{
push ebx
push eax
mov ebx,KeServiceDescriptorTable
mov ebx,[ebx]
mov eax,index
shl eax,2
add ebx,eax
mov ebx,[ebx]
mov SSDT_Cur_Addr,ebx
pop eax
pop ebx
}
return SSDT_Cur_Addr;
}
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
}
}
#pragma INITCODE
VOID Reg_DbgkpQueueMessage()
{
BYTE* _bp=(BYTE*)myGetCurrentAddress(0x7A);
while(1)
{
if((*(_bp)==0x8B)&&(*(_bp+3)==0x89)&&(*(_bp+10)==0x74)&&(*(_bp+11)==0x48)&&(*(_bp+12)==0x68))
{
addr_DbgkpQueueMessage=(ULONG)_bp-0xD;
break;
}
_bp++;
}
KdPrint(("DbgQueueMessage的地址为:%x\n",addr_DbgkpQueueMessage));
//BYTE b_byte[]={0x8B,0xFF,0x55,0x8B,0xEC,0x81,0xEC};
WPOFF();
RtlCopyBytes((void*)addr_DbgkpQueueMessage,MovEaxAddress2,7);
WPON();
}
#pragma PAGEDCODE
VOID Reg_DbgkpSetProcessDebugObject()
{
BYTE* _bp=(BYTE*)addr_DbgkpQueueMessage;
while(1)
{
if((*(_bp)==0x64)&&(*(_bp+6)==0x89)&&(*(_bp+9)==0x8D)&&(*(_bp+15)==0x89)&&(*(_bp+21)==0x33))
{
addr_DbgkpSetProcessDebugObject=(ULONG)_bp-0xB;
break;
}
_bp++;
}
KdPrint(("DbgkpSetProcessDebugObject的地址为:%x\n",addr_DbgkpSetProcessDebugObject));
//BYTE b_byte[]={0x8B,0xFF,0x55,0x8B,0xEC,0x83,0xEC};
WPOFF();
RtlCopyBytes((void*)addr_DbgkpSetProcessDebugObject,MovEaxAddress3,7);
WPON();
}
最新的TP 轩辕传奇反断点调试原理是什么?
我可以附加了,就是下断点(全部类型的断点),就退出,可能是R3级动了手脚?
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课