虛擬機: Windows 7 64bit函數
過PG工具工具
驅動加載工具測試
PCHunter64加密
系統自帶的計算器和任務管理器等spa
實際思路與win32的思路同樣.都是替換SSDT表裏邊的函數地址.不過微軟被搞怕了,因此在x64上作了一些手腳.code
具體手腳就是x64經過SSDT獲得的函數地址,不是真實的函數絕對地址了,而是加密了的.進程
HOOKip
1.獲得系統服務表基址內存
2.保存須要Hook的函數地址(實際爲偏移)get
3.使內存可寫,把表中要Hook的地址替換成KeBugCheckEx的地址,還原內存屬性
4.HookKeBugCheckEx函數,在其開始處jmp到咱們本身的函數地址.
5.本身實現Hook的函數,在其中作處理.
注:
簡單說一下,win10x64th2及以前的版本,原始地址的保存方式是八字節的,每一個地址是須要重定向的絕對地址,但從win10x64rs1開始,原始地址保存方式是四字節的,每一個地址是不須要重定向的相對地址。
簡單說公式就是
original_address=image_base+address_read_from_file
其中original_address和image_base是八字節整形,address_read_from_file是四字節整形
以前的公式是:
original_address=image_base+(address_read_from_file-file_image_base)
這四個變量都是八字節整形,括號內計算的是重定向
Tesla.Angela 則給出了新的計算公式
VA = KiServiceTable - NtosBase + ReloadedNtosBase;
OriAddr = getdword(VA+Index*4) + NtosBase;
x64要Hook的函數地址是 ServiceTableBase[Index]>>4 + ServiceTableBase
此處Hook了NtOpenProcess,導出序號是35號.處理告終束計算器進程的時候,禁止結束.
還原Hook的時候不須要還原KeBugCheckEx,由於這個函數就是崩潰藍屏須要執行的函數.
這篇文章不會講述過PG.
獲取服務表基址
//獲取服務表基址
ULONGLONG GetKeServiceDescriptorTable64()
{
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
UCHAR byte1 = 0, byte2 = 0, byte3 = 0;
ULONG temp = 0;
ULONGLONG addr = 0;
//開始搜索
for (i = StartSearchAddress;i < EndSearchAddress;i++)
{
if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
{
byte1 = *i;
byte2 = *(i + 1);
byte3 = *(i + 2);
if (byte1 == 0x4c && byte2 == 0x8d && byte3 == 0x15) //4c8d15
{
memcpy(&temp, i + 3, 4);
addr = (ULONGLONG)temp + (ULONGLONG)i + 7;
return addr;
}
}
}
return 0;
}
獲取SSDT表中的函數地址
//獲取SSDT中的函數地址
ULONGLONG GetSSDTFuncCurrentAddr(ULONG id)
{
LONG dwtemp = 0;
PULONG ServiceTableBase = NULL;
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
dwtemp = ServiceTableBase[id];
dwtemp = dwtemp >> 4;
return (LONGLONG)dwtemp + (ULONGLONG)ServiceTableBase;
}
開啓Hook
//開啓Hook
VOID HookSSDT()
{
KIRQL irql;
ULONGLONG dwtmp = 0;
PULONG ServiceTableBase = NULL;
//獲取老函數地址
g_OldOpenProcess = (NTOPENPROCESS)GetSSDTFuncCurrentAddr(35);
//HookKeBugCheckEx
InlineHookKeBugCheckEx();
//保存地址數據,替換數據
ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
OldTpVal = ServiceTableBase[35]; //保存表中的偏移變量
irql = WriteProtectOFFx64();
ServiceTableBase[35] = GetOffsetAddress((ULONGLONG)KeBugCheckEx);
WriteProtectONx64(irql);
}
HookKeBugCheckEx做爲跳轉
//InlineHook_KeBugCheckEx
VOID InlineHookKeBugCheckEx()
{
KIRQL irql;
ULONGLONG myfun;
UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";
myfun = (ULONGLONG)HookNtOpenProcess;//替換成本身的函數地址
memcpy(jmp_code + 2, &myfun, 8);
irql = WriteProtectOFFx64();
memset(KeBugCheckEx, 0x90, 15);
memcpy(KeBugCheckEx, jmp_code, 12);//拷貝12字節
WriteProtectONx64(irql);
}
過PG後,加載驅動,使用任務管理器結束"計算器"程序失敗,提示"拒絕訪問"
PCHunter64位查看,又看到驅動掛鉤了NtOpenProcess函數
PS:博客的技術內容的寬度但是開的有點大了,感受本身很難把這些坑都填完.盡力填吧,每個技術方面都盡力去深究.不過也有本身的事要作,填坑的速度確定是快不了的.