愛悠閑 > 關于SSDT HOOK取消內存寫保護的問題

關于SSDT HOOK取消內存寫保護的問題

分類: 驅動學習  |  作者: ccx_john 相關  |  發布日期 : 2014-06-09  |  熱度 : 1198°

有些人說不去掉也不會藍屏,照樣能HOOK成功
確實,我當時也是這樣過。。。
不過拿給別人機器一測試就藍了

網上找到了MJ給出的答案:
當使用大頁面映射內核文件時,代碼段和數據段在一塊兒,所以頁必須是可寫的,這種情況下直接改是沒有問題的

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management下面增加兩個DWORD值'LargePageMinimum" = 0xFFFFFFFF, "EnforceWriteProtection" = 1,重啟,重新跑自己的驅動。。。 
win2k上RAM超過127M,winxp和win server 2003上RAM超過255M,內存管理器會使用大頁面(x86上4M,IA64和X86-64上16M)來映射Ntoskrnl.exe,這樣由于代碼和數據可能駐留在同一個頁面,所以代碼寫保護是被禁止的。以上兩個注冊表修改項,第一個指明了當內存數量達到多少時使用大頁面來映射ntoskrnl,設置成0xFFFFFFFF就是相當于無限大,因此不會使用大頁面。第二個開啟代碼寫保護。


一般去掉寫保護有三種方法:
1.更改注冊表(需要重啟)
HKLM/SYSTEM/CurrentControlset/Control/Session Manger/
Memory Management/EnforceWriteProtection=0

HKLM/SYSTEM/CurrentControlset/Control/Session Manger/
Memory Management/DisablePagingExecutive=1

2.修改控制寄存器cr0
就是把CR0中WP(寫保護)位設置為0,就可以禁止內存保護了。

  1. //取消內存保護   
  2. _asm  
  3. {  
  4.     Push eax  
  5.     Mov eax,CR0  
  6.     And eax,0FFFEFFFFh  
  7.     Mov CR0,eax  
  8.     Pop eax  
  9. }  
  10. //重新開啟內存保護   
  11. _asm  
  12. {  
  13.     Push eax  
  14.     Mov eax,CR0  
  15.     Or eax NOT 0FFFEFFFFh  
  16.     Mov CR0,eax  
  17.     Pop eax  
  18. }  

3. 利用MDL(Memory Descriptor List)來繞過寫保護
我們可以在MDL中描述一段內存,包括內存段的起始位置、所擁有的進程、字節數、內存段的標志等等。
  1. //MDL reference defined in ntddk.h   
  2. Typedef struct  _MDL{  
  3.     Struct  _MDL    *Next;  
  4.     CSHORT  Size;  
  5.     CSHORT  MdlFlags;  
  6.     Struct  _EPROCESS   *Process;  
  7.     PVOID   MappedSystemVa;  
  8.     PVOID   StartVa;  
  9.     ULONG   ByteCount;  
  10.     ULONG   ByteOffset;  
  11. }MDL,*PMDL;  
  12. //MDL Flags   
  13. #define MDL_MAPPED_TO_SYSTEM_VA     0x0001   
  14. #define MDL_PAGES_LOCKED                0x0002   
  15. #define MDL_SOURCE_IS_NONPAGED_POOL 0x0004   
  16. #define MDL_ALLOCATED_FIXED_SIZE        0x0008   
  17. #define MDL_PARTIAL                     0x0010   
  18. #define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020   
  19. #define MDL_IO_PAGE_READ                0x0040   
  20. #define MDL_WRITE_OPERATION             0x0080   
  21. #define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100   
  22. #define MDL_LOCK_HELD                   0x0200   
  23. #define MDL_PHYSICAL_VIEW               0x0400   
  24. #define MDL_IO_SPACE                        0x0800   
  25. #define MDL_NETWORK_HEADER          0x1000   
  26. #define MDL_MAPPING_CAN_FAIL            0x2000   
  27. #define MDL_ALLOCATED_MUST_SUCCEED  0x4000  

為了改變內存的標志,下面的代碼首先聲明一個結構體,用來保存從windows內核中導出的KeServiceDescriptorTable。當調用MmCreateMdl時,需要知道KeServiceDescriptorTable的基地址和它所擁有的函數入口的數量。這個函數定義了你想要MDL描述的內存段的起始地址和大小,然后應用程序在內存的非分頁內存中創建MDL。在應用程序中可以通過改變MDL的標志使得可以寫內存段,也就是把MDLFlag設置為MDL_MAPPED_TO_SYSTEM_VA,然后調用MmMapLockedPages來鎖定內存中的MDL頁。在下面的代碼中,MappedSystemCallTable中的地址與SSDT的內容相一致,但是現在你可以修改它了。

  1. //聲明   
  2. #pragma pack(1)   
  3. Typedef struct  ServiceDescriptorEntry{  
  4.     Unsigned int*   ServiceTableBase;  
  5.     Unsigned int*   ServiceCounterTableBase;  
  6.     Unsigned int    NumberOfService;  
  7.     Unsigned char*  ParamTableBase;  
  8. }SSDT_Entry;  
  9. #pragma pack()   
  10. _declspec(dllimport) SSDT_Entry KeServiceDescriptorTable;  
  11. PMDL    g_pmdlSystemCall;  
  12. PVOID   *MappedSystemCallTable;  
  13. //保存原始的系統調用地址,映射到我們的域中,來改變MDL的保護   
  14. g_pmdlSystemCall = MmCreateMdl(NULL,  
  15.                 KeServiceDescriptorTable,  
  16.                 ServiceTableBase,  
  17.                 KeServcieDescriptorTable.NumberOfService*4);  
  18. If(!g_pmdlSystemCall)  
  19.     Return STATUS_UNSUCCESSFUL;  
  20. MmBuildMdlForNonPagedPool(g_pmdlSystemCall);  
  21. //改變MDL的標志   
  22. g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags |   
  23.                         MDL_MAPPED_TO_SYSTEM_VA  
  24. MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall,KernelMode);  

下面列出幾個對SSDT Hook比較有用的幾個宏。
  1. #define HOOK_INDEX(function2hook) *(PULONG)((PUCHAR)function2hook + 1)   
  2. #define HOOK(functionName, newPointer2Function, oldPointer2Function )  /   
  3. oldPointer2Function = (PVOID) InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) newPointer2Function)  
  4. #define UNHOOK(functionName, oldPointer2Function)  /   
  5. InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) oldPointer2Function)  
  6. #define UNHOOK(functionName, oldPointer2Function)  /   
  7. InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) oldPointer2Function)  


快乐彩中奖说明