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