Windows系统调用学习笔记(四)—— 系统服务表SSDT
生活随笔
收集整理的這篇文章主要介紹了
Windows系统调用学习笔记(四)—— 系统服务表SSDT
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Windows系統(tǒng)調(diào)用學習筆記(四)—— 系統(tǒng)服務表&SSDT
- 要點回顧
- 系統(tǒng)服務表
- 實驗:分析 KiSystemService 與 KiFastCallEntry 共同代碼
- SSDT
- 實驗:在SSDT中查找內(nèi)核函數(shù)信息
- 第一步:查看函數(shù)地址
- 第二步:查看參數(shù)個數(shù)
- 第三步:查看內(nèi)核函數(shù)反匯編
- 練習
要點回顧
API進入0環(huán)后調(diào)用的函數(shù):
上一篇留了幾個練習:
本篇將對第二個和第三個練習進行說明
系統(tǒng)服務表
描述:
結(jié)構(gòu)體:
typedef struct _SERVICE_DESCRIPTOR_TABLE {PULONG ServiceTableBase; // 指針,指向函數(shù)地址,每個成員占4字節(jié)PULONG ServiceCounterTableBase; // 當前系統(tǒng)服務表被調(diào)用的次數(shù)ULONG NumberOfService; // 服務函數(shù)的總數(shù)PUCHAR ParamTableBase; // 服務函數(shù)的參數(shù)總長度,以字節(jié)為單位,每個成員占一個字節(jié)// 如:服務函數(shù)有兩個參數(shù),每個參數(shù)占四字節(jié),那么對應參數(shù)總長度為8// 函數(shù)地址成員 與 參數(shù)總長度成員 一一對應 } SSDTEntry, *PSSDTEntry;結(jié)構(gòu)圖:
實驗:分析 KiSystemService 與 KiFastCallEntry 共同代碼
IDA反匯編:
.text:00406932 loc_406932: ; CODE XREF: _KiBBTUnexpectedRange+18↑j .text:00406932 ; _KiSystemService+71↑j .text:00406932 mov edi, eax ; 從 eax 寄存器中取出3環(huán)傳進來的系統(tǒng)調(diào)用號 .text:00406934 shr edi, 8 ; 系統(tǒng)調(diào)用號右移8位 .text:00406937 and edi, 30h ; 右移后的值和0x30進行與運算; 目的是檢測第12位是否為1; WindowsNT基本的(Native)系統(tǒng)調(diào)用有兩百多個,編號都小于0x1000; 編號大于0x1000的系統(tǒng)調(diào)用號是微軟擴展出來的; 這些擴展出的系統(tǒng)調(diào)用位于動態(tài)安裝的模塊中,即win32k.sys; 若第12位為0x00,則將低12位作為下標在 ntoskrl.exe 中尋找對應的系統(tǒng)調(diào)用; 若第12位為0x10,則將低12位作為下標在 win32k.sys 中尋找對應的系統(tǒng)調(diào)用 .text:0040693A mov ecx, edi ; 將運算結(jié)果賦值給 ecx .text:0040693C add edi, [esi+0E0h] ; 將系統(tǒng)服務表的指針賦值給 edi; nt!_KTHREAD; +0x0e0 ServiceTable : Ptr32 Void; 這里將系統(tǒng)服務表所在地址直接加上edi的運算結(jié)果; 巧妙地得到要查哪張表(兩張表是連續(xù)的),每張表占16字節(jié) .text:00406942 mov ebx, eax ; 將系統(tǒng)調(diào)用號賦值給 ebx .text:00406944 and eax, 0FFFh ; 將系統(tǒng)調(diào)用號與 0xFFF進行與運算; 目的是保留低12位,作為函數(shù)地址的下標 .text:00406949 cmp eax, [edi+8] ; typedef struct _SYSTEM_SERVICE_TABLE; {; PVOID ServiceTableBase; //這個指向系統(tǒng)服務函數(shù)地址表; PULONG ServiceCounterTableBase;; ULONG NumberOfService; //服務函數(shù)總數(shù); ULONG ParamTableBase; //參數(shù)總長度; }SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;;; +8 是服務函數(shù)的個數(shù) .text:0040694C jnb _KiBBTUnexpectedRange ; 若大于系統(tǒng)調(diào)用號的個數(shù)則跳轉(zhuǎn),即系統(tǒng)調(diào)用號越界 .text:00406952 cmp ecx, 10h ; 將 ecx 與0x10進行比較; ecx 保存的是 edi 與0x30與運算后的結(jié)果,只能是0x00貨0x10 .text:00406955 jnz short loc_406972 ; 若系統(tǒng)調(diào)用號小于0x1000,則跳轉(zhuǎn) .text:00406957 mov ecx, large fs:18h ; 只有當ecx == 0x10才會向下執(zhí)行; 作用是動態(tài)加載GUI等圖形相關函數(shù) .text:0040695E xor ebx, ebx .text:00406960 .text:00406960 loc_406960: .text:00406960 or ebx, [ecx+0F70h] .text:00406966 jz short loc_406972 .text:00406968 push edx .text:00406969 push eax .text:0040696A call ds:_KeGdiFlushUserBatch .text:00406970 pop eax .text:00406971 pop edx .text:00406972 .text:00406972 loc_406972: ; CODE XREF: _KiFastCallEntry+B6↑j .text:00406972 ; KiSystemServiceAccessTeb()+6↑j .text:00406972 inc large dword ptr fs:638h ; _KPRCB -> +0x518 KeSystemCalls 增加1 .text:00406979 mov esi, edx ; edx保存的是3環(huán)參數(shù)的指針 .text:0040697B mov ebx, [edi+0Ch] ; edi指向要使用的系統(tǒng)服務表; +0Ch是ParamTableBase(參數(shù)表指針) .text:0040697E xor ecx, ecx ;ecx清零 .text:00406980 mov cl, [eax+ebx] ; eax保存的是3環(huán)傳入的系統(tǒng)調(diào)用號; ebx保存的是是參數(shù)表指針; 這條指令的目的是得到內(nèi)核函數(shù)的參數(shù)總長度,存入cl .text:00406983 mov edi, [edi] ; 取出系統(tǒng)調(diào)用表的第一個成員(函數(shù)地址指針) .text:00406985 mov ebx, [edi+eax*4] ; 函數(shù)地址指針 + 系統(tǒng)調(diào)用號*4(乘4是因為每個成員占4字節(jié)); 目的是找到函數(shù)地址,存入ebx .text:00406988 sub esp, ecx ; 提升堆棧,大小為參數(shù)總長度 .text:0040698A shr ecx, 2 ; 參數(shù)總長度/4 = 參數(shù)個數(shù) .text:0040698D mov edi, esp ; 設置要COPY的目的地 .text:0040698F test byte ptr [ebp+72h], 2 .text:00406993 jnz short loc_40699B .text:00406995 test byte ptr [ebp+6Ch], 1 .text:00406999 jz loc_4069A7 .text:0040699B .text:0040699B loc_40699B: ; CODE XREF: KiSystemServiceAccessTeb()+33↑j .text:0040699B cmp esi, ds:_MmUserProbeAddress ; 全局變量存儲用戶能訪問的最大范圍; 這條指令的作用是判斷3環(huán)參數(shù)是否越界 .text:004069A1 jnb loc_406B4F ; 越界則跳轉(zhuǎn)至異常處理 .text:004069A7 .text:004069A7 loc_4069A7: .text:004069A7 rep movsd ; 將3環(huán)參數(shù)復制到0環(huán)堆棧 .text:004069A9 call ebx ; 調(diào)用函數(shù)SSDT
描述:
在WinDbg中查看已導出成員:
kd>dd KeServiceDescriptorTable
在WinDbg中查看未導出成員:
實驗:在SSDT中查找內(nèi)核函數(shù)信息
實驗說明
第一步:查看函數(shù)地址
函數(shù)地址表:
[函數(shù)地址表 + 系統(tǒng)服務號*4] = 內(nèi)核函數(shù)地址
第二步:查看參數(shù)個數(shù)
參數(shù)表:
[參數(shù)表 + 系統(tǒng)服務號] = 內(nèi)核函數(shù)參數(shù)個數(shù)(單位:字節(jié))
第三步:查看內(nèi)核函數(shù)反匯編
練習
要求:在SSDT表中追加一個函數(shù)地址(NtReadVirtualMemory),自己編寫API的3環(huán)部分調(diào)用這個新增的函數(shù)(注意:使用2-9-9-12分頁)。
答案:略(待補充)
總結(jié)
以上是生活随笔為你收集整理的Windows系统调用学习笔记(四)—— 系统服务表SSDT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows系统调用学习笔记(三)——
- 下一篇: Windows进程与线程学习笔记(一)—