x64技術之SSDT_Hook

測試環境:

虛擬機: 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.

關鍵代碼:

獲取服務表基址

 
  1. //獲取服務表基址

  2. ULONGLONG GetKeServiceDescriptorTable64()

  3. {

  4. PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);

  5. PUCHAR EndSearchAddress = StartSearchAddress + 0x500;

  6. PUCHAR i = NULL;

  7. UCHAR byte1 = 0, byte2 = 0, byte3 = 0;

  8. ULONG temp = 0;

  9. ULONGLONG addr = 0;

  10. //開始搜索

  11. for (i = StartSearchAddress;i < EndSearchAddress;i++)

  12. {

  13. if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))

  14. {

  15. byte1 = *i;

  16. byte2 = *(i + 1);

  17. byte3 = *(i + 2);

  18. if (byte1 == 0x4c && byte2 == 0x8d && byte3 == 0x15) //4c8d15

  19. {

  20. memcpy(&temp, i + 3, 4);

  21. addr = (ULONGLONG)temp + (ULONGLONG)i + 7;

  22. return addr;

  23. }

  24. }

  25. }

  26. return 0;

  27. }

獲取SSDT表中的函數地址

 
  1. //獲取SSDT中的函數地址

  2. ULONGLONG GetSSDTFuncCurrentAddr(ULONG id)

  3. {

  4. LONG dwtemp = 0;

  5. PULONG ServiceTableBase = NULL;

  6. ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;

  7. dwtemp = ServiceTableBase[id];

  8. dwtemp = dwtemp >> 4;

  9. return (LONGLONG)dwtemp + (ULONGLONG)ServiceTableBase;

  10. }

開啓Hook

 
  1. //開啓Hook

  2. VOID HookSSDT()

  3. {

  4. KIRQL irql;

  5. ULONGLONG dwtmp = 0;

  6. PULONG ServiceTableBase = NULL;

  7. //獲取老函數地址

  8. g_OldOpenProcess = (NTOPENPROCESS)GetSSDTFuncCurrentAddr(35);

  9. //HookKeBugCheckEx

  10. InlineHookKeBugCheckEx();

  11. //保存地址數據,替換數據

  12. ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;

  13. OldTpVal = ServiceTableBase[35]; //保存表中的偏移變量

  14. irql = WriteProtectOFFx64();

  15. ServiceTableBase[35] = GetOffsetAddress((ULONGLONG)KeBugCheckEx);

  16. WriteProtectONx64(irql);

  17. }

HookKeBugCheckEx做爲跳轉

 
  1. //InlineHook_KeBugCheckEx

  2. VOID InlineHookKeBugCheckEx()

  3. {

  4. KIRQL irql;

  5. ULONGLONG myfun;

  6. UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";

  7. myfun = (ULONGLONG)HookNtOpenProcess;//替換成本身的函數地址

  8. memcpy(jmp_code + 2, &myfun, 8);

  9. irql = WriteProtectOFFx64();

  10. memset(KeBugCheckEx, 0x90, 15);

  11. memcpy(KeBugCheckEx, jmp_code, 12);//拷貝12字節

  12. WriteProtectONx64(irql);

  13. }

測試效果:

過PG後,加載驅動,使用任務管理器結束"計算器"程序失敗,提示"拒絕訪問"

 

PCHunter64位查看,又看到驅動掛鉤了NtOpenProcess函數

PS:博客的技術內容的寬度但是開的有點大了,感受本身很難把這些坑都填完.盡力填吧,每個技術方面都盡力去深究.不過也有本身的事要作,填坑的速度確定是快不了的.

相關文章
相關標籤/搜索