Win10X64 获取SSDT、Shadow SSDT和SSDT内核函数地址, SSDT HOOK--Windows内核学习记录
编译环境Windows10 X64
首先通过 msr = (PUCHAR)__readmsr(0xC0000082);获取内核函数入口地址,
msr在开启内核隔离模式下获取到的是KiSystemCall64Shadow函数地址,在未开启内核隔离模式下获取到的是KiSystemCall64函数地址
通过msr + 21的值判断当前获取到的是哪个函数, *(msr + 21)==0x72是KiSystemCall64函数特征码, *(msr + 21)== 0x65是KiSystemCall64Shadow函数特征码
通过搜索特征码【4C 8D 15 XX XX XX XX 4C 8D 1D XX XX XX XX F7 43】找到KiSystemServiceRepeat函数,未搜索到或者搜索到多个判定搜索错误
如果当前获取到的msr是KiSystemCall64Shadow函数,得到的这个函数地址 msr减0x20000的地址开始搜索特征码,搜索到当前msr的地址
如果当前获取到的msr是KiSystemCall64,直接从这个地址往下搜索0x500个字节
找到KiSystemServiceRepeat这个函数后, 特征码第一段的4C 8D 1D XX XX XX XX 是SSDT地址, 第二段4C 8D 1D XX XX XX XX是Shadow SSDT地址
得到SSDT后可以通过 dwOffset = *((PULONG)SSDT->ServiceTableBase + FuncIndex); 获取到里面的函数偏移值, SSDT->ServiceTableBase+dwOffset就是函数地址
注意的是偏移要通过亦或才能得到真正的偏移值
dwOffset = *((PULONG)SSDT->ServiceTableBase + FuncIndex);
if (dwOffset & 0x80000000)
dwOffset = dwOffset >> 4 | 0xF0000000;
else
dwOffset = dwOffset >> 4;
FuncAddre = (PULONGLONG)((ULONGLONG)SSDT->ServiceTableBase + (ULONGLONG)dwOffset);
具体看代码
Driver.h
1 #pragma once 2 3 #include <ntifs.h> 4 #include <wdm.h> 5 #include <ntddk.h> 6 7 #define LPVOID PVOID 8 #define DWORD ULONG 9 #define BYTE UCHAR 10 #define WORD USHORT 11 12 typedef struct _KSYSTEM_SERVICE_TABLE /* SSDT表项*/ 13 { 14 PULONG ServiceTableBase; // 服务函数地址表基址 15 PULONG ServiceCounterTableBase; 16 ULONG NumberOfService; // 服务函数个数 17 PULONG ParamTableBase; // 服务函数参数表基址 18 }KSYSTEM_SERVICE_TABLE, * PKSYSTEM_SERVICE_TABLE; 19 20 typedef struct _UNICODE_STR 21 { 22 USHORT Length; 23 USHORT MaximumLength; 24 PWSTR pBuffer; 25 } UNICODE_STR, * PUNICODE_STR; 26 27 typedef struct _LDR_DATA_TABLE_ENTRY 28 { 29 //LIST_ENTRY InLoadOrderLinks; 30 LIST_ENTRY InMemoryOrderModuleList; 31 LIST_ENTRY InInitializationOrderModuleList; 32 PVOID DllBase; 33 PVOID EntryPoint; 34 ULONG SizeOfImage; 35 UNICODE_STR FullDllName; 36 UNICODE_STR BaseDllName; 37 ULONG Flags; 38 SHORT LoadCount; 39 SHORT TlsIndex; 40 LIST_ENTRY HashTableEntry; 41 ULONG TimeDateStamp; 42 } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 43 44 typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes 45 { 46 DWORD dwLength; 47 DWORD dwInitialized; 48 LPVOID lpSsHandle; 49 LIST_ENTRY InLoadOrderModuleList; 50 LIST_ENTRY InMemoryOrderModuleList; 51 LIST_ENTRY InInitializationOrderModuleList; 52 LPVOID lpEntryInProgress; 53 } PEB_LDR_DATA, * PPEB_LDR_DATA; 54 55 typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes 56 { 57 struct _PEB_FREE_BLOCK* pNext; 58 DWORD dwSize; 59 } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 60 61 typedef struct _RTL_CRITICAL_SECTION_DEBUG { 62 WORD Type; 63 WORD CreatorBackTraceIndex; 64 struct _RTL_CRITICAL_SECTION* CriticalSection; 65 LIST_ENTRY ProcessLocksList; 66 DWORD EntryCount; 67 DWORD ContentionCount; 68 DWORD Flags; 69 WORD CreatorBackTraceIndexHigh; 70 WORD SpareWORD; 71 } RTL_CRITICAL_SECTION_DEBUG, * PRTL_CRITICAL_SECTION_DEBUG, RTL_RESOURCE_DEBUG, * PRTL_RESOURCE_DEBUG; 72 73 typedef struct _RTL_CRITICAL_SECTION { 74 PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 75 76 // 77 // The following three fields control entering and exiting the critical 78 // section for the resource 79 // 80 81 LONG LockCount; 82 LONG RecursionCount; 83 HANDLE OwningThread; // from the thread's ClientId->UniqueThread 84 HANDLE LockSemaphore; 85 ULONG_PTR SpinCount; // force size on 64-bit systems when packed 86 } RTL_CRITICAL_SECTION, * PRTL_CRITICAL_SECTION; 87 88 89 typedef struct _PEB // 65 elements, 0x210 bytes 90 { 91 BYTE bInheritedAddressSpace; 92 BYTE bReadImageFileExecOptions; 93 BYTE bBeingDebugged; 94 BYTE bSpareBool; 95 LPVOID lpMutant; 96 LPVOID lpImageBaseAddress; 97 PPEB_LDR_DATA pLdr; 98 LPVOID lpProcessParameters; 99 LPVOID lpSubSystemData; 100 LPVOID lpProcessHeap; 101 PRTL_CRITICAL_SECTION pFastPebLock; 102 LPVOID lpFastPebLockRoutine; 103 LPVOID lpFastPebUnlockRoutine; 104 DWORD dwEnvironmentUpdateCount; 105 LPVOID lpKernelCallbackTable; 106 DWORD dwSystemReserved; 107 DWORD dwAtlThunkSListPtr32; 108 PPEB_FREE_BLOCK pFreeList; 109 DWORD dwTlsExpansionCounter; 110 LPVOID lpTlsBitmap; 111 DWORD dwTlsBitmapBits[2]; 112 LPVOID lpReadOnlySharedMemoryBase; 113 LPVOID lpReadOnlySharedMemoryHeap; 114 LPVOID lpReadOnlyStaticServerData; 115 LPVOID lpAnsiCodePageData; 116 LPVOID lpOemCodePageData; 117 LPVOID lpUnicodeCaseTableData; 118 DWORD dwNumberOfProcessors; 119 DWORD dwNtGlobalFlag; 120 LARGE_INTEGER liCriticalSectionTimeout; 121 DWORD dwHeapSegmentReserve; 122 DWORD dwHeapSegmentCommit; 123 DWORD dwHeapDeCommitTotalFreeThreshold; 124 DWORD dwHeapDeCommitFreeBlockThreshold; 125 DWORD dwNumberOfHeaps; 126 DWORD dwMaximumNumberOfHeaps; 127 LPVOID lpProcessHeaps; 128 LPVOID lpGdiSharedHandleTable; 129 LPVOID lpProcessStarterHelper; 130 DWORD dwGdiDCAttributeList; 131 LPVOID lpLoaderLock; 132 DWORD dwOSMajorVersion; 133 DWORD dwOSMinorVersion; 134 WORD wOSBuildNumber; 135 WORD wOSCSDVersion; 136 DWORD dwOSPlatformId; 137 DWORD dwImageSubsystem; 138 DWORD dwImageSubsystemMajorVersion; 139 DWORD dwImageSubsystemMinorVersion; 140 DWORD dwImageProcessAffinityMask; 141 DWORD dwGdiHandleBuffer[34]; 142 LPVOID lpPostProcessInitRoutine; 143 LPVOID lpTlsExpansionBitmap; 144 DWORD dwTlsExpansionBitmapBits[32]; 145 DWORD dwSessionId; 146 ULARGE_INTEGER liAppCompatFlags; 147 ULARGE_INTEGER liAppCompatFlagsUser; 148 LPVOID lppShimData; 149 LPVOID lpAppCompatInfo; 150 UNICODE_STR usCSDVersion; 151 LPVOID lpActivationContextData; 152 LPVOID lpProcessAssemblyStorageMap; 153 LPVOID lpSystemDefaultActivationContextData; 154 LPVOID lpSystemAssemblyStorageMap; 155 DWORD dwMinimumStackCommit; 156 } PEB, * PPEB; 157 158 159 160 161 162 PVOID64 GetSSDTAddre(); // 获取SSDT地址 163 PVOID64 GetSSDTFuncAddre(DWORD64 FuncIndex); // 获取SSDT函数的地址 164 PVOID64 SetSSDTFuncHook(DWORD64 FuncIndex, PVOID64 FuncAddre); // 设置SSDT HOOK
Driver
1 #include "Dirver.h" 2 3 #define _CRT_SECURE_NO_WARNINGS 4 5 NTSTATUS(_stdcall* OldProcess)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID) = 0; // 测试OpenProcess函数,旧函数地址 6 NTSTATUS cwkDispatch(PDEVICE_OBJECT, PIRP); // 驱动的IRP分发函数 7 void DriverUnload(PDRIVER_OBJECT); // 驱动的卸载函数 8 9 NTSTATUS _stdcall myOpenProcess( // 自己写的OpenProcess函数 10 PHANDLE ProcessHandle, 11 ACCESS_MASK DesiredAccess, 12 POBJECT_ATTRIBUTES ObjectAttributes, 13 PCLIENT_ID ClientId) 14 { 15 DbgPrint("[dbg]: NtOpenProcess Handle = %p [%wZ] UniqueProcess = %p UniqueThread=%p\n", 16 ProcessHandle, ObjectAttributes->ObjectName, ClientId->UniqueProcess, ClientId->UniqueThread); 17 18 return OldProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); 19 } 20 21 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 22 { 23 UNREFERENCED_PARAMETER(RegistryPath); 24 NTSTATUS nStatus = STATUS_SUCCESS; 25 DbgPrint("[dbg]: DriverObject=%p DriverStart=%p DriverExtension=%p\n", DriverObject, DriverObject->DriverStart, DriverObject->DriverExtension); 26 DriverObject->DriverUnload = DriverUnload; 27 for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 28 DriverObject->MajorFunction[i] = cwkDispatch; 29 30 PVOID64 Func = SetSSDTFuncHook(0x26, (PVOID64)&myOpenProcess); 31 OldProcess =(NTSTATUS(_stdcall *)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID))Func; 32 DbgPrint("[dbg]: NtOpenProcessAddre=%p \n", OldProcess); 33 34 return nStatus; 35 } 36 37 void DriverUnload(PDRIVER_OBJECT DriverObject) 38 { 39 if (OldProcess) 40 SetSSDTFuncHook(0X26, (PVOID64)&OldProcess); 41 42 if (!NT_SUCCESS(UnloadCOMDev(DriverObject))) 43 DbgPrint("[dbg]: Device Unload fail ----%x\n", __LINE__); 44 else 45 DbgPrint("[dbg]: Device Unload OK ----%x\n", __LINE__); 46 return; 47 } 48 49 NTSTATUS cwkDispatch(PDEVICE_OBJECT dev, PIRP irp) 50 { 51 PIO_STACK_LOCATION irpsp; 52 NTSTATUS nStatus = STATUS_UNSUCCESSFUL; 53 if (dev == COMDevObject) 54 { 55 nStatus = STATUS_SUCCESS; 56 irpsp = IoGetCurrentIrpStackLocation(irp); 57 switch (irpsp->MajorFunction) 58 { 59 case IRP_MJ_CREATE: 60 DbgPrint("[dbg]: 检测到应用层符号链接请求 \n"); 61 break; 62 63 case IRP_MJ_CLOSE: 64 DbgPrint("[dbg]: 检测到应用层关闭符号链接请求 \n"); 65 break; 66 default: 67 break; 68 } 69 } 70 71 72 // IRP消息 已处理 73 irp->IoStatus.Information = 0; 74 irp->IoStatus.Status = nStatus; 75 IoCompleteRequest(irp, IO_NO_INCREMENT); 76 return nStatus; 77 } 78 79 PVOID64 GetSSDTAddre() 80 { 81 PUCHAR msr = 0; 82 PUCHAR StartAddre = 0, EndAddre = 0; // 开始遍历的地方,和遍历长度,获取到SSDT的位置 83 UCHAR b0 = 0, b1 = 0, b2 = 0, b7 = 0, b8 = 0, b9 = 0 ,b14 = 0, b15=0; 84 ULONG deviation = 0; //KiSystemServiceRepeat+7到SSDT的偏移 85 ULONGLONG SSDTAddre = 0; 86 87 msr = (PUCHAR)__readmsr(0xC0000082); 88 // __readmsr(0xC0000082)在 开启内核隔离的情况下获取到的是KiSystemCall64Shadow函数,未开启内核隔离的是 KiSystemCall64 89 // 通过KiSystemCall64Shadow/ KiSystemCall64定位到 KiSystemServiceRepeat函数,KiSystemServiceRepeat 90 b0 = *(msr + 21); 91 if (b0 == 0x72) 92 { 93 // 系统未开启内核隔离模式 KiSystemCall64往下遍历 搜特征码【4C 8D 15 XX XX XX XX 4C 8D 1D XX XX XX XX F7 43】找到KiSystemServiceRepeat 94 // 第二个 4C 8D 1D XX XX XX XX 是Shadow SSDT地址 95 StartAddre = msr, EndAddre = msr + 0x500; 96 for (; StartAddre < EndAddre; StartAddre++) 97 if (MmIsAddressValid(StartAddre) && MmIsAddressValid(StartAddre + 1) && MmIsAddressValid(StartAddre + 2)) 98 { 99 b0 = *StartAddre; 100 b1 = *(StartAddre + 1); 101 b2 = *(StartAddre + 2); 102 b7 = *(StartAddre + 7); 103 b8 = *(StartAddre + 8); 104 b9 = *(StartAddre + 9); 105 b14 = *(StartAddre + 14); 106 b15 = *(StartAddre + 15); 107 if (b0 == 0x4C && b1 == 0x8d && b2 == 0x15 && b7 == 0x4C && b8 == 0x8d && b9 == 0x1D && b14 == 0xF7 && b15 == 0x43) 108 { 109 memcpy(&deviation, StartAddre + 3, 4); 110 SSDTAddre = (ULONGLONG)deviation + (ULONGLONG)StartAddre + 7; 111 DbgPrint("[dbg]: KiSystemCall64:=%p KiSystemServiceRepeat=%p SSDT=%p\n", msr, StartAddre, (PULONG64)SSDTAddre); 112 return (PVOID64)SSDTAddre; 113 } 114 } 115 } 116 else if (b0 == 0x65) 117 { 118 // 系统开启内核隔离模式通过 KiSystemCall64Shadow向上搜 特征码【4C 8D 15 XX XX XX XX 4C 8D 1D XX XX XX XX F7 43】找到 KiSystemServiceRepeat 119 // 第二个 4C 8D 1D XX XX XX XX 是Shadow SSDT地址 120 StartAddre = msr - 0x200000, EndAddre = msr; 121 for (; StartAddre < EndAddre; StartAddre++) 122 if (MmIsAddressValid(StartAddre) && MmIsAddressValid(StartAddre + 1) && MmIsAddressValid(StartAddre + 2)) 123 { 124 b0 = *StartAddre; 125 b1 = *(StartAddre + 1); 126 b2 = *(StartAddre + 2); 127 b7 = *(StartAddre + 7); 128 b8 = *(StartAddre + 8); 129 b9 = *(StartAddre + 9); 130 b14 = *(StartAddre + 14); 131 b15 = *(StartAddre + 15); 132 if (b0 == 0x4C && b1 == 0x8d && b2 == 0x15 && b7 == 0x4C && b8 == 0x8d && b9 == 0x1D && b14== 0xF7 && b15==0x43) 133 { 134 memcpy(&deviation, StartAddre + 3, 4); 135 SSDTAddre = (ULONGLONG)deviation + (ULONGLONG)StartAddre + 7; 136 DbgPrint("[dbg]: KiSystemCall64Shadow=%p KiSystemServiceRepeat=%p SSDT=%p\n", msr, StartAddre, (PULONG64)SSDTAddre); 137 return (PVOID64)SSDTAddre; 138 } 139 } 140 } 141 142 DbgPrint("[dbg]: No find SSDT\n"); 143 return NULL; 144 } 145 146 PVOID64 GetSSDTFuncAddre(DWORD64 FuncIndex) //FuncIndex是函数的索引 147 { 148 PKSYSTEM_SERVICE_TABLE SSDT = 0; 149 PULONGLONG FuncAddre = 0; 150 ULONG dwOffset = 0; 151 152 SSDT = GetSSDTAddre(); 153 if (SSDT) 154 { 155 dwOffset = *((PULONG)SSDT->ServiceTableBase + FuncIndex); 156 if (dwOffset & 0x80000000) 157 dwOffset = dwOffset >> 4 | 0xF0000000; 158 else 159 dwOffset = dwOffset >> 4; 160 FuncAddre = (PULONGLONG)((ULONGLONG)SSDT->ServiceTableBase + (ULONGLONG)dwOffset); 161 162 //DbgPrint("[dbg]: SSDTFuncAddre[%lld] [%p] = ServiceTableBase[%p] + dwOffset[%lx]\n", FuncIndex, (PVOID64)FuncAddre, SSDT->ServiceTableBase, dwOffset); 163 return FuncAddre; 164 } 165 DbgPrint("[dbg]: No find SSDT Function [%lld] ", FuncIndex); 166 return 0; 167 } 168 169 PVOID64 SetSSDTFuncHook(DWORD64 FuncIndex, PVOID64 FuncAddre) 170 { 171 PKSYSTEM_SERVICE_TABLE pSSDT = 0; 172 PULONGLONG OldFuncAddre = 0; 173 ULONG dwOffset = 0; 174 ULONG oldOffset = 0; 175 pSSDT = GetSSDTAddre(); 176 if (pSSDT) 177 { 178 179 oldOffset = *((PULONG)pSSDT->ServiceTableBase + FuncIndex); 180 if (oldOffset & 0x80000000) 181 oldOffset = oldOffset >> 4 | 0xF0000000; 182 else 183 oldOffset = oldOffset >> 4; 184 OldFuncAddre = (PULONGLONG)((ULONGLONG)pSSDT->ServiceTableBase + (ULONGLONG)oldOffset); 185 DbgPrint("[dbg]: SSDT OldFunction Addre[%p]\n",GetSSDTFuncAddre(FuncIndex)); 186 dwOffset = (ULONG)((ULONGLONG)FuncAddre - (ULONGLONG)pSSDT->ServiceTableBase); 187 dwOffset = dwOffset << 4; 188 if (!(dwOffset & 0xF0000000)) 189 dwOffset = dwOffset | 0x80000000; 190 *((PULONG)pSSDT->ServiceTableBase + FuncIndex) = dwOffset; 191 DbgPrint("[dbg]: SetSSDT office = %ld Function[%p]==[%p] \n", dwOffset, GetSSDTFuncAddre(FuncIndex), FuncAddre); 192 return OldFuncAddre; 193 } 194 195 return 0; 196 }