shadow ssdt学习笔记
1。取得shadow ssdt真實地址
系統只提供了KeServiceDescriptorTable導出
KeServiceDescriptorTableShadow是個未導出結構
定義
Copy code
??? typedef struct _SYSTEM_SERVICE_TABLE
??? {
????????? PNTPROC? ServiceTable;? // array of entry points
????????? PDWORD? CounterTable;? // array of usage counters
????????? DWORD? ServiceLimit;??? // number of table entries
????????? PBYTE??? ArgumentTable;? // array of byte counts
??? }
??? SYSTEM_SERVICE_TABLE,
??? *PSYSTEM_SERVICE_TABLE,
??? **PPSYSTEM_SERVICE_TABLE;
??? //-----------------------------------------------------------------------------------------------------------
??? typedef struct _SERVICE_DESCRIPTOR_TABLE
??? {
????????? SYSTEM_SERVICE_TABLE ntoskrnl;? // ntoskrnl.exe ( native api )
??????? SYSTEM_SERVICE_TABLE win32k;??? // win32k.sys (gdi/user support)
????????? SYSTEM_SERVICE_TABLE Table3;??? // not used
????????? SYSTEM_SERVICE_TABLE Table4;??? // not used
??? }
??? SYSTEM_DESCRIPTOR_TABLE,
??? *PSYSTEM_DESCRIPTOR_TABLE,
??? **PPSYSTEM_DESCRIPTOR_TABLE;
?
其實 KeServiceDescriptorTableShadow包含4個子結構,其中第一個就是ntoskrnl.exe ( native api ),和KeServiceDescriptorTable指向一樣 我們真正需要獲得的是第二個win32k.sys (gdi/user support),第三個和第四個一般不使用
定位方法
1。硬編碼
Copy code
??? //for xp
??? if(gKernelVersion==WINXP)
????? KeServiceDescriptorTableShadow=KeServiceDescriptorTable-0x40;
??? //for 2k
??? if(gKernelVersion==WIN2K)
????? KeServiceDescriptorTableShadow=KeServiceDescriptorTable+0xE0;
?
2。搜索KeAddSystemServiceTable
反匯編代碼可以看出
Copy code
??? lkd> u KeAddSystemServiceTable l 40
??? nt!KeAddSystemServiceTable:
??? 805ba589 8bff??????????? mov??? edi,edi
??? 805ba58b 55????????????? push??? ebp
??? 805ba58c 8bec??????????? mov??? ebp,esp
??? 805ba58e 837d1803??????? cmp??? dword ptr [ebp+18h],3
??? 805ba592 774e??????????? ja????? nt!KeAddSystemServiceTable+0x6b (805ba5e2)
??? 805ba594 8b4518????????? mov??? eax,dword ptr [ebp+18h]
??? 805ba597 c1e004????????? shl??? eax,4
??? 805ba59a 83b880a6558000? cmp??? dword ptr nt!KeServiceDescriptorTable (8055a680)[eax],0
??? 805ba5a1 753f??????????? jne??? nt!KeAddSystemServiceTable+0x6b (805ba5e2)
??? 805ba5a3 8d8840a65580??? lea??? ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax]
??? 805ba5a9 833900????????? cmp??? dword ptr [ecx],0
??? 805ba5ac 7534??????????? jne??? nt!KeAddSystemServiceTable+0x6b (805ba5e2)
??? 805ba5ae 837d1801??????? cmp??? dword ptr [ebp+18h],1
??? 805ba5b2 8b5508????????? mov??? edx,dword ptr [ebp+8]
??? 805ba5b5 56????????????? push??? esi
??? 805ba5b6 8b7510????????? mov??? esi,dword ptr [ebp+10h]
??? 805ba5b9 57????????????? push??? edi
??? 805ba5ba 8b7d14????????? mov??? edi,dword ptr [ebp+14h]
??? 805ba5bd 8911??????????? mov??? dword ptr [ecx],edx
??? 805ba5bf 8b4d0c????????? mov??? ecx,dword ptr [ebp+0Ch]
??? 805ba5c2 898844a65580??? mov??? dword ptr nt!KeServiceDescriptorTableShadow+0x4 (8055a644)[eax],ecx
??? 805ba5c8 89b048a65580??? mov??? dword ptr nt!KeServiceDescriptorTableShadow+0x8 (8055a648)[eax],esi
??? 805ba5ce 89b84ca65580??? mov??? dword ptr nt!KeServiceDescriptorTableShadow+0xc (8055a64c)[eax],edi
??? 805ba5d4 0f855a3e0300??? jne??? nt!KeAddSystemServiceTable+0x4d (805ee434)
??? 805ba5da 5f????????????? pop??? edi
??? 805ba5db b001??????????? mov??? al,1
??? 805ba5dd 5e????????????? pop??? esi
??? 805ba5de 5d????????????? pop??? ebp
??? 805ba5df c21400????????? ret??? 14h
??? 805ba5e2 32c0??????????? xor??? al,al
??? 805ba5e4 ebf8??????????? jmp??? nt!KeAddSystemServiceTable+0x6d (805ba5de)
??? 805ba5e6 90????????????? nop
??? 805ba5e7 90????????????? nop
??? 805ba5e8 90????????????? nop
??? 805ba5e9 90????????????? nop
??? 805ba5ea 90????????????? nop
?
搜索辦法很簡單
就是找到
805ba5a3 8d8840a65580??? lea??? ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax]
的8d88 40a65580??? lea??? ecx, nt!KeServiceDescriptorTableShadow
代碼如下
Copy code
??? void GetKeServiceDescriptorTableShadow()
??? {
??????? PUCHAR cPtr, pOpcode;
??????? ULONG Length;
????
??????? for (cPtr = (PUCHAR)KeAddSystemServiceTable;
??????????? cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;
??????????? cPtr += Length)
??????? {
??????????? if (!MmIsAddressValid(cPtr)) break;
??????????? Length = SizeOfCode(cPtr, &pOpcode);
??????????? if (!Length || (Length == 1 && *pOpcode == 0xC3)) break;
????????
??????????? if (*(PUSHORT)pOpcode == 0x888D)
??????????? {
??????????????? KeServiceDescriptorTableShadow = *(PVOID *)(pOpcode + 2);
??????????????? break;
??????????? }
??????? }
??? }
?
3。從KTHREAD.ServiceTable里面搜索
如果是GUI線程 那么就是指向ServiceDescriptorTableShadow
其實個人更加傾向這個辦法 穩定安全可靠,上面那個代碼也許會受到以后系統代碼變化影響 但是這個肯定不會
Copy code
??? GetServiceDescriptorTableShadowAddress proc uses esi edi ebx
??? local dwThreadId:DWORD
??????? xor ebx, ebx??????????????? ; = NULL. Assume ServiceDescriptorTableShadow will be not found
??????? mov eax, KeServiceDescriptorTable
??????? mov esi, [eax]
??????? ; Find KTHREAD.ServiceTable field
??????? ; For non-GUI threads this field == KeServiceDescriptorTable
??????? ; and it points to ServiceDescriptorTable
??????? ; For GUI threads
??????? ; ServiceDescriptorTableShadow
??????? invoke KeGetCurrentThread
??????? mov edi, 200h-4
??????? .while edi
??????????? .break .if dword ptr [eax][edi] == esi
??????????? dec edi
??????? .endw
??????? .if edi != 0
??????????? ; edi = offset to ServiceTable field in KTHREAD structure
??????????? mov dwThreadId, 080h
??????????? .while dwThreadId < 400h
??????????????? push eax??????????????????? ; reserve DWORD on stack
??????????????? invoke PsLookupThreadByThreadId, dwThreadId, esp
??????????????? pop ecx??????????????????????? ; -> ETHREAD/KTHREAD
??????????????? .if eax == STATUS_SUCCESS
??????????????????? push dword ptr [ecx][edi]
??????????????????? fastcall ObfDereferenceObject, ecx
??????????????????? pop eax
??????????????????? .if eax != esi
??????????????????????? mov edx, MmSystemRangeStart
??????????????????????? mov edx, [edx]
??????????????????????? mov edx, [edx]
??????????????????????? .if eax > edx??????? ; some stupid error checking
??????????????????????????? mov ebx, eax
??????????????????????????? invoke DbgPrint, $CTA0("FindShadowTable: Found in thread with ID: %X/n"), dwThreadId
??????????????????????????? .break
??????????????????????? .endif
??????????????????? .endif
??????????????? .endif
??????????????? add dwThreadId, 4
??????????? .endw
??????? .endif
??????? mov eax, ebx
??????? ret
??? GetServiceDescriptorTableShadowAddress endp
?
4.mj0011所說的搜索有效內存地址的辦法
Copy code
??? /*
??? define structure for the system service table
??? */
??? struct SYS_SERVICE_TABLE {
??? void **ServiceTable;
??? unsigned long CounterTable;
??? unsigned long ServiceLimit;
??? void **ArgumentsTable;
??? };
??? SYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow;
??? /*
??? Define KeServiceDescriptorTable based on the SST structure
??? */
??? extern struct SYS_SERVICE_TABLE *KeServiceDescriptorTable;
??? /*
??? Declare function GetServiceDescriptorShadowTableAddress()
??? */
??? //struct SYS_SERVICE_TABLE * GetServiceDescriptorShadowTableAddress ();
??? /*
??? Declare the KeAddSystemServiceTable. This is just a
??? handle to the call function, it will be used by the function
??? above to obtain the correct address of the KeServiceDescriptorShadowTable
??? */
??? __declspec(dllimport) KeAddSystemServiceTable (ULONG, ULONG, ULONG, ULONG, ULONG);
??? struct SYS_SERVICE_TABLE * GetServiceDescriptorShadowTableAddress ()
??? {
??? // First, obtain a pointer to KeAddSystemServiceTable
??? unsigned char *check = (unsigned char*)KeAddSystemServiceTable;
??? int i;
????? //Initialize an instance of System Service Table, will be used to
??? //obtain an address from KeAddSystemServiceTable
??? struct SYS_SERVICE_TABLE *rc=0;
??? // Make 100 attempts to match a valid address with that of KeServiceDescriptorTable
??? for (i=0; i<=99; i++) {
????? __try {
????? // try to obtain an address from? KeAddSystemServiceTable
????? rc = *(struct SYS_SERVICE_TABLE**)check;
????? // if this address is NOT valid OR it itself is the address of
????? //KeServiceDescriptorTable OR its first entry is NOT equal
????? //to the first entry of KeServiceDescriptorTable
????? if (!MmIsAddressValid (rc) || (rc == KeServiceDescriptorTable)
??????? || (memcmp (rc, KeServiceDescriptorTable, sizeof (*rc)) != 0)) {
??????? // Proceed with the next address
??????? check++;
??????? // don't forget to reset the old address
??????? rc = 0;
????? }
????? } __except (EXCEPTION_EXECUTE_HANDLER) { rc = 0; }
????? // when the loop is completed, check if it produced a valid address
????? if (rc)
????? // because if it didn't, we failed to find the address of KeServiceDescriptorTableShadow
????? break;
??? }
??? // otherwise, there is a valid address! So return it!
??? return rc;
??? }
?
?
二。函數名定位
這個似乎沒有多少好辦法,解析pdb可以是可以 但是很麻煩
不過還好的是 同一個版本的系統 調用號一樣
所以只需要3套 2k xp 2k3的調用號就可以完成hook
pdb辦法
SymInitialize初始化
SymSetSearchPath “srv**symbols*http://msdl.microsoft.com/”
SymLoadModule
SymGetSymFromName
老v曾經發出1個獲取shadow地址和函數名稱的工具 使用他可以很方便的獲取
具體代碼可以F5查看
以上讀取pdb的方法測試使用的可以的
但是實際使用很麻煩
經過分析 我找到了1個比較好的定位辦法
我們以SetWindowsHookExA為例子
Copy code
??? _text:77D311D1 ; HHOOK __stdcall SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId)
??? _text:77D311D1??????????????? public _SetWindowsHookExA@16
??? _text:77D311D1 _SetWindowsHookExA@16 proc near
??? _text:77D311D1
??? _text:77D311D1 idHook????????? = dword ptr? 8
??? _text:77D311D1 lpfn??????????? = dword ptr? 0Ch
??? _text:77D311D1 hModule??????? = dword ptr? 10h
??? _text:77D311D1 dwThreadId????? = dword ptr? 14h
??? _text:77D311D1
??? _text:77D311D1??????????????? mov??? edi, edi
??? _text:77D311D3??????????????? push??? ebp
??? _text:77D311D4??????????????? mov??? ebp, esp
??? _text:77D311D6??????????????? push??? 2????????????? ; int
??? _text:77D311D8??????????????? push??? [ebp+dwThreadId] ; int
??? _text:77D311DB??????????????? push??? [ebp+hModule]? ; hModule
??? _text:77D311DE??????????????? push??? [ebp+lpfn]????? ; int
??? _text:77D311E1??????????????? push??? [ebp+idHook]??? ; int
??? _text:77D311E4??????????????? call??? _SetWindowsHookExAW@20 ; SetWindowsHookExAW(x,x,x,x,x)
??? _text:77D311E9??????????????? pop??? ebp
??? _text:77D311EA??????????????? retn??? 10h
??? _text:77D311EA _SetWindowsHookExA@16 endp
??? _text:77D2DCFD ; int __stdcall SetWindowsHookExAW(int, int, HMODULE hModule, int, int)
??? _text:77D2DCFD _SetWindowsHookExAW@20 proc near??????? ; CODE XREF: SetWindowsHookExW(x,x,x,x)+13p
??? _text:77D2DCFD??????????????????????????????????????? ; SetWindowsHookExA(x,x,x,x)+13p
??? _text:77D2DCFD
??? _text:77D2DCFD Filename??????? = word ptr -20Ch
??? _text:77D2DCFD var_4????????? = dword ptr -4
??? _text:77D2DCFD arg_0????????? = dword ptr? 8
??? _text:77D2DCFD arg_4????????? = dword ptr? 0Ch
??? _text:77D2DCFD hModule??????? = dword ptr? 10h
??? _text:77D2DCFD arg_C????????? = dword ptr? 14h
??? _text:77D2DCFD arg_10????????? = dword ptr? 18h
??? _text:77D2DCFD
??? _text:77D2DCFD??????????????? mov??? edi, edi
??? _text:77D2DCFF??????????????? push??? ebp
??? _text:77D2DD00??????????????? mov??? ebp, esp
??? _text:77D2DD02??????????????? sub??? esp, 20Ch
??? _text:77D2DD08??????????????? mov??? eax, ___security_cookie
??? _text:77D2DD0D??????????????? push??? esi
??? _text:77D2DD0E??????????????? mov??? esi, [ebp+hModule]
??? _text:77D2DD11??????????????? test??? esi, esi
??? _text:77D2DD13??????????????? push??? edi
??? _text:77D2DD14??????????????? mov??? edi, [ebp+arg_4]
??? _text:77D2DD17??????????????? mov??? [ebp+var_4], eax
??? _text:77D2DD1A??????????????? jz????? short loc_77D2DD33
??? _text:77D2DD1C??????????????? push??? 104h??????????? ; nSize
??? _text:77D2DD21??????????????? lea??? eax, [ebp+Filename]
??? _text:77D2DD27??????????????? push??? eax??????????? ; lpFilename
??? _text:77D2DD28??????????????? push??? esi??????????? ; hModule
??? _text:77D2DD29??????????????? call??? ds:__imp__GetModuleFileNameW@12 ; GetModuleFileNameW(x,x,x)
??? _text:77D2DD2F??????????????? test??? eax, eax
??? _text:77D2DD31??????????????? jz????? short loc_77D2DD52
??? _text:77D2DD33
??? _text:77D2DD33 loc_77D2DD33:????????????????????????? ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+1Dj
??? _text:77D2DD33??????????????? push??? [ebp+arg_10]
??? _text:77D2DD36??????????????? mov??? eax, esi
??? _text:77D2DD38??????????????? push??? edi
??? _text:77D2DD39??????????????? push??? [ebp+arg_0]
??? _text:77D2DD3C??????????????? neg??? eax
??? _text:77D2DD3E??????????????? push??? [ebp+arg_C]
??? _text:77D2DD41??????????????? sbb??? eax, eax
??? _text:77D2DD43??????????????? lea??? ecx, [ebp+Filename]
??? _text:77D2DD49??????????????? and??? eax, ecx
??? _text:77D2DD4B??????????????? push??? eax
??? _text:77D2DD4C??????????????? push??? esi
??? _text:77D2DD4D??????????????? call??? __SetWindowsHookEx@24 ; _SetWindowsHookEx(x,x,x,x,x,x)
??? _text:77D2DD52
??? _text:77D2DD52 loc_77D2DD52:????????????????????????? ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+34j
??? _text:77D2DD52??????????????? mov??? ecx, [ebp+var_4]
??? _text:77D2DD55??????????????? pop??? edi
??? _text:77D2DD56??????????????? pop??? esi
??? _text:77D2DD57??????????????? call??? @__security_check_cookie@4 ; __security_check_cookie(x)
??? _text:77D2DD5C??????????????? leave
??? _text:77D2DD5D??????????????? retn??? 14h
??? _text:77D2DD5D _SetWindowsHookExAW@20 endp
??? _text:77D2DD5D
??? _text:77D2DD65 ; __stdcall _SetWindowsHookEx(x, x, x, x, x, x)
??? _text:77D2DD65 __SetWindowsHookEx@24 proc near??????? ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+50p
??? _text:77D2DD65
??? _text:77D2DD65 var_10????????? = byte ptr -10h
??? _text:77D2DD65 var_8????????? = dword ptr -8
??? _text:77D2DD65 var_4????????? = dword ptr -4
??? _text:77D2DD65 arg_0????????? = dword ptr? 8
??? _text:77D2DD65 arg_4????????? = dword ptr? 0Ch
??? _text:77D2DD65 arg_8????????? = dword ptr? 10h
??? _text:77D2DD65 arg_C????????? = dword ptr? 14h
??? _text:77D2DD65 arg_10????????? = dword ptr? 18h
??? _text:77D2DD65 arg_14????????? = dword ptr? 1Ch
??? _text:77D2DD65
??? _text:77D2DD65??????????????? mov??? edi, edi
??? _text:77D2DD67??????????????? push??? ebp
??? _text:77D2DD68??????????????? mov??? ebp, esp
??? _text:77D2DD6A??????????????? sub??? esp, 10h
??? _text:77D2DD6D??????????????? push??? [ebp+arg_4]
??? _text:77D2DD70??????????????? and??? [ebp+var_4], 0
??? _text:77D2DD74??????????????? lea??? eax, [ebp+var_10]
??? _text:77D2DD77??????????????? push??? eax
??? _text:77D2DD78??????????????? mov??? [ebp+var_8], eax
??? _text:77D2DD7B??????????????? call??? ds:__imp__RtlInitUnicodeString@8 ; RtlInitUnicodeString(x,x)
??? _text:77D2DD81??????????????? push??? [ebp+arg_14]
??? _text:77D2DD84??????????????? push??? [ebp+arg_10]
??? _text:77D2DD87??????????????? push??? [ebp+arg_C]
??? _text:77D2DD8A??????????????? push??? [ebp+arg_8]
??? _text:77D2DD8D??????????????? push??? [ebp+var_8]
??? _text:77D2DD90??????????????? push??? [ebp+arg_0]
??? _text:77D2DD93??????????????? call??? _NtUserSetWindowsHookEx@24 ; NtUserSetWindowsHookEx(x,x,x,x,x,x)
??? _text:77D2DD98??????????????? leave
??? _text:77D2DD99??????????????? retn??? 18h
??? _text:77D2DD99 __SetWindowsHookEx@24 endp
??? _text:77D2DD99
??? _text:77D2DDA1 ; __stdcall NtUserSetWindowsHookEx(x, x, x, x, x, x)
??? _text:77D2DDA1 _NtUserSetWindowsHookEx@24 proc near??? ; CODE XREF: _SetWindowsHookEx(x,x,x,x,x,x)+2Ep
??? _text:77D2DDA1??????????????? mov??? eax, 1225h
??? _text:77D2DDA6??????????????? mov??? edx, 7FFE0300h
??? _text:77D2DDAB??????????????? call??? dword ptr [edx]
??? _text:77D2DDAD??????????????? retn??? 18h
??? _text:77D2DDAD _NtUserSetWindowsHookEx@24 endp
?
我們看這里 _text:77D2DDA1??????????????? mov??? eax, 1225h
里面有和ssdt一樣的調用號 但是有個問題 NtUserSetWindowsHookEx在user32里面沒有導出,我們需要多次搜索才行
Copy code
??? HHOOK STDCALL??? NtUserSetWindowsHookEx (HINSTANCE Mod, PUNICODE_STRING UnsafeModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi)
這個就是原型 不過搜索起來確實是比較麻煩的,不知道還有無其他好辦法了
三。如何hook
似乎這個問題并不大,shadow ssdt和ssdt本質上都是1個地址表,最為簡單的方法是把你的函數替換地址表的對應項,具體hook代碼甚至可以完全照抄ssdt的,這里只說1下幾個偶遇到的小問題
1。win32k.sys不是常在內存的,如果不是GUI線程,shadow ssdt地址無效
解決辦法:
1。在driverdispatch中hokk
driverdispatch是位于執行driveriocontrol的線程上下文的
我們使用1個GUI線程去driveriocontrol
2。attachtoprocess
通常 我們使用cerss.exe
Copy code
??? HANDLE GetCsrPid()
??? {
??????? HANDLE??????????????????????? Process, hObject;
??????? HANDLE??????????????????????? CsrId = (HANDLE)0;
??????? OBJECT_ATTRIBUTES??????????? obj;
??????? CLIENT_ID??????????????????? cid;
??????? UCHAR??????????????????????? Buff[0x100];
??????? POBJECT_NAME_INFORMATION????? ObjName = (PVOID)&Buff;
??????? PSYSTEM_HANDLE_INFORMATION_EX Handles;
??????? ULONG??????????????????????? r;
??????? Handles = GetInfoTable(SystemHandleInformation);
??????? if (!Handles) return CsrId;
??????? for (r = 0; r < Handles->NumberOfHandles; r++)
??????? {
??????????? if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
??????????? {
??????????????? InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
????????????
??????????????? cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
??????????????? cid.UniqueThread? = 0;
??????????????? if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
??????????????? {
??????????????????? if (NT_SUCCESS(ZwDuplicateObject(Process,
??????????????????????????????????????????????????? (HANDLE)Handles->Information[r].Handle,
??????????????????????????????????????????????????? NtCurrentProcess(),
??????????????????????????????????????????????????? &hObject,
????????????????????????????????????????????????????? 0, 0, DUPLICATE_SAME_ACCESS)))
??????????????????? {
??????????????????????? if (NT_SUCCESS(ZwQueryObject(hObject,
??????????????????????????????????????????????????? ObjectNameInformation,
??????????????????????????????????????????????????????? ObjName,
??????????????????????????????????????????????????? 0x100, NULL)))
??????????????????????? {
??????????????????????????? if (ObjName->Name.Buffer &&
??????????????????????????????? !wcsncmp(L"//Windows//ApiPort", ObjName->Name.Buffer, 20))
??????????????????????????? {
??????????????????????????????? CsrId = (HANDLE)Handles->Information[r].ProcessId;
??????????????????????????? }
??????????????????????? }
??????????????????????? ZwClose(hObject);
??????????????????? }
??????????????????? ZwClose(Process);
??????????????? }
??????????? }
??????? }
??????? ExFreePool(Handles);
??????? return CsrId;
??? }
?
然后我們KeAttachProcess
Copy code
????? ntStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);
??????????? if (!NT_SUCCESS( ntStatus ))
????? {
????? DbgPrint("PsLookupProcessByProcessId()/n");
????????????????? return ntStatus;
????? }
??????????? KeAttachProcess(EProcess);
?
3.使用MDL映射一塊不分頁內存,設置成可以寫入
不分頁內存? ExAllocatePool(NonPagedPool
即為不會被切換到pagefile的內存,是常駐在物理內存的,比較希缺,使用完畢以后記住釋放掉
參考regmon的代碼
Copy code
??? PVOID *
??? RegmonMapServiceTable(
????? SERVICE_HOOK_DESCRIPTOR **ServiceIsHooked
????? )
??? {
????? *ServiceIsHooked = (SERVICE_HOOK_DESCRIPTOR*)
????????????????? ExAllocatePool(NonPagedPool, KeServiceDescriptorTable->TableSize);
????? if( *ServiceIsHooked )
????? {
??????? RtlZeroMemory(*ServiceIsHooked, KeServiceDescriptorTable->TableSize);
??????? KeServiceTableMdl = MmCreateMdl(0, KeServiceDescriptorTable->ServiceTable, KeServiceDescriptorTable->TableSize << 2);
??????? if( KeServiceTableMdl )
??????? {
??????????? MmBuildMdlForNonPagedPool(KeServiceTableMdl);
??????????? KeServiceTableMdl->MdlFlags |= 1;
??????????? return (PVOID*)MmMapLockedPages(KeServiceTableMdl, KernelMode);
??????? }
????? }
????? return NULL;
??? };
?
看起來shadowssdt何hook本身并沒有什么難度
只要正確定位了地址,hook起來和ssdt完全一樣
unhook不在重復 完全抄ssdt的代碼即可
四。checkhook
hook用的人多了 難免出現重復hook的情況 為了實現和別人的東西和平共處,最好hook之前做個檢測
hook的方法是固定的,就那么2種 改地址表 或者inline hook,我們分別來對待
1。修改地址表的hook
? 這個對付起來幾乎不用特別對待,只是你保存的OldFunc是其他的程序hook函數所在的地址,判斷方法很簡單,看看這個地址在不在win32k的模塊里面,和平共處的辦法是你的myfunc里面call別人的hook函數,當然 如果你不想要別人的hook了,直接搜索到原始地址call之也是可行的
另外說1下 在別人的函數里面搜索原始地址 用MmIsAddressValid+ismodulewin32k
可以判斷(這個辦法好像是在mj文章里面看到的 記不清了)
2。inlinehook
這個比較麻煩了 如果是修改前面5個字節還好,直接替換處理都可以不改變
麻煩是函數中間地方被hook,盲目修改可能直接BSOD了,這個需要1個反匯編引擎來幫助分析代碼字節長度,海風大大的hooklib很不錯 可以完成這個功能
五,簡單說1下restore
Copy code
??? pWin32k = GetModuleHandle("win32k.sys");
??? SdtRVA = &KeServiceDescriptorTable->win32k.ServiceTable - pWin32k ;
??? w32kCopy = LoadPeFile("win32k.sys");
??? ProcessRelocs(w32kCopy, pWin32k);
??? memcpy(&KeServiceDescriptorTable->win32k.ServiceTable, w32kCopy + SdtRVA, SdtSize);
不過 其實可以不用ProcessRelocs處理
因為你可以使用lordpe查看1下 win32k.sys的默認基址就是系統加載的基址
可以不需要ProcessRelocs,不過為了更加方便和通用,這么做也可以的
?
總結
以上是生活随笔為你收集整理的shadow ssdt学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 荒废的周末
- 下一篇: LeetCode C语言刷题——day1