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 }

 

posted @ 2021-08-04 16:02  伤痕累累的笨蛋  阅读(2846)  评论(0编辑  收藏  举报