日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows系统调用学习笔记(三)—— 保存现场

發(fā)布時(shí)間:2025/3/21 windows 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows系统调用学习笔记(三)—— 保存现场 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Windows系統(tǒng)調(diào)用學(xué)習(xí)筆記(三)—— 保存現(xiàn)場

    • 要點(diǎn)回顧
    • 基本概念
      • Trap Frame 結(jié)構(gòu)
      • 線程相關(guān)的結(jié)構(gòu)體
        • ETHREAD
        • KTHREAD
      • CPU相關(guān)的結(jié)構(gòu)體
        • KPCR
        • _NT_TIB
        • KPRCB
    • 實(shí)驗(yàn)一:分析 KiSystemService
    • 實(shí)驗(yàn)二:分析 KiFastCallEntry
      • 總結(jié)

要點(diǎn)回顧

API進(jìn)入0環(huán)后調(diào)用的函數(shù):

  • 中斷門 – KiSystemService
  • 快速調(diào)用 – KiFastCallEntry
  • 上一篇留了幾個(gè)練習(xí):

  • 進(jìn)0環(huán)后,原來的寄存器存在哪里?
  • 如何根據(jù)系統(tǒng)服務(wù)號(eax中存儲(chǔ))找到要執(zhí)行的內(nèi)核函數(shù)?
  • 調(diào)用時(shí)參數(shù)是存儲(chǔ)到3環(huán)的堆棧,如何傳遞給內(nèi)核函數(shù)?
  • 2種調(diào)用方式是如何返回到3環(huán)的?
  • 本篇將對第一個(gè)練習(xí)進(jìn)行說明

    基本概念

    Trap Frame 結(jié)構(gòu)

    描述

  • 無論是通過中斷門進(jìn)入0環(huán),還是通過快速調(diào)用進(jìn)入0環(huán),進(jìn)入0環(huán)前(3環(huán))的所有寄存器都會(huì)存到這個(gè)結(jié)構(gòu)體中
  • 這個(gè)結(jié)構(gòu)體本身處于0環(huán),由windows操作系統(tǒng)進(jìn)行維護(hù)
  • 當(dāng)程序通過中斷門從3環(huán)進(jìn)入0環(huán)時(shí),ESP指向TrapFrame+0x64的位置
  • 當(dāng)程序通過快速調(diào)用從3環(huán)進(jìn)入0環(huán)時(shí),ESP指向TrapFrame+0x78的位置
  • 結(jié)構(gòu)體

    在WinDbg中查看:

    kd> dt _Ktrap_frame

    注意
    5. 在保護(hù)模式下,最后四個(gè)成員(0x7C~0x88)并沒有被使用,因此無需考慮;只有在虛擬8086模式下,才會(huì)用到
    6. 當(dāng)中斷門執(zhí)行時(shí),3環(huán)的SS、ESP、EFLAGS、CS、EIP會(huì)被存儲(chǔ)到結(jié)構(gòu)體的0x68~0x78中,而執(zhí)行快速調(diào)用時(shí)不會(huì)

    線程相關(guān)的結(jié)構(gòu)體

    ETHREAD

    結(jié)構(gòu)體

    KTHREAD

    結(jié)構(gòu)體

    kd> dt _KTHREAD

    CPU相關(guān)的結(jié)構(gòu)體

    KPCR

    描述

  • 全稱為CPU控制區(qū)(Processor Control Region)
  • 每一個(gè)CPU都有一個(gè)CPU控制區(qū),一核一個(gè)KPCR
  • 結(jié)構(gòu)體

    查看CPU數(shù)量:

    kd>dd KeNumBerProcessors

    查看KPCR:

    kd>dd KiProcessorBlock L2
    ffdff120 00000000
    若第二個(gè)成員有值,說明當(dāng)前CPU有兩個(gè)核

    _NT_TIB

    描述
    _NT_TIB是KPCR結(jié)構(gòu)體的成員之一

    結(jié)構(gòu)體

    KPRCB

    描述
    KPRCB是KPCR結(jié)構(gòu)體的成員之一

    結(jié)構(gòu)體

    kd> dt _KPRCB

    實(shí)驗(yàn)一:分析 KiSystemService

    注意:當(dāng)進(jìn)入KiSystemService時(shí),3環(huán)的SS、ESP、EFLAGS、CS、EIP就已經(jīng)被存儲(chǔ)到 Trap Frame 結(jié)構(gòu)體中

    IDA反匯編

    .text:004067D1 push 0 ; nt!_KTRAP_FRAME; +0x064 ErrCode : Uint4B; 中斷門產(chǎn)生權(quán)限切換時(shí)一般往堆棧中壓入5個(gè)值,但有些情況會(huì)壓入6個(gè)值,第六個(gè)值為Error Code; 具體細(xì)節(jié)可以參考Intel白皮書第三卷,章節(jié)名:Input and Exception Handling; 其中有一小節(jié)叫做 Error Code;; 當(dāng)通過 INT 2E 進(jìn)入0環(huán)時(shí),并沒有壓入Error Code; 操作系統(tǒng)為了對齊,自己補(bǔ)了個(gè)0 .text:004067D3 push ebp ; nt!_KTRAP_FRAME; +0x060 Ebp : Uint4B .text:004067D4 push ebx ; +0x05c Ebx : Uint4B .text:004067D5 push esi ; +0x058 Esi : Uint4B .text:004067D6 push edi ; +0x054 Edi : Uint4B .text:004067D7 push fs ; +0x050 SegFs : Uint4B .text:004067D9 mov ebx, 30h ; 為FS寄存器賦值,指向KPCR結(jié)構(gòu)體 .text:004067DE mov fs, ebx ; 加載下標(biāo)為6的段描述符到fs

    在WinDbg中查看GDT表中下標(biāo)為6的段描述符:

    段描述符:ffc093df`f0000001
    fs.Base:0xffdff000(KPCR

    .text:004067E0 push large dword ptr fs:0 ; 保存老的ExceptionList(異常列表); nt!_KPCR; +0x000 NtTib : _NT_TIB; nt!_NT_TIB; +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD;; nt!_KTRAP_FRAME; +0x04c ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD .text:004067E7 mov large dword ptr fs:0, 0FFFFFFFFh ; 新的ExceptionList為空白 .text:004067F2 mov esi, large fs:124h ; 得到當(dāng)前正在執(zhí)行的線程信息; nt!_KPCR; +0x120 +0x4 CurrentThread : Ptr32 _KTHREAD; 存儲(chǔ)了當(dāng)前正在跑的線程的信息,為 KTHREAD 結(jié)構(gòu)體

    在WinDbg中查看 KPCR + 0x120 + 0x4

    .text:004067F9 push dword ptr [esi+140h] ; 保存老的"先前模式"到堆棧; nt!_KTHREAD; +0x140 PreviousMode : Char .text:004067FF sub esp, 48h ; 執(zhí)行前,ESP位于_KTRAP_FRAME + 0x48 = PreviousPreviousMode; 執(zhí)行后,ESP 等于 _KTRAP_FRAME 結(jié)構(gòu)指針 .text:00406802 mov ebx, [esp+68h+arg_0] ; arg_0 = 4; 取出三環(huán)壓入的參數(shù)CS(_KTRAP_FRAME + 0x6C) .text:00406806 and ebx, 1 ; 權(quán)限檢查:0環(huán)最低位為0,3環(huán)最低位為1 .text:00406809 mov [esi+140h], bl ; 新的"先前模式"; 將權(quán)限檢查的結(jié)果存儲(chǔ)到 PreviousMode 中; 目的是檢測調(diào)用該代碼前,程序處于幾環(huán) .text:0040680F mov ebp, esp ; ebp = esp = _KTRAP_FRAME 結(jié)構(gòu)指針 .text:00406811 mov ebx, [esi+134h] ; _KTHREAD 的成員 TrapFrame .text:00406817 mov [ebp+3Ch], ebx ; 將 _KTHREAD 中的 TrapFrame 暫時(shí)存放在這個(gè)位置; 之后會(huì)將這個(gè)值重新取出來,賦值給 _KTHREAD 的 TrapFrame .text:0040681A mov [esi+134h], ebp ; 將堆棧中形成的 _KTRAP_FRAME 結(jié)構(gòu)指針賦值給 _KTHREAD 的 TrapFrame .text:00406820 cld .text:00406821 mov ebx, [ebp+60h] ; 將原來3環(huán)的ebp賦值給ebx .text:00406824 mov edi, [ebp+68h] ; 將原來3環(huán)的eip賦值給edi .text:00406827 mov [ebp+0Ch], edx ; edx存儲(chǔ)的是3環(huán)參數(shù)的指針:;; _KiFasSystemCall函數(shù):; mov edx, esp; sysenter; .text:0040682A mov dword ptr [ebp+8], 0BADB0D00h ; 給操作系統(tǒng)用的標(biāo)志 .text:00406831 mov [ebp+0], ebx ; 原來3環(huán)的ebp存儲(chǔ)到 _KTRAP_FRAME; + 0x000 DbgEbp 的位置 .text:00406834 mov [ebp+4], edi ; 原來3環(huán)的eip存儲(chǔ)到 _KTRAP_FRAME; + 0x004 DbgEbp 的位置 .text:00406837 test byte ptr [esi+2Ch], 0FFh ; 判斷 _KTHREAD + 0x02c DebugActive 是否為 -1; 若為 -1, 即當(dāng)前線程 未 處于調(diào)試狀態(tài) .text:0040683B jnz Dr_kss_a ; 若處于調(diào)試狀態(tài),則跳轉(zhuǎn); 功能是對TrapFrame的Dr0~Dr7進(jìn)行賦值; 也就是TrapFrame+0x18 ~ TrapFrame+0x2c的位置進(jìn)行賦值; 若未處于調(diào)試狀態(tài),則繼續(xù)向下執(zhí)行(loc_406841)

    在WinDbg中查看KTHREAD + 0x02c

    .text:00406841 sti ; 關(guān)閉中斷 .text:00406842 jmp loc_406932 ; KiSystemService 與 KiFastCallEntry 函數(shù)的共同代碼片段; 下篇學(xué)習(xí)系統(tǒng)服務(wù)表時(shí)再進(jìn)行分析

    實(shí)驗(yàn)二:分析 KiFastCallEntry

    IDA反匯編

    .text:0040689F mov ecx, 23h ; ECX = 0x23 .text:004068A4 push 30h ; 通過堆棧的入棧和出棧加載fs .text:004068A6 pop fs ; 加載fs段寄存器:GDT表下標(biāo)為6的段描述符

    在WinDbg中查看GDT表下標(biāo)為6的段描述符:

    段描述符:ffc093df`f0000001
    fs.Base:0xffdff000(KPCR

    .text:004068A8 mov ds, ecx ; RPL=3;TI=0;INDEX=4; 加載GDT表下標(biāo)為4的段描述符給ds .text:004068AA mov es, ecx ; 加載GDT表下標(biāo)為4的段描述符給es

    在WinDbg中查看GDT表下標(biāo)為4的段描述符:

    .text:004068AC mov ecx, large fs:40h ; ECX = TSS指針; nt!_KPCR; +0x040 TSS : Ptr32 _KTSS .text:004068B3 mov esp, [ecx+4] ; nt!_KTSS; +0x004 Esp0 : Uint4B .text:004068B6 push 23h ; nt!_KTRAP_FRAME; +0x078 HardwareSegSs : Uint4B .text:004068B8 push edx ; edx保存的是3環(huán)參數(shù)的指針; nt!_KTRAP_FRAME; +0x074 HardwareEsp : Uint4B .text:004068B9 pushf ; 舊的標(biāo)志寄存器入棧 .text:004068BA .text:004068BA loc_4068BA: ; CODE XREF: _KiFastCallEntry2+23↑j .text:004068BA push 2 ; 新的標(biāo)志寄存器的值入棧 .text:004068BC add edx, 8 .text:004068BF popf ; 新的標(biāo)志寄存器的值出棧 ; EFlags = 2,即第二位置1,其它位清零 .text:004068C0 or [esp+0Ch+var_B], 2 .text:004068C5 push 1Bh ; nt!_KTRAP_FRAME; +0x06c SegCs : Uint4B .text:004068C7 push dword ptr ds:0FFDF0304h ; +0x068 Eip : Uint4B .text:004068CD push 0 ; +0x064 ErrCode : Uint4B .text:004068CF push ebp ; +0x060 Ebp : Uint4B .text:004068D0 push ebx ; +0x05c Ebx : Uint4B .text:004068D1 push esi ; +0x058 Esi : Uint4B .text:004068D2 push edi ; +0x054 Edi : Uint4B .text:004068D3 mov ebx, large fs:1Ch ; nt!_KPCR; +0x01c SelfPcr : Ptr32 _KPCR; 指向當(dāng)前 KPCR 結(jié)構(gòu)體本身,目的是方便查找 .text:004068DA push 3Bh ; nt!_KTRAP_FRAME; +0x050 SegFs : Uint4B .text:004068DC mov esi, [ebx+124h] ; nt!_KPCR; +0x120 +0x4 CurrentThread : Ptr32 _KTHREAD; 存儲(chǔ)了當(dāng)前正在跑的線程的信息,為 KTHREAD 結(jié)構(gòu)體 .text:004068E2 push dword ptr [ebx] ; ebx 保存的是KPCR結(jié)構(gòu)體的地址; KPCR 第一個(gè)成員為結(jié)構(gòu)體 NT_TIB 的指針; NT_TIB 的第一個(gè)值為 ExceptionList(異常列表); 這句話的目的是將異常列表保存到TrapFrame結(jié)構(gòu)體中; nt!_KPCR; +0x000 NtTib : _NT_TIB; nt!_NT_TIB; +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD;; nt!_KTRAP_FRAME; +0x04c ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD .text:004068E4 mov dword ptr [ebx], 0FFFFFFFFh ; 將 ExceptionList(異常列表)置為 -1 .text:004068EA mov ebp, [esi+18h] ; nt!_KTHREAD; +0x018 InitialStack : Ptr32 Void .text:004068ED push 1 ; nt!_KTRAP_FRAME; +0x048 PreviousPreviousMode : Uint4B; 往棧中壓入老的先前模式,1表示先前模式為3環(huán) .text:004068EF sub esp, 48h ; 執(zhí)行前,ESP位于_KTRAP_FRAME + 0x48 = PreviousPreviousMode; 執(zhí)行后,ESP 等于 _KTRAP_FRAME 結(jié)構(gòu)指針 .text:004068F2 sub ebp, 29Ch .text:004068F8 mov byte ptr [esi+140h], 1 ; 新的先前模式; nt!_KTHREAD; +0x140 PreviousMode : Char .text:004068FF cmp ebp, esp ; 檢查 ebp 是否等于 esp,也就是 _KTRAP_FRAME 結(jié)構(gòu)指針 .text:00406901 jnz loc_40686C ; 若不等于,則跳轉(zhuǎn),進(jìn)行異常處理 .text:00406907 and dword ptr [ebp+2Ch], 0 ; 修改 TrapFrame 結(jié)構(gòu)體中 Dr7 的值; nt!_KTRAP_FRAME; +0x02c Dr7 : Uint4B .text:0040690B test byte ptr [esi+2Ch], 0FFh ; 檢測當(dāng)前進(jìn)程是否處于調(diào)試狀態(tài); nt!_KTHREAD; +0x02c DebugActive : UChar; 若不處于調(diào)試狀態(tài),則 DebugActive 的值為FF .text:0040690F mov [esi+134h], ebp ; 將 TrapFrame 結(jié)構(gòu)指針寫入當(dāng)前線程信息中; nt!_KTHREAD; +0x134 TrapFrame : Ptr32 _KTRAP_FRAME .text:00406915 jnz Dr_FastCallDrSave ; 若當(dāng)前進(jìn)程處于被調(diào)試狀態(tài),則跳轉(zhuǎn),為 Dr0 ~ Dr7 進(jìn)行賦值; 若當(dāng)前進(jìn)程不處于被調(diào)試狀態(tài),則繼續(xù)向下執(zhí)行 .text:0040691B .text:0040691B loc_40691B: ; CODE XREF: Dr_FastCallDrSave+10↑j .text:0040691B ; Dr_FastCallDrSave+7C↑j .text:0040691B mov ebx, [ebp+60h] ; 從 TrapFrame 結(jié)構(gòu)體中取出 Ebp 到 ebx 寄存器 .text:0040691E mov edi, [ebp+68h] ; 從 TrapFrame 結(jié)構(gòu)體中取出 Eip 到 edi 寄存器 .text:00406921 mov [ebp+0Ch], edx ; nt!_KTRAP_FRAME; +0x000 DbgEbp : Uint4B .text:00406924 mov dword ptr [ebp+8], 0BADB0D00h; +0x008 DbgArgMark : Uint4B .text:0040692B mov [ebp+0], ebx ; +0x000 DbgEbp : Uint4B .text:0040692E mov [ebp+4], edi ; +0x004 DbgEip : Uint4B .text:00406931 sti ; 關(guān)閉中斷 .text:00406932 .text:00406932 loc_406932: ; CODE XREF: _KiBBTUnexpectedRange+18↑j .text:00406932 ; _KiSystemService+71↑j; KiSystemService 與 KiFastCallEntry 函數(shù)的共同代碼部分; 下篇學(xué)習(xí)系統(tǒng)服務(wù)表時(shí)再進(jìn)行分析

    總結(jié)

  • 當(dāng)程序通過中斷門從3環(huán)進(jìn)入0環(huán)時(shí),ESP指向TrapFrame+0x64的位置
  • 當(dāng)程序通過快速調(diào)用從3環(huán)進(jìn)入0環(huán)時(shí),ESP指向TrapFrame+0x78的位置
  • 若通過中斷門進(jìn)入0環(huán),在KiSystemService函數(shù)開始執(zhí)行時(shí),3環(huán)的SS、ESP、EFLAGS、CS、EIP就已經(jīng)被存儲(chǔ)到 TrapFrame 結(jié)構(gòu)體中了
  • TrapFrame 結(jié)構(gòu)體的其它成員通過 KiSystemServiceKiFastCallEntry 進(jìn)行賦值
  • 不管是 KiSystemService 還是 KiFastCallEntry,最終都要執(zhí)行一部分相同的代碼,分為兩個(gè)函數(shù)是因?yàn)檫M(jìn)入0環(huán)時(shí),堆棧里的值不一樣,走同一條函數(shù)會(huì)出問題
  • 總結(jié)

    以上是生活随笔為你收集整理的Windows系统调用学习笔记(三)—— 保存现场的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。