日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Win64 驱动内核编程-18.SSDT

發布時間:2025/6/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win64 驱动内核编程-18.SSDT 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SSDT

?學習資料:http://blog.csdn.net/zfdyq0/article/details/26515019

?學習資料:WIN64內核編程基礎?胡文亮

?

???SSDT(系統服務描述表),剛開始接觸什么進程保護XXX啥的,都是看到在說SSDT(雖然說目前很多殺軟都已經采用穩定簡單的回調姿勢了)。這次就弄清楚兩個問題:

????如何在內核里動態獲得?SSDT?的基址;

如何在內核里動態獲得?SSDT?函數的地址;

????在?WIN32?下,第一個問題就根本不是問題,因為?KeServiceDescriptorTable?直接被導

出了。但是?WIN64?下?KeServiceDescriptorTable?沒有被導出。所以必須搜索得到它的地址。

反匯編:uf?KisystemCall64


? ? 上面看到,貌似直接反匯編uf?KiSystemServiceRepeat?試了下,一樣可以找到SSDT基址,但是問題是,KiSystemServiceRepeat這個東西的地址找不到,而KiSystemCall64的地址直接可以直接讀取指定的?msr?得出。

通過讀取?C0000082?寄存器,能夠得到?KiSystemCall64?的地址,然后從

KiSystemCall64?的地址開始,往下搜索?0x500?字節左右(特征碼是?4c8d15),就能得到

KeServiceDescriptorTable?的地址了。同理,我們換一下特征碼(4c8d1d),就能獲得

KeServiceDescriptorTableShadow?的地址了。


然后是資料里面帶的兩個SSDT基址的函數:

? ? 方法1(這個方法藍屏了,我直接用的方法2)

