(49)逆向分析KiSystemService/KiFastCallEntry调用内核函数部分(SST,SSDT,SSPT)
一、回顧
前兩篇博客,我逆向分析了 KiSystemService 和 KiFastCallEntry 填充_KTRAP_FRAME 結(jié)構(gòu)體的代碼,二者大同小異,主要的區(qū)別是 sysenter 只改了eip,cs,ss,雖然esp也改了,但是windows不使用,而是從TSS里取esp0;另外sysenter并沒有像中斷門那樣壓棧,所以3環(huán)的 ss, esp, eflags, cs,eip都要在函數(shù)里依次保存到 _KTRAP_FRAME 。
這次課后作業(yè)是逆向 KiSystemService / KiFastCallEntry 調(diào)用內(nèi)核函數(shù)部分,放在一塊講是因?yàn)檫@兩個(gè)函數(shù)雖然入口不同,但是填充完 _KTRAP_FRAME 后,就會(huì)執(zhí)行相同的代碼。他們兩個(gè)函數(shù)就像兩頭蛇一樣,有兩個(gè)入口,初始化的工作有區(qū)別,但是往后就共用一個(gè)函數(shù)體。
在逆向之前,先介紹所需的前置知識。同時(shí),思考兩個(gè)問題:
- 如何根據(jù)系統(tǒng)服務(wù)號(eax中存儲(chǔ))找到要執(zhí)行的內(nèi)核函數(shù)?
- 調(diào)用時(shí)參數(shù)是存儲(chǔ)到3環(huán)的堆棧,如何傳遞給內(nèi)核函數(shù)?
二、SystemServiceTable 系統(tǒng)服務(wù)表SST
SST:系統(tǒng)服務(wù)表
SSDT:系統(tǒng)服務(wù)調(diào)度表
SSPT:系統(tǒng)服務(wù)參數(shù)表
關(guān)系:
首先強(qiáng)調(diào),SystemServiceTable 系統(tǒng)服務(wù)表不是SSDT。
看示意圖:
通過此圖,我們可以得知以下信息:
- 通過 _KTHREAD 可以找到系統(tǒng)服務(wù)表
- 系統(tǒng)服務(wù)表又指向了函數(shù)地址表和函數(shù)參數(shù)表
- 有兩張系統(tǒng)服務(wù)表,第一張是用來找內(nèi)核函數(shù)的,第二張是找Win32k.sys驅(qū)動(dòng)函數(shù)的。
通過逆向,我們還可以判定,其實(shí)兩張系統(tǒng)服務(wù)表是線性地址連續(xù)的,每張16字節(jié)。
說明一下表的4個(gè)屬性:
ServiceTable 指向函數(shù)地址表,Count沒有用,ArgmentTable 指向函數(shù)參數(shù)表,ServiceLimit 是這兩張表的長度。
要注意函數(shù)參數(shù)表每項(xiàng)存儲(chǔ)的是對應(yīng)函數(shù)參數(shù)占的字節(jié)數(shù),每項(xiàng)只有1字節(jié)。 這個(gè)在逆向中也可以驗(yàn)證。
最后補(bǔ)充一點(diǎn),我們之前逆向API三環(huán)部分時(shí),它進(jìn)0環(huán)之前,無論是中斷門還是快速調(diào)用,都會(huì)在 eax 里存一個(gè)值,我們稱之為系統(tǒng)調(diào)用號或者服務(wù)號,這個(gè)東西的低12位就是函數(shù)參數(shù)表和函數(shù)地址表的下標(biāo),而第13位(下標(biāo)12)如果是0,表示找第一張系統(tǒng)服務(wù)表(綠色的表),如果是1,那么找第二張表(黃色的表)。這點(diǎn)可以先記住,待會(huì)逆向的時(shí)候可以印證這個(gè)結(jié)論。
三、逆向分析 KiSystemService / KiFastCallEntry 調(diào)用內(nèi)核函數(shù)部分
從Kernel32.dll中的某個(gè)函數(shù)開始分析其執(zhí)行流程(怎么找到對應(yīng)的內(nèi)核函數(shù) 怎么找到參數(shù) 如何將參數(shù)傳遞到0環(huán))
這是作業(yè)要求,我這里就只貼了0環(huán)逆向部分,至于3環(huán)那些,我在之前的博客已經(jīng)詳細(xì)分析了,有需要可以查看前面的博客。
直接貼結(jié)果了,比較簡單,看注釋就能看懂了。
.text:004665CD loc_4665CD: ; CODE XREF: _KiBBTUnexpectedRange+18j .text:004665CD ; _KiSystemService+6Fj .text:004665CD mov edi, eax ; 這里是 KiSystemService 和 KiFastCallEntry 的匯合處 .text:004665CD ; edi = eax = 系統(tǒng)調(diào)用號 .text:004665CF shr edi, 8 .text:004665D2 and edi, 30h ; 檢測系統(tǒng)調(diào)用號12位 .text:004665D2 ; 如果等于1,那么 edi == 0x10 .text:004665D2 ; 如果等于0,那么 edi == 0x00 .text:004665D5 mov ecx, edi .text:004665D7 add edi, [esi+0E0h] ; edi += CurrentThread.ServiceTable .text:004665D7 ; 此時(shí) edi 指向了API對應(yīng)的系統(tǒng)服務(wù)表 .text:004665D7 ; .text:004665D7 ; 他這個(gè)設(shè)計(jì) 0x10 剛好是系統(tǒng)服務(wù)表的大小 .text:004665D7 ; 系統(tǒng)服務(wù)表有 ServiceTable, Count, ServiceLimit 和 ArgmentTable .text:004665D7 ; 4項(xiàng)共0x10字節(jié),所以通過這里的代碼也可以推斷,內(nèi)核和win32k.sys的系統(tǒng)服務(wù)表是連續(xù)的 .text:004665D7 ; 第一張是內(nèi)核的,第二張是win32k.sys的 .text:004665DD mov ebx, eax ; ebx = 系統(tǒng)調(diào)用號 .text:004665DF and eax, 0FFFh ; eax = 系統(tǒng)服務(wù)表下標(biāo) .text:004665E4 cmp eax, [edi+8] .text:004665E7 jnb _KiBBTUnexpectedRange ; 檢查系統(tǒng)調(diào)用號是否超過系統(tǒng)服務(wù)表的范圍,超過就跳到異常處理 .text:004665ED cmp ecx, 10h .text:004665F0 jnz short loc_46660C ; 跳轉(zhuǎn)條件:系統(tǒng)服務(wù)(ntdll.dll 的API) .text:004665F0 ; 不跳轉(zhuǎn)條件:圖形及用戶界面(gdi.dll 的API) .text:004665F2 mov ecx, ds:0FFDFF018h ; ecx 指向 _KPCR .text:004665F8 xor ebx, ebx .text:004665FA .text:004665FA loc_4665FA: ; DATA XREF: _KiTrap0E+113o .text:004665FA or ebx, [ecx+0F70h] .text:00466600 jz short loc_46660C .text:00466602 push edx .text:00466603 push eax .text:00466604 call ds:_KeGdiFlushUserBatch .text:0046660A pop eax .text:0046660B pop edx .text:0046660C .text:0046660C loc_46660C: ; CODE XREF: _KiSystemService+16Fj .text:0046660C ; _KiSystemService+17Fj .text:0046660C inc dword ptr ds:0FFDFF638h ; _KCPR.KPRCB.KeSystemCalls += 1, 系統(tǒng)調(diào)用計(jì)數(shù)加1 .text:00466612 mov esi, edx ; esi = edx = 3環(huán)參數(shù)指針 .text:00466614 mov ebx, [edi+0Ch] ; edi 指向系統(tǒng)服務(wù)表 .text:00466614 ; ebx 指向函數(shù)參數(shù)表 .text:00466614 ; eax 是系統(tǒng)服務(wù)表下標(biāo) .text:00466617 xor ecx, ecx .text:00466619 mov cl, [eax+ebx] ; cl = 參數(shù)字節(jié)數(shù) .text:0046661C mov edi, [edi] ; edi 指向函數(shù)地址表 .text:0046661E mov ebx, [edi+eax*4] ; ebx 指向函數(shù) .text:00466621 sub esp, ecx ; 從這句開始,到call為止,完成了復(fù)制3環(huán)參數(shù)的工作 .text:00466621 ; 這句是模擬壓棧操作 .text:00466623 shr ecx, 2 ; 參數(shù)字節(jié)數(shù) / 4,得到參數(shù)個(gè)數(shù) .text:00466626 mov edi, esp .text:00466628 cmp esi, ds:_MmUserProbeAddress ; 越界檢查 .text:00466628 ; 如果 esi(3環(huán)參數(shù)指針)大于等于 0x7fff0000,則返回 c0000005 異常 .text:0046662E jnb loc_4667DC .text:00466634 .text:00466634 loc_466634: ; CODE XREF: _KiSystemService+35Fj .text:00466634 ; DATA XREF: _KiTrap0E+109o .text:00466634 rep movsd ; 復(fù)制參數(shù):復(fù)制 esi 到 edi,每次復(fù)制4字節(jié),次數(shù)由 ecx 決定 .text:00466634 ; 方向由DF決定,DF=0,故每次復(fù)制后,edi 和 esi 都加4 .text:00466636 call ebx ; 調(diào)用內(nèi)核函數(shù)至此,系統(tǒng)調(diào)用過程,除了0環(huán)返回3環(huán)(涉及APC知識),我們都已經(jīng)分析完成了。
總結(jié)
以上是生活随笔為你收集整理的(49)逆向分析KiSystemService/KiFastCallEntry调用内核函数部分(SST,SSDT,SSPT)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (48)逆向分析 KiFastCallE
- 下一篇: (50)补充内容:SSDT HOOK 模