先获取_KPCR->_KPRCB->_KTHREAD->ServiceTable
typedef struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE {
PVOID ServiceTableBase; //SSDT表的基地址
PVOID ServiceCounterTableBase;
ULONG_PTR NumberOfServices; //SSDT表中服务函数的个数
PVOID ParameterTableBase;
}SYSTEM_SERVICE_DESCRIPTOR_TABLE, * PSYSTEM_SERVICE_DESCRIPTOR_TABLE;
PSYSTEM_SERVICE_DESCRIPTOR_TABLE ServiceTable = 0;
__asm {
mov eax, fs : [0x124];
mov eax, [eax + 0xbc];
mov[ServiceTable], eax;
}
然后需要关闭写保护->修改函数->开启写保护
VOID SSDTHook(DWORD serviceNum) {
PSYSTEM_SERVICE_DESCRIPTOR_TABLE ServiceTable = 0;
__asm {
mov eax, fs : [0x124];
mov eax, [eax + 0xbc];
mov[ServiceTable], eax;
mov eax, cr0;
and eax, ~0x10000;
mov cr0, eax;
}
pTargetFunc = (PULONG)ServiceTable->ServiceTableBase + serviceNum;
oraginalFunc = *pTargetFunc;
*pTargetFunc = test;
__asm {
mov eax, cr0;
or eax, 0x10000;
mov cr0, eax;
}
}
替换的函数注意堆栈平衡,后来研究发现,如果是需要管理员权限的程序是打不开的,大概率因为函数内部做了检查函数地址
NTSTATUS __declspec(naked) test(DWORD par1, DWORD par2, DWORD par3, DWORD par4) {
__asm {
push ebp;
mov ebp, esp;
sub esp, 8;
mov eax, oraginalFunc;
mov[ebp - 8], eax;
}
DbgPrint("Hell world\n");
__asm {
push par4;
push par3;
push par2;
push par1;
mov edx, [ebp - 8];
mov [ebp - 4], edx;
call [ebp - 4];
mov esp, ebp;
pop ebp;
retn 0x10;
}
}