ULONGLONG GetKeServiceDescriptorTable64() { char KiSystemServiceStart_pattern[13] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00"; ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp; ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent; UNICODE_STRING Symbol; ULONGLONG i, tbl_address, b; for (i = 0; i < CodeScanEnd - CodeScanStart; i++) { if (!memcmp((char*)(ULONGLONG)CodeScanStart +i, (char*)KiSystemServiceStart_pattern,13)) { for (b = 0; b < 50; b++) { tbl_address = ((ULONGLONG)CodeScanStart+i+b); if (*(USHORT*) ((ULONGLONG)tbl_address ) == (USHORT)0x8d4c) return ((LONGLONG)tbl_address +7) + *(LONG*)(tbl_address +3); } } } return 0; }方法2

ULONGLONG MyGetKeServiceDescriptorTable64() { PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);PUCHAR EndSearchAddress = StartSearchAddress + 0x500; PUCHAR i = NULL; UCHAR b1=0,b2=0,b3=0; ULONG templong=0; ULONGLONG addr=0; for(i=StartSearchAddress;i<EndSearchAddress;i++) { if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) ) { b1=*i; b2=*(i+1); b3=*(i+2); if( b1==0x4c && b2==0x8d && b3==0x15 ) //4c8d15 { memcpy(&templong,i+3,4); addr = (ULONGLONG)templong + (ULONGLONG)i + 7; return addr; } } } return 0; }

????接下來就是講述?SSDT?函數地址了。在獲得地址之前,需要知道?SSDT?函數的?INDEX。獲得這個?INDEX?的方法很簡單,直接在?RING3?讀取?NTDLL?的內容即可。使用?WINDBG?的方法如下:隨便創建一個進程,然后使用?WINDBG?附加:


? ? 可以看到兩次反匯編的結果幾乎完全相同,唯一不同的地方是第二句。XXh?就是此函數的?index。知道?INDEX?之后,就可以計算地址了(資料上也是給了兩個方法,建議使用方法2)。

方法1

VOID Initxxxx() { UCHAR strShellCode[36]="\x48\x8B\xC1\x4C\x8D\x12\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x4E\x8B\x14\x17\x4D\x63\x1C\x82\x49\x8B\xC3\x49\xC1\xFB\x04\x4D\x03\xD3\x49\x8B\xC2\xC3"; /* mov rax, rcx ;rcx=index lea r10,[rdx] ;rdx=ssdt mov edi,eax shr edi,7 and edi,20h mov r10, qword ptr [r10+rdi] movsxd r11,dword ptr [r10+rax*4] mov rax,r11 sar r11,4 add r10,r11 mov rax,r10 ret */ scfn=ExAllocatePool(NonPagedPool,36); memcpy(scfn,strShellCode,36); } ULONGLONG GetSSDTFunctionAddress64(ULONGLONG NtApiIndex) { ULONGLONG ret=0; ULONGLONG ssdt= MyGetKeServiceDescriptorTable64(); if(scfn==NULL) Initxxxx(); ret=scfn(NtApiIndex, ssdt); return ret; }
方法2

typedef struct _SYSTEM_SERVICE_TABLE{ PVOID ServiceTableBase; PVOID ServiceCounterTableBase; ULONGLONG NumberOfServices; PVOID ParamTableBase; } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;ULONGLONG GetSSDTFunctionAddress64_2(ULONGLONG Index) { LONG dwTemp=0; ULONGLONG qwTemp=0,stb=0,ret=0; PSYSTEM_SERVICE_TABLE ssdt=(PSYSTEM_SERVICE_TABLE)MyGetKeServiceDescriptorTable64(); stb=(ULONGLONG)(ssdt->ServiceTableBase); qwTemp = stb + 4 * Index; dwTemp = *(PLONG)qwTemp; dwTemp = dwTemp >> 4; ret = stb + (LONG64)dwTemp; return ret; }

????最后,總結一下?WIN32?和?WIN64?在?SSDT?方面的不同(我直接截圖過來)。大家可以把?SSDT(其實?SHADOWSSDT?同理)想像成一排保險柜,每個柜子都有編號(從?0?開始),柜子的長度為四字節,每個柜子里都放了一個?LONG?數據。但不同的是,WIN32?的“柜子”里放的數據是某個函數的絕對地址,而?WIN64?的“柜子”里放的數據是某個函數的偏移地址。這個偏移地址要經過一定的計算才能變成絕對地址。


測試代碼:

#include <ntddk.h> #include <windef.h> #include "MyDriver.h" #pragma intrinsic(__readmsr) typedef UINT64 (__fastcall *SCFN)(UINT64,UINT64); SCFN scfn;ULONGLONG MyGetKeServiceDescriptorTable64() { PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);PUCHAR EndSearchAddress = StartSearchAddress + 0x500; PUCHAR i = NULL; UCHAR b1=0,b2=0,b3=0; ULONG templong=0; ULONGLONG addr=0; for(i=StartSearchAddress;i<EndSearchAddress;i++) { if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) ) { b1=*i; b2=*(i+1); b3=*(i+2); if( b1==0x4c && b2==0x8d && b3==0x15 ) //4c8d15 { memcpy(&templong,i+3,4); addr = (ULONGLONG)templong + (ULONGLONG)i + 7; return addr; } } } return 0; }VOID Initxxxx() { UCHAR strShellCode[36]="\x48\x8B\xC1\x4C\x8D\x12\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x4E\x8B\x14\x17\x4D\x63\x1C\x82\x49\x8B\xC3\x49\xC1\xFB\x04\x4D\x03\xD3\x49\x8B\xC2\xC3"; /* mov rax, rcx ;rcx=index lea r10,[rdx] ;rdx=ssdt mov edi,eax shr edi,7 and edi,20h mov r10, qword ptr [r10+rdi] movsxd r11,dword ptr [r10+rax*4] mov rax,r11 sar r11,4 add r10,r11 mov rax,r10 ret */ scfn=ExAllocatePool(NonPagedPool,36); memcpy(scfn,strShellCode,36); }ULONGLONG GetSSDTFunctionAddress64(ULONGLONG NtApiIndex) { ULONGLONG ret=0; ULONGLONG ssdt= MyGetKeServiceDescriptorTable64(); if(scfn==NULL) Initxxxx(); ret=scfn(NtApiIndex, ssdt); return ret; }typedef struct _SYSTEM_SERVICE_TABLE{ PVOID ServiceTableBase; PVOID ServiceCounterTableBase; ULONGLONG NumberOfServices; PVOID ParamTableBase; } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;ULONGLONG GetSSDTFunctionAddress64_2(ULONGLONG Index) { LONG dwTemp=0; ULONGLONG qwTemp=0,stb=0,ret=0; PSYSTEM_SERVICE_TABLE ssdt=(PSYSTEM_SERVICE_TABLE)MyGetKeServiceDescriptorTable64(); stb=(ULONGLONG)(ssdt->ServiceTableBase); qwTemp = stb + 4 * Index; dwTemp = *(PLONG)qwTemp; dwTemp = dwTemp >> 4; ret = stb + (LONG64)dwTemp; return ret; }VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; RtlInitUnicodeString(&strLink, LINK_NAME); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); }NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInSize; ULONG uOutSize; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) { ; } if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uOutSize; else pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevObj; pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; pDriverObj->DriverUnload = DriverUnload; RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj); if(!NT_SUCCESS(status)) return status; if(IoIsWdmVersionAvailable(1, 0x10)) RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME); else RtlInitUnicodeString(&ustrLinkName, LINK_NAME); status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if(!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } //test DbgPrint("[method 1]SSDT: %llx\n",MyGetKeServiceDescriptorTable64());DbgPrint("[method 1]NtOpenProcess: %llx\n",GetSSDTFunctionAddress64(0x23)); //WIN7X64 HARDCODE DbgPrint("[method 1]NtTerminateProcess: %llx\n",GetSSDTFunctionAddress64(0x29)); //WIN7X64 HARDCODEDbgPrint("[method 2]NtOpenProcess: %llx\n",GetSSDTFunctionAddress64_2(0x23)); //WIN7X64 HARDCODE DbgPrint("[method 2]NtTerminateProcess: %llx\n",GetSSDTFunctionAddress64_2(0x29));//WIN7X64 HARDCODE //test return STATUS_SUCCESS; }執行結果:


《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Win64 驱动内核编程-18.SSDT的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。