Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)
SHADOW?SSDT?HOOK
????HOOK?和?UNHOOK?SHADOW?SSDT?跟之前的?HOOK/UNHOOK?SSDT?類似,區(qū)別是查找SSSDT的特征碼,以及根據(jù)索引計算函數(shù)地址的公式,還有一個就是吧跳轉(zhuǎn)函數(shù)寫在什么位置,SSDT的時候是寫在藍屏函數(shù)里了。
一、獲得?w?KeServiceDescriptorTableShadow的地址
????這個跟獲得?KeServiceDescriptorTable?差不多,唯一不同就是特征碼:
?
ULONGLONG GetKeServiceDescriptorTableShadow64() { 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==0x1d ) //4c8d1d { memcpy(&templong,i+3,4); addr = (ULONGLONG)templong + (ULONGLONG)i + 7; return addr; } } } return 0; }?
?
?
二、根據(jù)?X?INDEX??獲得?T?SSSDT??函數(shù)在內(nèi)核里的地址
????原理跟獲得?SSDT?函數(shù)在在內(nèi)核里的地址差不多,先獲得?W32pServiceTable的地址,然后再獲得每個函數(shù)的偏移地址,在把偏移地址與?W32pServiceTable相加。為什么下面的計算公式是?W32pServiceTable?+?4?*?(index-0x1000)呢?其實這只是個理解上的問題。SSDT?函數(shù)的起始?INDEX?是?0x0,SSSDT?函數(shù)的起始?INDEX?是?0x1000,但函數(shù)地址在?W32pServiceTable?是從基址開始記錄
的(假設(shè)?W32pServiceTable?的地址是?0xfffff800~80000000,第?0?個函數(shù)的地址就記錄在?0xfffff800~80000000,第?1?個函數(shù)的地址就記錄在0xfffff800~80000004,第?2?個函數(shù)的地址就記錄在?0xfffff800~80000008,以此類推)。
?
ULONGLONG GetSSSDTFuncCurAddr64(ULONG64 Index) { ULONGLONG W32pServiceTable=0, qwTemp=0; LONG dwTemp=0; PSYSTEM_SERVICE_TABLE pWin32k; pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE)); W32pServiceTable=(ULONGLONG)(pWin32k->ServiceTableBase); ul64W32pServiceTable = W32pServiceTable; qwTemp = W32pServiceTable + 4 * (Index-0x1000); //這里是獲得偏移地址的位置,要HOOK的話修改這里即可 dwTemp = *(PLONG)qwTemp; dwTemp = dwTemp >> 4; qwTemp = W32pServiceTable + (LONG64)dwTemp; return qwTemp; }三、修改SSSDT里的地址
?
? ? 還是跟?SSDT?類似,修改?W32pServiceTable+4*index?地址的?DWORD?值(偏移地址值)。
?
VOID ModifySSSDT(ULONG64 Index, ULONG64 Address) {ULONGLONG W32pServiceTable=0, qwTemp=0;LONG dwTemp=0;PSYSTEM_SERVICE_TABLE pWin32k;KIRQL irql;pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE)); //4*8W32pServiceTable=(ULONGLONG)(pWin32k->ServiceTableBase);qwTemp = W32pServiceTable + 4 * (Index-0x1000);dwTemp = (LONG)(Address - W32pServiceTable);dwTemp = dwTemp << 4; irql=WPOFFx64();*(PLONG)qwTemp = dwTemp;WPONx64(irql); }?
? ? 第一個代理函數(shù)用機器碼寫成,總共就 14 個字節(jié),前 6 字節(jié)為 ff 25 00 00 00 00,后 8 字節(jié)為第二個代理函數(shù)的地址(JMP QWORD PTR)。
?
VOID ModifySSSDT(ULONG64 Index, ULONG64 Address) { ULONGLONG W32pServiceTable=0, qwTemp=0; LONG dwTemp=0; PSYSTEM_SERVICE_TABLE pWin32k; KIRQL irql; pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE)); //4*8 W32pServiceTable=(ULONGLONG)(pWin32k->ServiceTableBase); qwTemp = W32pServiceTable + 4 * (Index-0x1000); dwTemp = (LONG)(Address - W32pServiceTable); dwTemp = dwTemp << 4; irql=WPOFFx64(); *(PLONG)qwTemp = dwTemp; WPONx64(irql); }代理函數(shù)地址:
?
?
ULONG64 ProxyNtUserPostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { if( NtUserQueryWindow(hWnd,0)==MyProcessId && PsGetCurrentProcessId()!=(HANDLE)MyProcessId ) { DbgPrint("Do not fuck with me!"); return 0; } else { DbgPrint("OriNtUserPostMessage called!"); return NtUserPostMessage(hWnd,Msg,wParam,lParam); } }?
注意UnHOOK就是把真正的函數(shù)地址給填寫回去
?
VOID UNHOOK_SSSDT() { ModifySSSDT(IndexOfNtUserPostMessage, (ULONG64)NtUserPostMessage); DbgPrint("UNHOOK_SSSDT OK!"); }?
?
?
執(zhí)行效果測試
以下是窗口攻擊函數(shù):
?
int main2() { DWORD pid, wpid, i, j; HWND hWnd; gogogo: printf("pid: "); scanf("%ld", &pid); for (i = 100; i<0xffffff; i += 2) { GetWindowThreadProcessId((HWND)i, &wpid); if (wpid == pid && IsWindowVisible((HWND)i) == 1) { hWnd = (HWND)i; for (j = 0; j<0x10000; j++) { PostMessage(hWnd, j, 0, 0); } } } printf("Ok!"); getchar(); getchar(); goto gogogo; return 0; }通過HOOK PostMessage 來保護自己不被干掉:
?
?
?
? ? 至于Un SSSDT HOOK 是和SSDT思路一樣的,也是自己加載相關(guān)內(nèi)核模塊,得到一些地址,然后在通過驅(qū)動通訊,在內(nèi)核里獲得一些地址,最后計算出來函數(shù)的真正地址,然后把原地址填寫回去(這個地方就是繼續(xù)hook一遍)就行了。直接把資料相關(guān)代碼粘貼過來吧:
?
?R3的代碼:
?
#include <stdio.h> #include <direct.h> #include <Windows.h> #include "EnumDrv.h" #include "DrvCtrl.h"HANDLE hMyDrv;void PrintAddressByIndex() { LONG64 id=0; ULONG64 addr=0; st: printf("Input index (HEX without \"0x\" like: 1000, input -1 to exit): "); scanf("%llx",&id); if (id<0) return; IoControl(hMyDrv ,CTL_CODE_GEN(0x807), &id, 8, &addr, 8); printf("%llx\n",addr); getchar(); goto st; }DWORD FileLen(char *filename) { WIN32_FIND_DATAA fileInfo={0}; DWORD fileSize=0; HANDLE hFind; hFind = FindFirstFileA(filename ,&fileInfo); if(hFind != INVALID_HANDLE_VALUE) { fileSize = fileInfo.nFileSizeLow; FindClose(hFind); } return fileSize; }CHAR *LoadDllContext(char *filename) { DWORD dwReadWrite, LenOfFile=FileLen(filename); HANDLE hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { PCHAR buffer=(PCHAR)malloc(LenOfFile); SetFilePointer(hFile, 0, 0, FILE_BEGIN); ReadFile(hFile, buffer, LenOfFile, &dwReadWrite, 0); CloseHandle(hFile); return buffer; } return NULL; }ULONG64 GetWin32kImageBase() { PIMAGE_NT_HEADERS64 pinths64; PIMAGE_DOS_HEADER pdih; char *NtosFileData=NULL; NtosFileData=LoadDllContext("c:\\win32k.dll"); pdih=(PIMAGE_DOS_HEADER)NtosFileData; pinths64=(PIMAGE_NT_HEADERS64)(NtosFileData+pdih->e_lfanew); return pinths64->OptionalHeader.ImageBase; }void GetOriAddress() { ULONG64 W32pServiceTable, Win32kBase, Win32kImageBase, Win32kInProcess=0, retv; IoControl(hMyDrv ,CTL_CODE_GEN(0x806), NULL, 0, &W32pServiceTable, 8); Win32kBase = GetWin32kBase(); CopyFileA("c:\\windows\\system32\\win32k.sys","c:\\win32k.dll",0); Win32kImageBase = GetWin32kImageBase(); printf("W32pServiceTable: %llx\n", W32pServiceTable); printf("WIN32K.SYS base: %llx\n", Win32kBase); printf("WIN32K.SYS image base: %llx\n\n\n", Win32kImageBase); ULONG index=0; if ( Win32kInProcess==0 ) Win32kInProcess = (ULONGLONG)LoadLibraryExA("c:\\win32k.dll",0, DONT_RESOLVE_DLL_REFERENCES); for(index=0;index<825;index++) //825是WIN7X64上SSSDT的函數(shù)個數(shù) { ULONGLONG RVA=W32pServiceTable-Win32kBase; ULONGLONG temp=*(PULONGLONG)(Win32kInProcess+RVA+8*(ULONGLONG)index); ULONGLONG RVA_index=temp-Win32kImageBase; retv = RVA_index+Win32kBase; printf("Shadow SSDT Function[%ld]: %llx\n",index,retv); if(index % 100 ==0) { printf("Press any key to continue......\n"); getchar(); } } }int main() { hMyDrv=openDriver(); GetOriAddress(); uninstallDriver(); return 0; }宋孖健,13
?
總結(jié)
以上是生活随笔為你收集整理的Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win64 驱动内核编程-21.DKOM
- 下一篇: Win64 驱动内核编程-23.Ring