源码:
https://github.com/haidragon/SSDTHOOK_win7x64/tree/master/SSDTHOOK_win7x64
SSDT表的查找:
https://blog.csdn.net/zfdyq0/article/details/26515019
https://bbs.pediy.com/thread-249851.htm
补充知识点:
https://blog.csdn.net/liuyez123/article/details/50992038
https://bbs.pediy.com/thread-124770.htm
https://blog.csdn.net/liujiayu2/article/details/72874928
syscall是AMD CPU下的sysenter,以此进入内核层,由于64位下没有nt!KiFastCallEntry,而改用的是nt!KiSystemCall64,在64位系统下启用了四个新的MSR寄存器,有不同的作用,其中MSR_LSTAR保存的是rip的相关信息,可以通过rdmsr c0000082的方法查看到syscall跳转地址。这个地址正是nt!KiSystemCall64的入口地址。
32位与64位call地址的区别见:
加密解密4 543页
方式有push/ret
但是x64push只能为32位。但由于对其实际为64位。
因此方式为 push 高位
push 55667788h //对应opcode 6844332211
mov dword ptr[rsp+4],11223344h //对应opcode c744240488776655
ret //对应opcode c3
总共占 14字节
第二种 jmp [addr]
opcode是
ff25 0x00 00 00 00 xx xx xx xx xx xx xx xx 也是总共14字节 前面0x00 00 00 00 用做偏移
第三种是 jmp eax
mov rax,1122334455667788 //opcode 48b8 8877665544332211
jmp rax //opcode ffe0
共12字节
逆向工程核心原理 390页
纠正上面博客的一个错误:
刚好是fffff800`03e82772 4c8d15c7202300 后面四个字节(002320C7)
4c8d 是lea指令opcode 15表示r10
kd> u KiSystemServiceStart
nt!KiSystemServiceStart:
fffff800`03e8275e 4889a3d8010000 mov qword ptr [rbx+1D8h],rsp
fffff800`03e82765 8bf8 mov edi,eax
fffff800`03e82767 c1ef07 shr edi,7
fffff800`03e8276a 83e720 and edi,20h
fffff800`03e8276d 25ff0f0000 and eax,0FFFh
nt!KiSystemServiceRepeat:
fffff800`03e82772 4c8d15c7202300 lea r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]
fffff800`03e82779 4c8d1d00212300 lea r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]
fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h
SSDT hook
https://blog.csdn.net/zfdyq0/article/details/26753797
源码:
main.c
#include <hookssdt.h>
//驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
UnhookSSDT();
DbgPrint("Driver Unload\n");
}
//驱动入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath)
{
DbgPrint("Hello World\n");
//获取KeServiceDescriptorTable
KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
//开启Hook
HookSSDT();
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
hookssdt.h
#include <ntddk.h>
typedef struct _SYSTEM_SERVICE_TABLE {
PVOID ServiceTableBase;
PVOID ServiceCounterTableBase;
ULONGLONG NumberOfServices;
PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef struct _SERVICE_DESCRIPTOR_TABLE {
SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe (native api)
SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user)
SYSTEM_SERVICE_TABLE Table3; // not used
SYSTEM_SERVICE_TABLE Table4; // not used
}SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;
//NtTerminateProcess
typedef NTSTATUS(__fastcall *NTTERMINATEPROCESS)(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus);
NTKERNELAPI UCHAR * PsGetProcessImageFileName(PEPROCESS Process);
//SSDT表基址
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
NTTERMINATEPROCESS NtTerminateProcess = NULL;
ULONG OldTpVal;
//自己的NtTerminateProcess
NTSTATUS __fastcall Fuck_NtTerminateProcess(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus)
{
PEPROCESS Process;
NTSTATUS st = ObReferenceObjectByHandle(ProcessHandle, 0, *PsProcessType, KernelMode, &Process, NULL);
DbgPrint("Fake_NtTerminateProcess called!");
if (NT_SUCCESS(st))
{
if (!_stricmp(PsGetProcessImageFileName(Process), "calc.exe"))
return STATUS_ACCESS_DENIED;
else
return NtTerminateProcess(ProcessHandle, ExitStatus);
}
else
return STATUS_ACCESS_DENIED;
}
//关闭写保护
KIRQL WPOFFx64()
{
KIRQL irql = KeRaiseIrqlToDpcLevel();
UINT64 cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
return irql;
}
//开启写保护
void WPONx64(KIRQL irql)
{
UINT64 cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
KeLowerIrql(irql);
}
ULONGLONG GetKeServiceDescriptorTable64() //我的方法
{
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
UCHAR b1 = 0, b2 = 0, b3 = 0;
ULONG templong = 0;
ULONGLONG addr = 0;
for (i = StartSearchAddress;i < EndSearchAddress;i++)
{
if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
{
b1 = *i;
b2 = *(i + 1);
b3 = *(i + 2);
if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
{
memcpy(&templong, i + 3, 4);
addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
return addr;
}
}
}
return 0;
}
//获取SSDT中的函数地址
ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
LONG dwtmp = 0;
PULONG ServiceTableBase = NULL;
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
dwtmp = ServiceTableBase[id];
dwtmp = dwtmp >> 4;
return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}
ULONG GetOffsetAddress(ULONGLONG FuncAddr)
{
ULONG dwtmp = 0;
PULONG ServiceTableBase = NULL;
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
dwtmp = (ULONG)(FuncAddr - (ULONGLONG)ServiceTableBase);
return dwtmp << 4;
}
//InlineHook_KeBugCheckEx
VOID FuckKeBugCheckEx()
{
KIRQL irql;
ULONGLONG myfun;
UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";
myfun = (ULONGLONG)Fuck_NtTerminateProcess;//替换成自己的函数地址
memcpy(jmp_code + 2, &myfun, 8);
irql = WPOFFx64();
memset(KeBugCheckEx, 0x90, 15);
memcpy(KeBugCheckEx, jmp_code, 12);
WPONx64(irql);
}
VOID HookSSDT()
{
KIRQL irql;
ULONGLONG dwtmp = 0;
PULONG ServiceTableBase = NULL;
//get old address
NtTerminateProcess = (NTTERMINATEPROCESS)GetSSDTFuncCurAddr(41);
DbgPrint("Old_NtTerminateProcess: %llx", (ULONGLONG)NtTerminateProcess);
//set kebugcheckex
FuckKeBugCheckEx();
//show new address
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
OldTpVal = ServiceTableBase[41]; //record old offset value
irql = WPOFFx64();
ServiceTableBase[41] = GetOffsetAddress((ULONGLONG)KeBugCheckEx);
WPONx64(irql);
DbgPrint("KeBugCheckEx: %llx", (ULONGLONG)KeBugCheckEx);
DbgPrint("New_NtTerminateProcess: %llx", GetSSDTFuncCurAddr(41));
}
VOID UnhookSSDT()
{
KIRQL irql;
PULONG ServiceTableBase = NULL;
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
//set value
irql = WPOFFx64();
ServiceTableBase[41] = GetOffsetAddress((ULONGLONG)NtTerminateProcess); //OldTpVal; //直接填写这个旧值也行
WPONx64(irql);
//没必要恢复KeBugCheckEx的内容了,反正执行到KeBugCheckEx时已经完蛋了。
DbgPrint("NtTerminateProcess: %llx", GetSSDTFuncCurAddr(41));
}
转载于:https://blog.51cto.com/haidragon/2309601