标签:
首先要知道Ring3层调用OpenProcess的流程
//当Ring3调用OpenProcess
//1从自己的模块(.exe)的导入表中取值
//2Ntdll.dll模块的导出表中执行ZwOpenProcess(取索引 进入Ring0层)
//3进入Ring0 从Ntoskernel.exe模块的导出表中执行ZwOpenProcess(取索引 获得SSDT服务地址)
//4通过索引在SSDT表中取值(NtOpenProcess的地址)
//5真正调用NtOpenProcess函数
我们可以通过在第4部通过索引将NtOpenProcess 换成 Base[索引] = FakeNtOpenProcess;
1.我们要获取SSDT的结构信息
XP 32位的SSDT在Ntos模块导出表中有
1 //SSDT表的基地址32位(4Bytes)64位(8Bytes) 2 //XP 32位Ntos模块导出表中有 Win7 64 Ntos模块导出表中无 3 BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress) 4 { 5 //从NtosKernel.exe 模块中的导出表获得该导出变量 KeServiceDescriptorTable 6 7 /* 8 kd> dd KeServiceDescriptorTable 9 80563520 804e58a0 00000000 0000011c 805120bc 10 */ 11 *SSDTAddress = NULL; 12 *SSDTAddress = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeServiceDescriptorTable"); 13 14 if (*SSDTAddress!=NULL) 15 { 16 return TRUE; 17 } 18 19 return FALSE; 20 }
win7 64位没有被导出 但可以通过读取制定的msr得出
// 来自 作者:胡文亮
Msr 的中文全称是就是“特别模块寄存器” (model specific
register) ,它控制 CPU 的工作环境和标示 CPU 的工作状态等信息(例如倍频、最大 TDP、
危险警报温度) ,它能够读取,也能够写入,但是无论读取还是写入,都只能在 Ring 0 下
进行。我们通过读取 C0000082 寄存器,能够得到 KiSystemCall64 的地址,然后从
KiSystemCall64 的地址开始,往下搜索 0x500 字节左右(特征码是 4c8d15) ,就能得到
KeServiceDescriptorTable 的地址了。同理,我们换一下特征码(4c8d1d) ,就能获得
KeServiceDescriptorTableShadow 的地址了。
1 BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress) 2 { 3 4 5 /* 6 kd> rdmsr c0000082 7 msr[c0000082] = fffff800`03ecf640 8 kd> u fffff800`03ecf640 l 50 9 nt!KiSystemCall64: 10 fffff800`03ecf640 0f01f8 swapgs 11 fffff800`03ecf643 654889242510000000 mov qword ptr gs:[10h],rsp 12 fffff800`03ecf64c 65488b2425a8010000 mov rsp,qword ptr gs:[1A8h] 13 fffff800`03ecf655 6a2b push 2Bh 14 fffff800`03ecf657 65ff342510000000 push qword ptr gs:[10h] 15 fffff800`03ecf65f 4153 push r11 16 fffff800`03ecf661 6a33 push 33h 17 fffff800`03ecf663 51 push rcx 18 fffff800`03ecf664 498bca mov rcx,r10 19 fffff800`03ecf667 4883ec08 sub rsp,8 20 fffff800`03ecf66b 55 push rbp 21 fffff800`03ecf66c 4881ec58010000 sub rsp,158h 22 fffff800`03ecf673 488dac2480000000 lea rbp,[rsp+80h] 23 fffff800`03ecf67b 48899dc0000000 mov qword ptr [rbp+0C0h],rbx 24 fffff800`03ecf682 4889bdc8000000 mov qword ptr [rbp+0C8h],rdi 25 fffff800`03ecf689 4889b5d0000000 mov qword ptr [rbp+0D0h],rsi 26 fffff800`03ecf690 c645ab02 mov byte ptr [rbp-55h],2 27 fffff800`03ecf694 65488b1c2588010000 mov rbx,qword ptr gs:[188h] 28 fffff800`03ecf69d 0f0d8bd8010000 prefetchw [rbx+1D8h] 29 fffff800`03ecf6a4 0fae5dac stmxcsr dword ptr [rbp-54h] 30 fffff800`03ecf6a8 650fae142580010000 ldmxcsr dword ptr gs:[180h] 31 fffff800`03ecf6b1 807b0300 cmp byte ptr [rbx+3],0 32 fffff800`03ecf6b5 66c785800000000000 mov word ptr [rbp+80h],0 33 fffff800`03ecf6be 0f848c000000 je nt!KiSystemCall64+0x110 (fffff800`03ecf750) 34 fffff800`03ecf6c4 488945b0 mov qword ptr [rbp-50h],rax 35 fffff800`03ecf6c8 48894db8 mov qword ptr [rbp-48h],rcx 36 fffff800`03ecf6cc 488955c0 mov qword ptr [rbp-40h],rdx 37 fffff800`03ecf6d0 f6430303 test byte ptr [rbx+3],3 38 fffff800`03ecf6d4 4c8945c8 mov qword ptr [rbp-38h],r8 39 fffff800`03ecf6d8 4c894dd0 mov qword ptr [rbp-30h],r9 40 fffff800`03ecf6dc 7405 je nt!KiSystemCall64+0xa3 (fffff800`03ecf6e3) 41 fffff800`03ecf6de e80d140000 call nt!KiSaveDebugRegisterState (fffff800`03ed0af0) 42 fffff800`03ecf6e3 f6430380 test byte ptr [rbx+3],80h 43 fffff800`03ecf6e7 7442 je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 44 fffff800`03ecf6e9 b9020100c0 mov ecx,0C0000102h 45 fffff800`03ecf6ee 0f32 rdmsr 46 fffff800`03ecf6f0 48c1e220 shl rdx,20h 47 fffff800`03ecf6f4 480bc2 or rax,rdx 48 fffff800`03ecf6f7 483983b8000000 cmp qword ptr [rbx+0B8h],rax 49 fffff800`03ecf6fe 742b je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 50 fffff800`03ecf700 483983b0010000 cmp qword ptr [rbx+1B0h],rax 51 fffff800`03ecf707 7422 je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 52 fffff800`03ecf709 488b93b8010000 mov rdx,qword ptr [rbx+1B8h] 53 fffff800`03ecf710 0fba6b4c0b bts dword ptr [rbx+4Ch],0Bh 54 fffff800`03ecf715 66ff8bc4010000 dec word ptr [rbx+1C4h] 55 fffff800`03ecf71c 48898280000000 mov qword ptr [rdx+80h],rax 56 fffff800`03ecf723 fb sti 57 fffff800`03ecf724 e8170b0000 call nt!KiUmsCallEntry (fffff800`03ed0240) 58 fffff800`03ecf729 eb0f jmp nt!KiSystemCall64+0xfa (fffff800`03ecf73a) 59 fffff800`03ecf72b f6430340 test byte ptr [rbx+3],40h 60 fffff800`03ecf72f 7409 je nt!KiSystemCall64+0xfa (fffff800`03ecf73a) 61 fffff800`03ecf731 f00fbaab0001000008 lock bts dword ptr [rbx+100h],8 62 fffff800`03ecf73a 488b45b0 mov rax,qword ptr [rbp-50h] 63 fffff800`03ecf73e 488b4db8 mov rcx,qword ptr [rbp-48h] 64 fffff800`03ecf742 488b55c0 mov rdx,qword ptr [rbp-40h] 65 fffff800`03ecf746 4c8b45c8 mov r8,qword ptr [rbp-38h] 66 fffff800`03ecf74a 4c8b4dd0 mov r9,qword ptr [rbp-30h] 67 fffff800`03ecf74e 6690 xchg ax,ax 68 fffff800`03ecf750 fb sti 69 fffff800`03ecf751 48898be0010000 mov qword ptr [rbx+1E0h],rcx 70 fffff800`03ecf758 8983f8010000 mov dword ptr [rbx+1F8h],eax 71 nt!KiSystemServiceStart: 72 fffff800`03ecf75e 4889a3d8010000 mov qword ptr [rbx+1D8h],rsp 73 fffff800`03ecf765 8bf8 mov edi,eax 74 fffff800`03ecf767 c1ef07 shr edi,7 75 fffff800`03ecf76a 83e720 and edi,20h 76 fffff800`03ecf76d 25ff0f0000 and eax,0FFFh 77 nt!KiSystemServiceRepeat: 78 fffff800`03ecf772 4c8d15c7202300 lea r10,[nt!KeServiceDescriptorTable (fffff800`04101840)] 79 80 fffff800`03ecf772 + 002320c7 + 7 = fffff800`04101840 81 */ 82 83 84 85 86 PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082); //fffff800`03ecf640 87 PUCHAR EndSearchAddress = StartSearchAddress + 0x500; 88 PUCHAR i = NULL; 89 UCHAR v1=0,v2=0,v3=0; 90 INT64 iOffset = 0; //002320c7 91 ULONG64 VariableAddress = 0; 92 *SSDTAddress = NULL; 93 for(i=StartSearchAddress;i<EndSearchAddress;i++) 94 { 95 if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) ) 96 { 97 v1=*i; 98 v2=*(i+1); 99 v3=*(i+2); 100 if(v1==0x4c && v2==0x8d && v3==0x15 ) 101 { 102 memcpy(&iOffset,i+3,4); 103 *SSDTAddress = iOffset + (ULONG64)i + 7; 104 105 break; 106 } 107 } 108 } 109 110 if (*SSDTAddress==NULL) 111 { 112 return FALSE; 113 } 114 115 /* 116 kd> dq fffff800`04101840 117 fffff800`04101840 fffff800`03ed1300 00000000`00000000 118 fffff800`04101850 00000000`00000191 fffff800`03ed1f8c 119 120 */ 121 return TRUE; 122 }
2从Ntdll模块中的导出表获得要Hook的函数索引
1 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex) 2 { 3 /* 4 0:001> u zwopenprocess 5 ntdll!ZwOpenProcess: 6 7c92d5e0 b87a000000 mov eax,7Ah 7 7c92d5e5 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 8 7c92d5ea ff12 call dword ptr [edx] 9 7c92d5ec c21000 ret 10h 10 7c92d5ef 90 nop 11 */ 12 13 ULONG32 ulOffset_SSDTFunctionIndex = 1; 14 15 16 //从Ntdll模块的导出表中获得7c92d5e0 17 //使用内存映射将Ntdll模块映射到System进程的内存空间进行查找(Ntdll.dll模块的导出表中进行搜索) 18 ULONG i; 19 BOOLEAN bOk = FALSE; 20 WCHAR wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; 21 SIZE_T MappingViewSize = 0; 22 PVOID MappingBaseAddress = NULL; 23 PIMAGE_NT_HEADERS NtHeader = NULL; 24 PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 25 ULONG32* AddressOfFunctions = NULL; 26 ULONG32* AddressOfNames = NULL; 27 USHORT* AddressOfNameOrdinals = NULL; 28 CHAR* szFunctionName = NULL; 29 ULONG32 ulFunctionOrdinal = 0; 30 ULONG32 ulFunctionAddress = 0; 31 32 *SSDTFunctionIndex = -1; 33 34 35 //将Ntdll.dll 当前的空间中 36 bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize); 37 if (bOk==FALSE) 38 { 39 return FALSE; 40 } 41 else 42 { 43 __try{ 44 NtHeader = RtlImageNtHeader(MappingBaseAddress); 45 if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) 46 { 47 ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG32)MappingBaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 48 49 50 51 AddressOfFunctions = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfFunctions); 52 AddressOfNames = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfNames); 53 AddressOfNameOrdinals = (USHORT*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfNameOrdinals); 54 for(i = 0; i < ExportDirectory->NumberOfNames; i++) 55 { 56 szFunctionName = (char*)((ULONG32)MappingBaseAddress + AddressOfNames[i]); //获得函数名称 57 if (_stricmp(szFunctionName, szFindFunctionName) == 0) 58 { 59 ulFunctionOrdinal = AddressOfNameOrdinals[i]; 60 ulFunctionAddress = (ULONG32)((ULONG32)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]); 61 62 63 *SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex); 64 break; 65 } 66 } 67 } 68 }__except(EXCEPTION_EXECUTE_HANDLER) 69 { 70 ; 71 } 72 } 73 74 75 ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); 76 77 78 if (*SSDTFunctionIndex==-1) 79 { 80 return FALSE; 81 } 82 83 return TRUE; 84 }
1 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex) 2 { 3 /* 4 0:004> u zwopenprocess 5 ntdll!NtOpenProcess: 6 00000000`774ddc10 4c8bd1 mov r10,rcx 7 00000000`774ddc13 b823000000 mov eax,23h 8 00000000`774ddc18 0f05 syscall 9 00000000`774ddc1a c3 ret 10 00000000`774ddc1b 0f1f440000 nop dword ptr [rax+rax] 11 */ 12 13 ULONG32 ulOffset_SSDTFunctionIndex = 4; 14 15 ULONG i; 16 BOOLEAN bOk = FALSE; 17 WCHAR wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; 18 SIZE_T MappingViewSize = 0; 19 PVOID MappingBaseAddress = NULL; 20 PIMAGE_NT_HEADERS NtHeader = NULL; 21 PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 22 ULONG32* AddressOfFunctions = NULL; 23 ULONG32* AddressOfNames = NULL; 24 USHORT* AddressOfNameOrdinals = NULL; 25 CHAR* szFunctionName = NULL; 26 ULONG32 ulFunctionOrdinal = 0; 27 ULONG64 ulFunctionAddress = 0; 28 29 *SSDTFunctionIndex = -1; 30 31 32 //将Ntdll.dll 当前的空间中 33 bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize); 34 if (bOk==FALSE) 35 { 36 return FALSE; 37 } 38 else 39 { 40 __try{ 41 NtHeader = RtlImageNtHeader(MappingBaseAddress); 42 if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) 43 { 44 ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG64)MappingBaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 45 46 47 48 AddressOfFunctions = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfFunctions); 49 AddressOfNames = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfNames); 50 AddressOfNameOrdinals = (USHORT*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfNameOrdinals); 51 for(i = 0; i < ExportDirectory->NumberOfNames; i++) 52 { 53 szFunctionName = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]); //获得函数名称 54 if (_stricmp(szFunctionName, szFindFunctionName) == 0) 55 { 56 ulFunctionOrdinal = AddressOfNameOrdinals[i]; 57 ulFunctionAddress = (ULONG64)((ULONG64)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]); 58 59 60 *SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex); 61 break; 62 } 63 } 64 } 65 }__except(EXCEPTION_EXECUTE_HANDLER) 66 { 67 ; 68 } 69 } 70 71 72 ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); 73 74 75 if (*SSDTFunctionIndex==-1) 76 { 77 return FALSE; 78 } 79 80 return TRUE; 81 }
3.保存原先函数的地址
64位与32位不同 64为中存放的并不是SSDT函数的完整地址而是其相对于
ServiceTableBase[Index]>>4 的数据(称它为偏移地址)
4.在32位中换掉Base中索引里的数据 NtOpenProcess Base[索引] == FakeNtOpenProcess -->HookSSDT
在32位中 直接替换就可以了但是......................
/* 一系列的说明 作者:胡文亮 */
HOOK SSDT 就很简单了,首先获得待 HOOK 函数的序号
Index,然后通过公式把自己的代理函数的地址转化为偏移地址,然后把偏移地
址的数据填入 ServiceTableBase[Index]。也许有些读者看到这里,已经觉得胜
利在望了,我当时也是如此。但实际上我在这里栽了个大跟头,整整郁闷了很长
时间!因为我低估了设计这套算法的工程师的智商,我没有考虑一个问题,为什
么 WIN64 的 SSDT 表存放地址的形式这么奇怪?只存放偏移地址,而不存放完整
地址?难道是为了节省内存?这肯定是不可能的,要知道现在内存白菜价。那么
不是为了节省内存,唯一的可能性就是要给试图挂钩 SSDT 的人制造麻烦!要知
道,WIN64 内核里每个驱动都 不在同一个 B 4GB 里,而 4 字节的整数只能表示 4GB
的范围!所以无论你怎么修改这个值,都跳不出 ntoskrnl 的手掌心。如果你想
通过修改这个值来跳转到你的代理函数, 那是绝对不可能的。 因为你的驱动的地
址不 可能跟 l ntoskrnl 在同一个 B 4GB 里。然而,这位工程师也低估了我们中国人
的智商, 在中国有两句成语, 这位工程师一定没听过, 叫 “明修栈道, 暗渡陈仓”
以及“上有政策,下有对策” 。虽然不能直接用 4 字节来表示自己的代理函数所
在的地址, 但是还是可以修改这个值的。 要知道, ntoskrnl 虽然有很多地方的代
码通常是不会被执行的, 比如 KeBugCheckEx。 所以我的办法是: 修改这个偏移地
址的值,使之跳转到 KeBugCheckEx ,然后在 x KeBugCheckEx 的头部写一个 2 12 字
节的 mov - - jmp , 这是一个可以跨越 4GB B ! 的跳转, 跳到我们的函数里!
1 VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable) 2 { 3 //寻找一个内核不常用的函数(KeBugCheckEx) 进行InlineHook使其跳转到Fake_NtOpenProcess函数 4 ULONG32 ulVariable = 0; 5 6 WPOFF(); 7 InlineHook(KeBugCheckEx,ulFakeVariable,szOldKeBugCheckExCode,15); 8 WPON(); 9 10 11 //寻找一个内核不常用的函数(KeBugCheckEx) 计算SSDT中的偏移 进行置换 12 13 ulVariable = CalcFunctionOffsetInSSDT(KeBugCheckEx,5); 14 15 WPOFF(); 16 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulVariable; 17 WPON(); 18 }
1 VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable) 2 { 3 WPOFF(); 4 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulFakeVariable; 5 WPON(); 6 }
完整代码
1 #ifndef CXX_HOOKSSDT_H 2 # include "HookSSDT.h" 3 #endif 4 5 6 //1获得SSDT表的结构信息 Base 7 //2从Ntdll模块中的导出表获得要Hook的函数索引 8 //3换掉Base中索引里的数据 NtOpenProcess Base[索引] == FakeNtOpenProcess --->HookSSDT 9 10 PULONG32 ServiceTableBase = NULL; 11 ULONG32 SSDT_NtOpenProcessIndex = 0; 12 pfnNtOpenProcess Old_NtOpenProcess = NULL; 13 ULONG32 Old_NtOpenProcessOffset = 0; //针对Win7 x64 14 15 UCHAR szOldKeBugCheckExCode[15] = {0}; 16 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath) 17 { 18 19 20 #ifdef _WIN64 21 ULONG64 SSDTAddress = NULL; 22 ULONG32 ulVariable = 0; 23 24 CHAR szFindFunctionName[] = "ZwOpenProcess"; 25 26 27 if (GetSSDTAddressInWin7_X64(&SSDTAddress)==FALSE) 28 { 29 return STATUS_UNSUCCESSFUL; 30 } 31 32 DbgPrint("Win7x64 SSDT:%p\r\n",SSDTAddress); 33 DbgPrint("Win7x64 SSDTBase:%p\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)->ServiceTableBase); 34 35 36 /* 37 kd> dd FFFFF80003E8B300 l 200 38 fffff800`03e8b300 040d9a00 02f55c00 fff6ea00 02e87805 39 fffff800`03e8b310 031a4a06 03116a05 02bb9901 02b4f200 40 fffff800`03e8b320 0312cc40 03dd7400 02c84700 02e7d100 41 fffff800`03e8b330 02f68100 02e02301 02dd0601 02d96100 42 fffff800`03e8b340 02df4602 02f18600 02ad0500 02cefe01 43 fffff800`03e8b350 02d01d02 02f69902 03101101 0323ca01 44 fffff800`03e8b360 0455c305 02ed29c0 02b2e703 ffec1d00 45 fffff800`03e8b370 043c2800 02f51040 02c52c01 03126c00 46 fffff800`03e8b380 02d96302 02d30380 02ec7301 02d1fec0(NtOpenProcess Offset) 47 48 49 50 */ 51 52 /* 53 kd> u NtOpenProcess 54 nt!NtOpenProcess: 55 fffff800`0415d2ec 4883ec38 sub rsp,38h 56 fffff800`0415d2f0 65488b042588010000 mov rax,qword ptr gs:[188h] 57 fffff800`0415d2f9 448a90f6010000 mov r10b,byte ptr [rax+1F6h] 58 fffff800`0415d300 4488542428 mov byte ptr [rsp+28h],r10b 59 fffff800`0415d305 4488542420 mov byte ptr [rsp+20h],r10b 60 fffff800`0415d30a e851fcffff call nt!PsOpenProcess (fffff800`0415cf60) 61 fffff800`0415d30f 4883c438 add rsp,38h 62 fffff800`0415d313 c3 ret 63 64 65 */ 66 67 //fffff8000415d2ec - FFFFF80003E8B300 = 2D1FEC<<4 = 2D1FEC0 68 DbgPrint("Win7x64 SSDTNumberOfService:%d\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)->NumberOfServices); 69 70 71 if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(szFindFunctionName,&SSDT_NtOpenProcessIndex)==FALSE) 72 { 73 return STATUS_UNSUCCESSFUL; 74 } 75 76 DbgPrint("Win7x64 SSDT_NtOpenProcessIndex:%d\r\n",SSDT_NtOpenProcessIndex); 77 78 79 80 ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE)SSDTAddress)->ServiceTableBase; 81 Old_NtOpenProcessOffset = (ULONG32)(ServiceTableBase[SSDT_NtOpenProcessIndex]); 82 ulVariable = Old_NtOpenProcessOffset>>4; 83 Old_NtOpenProcess = (ULONG64)((PSYSTEM_SERVICE_TABLE)SSDTAddress)->ServiceTableBase + ulVariable; 84 DbgPrint("Win7x64 Old_NtOpenProcess:%p\r\n",ulVariable); 85 86 /* 87 kd> u FFFFF8000415D2EC 88 nt!NtOpenProcess: 89 fffff800`0415d2ec 4883ec38 sub rsp,38h 90 fffff800`0415d2f0 65488b042588010000 mov rax,qword ptr gs:[188h] 91 fffff800`0415d2f9 448a90f6010000 mov r10b,byte ptr [rax+1F6h] 92 fffff800`0415d300 4488542428 mov byte ptr [rsp+28h],r10b 93 fffff800`0415d305 4488542420 mov byte ptr [rsp+20h],r10b 94 fffff800`0415d30a e851fcffff call nt!PsOpenProcess (fffff800`0415cf60) 95 fffff800`0415d30f 4883c438 add rsp,38h 96 fffff800`0415d313 c3 ret 97 */ 98 99 HookSSDTWin7_X64(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG64)Fake_NtOpenProcess); 100 #else 101 ULONG32 SSDTAddress = NULL; 102 CHAR szFindFunctionName[] = "ZwOpenProcess"; 103 104 105 if (GetSSDTAddressInWinXP_X86(&SSDTAddress)==FALSE) 106 { 107 return STATUS_UNSUCCESSFUL; 108 } 109 DbgPrint("WinXPx86 SSDT:%p\r\n",SSDTAddress); 110 DbgPrint("WinXPx86 SSDTBase:%p\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)->ServiceTableBase); 111 /* 112 kd> dd 804E58A0 l 200 SSDTBase 113 804e58a0 80591bfb 80585356 805e1f35 805dbc47 114 804e58b0 805e1fbc 80640cc2 80642e4b 80642e94 115 804e58c0 805835b2 80650bbb 8064047d 805e1787 116 804e58d0 8063878a 80586fa1 805e08e8 8062f432 117 804e58e0 805d9781 80571d45 805e8258 805e939e 118 804e58f0 804e5eb4 80650ba7 805cd537 804ed812 119 804e5900 805719b7 80570af2 805e1b65 80656cec 120 804e5910 805e0ff3 805887b7 80656f5b 80586563 121 804e5920 804e221d 8066239e 805aa76b 8057dd2d 122 804e5930 8065120c 8057d330 805db662 805d6cd6 123 804e5940 80638c31 80578925 805d7e7f 805803c0 124 804e5950 80589caa 805b5823 8059a02a 805b1470 125 804e5960 8058c7cd 8065182d 8056eb66 8057b9e4 126 804e5970 805e7e56 80587c43 80598cb2 805a7ada 127 804e5980 805ab552 80663519 80663673 8056fb07 128 804e5990 805ddc8b 80650ba7 805d64ac 80594334 129 804e59a0 80642eef 80592f8b 805899a6 805b6cd8 130 804e59b0 8058221e 80584451 80650bbb 80579e1c 131 804e59c0 80650b93 80588691 8062e3f1 805cf473 132 804e59d0 805e36f2 80586ceb 80588bf9 805da3bb 133 804e59e0 805e9ab6 8062fc8f 8062f7e5 805723df 134 804e59f0 805813f3 80636711 80634be3 8059c497 135 804e5a00 8054070f 80599bde 805e0d66 8058968d 136 804e5a10 805aad25 806349af 80638ae7 80634bca 137 804e5a20 805aab94 805a9f96 805cf7e5 805cf944 138 804e5a30 805de058 805cece7 805c8155 805af0d5 139 804e5a40 805e804c 805e8113 8062ea8e 8062eee7 140 804e5a50 8057f371 80650ba7 805de2ef 805e318f 141 804e5a60 805e2fa1 8058b0b6 8058aa51 806512fd 142 804e5a70 8057d4a4 806220ab 80638e89 80573bfc 143 804e5a80 8058046e 805ea252 8058270a(NtOpenProcess) 80578308 144 145 */ 146 DbgPrint("WinXPx86 SSDTNumberOfService:%d\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)->NumberOfServices); 147 148 if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(szFindFunctionName,&SSDT_NtOpenProcessIndex)==FALSE) 149 { 150 return STATUS_UNSUCCESSFUL; 151 } 152 DbgPrint("WinXPx86 SSDT_NtOpenProcessIndex:%d\r\n",SSDT_NtOpenProcessIndex); 153 154 //先保存原先的函数地址 155 ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE)SSDTAddress)->ServiceTableBase; 156 Old_NtOpenProcess = (pfnNtOpenProcess)(ServiceTableBase[SSDT_NtOpenProcessIndex]); 157 DbgPrint("WinXPx86 Old_NtOpenProcess:%p\r\n",Old_NtOpenProcess); 158 159 160 /* 161 kd> u 8058270A 162 nt!NtOpenProcess: 163 8058270a 68c4000000 push 0C4h 164 8058270f 68d8524f80 push offset nt!ObWatchHandles+0x25c (804f52d8) 165 80582714 e85a17f6ff call nt!_SEH_prolog (804e3e73) 166 80582719 33f6 xor esi,esi 167 8058271b 8975d4 mov dword ptr [ebp-2Ch],esi 168 8058271e 33c0 xor eax,eax 169 80582720 8d7dd8 lea edi,[ebp-28h] 170 80582723 ab stos dword ptr es:[edi] 171 172 */ 173 HookSSDTWinXP_X86(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Fake_NtOpenProcess); 174 175 176 177 #endif 178 179 180 DriverObject->DriverUnload = UnloadDriver; 181 182 183 return STATUS_SUCCESS; 184 } 185 186 //SSDT表的基地址32位(4Bytes)64位(8Bytes) 187 //XP 32位Ntos模块导出表中有 Win7 64 Ntos模块导出表中无 188 BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress) 189 { 190 //从NtosKernel.exe 模块中的导出表获得该导出变量 KeServiceDescriptorTable 191 192 /* 193 kd> dd KeServiceDescriptorTable 194 80563520 804e58a0 00000000 0000011c 805120bc 195 */ 196 *SSDTAddress = NULL; 197 *SSDTAddress = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeServiceDescriptorTable"); 198 199 if (*SSDTAddress!=NULL) 200 { 201 return TRUE; 202 } 203 204 return FALSE; 205 } 206 207 208 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex) 209 { 210 /* 211 0:001> u zwopenprocess 212 ntdll!ZwOpenProcess: 213 7c92d5e0 b87a000000 mov eax,7Ah 214 7c92d5e5 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 215 7c92d5ea ff12 call dword ptr [edx] 216 7c92d5ec c21000 ret 10h 217 7c92d5ef 90 nop 218 */ 219 220 ULONG32 ulOffset_SSDTFunctionIndex = 1; 221 222 223 //从Ntdll模块的导出表中获得7c92d5e0 224 //使用内存映射将Ntdll模块映射到System进程的内存空间进行查找(Ntdll.dll模块的导出表中进行搜索) 225 ULONG i; 226 BOOLEAN bOk = FALSE; 227 WCHAR wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; 228 SIZE_T MappingViewSize = 0; 229 PVOID MappingBaseAddress = NULL; 230 PIMAGE_NT_HEADERS NtHeader = NULL; 231 PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 232 ULONG32* AddressOfFunctions = NULL; 233 ULONG32* AddressOfNames = NULL; 234 USHORT* AddressOfNameOrdinals = NULL; 235 CHAR* szFunctionName = NULL; 236 ULONG32 ulFunctionOrdinal = 0; 237 ULONG32 ulFunctionAddress = 0; 238 239 *SSDTFunctionIndex = -1; 240 241 242 //将Ntdll.dll 当前的空间中 243 bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize); 244 if (bOk==FALSE) 245 { 246 return FALSE; 247 } 248 else 249 { 250 __try{ 251 NtHeader = RtlImageNtHeader(MappingBaseAddress); 252 if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) 253 { 254 ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG32)MappingBaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 255 256 257 258 AddressOfFunctions = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfFunctions); 259 AddressOfNames = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfNames); 260 AddressOfNameOrdinals = (USHORT*)((ULONG32)MappingBaseAddress + ExportDirectory->AddressOfNameOrdinals); 261 for(i = 0; i < ExportDirectory->NumberOfNames; i++) 262 { 263 szFunctionName = (char*)((ULONG32)MappingBaseAddress + AddressOfNames[i]); //获得函数名称 264 if (_stricmp(szFunctionName, szFindFunctionName) == 0) 265 { 266 ulFunctionOrdinal = AddressOfNameOrdinals[i]; 267 ulFunctionAddress = (ULONG32)((ULONG32)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]); 268 269 270 *SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex); 271 break; 272 } 273 } 274 } 275 }__except(EXCEPTION_EXECUTE_HANDLER) 276 { 277 ; 278 } 279 } 280 281 282 ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); 283 284 285 if (*SSDTFunctionIndex==-1) 286 { 287 return FALSE; 288 } 289 290 return TRUE; 291 } 292 293 294 295 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex) 296 { 297 /* 298 0:004> u zwopenprocess 299 ntdll!NtOpenProcess: 300 00000000`774ddc10 4c8bd1 mov r10,rcx 301 00000000`774ddc13 b823000000 mov eax,23h 302 00000000`774ddc18 0f05 syscall 303 00000000`774ddc1a c3 ret 304 00000000`774ddc1b 0f1f440000 nop dword ptr [rax+rax] 305 */ 306 307 ULONG32 ulOffset_SSDTFunctionIndex = 4; 308 309 ULONG i; 310 BOOLEAN bOk = FALSE; 311 WCHAR wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; 312 SIZE_T MappingViewSize = 0; 313 PVOID MappingBaseAddress = NULL; 314 PIMAGE_NT_HEADERS NtHeader = NULL; 315 PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 316 ULONG32* AddressOfFunctions = NULL; 317 ULONG32* AddressOfNames = NULL; 318 USHORT* AddressOfNameOrdinals = NULL; 319 CHAR* szFunctionName = NULL; 320 ULONG32 ulFunctionOrdinal = 0; 321 ULONG64 ulFunctionAddress = 0; 322 323 *SSDTFunctionIndex = -1; 324 325 326 //将Ntdll.dll 当前的空间中 327 bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize); 328 if (bOk==FALSE) 329 { 330 return FALSE; 331 } 332 else 333 { 334 __try{ 335 NtHeader = RtlImageNtHeader(MappingBaseAddress); 336 if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) 337 { 338 ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG64)MappingBaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 339 340 341 342 AddressOfFunctions = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfFunctions); 343 AddressOfNames = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfNames); 344 AddressOfNameOrdinals = (USHORT*)((ULONG64)MappingBaseAddress + ExportDirectory->AddressOfNameOrdinals); 345 for(i = 0; i < ExportDirectory->NumberOfNames; i++) 346 { 347 szFunctionName = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]); //获得函数名称 348 if (_stricmp(szFunctionName, szFindFunctionName) == 0) 349 { 350 ulFunctionOrdinal = AddressOfNameOrdinals[i]; 351 ulFunctionAddress = (ULONG64)((ULONG64)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]); 352 353 354 *SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex); 355 break; 356 } 357 } 358 } 359 }__except(EXCEPTION_EXECUTE_HANDLER) 360 { 361 ; 362 } 363 } 364 365 366 ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); 367 368 369 if (*SSDTFunctionIndex==-1) 370 { 371 return FALSE; 372 } 373 374 return TRUE; 375 } 376 377 378 BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress) 379 { 380 381 382 /* 383 kd> rdmsr c0000082 384 msr[c0000082] = fffff800`03ecf640 385 kd> u fffff800`03ecf640 l 50 386 nt!KiSystemCall64: 387 fffff800`03ecf640 0f01f8 swapgs 388 fffff800`03ecf643 654889242510000000 mov qword ptr gs:[10h],rsp 389 fffff800`03ecf64c 65488b2425a8010000 mov rsp,qword ptr gs:[1A8h] 390 fffff800`03ecf655 6a2b push 2Bh 391 fffff800`03ecf657 65ff342510000000 push qword ptr gs:[10h] 392 fffff800`03ecf65f 4153 push r11 393 fffff800`03ecf661 6a33 push 33h 394 fffff800`03ecf663 51 push rcx 395 fffff800`03ecf664 498bca mov rcx,r10 396 fffff800`03ecf667 4883ec08 sub rsp,8 397 fffff800`03ecf66b 55 push rbp 398 fffff800`03ecf66c 4881ec58010000 sub rsp,158h 399 fffff800`03ecf673 488dac2480000000 lea rbp,[rsp+80h] 400 fffff800`03ecf67b 48899dc0000000 mov qword ptr [rbp+0C0h],rbx 401 fffff800`03ecf682 4889bdc8000000 mov qword ptr [rbp+0C8h],rdi 402 fffff800`03ecf689 4889b5d0000000 mov qword ptr [rbp+0D0h],rsi 403 fffff800`03ecf690 c645ab02 mov byte ptr [rbp-55h],2 404 fffff800`03ecf694 65488b1c2588010000 mov rbx,qword ptr gs:[188h] 405 fffff800`03ecf69d 0f0d8bd8010000 prefetchw [rbx+1D8h] 406 fffff800`03ecf6a4 0fae5dac stmxcsr dword ptr [rbp-54h] 407 fffff800`03ecf6a8 650fae142580010000 ldmxcsr dword ptr gs:[180h] 408 fffff800`03ecf6b1 807b0300 cmp byte ptr [rbx+3],0 409 fffff800`03ecf6b5 66c785800000000000 mov word ptr [rbp+80h],0 410 fffff800`03ecf6be 0f848c000000 je nt!KiSystemCall64+0x110 (fffff800`03ecf750) 411 fffff800`03ecf6c4 488945b0 mov qword ptr [rbp-50h],rax 412 fffff800`03ecf6c8 48894db8 mov qword ptr [rbp-48h],rcx 413 fffff800`03ecf6cc 488955c0 mov qword ptr [rbp-40h],rdx 414 fffff800`03ecf6d0 f6430303 test byte ptr [rbx+3],3 415 fffff800`03ecf6d4 4c8945c8 mov qword ptr [rbp-38h],r8 416 fffff800`03ecf6d8 4c894dd0 mov qword ptr [rbp-30h],r9 417 fffff800`03ecf6dc 7405 je nt!KiSystemCall64+0xa3 (fffff800`03ecf6e3) 418 fffff800`03ecf6de e80d140000 call nt!KiSaveDebugRegisterState (fffff800`03ed0af0) 419 fffff800`03ecf6e3 f6430380 test byte ptr [rbx+3],80h 420 fffff800`03ecf6e7 7442 je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 421 fffff800`03ecf6e9 b9020100c0 mov ecx,0C0000102h 422 fffff800`03ecf6ee 0f32 rdmsr 423 fffff800`03ecf6f0 48c1e220 shl rdx,20h 424 fffff800`03ecf6f4 480bc2 or rax,rdx 425 fffff800`03ecf6f7 483983b8000000 cmp qword ptr [rbx+0B8h],rax 426 fffff800`03ecf6fe 742b je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 427 fffff800`03ecf700 483983b0010000 cmp qword ptr [rbx+1B0h],rax 428 fffff800`03ecf707 7422 je nt!KiSystemCall64+0xeb (fffff800`03ecf72b) 429 fffff800`03ecf709 488b93b8010000 mov rdx,qword ptr [rbx+1B8h] 430 fffff800`03ecf710 0fba6b4c0b bts dword ptr [rbx+4Ch],0Bh 431 fffff800`03ecf715 66ff8bc4010000 dec word ptr [rbx+1C4h] 432 fffff800`03ecf71c 48898280000000 mov qword ptr [rdx+80h],rax 433 fffff800`03ecf723 fb sti 434 fffff800`03ecf724 e8170b0000 call nt!KiUmsCallEntry (fffff800`03ed0240) 435 fffff800`03ecf729 eb0f jmp nt!KiSystemCall64+0xfa (fffff800`03ecf73a) 436 fffff800`03ecf72b f6430340 test byte ptr [rbx+3],40h 437 fffff800`03ecf72f 7409 je nt!KiSystemCall64+0xfa (fffff800`03ecf73a) 438 fffff800`03ecf731 f00fbaab0001000008 lock bts dword ptr [rbx+100h],8 439 fffff800`03ecf73a 488b45b0 mov rax,qword ptr [rbp-50h] 440 fffff800`03ecf73e 488b4db8 mov rcx,qword ptr [rbp-48h] 441 fffff800`03ecf742 488b55c0 mov rdx,qword ptr [rbp-40h] 442 fffff800`03ecf746 4c8b45c8 mov r8,qword ptr [rbp-38h] 443 fffff800`03ecf74a 4c8b4dd0 mov r9,qword ptr [rbp-30h] 444 fffff800`03ecf74e 6690 xchg ax,ax 445 fffff800`03ecf750 fb sti 446 fffff800`03ecf751 48898be0010000 mov qword ptr [rbx+1E0h],rcx 447 fffff800`03ecf758 8983f8010000 mov dword ptr [rbx+1F8h],eax 448 nt!KiSystemServiceStart: 449 fffff800`03ecf75e 4889a3d8010000 mov qword ptr [rbx+1D8h],rsp 450 fffff800`03ecf765 8bf8 mov edi,eax 451 fffff800`03ecf767 c1ef07 shr edi,7 452 fffff800`03ecf76a 83e720 and edi,20h 453 fffff800`03ecf76d 25ff0f0000 and eax,0FFFh 454 nt!KiSystemServiceRepeat: 455 fffff800`03ecf772 4c8d15c7202300 lea r10,[nt!KeServiceDescriptorTable (fffff800`04101840)] 456 457 fffff800`03ecf772 + 002320c7 + 7 = fffff800`04101840 458 */ 459 460 461 462 463 PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082); //fffff800`03ecf640 464 PUCHAR EndSearchAddress = StartSearchAddress + 0x500; 465 PUCHAR i = NULL; 466 UCHAR v1=0,v2=0,v3=0; 467 INT64 iOffset = 0; //002320c7 468 ULONG64 VariableAddress = 0; 469 *SSDTAddress = NULL; 470 for(i=StartSearchAddress;i<EndSearchAddress;i++) 471 { 472 if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) ) 473 { 474 v1=*i; 475 v2=*(i+1); 476 v3=*(i+2); 477 if(v1==0x4c && v2==0x8d && v3==0x15 ) 478 { 479 memcpy(&iOffset,i+3,4); 480 *SSDTAddress = iOffset + (ULONG64)i + 7; 481 482 break; 483 } 484 } 485 } 486 487 if (*SSDTAddress==NULL) 488 { 489 return FALSE; 490 } 491 492 /* 493 kd> dq fffff800`04101840 494 fffff800`04101840 fffff800`03ed1300 00000000`00000000 495 fffff800`04101850 00000000`00000191 fffff800`03ed1f8c 496 497 */ 498 return TRUE; 499 } 500 501 PVOID 502 GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName) 503 { 504 UNICODE_STRING uniVariableName; 505 PVOID VariableAddress = NULL; 506 507 if (wzVariableName && wcslen(wzVariableName) > 0) 508 { 509 RtlInitUnicodeString(&uniVariableName, wzVariableName); 510 511 //从Ntos模块的导出表中获得一个导出变量的地址 512 VariableAddress = MmGetSystemRoutineAddress(&uniVariableName); 513 } 514 515 return VariableAddress; 516 } 517 518 519 520 VOID UnloadDriver(PDRIVER_OBJECT DriverObject) 521 { 522 523 524 #ifdef _WIN64 525 UnHookSSDTWin7_X64(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Old_NtOpenProcessOffset); 526 #else 527 UnHookSSDTWinXP_X86(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Old_NtOpenProcess); 528 #endif 529 530 531 532 } 533 534 535 VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable) 536 { 537 //寻找一个内核不常用的函数(KeBugCheckEx) 进行InlineHook使其跳转到Fake_NtOpenProcess函数 538 ULONG32 ulVariable = 0; 539 540 WPOFF(); 541 InlineHook(KeBugCheckEx,ulFakeVariable,szOldKeBugCheckExCode,15); 542 WPON(); 543 544 545 //寻找一个内核不常用的函数(KeBugCheckEx) 计算SSDT中的偏移 进行置换 546 547 ulVariable = CalcFunctionOffsetInSSDT(KeBugCheckEx,5); 548 549 WPOFF(); 550 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulVariable; 551 WPON(); 552 } 553 554 555 VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable) 556 { 557 WPOFF(); 558 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulFakeVariable; 559 WPON(); 560 } 561 562 563 VOID 564 UnHookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable) 565 { 566 567 WPOFF(); 568 UnInlineHook(KeBugCheckEx,szOldKeBugCheckExCode,15); 569 WPON(); 570 571 WPOFF(); 572 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulOldVariable; 573 WPON(); 574 } 575 576 577 VOID 578 UnHookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable) 579 { 580 WPOFF(); 581 ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulOldVariable; 582 WPON(); 583 } 584 585 586 587 588 //将Ntdll.dll 模块映射到System.exe进程空间中 589 BOOLEAN 590 MappingPEFileInRing0Space(WCHAR* wzFileFullPath,OUT PVOID* MappingBaseAddress,PSIZE_T MappingViewSize) 591 { 592 UNICODE_STRING uniFileFullPath; 593 OBJECT_ATTRIBUTES oa; 594 NTSTATUS Status; 595 IO_STATUS_BLOCK Iosb; 596 597 HANDLE hFile = NULL; 598 HANDLE hSection = NULL; 599 600 if (!wzFileFullPath || !MappingBaseAddress){ 601 return FALSE; 602 } 603 604 RtlInitUnicodeString(&uniFileFullPath, wzFileFullPath); 605 InitializeObjectAttributes(&oa, 606 &uniFileFullPath, 607 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 608 NULL, 609 NULL 610 ); 611 612 613 //获得文件句柄 614 Status = IoCreateFile(&hFile, 615 GENERIC_READ | SYNCHRONIZE, 616 &oa, //文件绝对路径 617 &Iosb, 618 NULL, 619 FILE_ATTRIBUTE_NORMAL, 620 FILE_SHARE_READ, 621 FILE_OPEN, 622 FILE_SYNCHRONOUS_IO_NONALERT, 623 NULL, 624 0, 625 CreateFileTypeNone, 626 NULL, 627 IO_NO_PARAMETER_CHECKING 628 ); 629 if (!NT_SUCCESS(Status)) 630 { 631 632 return FALSE; 633 } 634 635 oa.ObjectName = NULL; 636 Status = ZwCreateSection(&hSection, 637 SECTION_QUERY | SECTION_MAP_READ, 638 &oa, 639 NULL, 640 PAGE_WRITECOPY, 641 SEC_IMAGE, //?? 指示内存对齐 642 hFile 643 ); 644 ZwClose(hFile); 645 if (!NT_SUCCESS(Status)) 646 { 647 648 return FALSE; 649 } 650 Status = ZwMapViewOfSection(hSection, 651 NtCurrentProcess(), //映射到当前进程的内存空间中 652 MappingBaseAddress, 653 0, 654 0, 655 0, 656 MappingViewSize, 657 ViewUnmap, 658 0, 659 PAGE_WRITECOPY 660 ); 661 ZwClose(hSection); 662 if (!NT_SUCCESS(Status)) 663 { 664 return FALSE; 665 } 666 667 return TRUE; 668 } 669 670 671 672 673 674 VOID WPOFF() 675 { 676 //选择性编译,是给编译器看的 677 #if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_) 678 _disable(); 679 __writecr0(__readcr0() & (~(0x10000))); 680 #else 681 __asm 682 { 683 CLI ; 684 MOV EAX, CR0; 685 AND EAX, NOT 10000H; 686 MOV CR0, EAX; 687 } 688 #endif 689 } 690 VOID WPON() 691 { 692 #if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_) 693 __writecr0(__readcr0() ^ 0x10000); 694 _enable(); 695 #else 696 __asm 697 { 698 MOV EAX, CR0; 699 OR EAX, 10000H; 700 MOV CR0, EAX; 701 STI; 702 } 703 #endif 704 } 705 706 707 708 NTSTATUS Fake_NtOpenProcess( 709 PHANDLE ProcessHandle, 710 ACCESS_MASK DesiredAccess, 711 POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId) 712 { 713 PEPROCESS EProcess = PsGetCurrentProcess(); //进程上下背景文 714 if (EProcess!=NULL) 715 { 716 //通过EProcess 获得进程名称 717 718 char *szProcessImageName = PsGetProcessImageFileName(EProcess); 719 720 if (strstr(szProcessImageName,"EnumProcess")!=0) 721 { 722 723 return STATUS_ACCESS_DENIED; 724 } 725 } 726 727 Old_NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId); 728 } 729 730 731 732 733 734 735 ULONG32 CalcFunctionOffsetInSSDT(ULONG64 ulFunctionAddress,ULONG32 ulParamCount) 736 { 737 738 /* 739 kd> rdmsr c0000082 740 msr[c0000082] = fffff800`03edd640 741 742 kd>u fffff800`03edd640 743 fffff800`03edd751 48898be0010000 mov qword ptr [rbx+1E0h],rcx 744 fffff800`03edd758 8983f8010000 mov dword ptr [rbx+1F8h],eax 745 nt!KiSystemServiceStart: 746 fffff800`03edd75e 4889a3d8010000 mov qword ptr [rbx+1D8h],rsp 747 fffff800`03edd765 8bf8 mov edi,eax 748 fffff800`03edd767 c1ef07 shr edi,7 749 fffff800`03edd76a 83e720 and edi,20h 750 fffff800`03edd76d 25ff0f0000 and eax,0FFFh 751 nt!KiSystemServiceRepeat: 752 fffff800`03edd772 4c8d15c7202300 lea r10,[nt!KeServiceDescriptorTable (fffff800`0410f840)] 753 754 755 kd> dq fffff800`0410f840 756 fffff800`0410f840 fffff800`03edf300 00000000`00000000 757 fffff800`0410f850 00000000`00000191 fffff800`03edff8c 758 fffff800`0410f860 00000000`00000000 00000000`00000000 759 fffff800`0410f870 00000000`00000000 00000000`00000000 760 761 kd> dd fffff800`03edf300 762 fffff800`03edf300 040d9a00 02f55c00 fff6ea00 02e87805 763 fffff800`03edf310 031a4a06 03116a05 02bb9901 02b4f200 764 765 fffff800`03edf300 + (02e87805>>4) = FFFFF800041C7A80 766 767 kd> u FFFFF800041C7A80 768 nt!NtReadFile: 769 fffff800`041c7a80 4c8bdc mov r11,rsp 770 fffff800`041c7a83 4d894b20 mov qword ptr [r11+20h],r9 771 fffff800`041c7a87 4d894318 mov qword ptr [r11+18h],r8 772 fffff800`041c7a8b 49895310 mov qword ptr [r11+10h],rdx 773 fffff800`041c7a8f 53 push rbx 774 775 776 5 --->9 777 6 --->10 778 779 如果一个函数的参数个数小于等于4 就是0 780 781 */ 782 783 ULONG32 ulVariable = 0,i; 784 CHAR v1 = 0; 785 786 CHAR szBits[4] = {0}; 787 788 789 ulVariable = (ULONG32)(ulFunctionAddress-(ULONG64)ServiceTableBase); 790 ulVariable = ulVariable<<4; 791 792 793 if(ulParamCount>4) 794 { 795 ulParamCount = ulParamCount-4; //NtReadFile 9个参数 796 } 797 else 798 { 799 ulParamCount = 0; 800 } 801 802 //处理低四位,填写参数个数 如果一个函数的参数为5 那么dwTemp的低4位就是 0001 如果参数是6 就是0002 因为 6要减4 803 804 #define SETBIT(x,y) x|=(1<<y) //将X的第Y位置1 805 #define CLRBIT(x,y) x&=~(1<<y) //将X的第Y位清0 806 #define GETBIT(x,y) (x & (1 << y)) //取X的第Y位,返回0或非0 807 808 809 for(i=0;i<4;i++) //一个16进制 4个二进制 0000 810 { 811 szBits[i]=GETBIT(ulParamCount,i); 812 if(szBits[i]) 813 { 814 SETBIT(v1,i); 815 } 816 else 817 { 818 CLRBIT(v1,i); 819 } 820 } 821 /* 822 ulParamCount i szBits[i] b i b 823 0101 0 1 0000 0 0001 set 824 0101 1 0 0001 1 0001 clr 825 0101 2 1 0001 2 0101 set 826 0101 3 0 0101 3 0101 clr 827 828 */ 829 830 831 //把数据复制回去 832 memcpy(&ulVariable,&v1,1); 833 return ulVariable; 834 } 835 836 837 838 VOID InlineHook(ULONG64 ulOldVariable,ULONG64 ulFakeVariable,UCHAR* szOldCode,ULONG32 ulOldeCodeLength) 839 { 840 841 ULONG64 ulVariable = 0; 842 UCHAR szNewCode[]="\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; //InlineHook 843 844 845 ulVariable = ulFakeVariable; 846 memcpy(szOldCode,(PVOID)ulOldVariable,ulOldeCodeLength); 847 memcpy(szNewCode+6,&ulVariable,8); 848 849 memset((PVOID)ulOldVariable,0x90,ulOldeCodeLength); 850 memcpy((PVOID)ulOldVariable,szNewCode,14); 851 } 852 853 854 VOID UnInlineHook(ULONG64 ulOldVariable,UCHAR* szOldCode,ULONG32 ulOldCodeLength) 855 { 856 memcpy((PVOID)ulOldVariable,szOldCode,ulOldCodeLength); 857 }
1 #ifndef CXX_HOOKSSDT_H 2 #define CXX_HOOKSSDT_H 3 4 #include <ntifs.h> 5 #include <ntimage.h> 6 7 8 #define SEC_IMAGE 0x01000000 9 10 //定义SSDT表的结构 11 typedef struct _SYSTEM_SERVICE_TABLE_X64{ 12 PVOID ServiceTableBase; 13 PVOID ServiceCounterTableBase; 14 ULONG64 NumberOfServices; //SSDT表中的函数个数 0x191 15 PVOID ParamTableBase; 16 } SYSTEM_SERVICE_TABLE_X64, *PSYSTEM_SERVICE_TABLE_X64; 17 18 typedef struct _SYSTEM_SERVICE_TABLE_X86 { 19 PVOID ServiceTableBase; 20 PVOID ServiceCounterTableBase; 21 ULONG32 NumberOfServices; //SSDT表中的函数个数 0x11c 22 PVOID ParamTableBase; 23 } SYSTEM_SERVICE_TABLE_X86, *PSYSTEM_SERVICE_TABLE_X86; 24 25 26 27 #ifdef _WIN64 28 #define PSYSTEM_SERVICE_TABLE PSYSTEM_SERVICE_TABLE_X64 29 #else 30 #define PSYSTEM_SERVICE_TABLE PSYSTEM_SERVICE_TABLE_X86 31 #endif 32 33 34 35 36 37 38 /* 39 ServiceTableBase [][][][][][][][] 40 */ 41 extern 42 char* PsGetProcessImageFileName(PEPROCESS EProcess); 43 44 extern 45 PIMAGE_NT_HEADERS 46 NTAPI 47 RtlImageNtHeader(PVOID BaseAddress); 48 49 typedef 50 NTSTATUS 51 (*pfnNtOpenProcess)( 52 PHANDLE ProcessHandle, 53 ACCESS_MASK DesiredAccess, 54 POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId); 55 56 NTSTATUS Fake_NtOpenProcess( 57 PHANDLE ProcessHandle, 58 ACCESS_MASK DesiredAccess, 59 POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId); 60 61 62 VOID UnloadDriver(PDRIVER_OBJECT DriverObject); 63 64 BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress); 65 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex); 66 67 68 69 BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress); 70 BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex); 71 ULONG32 CalcFunctionOffsetInSSDT(ULONG64 ulFunctionAddress,ULONG32 ulParamCount); 72 VOID InlineHook(ULONG64 ulOldVariable,ULONG64 ulFakeVariable,UCHAR* szOldCode,ULONG32 ulOldeCodeLength); 73 VOID UnInlineHook(ULONG64 ulOldVariable,UCHAR* szOldCode,ULONG32 ulOldCodeLength); 74 75 PVOID GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName); 76 77 BOOLEAN MappingPEFileInRing0Space(WCHAR* wzFileFullPath,OUT PVOID* MappingBaseAddress,PSIZE_T MappingViewSize); 78 79 80 VOID WPOFF(); 81 VOID WPON(); 82 VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable); 83 VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable); 84 85 86 VOID UnHookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable); 87 VOID UnHookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable); 88 #endif
HookSSDT 通过HookOpenProcess函数阻止暴力枚举进程
标签:
原文地址:http://www.cnblogs.com/yifi/p/4898406.html