#pragma once
#include <string.h>
#include "function.h"
// 地址 精准特征码 模糊特征码================================
BOOLEAN bCompare(const UCHAR* pData, const UCHAR* bMask, const char* szMask)
{
for (; *szMask; ++szMask, ++pData, ++bMask)
{
if (*szMask == 'x' && *pData != *bMask) {
return 0;
}
}
return *szMask == '\0';
}
// 开始地址 长度 精准特征码 模糊特征码============================
ULONG FindPattern(ULONG dwdwAdd, ULONG dwLen, UCHAR *bMask, char *szMask)
{
for (ULONG i = 0; i < dwLen; i++) {
if (bCompare((UCHAR*)(dwdwAdd + i), bMask, szMask)) {
return (dwdwAdd + i);
}
}
return 0;
}
//恢复内存保护 ======================================================================================
void PageProtectOn()
{
__asm {
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
}
//去掉内存保护=======================================================================================
void PageProtectOff()
{
__asm {
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
}
BOOLEAN HookOrUnhookAPI(
IN ULONG ulApiAddr, //被hook的API地址
IN ULONG ulFunctionAddr, //跳转到的函数地址
IN OUT UCHAR *ucApiHeader_5, //API的头5个字节, true:作为返回值使用.false:为传递参数
IN BOOLEAN bHookOrUnhook)//TRUE 为 hook ,FALSE 为Unhook
{
BOOLEAN bState = TRUE;
ULONG ulJumpOffset = 0;
UCHAR ucJumpCode_5[5];
if (bHookOrUnhook)
{ //参数检查
if (ulApiAddr == 0 || ulFunctionAddr == 0 || ucApiHeader_5 == NULL)
{
KdPrint(("hook参数错误,前3个参数不能为0!\n"));
bState = FALSE;
return bState;
}
//计算跳转偏移
ulJumpOffset = ulFunctionAddr - ulApiAddr - 5;
ucJumpCode_5[0] = 0xe9;
*(PULONG)(ucJumpCode_5 + 1) = ulJumpOffset;
//保存api前5个字节
memcpy((PVOID)ucApiHeader_5, (PVOID)ulApiAddr, 5);
//hook api
PageProtectOff();
memcpy((PVOID)ulApiAddr, (PVOID)ucJumpCode_5, 5);
PageProtectOn();
}
else {
if (ulApiAddr == 0 || ucApiHeader_5 == NULL)
{
KdPrint(("Unhook参数错误,参数不能为0!\n"));
bState = FALSE;
return bState;
}
PageProtectOff();
memcpy((PVOID)ulApiAddr, (PVOID)ucApiHeader_5, 5);
PageProtectOn();
}
return bState;
}
__declspec(naked) PMDL My_IoAllocateMDL(
__in_opt PVOID VirtualAddress,
__in ULONG Length,
__in BOOLEAN SecondaryBuffer,
__in BOOLEAN ChargeQuota,
__inout_opt PIRP Irp OPTIONAL)
{
__asm {
mov edi, edi
push ebp
mov ebp, esp
push eax
pushfd
mov eax, gpv_KdEnteredDebugger
cmp VirtualAddress, eax
jne __JmpAPI_5
add VirtualAddress,0x40
__JmpAPI_5:
popfd
pop eax
jmp gul_Jmp_IoAllocateMDL_5
}
}
//======================================================================================
BOOLEAN filter(void) {
PEPROCESS curproc = (char*)PsGetCurrentProcess() + 0x16C;
//KdPrint(("=================================================\n"));
if (strstr(curproc, "TASLogin.exe") != 0)
return TRUE;
else
return FALSE;
}
//建立一个自己的KdpStub用于进行过滤
void __declspec(naked) MyKdpStub(void)
{
//return ((KDPSTUB)KdpStubAddr)(TrapFrame, ExceptionFrame, ExceptionRecord, ContextRecord, PreviousMode, SecondChance);
//如果检测到是TP的登录进程,在这个地方就返回KdpStub 174 XP 16C WIN7
__asm
{
pushad
pushfd
call filter
cmp eax, 0
je __KdpTrap
popfd
popad
mov edi, edi
push ebp
mov ebp, esp
jmp gulJmp_KdpStubAddr_5
__KdpTrap :
popfd
popad
jmp gul_KdpTrap_Address
}
}
//返回值为 KiDebugRoutine 全局变量地址
//参数返回 KdpStub() 函数地址
ULONG GetPfnKiDebugRoutineAndKdpKdpStubAddress(PULONG pul_KdpStub)
{
UNICODE_STRING usKdDisableDebugger;
ULONG ulKdDisableDebuggerAddr = 0;
ULONG ulKdDisableDebuggerWithLockAddr = 0;
ULONG ulKiDebugRoutineAddr = 0;
/* nt!KdDisableDebugger:
83eea846 6a01 push 1
83eea848 e806ffffff call nt!KdDisableDebuggerWithLock(83eea753)
83eea84d c3 ret */
RtlInitUnicodeString(&usKdDisableDebugger, L"KdDisableDebugger");
ulKdDisableDebuggerAddr = (ULONG)MmGetSystemRoutineAddress(&usKdDisableDebugger);
if (ulKdDisableDebuggerAddr != 0)
{
KdPrint(("KdDisableDebugger地址:%08x\r\n", ulKdDisableDebuggerAddr));
//获取 KdDisableDebuggerWithLock 函数地址>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ulKdDisableDebuggerAddr += 2;
ulKdDisableDebuggerWithLockAddr = ulKdDisableDebuggerAddr + *(PULONG)(ulKdDisableDebuggerAddr + 1) + 5;
KdPrint(("KdDisableDebuggerWithLock地址:%08x\r\n", ulKdDisableDebuggerWithLockAddr));
//83eea7ee 881d2c2df783 mov byte ptr[nt!KdDebuggerEnabled(83f72d2c)], bl
//83eea7f4 c705bc79f783afa9ee83 mov dword ptr[nt!KiDebugRoutine(83f779bc)], offset nt!KdpStub(83eea9af)
//83eea7fe 881dd402dfff mov byte ptr ds : [0FFDF02D4h], bl
//83eea804 ff056061f483 inc dword ptr[nt!KdDisableCount(83f46160)]
ulKiDebugRoutineAddr = FindPattern(ulKdDisableDebuggerWithLockAddr, 512,
(PUCHAR)"\xc7\x05\xbc\x79\xf7\x83\xaf\xa9\xee\x83\x88\x1d", "xx????????xx");
if (ulKiDebugRoutineAddr != 0)
{
//获取 KdpStub() 地址
if (pul_KdpStub)
{
ULONG ulTemp;
ulTemp = ulKiDebugRoutineAddr + 6;
ulTemp = *(PULONG)ulTemp;
*pul_KdpStub = ulTemp;
KdPrint(("KdpStub()地址:%08x\r\n", *pul_KdpStub));
}
//获取 KiDebugRoutine 地址
ulKiDebugRoutineAddr += 2;
ulKiDebugRoutineAddr = *(PULONG)ulKiDebugRoutineAddr;
KdPrint(("KiDebugRoutineAddr地址:%08x\r\n", ulKiDebugRoutineAddr));
}
else {
ulKiDebugRoutineAddr = 0;
KdPrint(("搜索KiDebugRoutine地址失败\n"));
}
}
else {
KdPrint(("搜索KdDisableDebugger失败\n"));
return 0;
}
return ulKiDebugRoutineAddr;
}
//======================================================================================
BOOLEAN ChangeKiDebugRoutineAddr(void)
{
ULONG ulJumpOffset;
//第一步,获取 KiDebugRoutine 函数指针地址>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//在这个函数内直接获取 KdpStub() 函数地址,在参数中返回给全局变量
gul_KiDebugRoutine_Address = GetPfnKiDebugRoutineAndKdpKdpStubAddress(&gul_KdpStub_Address);
if (0 == gul_KiDebugRoutine_Address)
{
KdPrint(("搜索KiDebugRoutine地址失败\n"));
return FALSE;
}
KdPrint(("KiDebugRoutine地址:%08x\r\n", gul_KiDebugRoutine_Address));
//第二步获取 KdpTrap()函数地址,
//以调试模式启动系统时 KiDebugRoutine 函数指针刚好指向 KdpTrap()函数地址
gul_KdpTrap_Address = *(PULONG)gul_KiDebugRoutine_Address;
KdPrint(("KdpTrap()地址:%08x\r\n", gul_KdpTrap_Address));
//第三步 HOOK KdpStub() 函数前五个字节,跳转到自己的过滤函数>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/* nt!KdpStub:
83f1c9af 8bff mov edi,edi
83f1c9b1 55 push ebp
83f1c9b2 8bec mov ebp,esp
83f1c9b4 53 push ebx
83f1c9b5 56 push esi*/
gulJmp_KdpStubAddr_5 = gul_KdpStub_Address + 5;
ulJumpOffset = (ULONG)MyKdpStub - gul_KdpStub_Address - 5;
PageProtectOff();
*(PUCHAR)gul_KdpStub_Address = 0xe9;
*(PULONG)(gul_KdpStub_Address + 1) = ulJumpOffset;
//*(PVOID*)ulAddr = (PVOID)MyKdpStub;
PageProtectOn();
return TRUE;
}
// HOOK IoAllocateMdl()处理 DWORD KdEnteredDebugger变量
BOOLEAN HookIoAllocateMdl(void)
{
BOOLEAN bStatus = TRUE;
UNICODE_STRING usKdEnteredDebugger;
//获取 KdEnteredDebugger 地址>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
RtlInitUnicodeString(&usKdEnteredDebugger, L"KdEnteredDebugger");
gpv_KdEnteredDebugger = (PVOID)MmGetSystemRoutineAddress(&usKdEnteredDebugger);
if (gpv_KdEnteredDebugger != NULL)
{
KdPrint(("搜索KdEnteredDebugger地址:%08x\r\n", gpv_KdEnteredDebugger));
}
else {
KdPrint(("搜索KdEnteredDebugger失败\n"));
bStatus = FALSE;
return bStatus;
}
//hook IoAllocateMdl()
gul_Jmp_IoAll