編譯環境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);
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; 6 NTSTATUS cwkDispatch(PDEVICE_OBJECT, PIRP); // 驅動的IRP分發函數 7 void DriverUnload(PDRIVER_OBJECT); // 驅動的卸載函數 8 9 NTSTATUS _stdcall myOpenProcess( 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 }