任務段與任務門


Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html

任務段與任務門

索引:

1.任務段

2.如何加載一個段寄存器和取出段寄存器

3.TSS的作用(在Windows操作系統上)

4.如何查看TSS段內容

5.構造TSS門並進行提權

6.使用int3指令斷下觀察esp的實驗(出現一個elfags標志位的坑)

7.int3斷下時,如果不回復eflags寄存器,其就會卡死

8.任務門的作用(在Windows操作系統上)

9.任務門實驗

 

解答:

1.  任務段

   任務段是系統段的一種,Windows操作系統只運行一個(啟動時就已經確定)
    

    查看對應的任務段的屬性,當切換進執行程序時,其會將任務段屬性改為繁忙,
    可以看出下表紅色的位置。
    

    tr 寄存器表示當前的任務段,我們可以使用windbg 的 dg指令解析該段

  

 

2. 如何加載一個段寄存器和取出段寄存器
    加載段寄存器 load (零環)
    mov ax,0x28
    ltr ax
    取出段寄存器 store (三環)
    str dword ds:[0x12345678]
    獲取gdt:  sgdt (三環)  加載gdt: lgdt (零環)
 獲取idt: sidt ……………

 3. TSS的作用(在Windows操作系統上)
    線程切換時,一次保存多個寄存器。
    注意:是線程切換,不是進程切換,進程切換還要替換整個環境遠不止寄存器那么多!!


4. 如何查看TSS段內的內容
    TSS的地址就是TSS段描述符描述的基地址,因此我們通過 dg tr 查看其Base為 80042000。
    對於查看TSS段,有一個單獨的指令。
    dt _KTSS base_address
    效果如下圖(此時沒用到,之后線程切換會有新的效果)

   

 

 5. 構造tss門並進行提權
  1)實驗代碼

    
        // test.cpp : Defines the entry point for the console application.
        //
        
        #include "stdafx.h"
        #include "windows.h"
        
        DWORD iTSS[26];
        DWORD ESP0[0x1000];
        DWORD ESP3[0x1000];
        
        DWORD dwESP;
        DWORD dwCS;
        DWORD dwCR3;
        
        _declspec(naked) void Call(){
            _asm{
            
                mov dwESP,ESP;
                mov ax,cs;
                mov dwCS,eax;
        
                iretd;
            }
        }
        int main(int argc, char* argv[])
        {
            memset(iTSS,0,sizeof(iTSS));
            memset(ESP0,0,sizeof(ESP0));
            memset(ESP3,0,sizeof(ESP3));
        
            dwESP = 0;
            dwCS = 0;
            dwCR3 = 0;
        
            iTSS[1] = (DWORD)(ESP0+0x900);    // ESP
            iTSS[2] = 0x10;                    // SS0
            iTSS[8] = (DWORD)Call;            // EIP
            iTSS[14] = (DWORD)(ESP3+0x900); // ESP3
            iTSS[18] = 0x23;    // ES
            iTSS[19] = 0x08;    // CS
            iTSS[20] = 0x10;    // SS
            iTSS[21] = 0x23;    // DS
            iTSS[22] = 0x30;    // FS
        
            printf("iTSS:%x ESP3:%x ESP0:%x\n",iTSS,(ESP3+0x900),(ESP0+0x900));
            printf("input cr3:");
            scanf("%x",&dwCR3);
            iTSS[7] = dwCR3;        // cr3
        
            char buf[6] = {0,0,0,0,0x48,0};
            _asm{
                call fword ptr buf;
            }
            printf("ESP:%x CS:%x\n",dwESP,dwCS);
            return 0;
            return 0;
}

  2)查看TSS的內存地址,然后來修改任務門的偏移量(注意之前為函數地址,但任務門是一次性替換全部寄存器,因此函數地址在tss的eip中)。

    

     0x48偏移處構造,windbg指令 eq 8003f048 0000e943`2c680068

  3)使用 !process 0 0 找到對應的CR3(物理頁處),然后輸入進去。

    

   4)可以看到其直接使用了三環的esp(雖然我們權限是零環,但它並沒有使用零環esp,而是直接替換目錄中的esp)。

    

 

 6. 使用int3指令斷下觀察esp的實驗(出現一個eflags標志位的坑)

    //
    
    #include "stdafx.h"
    #include "windows.h"
    
    DWORD iTSS[26];
    DWORD ESP0[0x1000];
    DWORD ESP3[0x1000];
    
    DWORD dwESP;
    DWORD dwCS;
    DWORD dwCR3;
    
    _declspec(naked) void Call(){
        _asm{
            int 3;
    
            mov dwESP,ESP;
            mov ax,cs;
            mov dwCS,eax;
    
            // reset the NT flag in eflags register
            pushfd;
            pop eax;
            or eax,0x4000;
            push eax;
            popfd;
    
            iretd;
        }
    }
    int main(int argc, char* argv[])
    {
        memset(iTSS,0,sizeof(iTSS));
        memset(ESP0,0,sizeof(ESP0));
        memset(ESP3,0,sizeof(ESP3));
        VirtualLock(iTSS),0x2000);
        VirtualLock(ESP0),0x2000);
        VirtualLock(ESP3),0x2000);
        dwESP = 0;
        dwCS = 0;
        dwCR3 = 0;
    
        iTSS[1] = (DWORD)(ESP0+0x900);    // ESP
        iTSS[2] = 0x10;                    // SS0
        iTSS[8] = (DWORD)Call;            // EIP
        iTSS[14] = (DWORD)(ESP3+0x900); // ESP3
        iTSS[18] = 0x23;    // ES
        iTSS[19] = 0x08;    // CS
        iTSS[20] = 0x10;    // SS
        iTSS[21] = 0x23;    // DS
        iTSS[22] = 0x30;    // FS
    
        printf("iTSS:%x ESP3:%x ESP0:%x\n",iTSS,(ESP3+0x900),(ESP0+0x900));
        printf("input cr3:");
        scanf("%x",&dwCR3);
        iTSS[7] = dwCR3;        // cr3
    
        char buf[6] = {0,0,0,0,0x48,0};
        _asm{
            call fword ptr buf;
        }
        printf("ESP:%x CS:%x\n",dwESP,dwCS);
        return 0;
        return 0;
    }

  

 

7. int 3 斷下時,如果不恢復eflags寄存器,其就會卡死。
    因為當進行TSS跳轉時,其會將老的TSS保存在新的TSS頭部(上面我們看到),當我們使用iretd返回時,其不是像中斷那樣根據返回地址,而是根據TSS段選擇子找舊的TSS段內存,然后將里面的寄存器全部加載進去。
    而INT 3 會清空 VM、NT、IF、TF四個位,其中NT表示嵌套任務段(nested task),如果清空,其就認為不存在任務段嵌套,直接像常規那樣,根據返回地址返回,此時就會出錯。
    因此就會存在下面一段代碼來修改elfags寄存器中的NT位。
    // reset the NT flag in eflags register
    pushfd;
    pop eax;
    or eax,0x4000;
    push eax;
 popfd;

 

8. 任務門的作用
    

  當CPU出現雙重錯誤,其就會通過任務門,調到08到中斷去。

  任務門在IDT表中,觸發同樣適用 int 0x20;

 

9. 任務門實驗

    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include <windows.h>
    #include <memory.h>
    DWORD iTSS[26];
    DWORD ESP0[0x1000];
    DWORD ESP3[0x1000];
    
    DWORD dwESP;
    DWORD dwCS;
    DWORD dwCR3;
    
    _declspec(naked) void Call(){
        _asm{
            //int 3;
    
            mov dwESP,ESP;
            mov ax,cs;
            mov dwCS,eax;
    
            // reset the NT flag in eflags register
            /*
            pushfd;
            pop eax;
            or eax,0x4000;
            push eax;
            popfd;
            */
            iretd;
        }
    }
    int main(int argc, char* argv[])
    {
        memset(iTSS,0,sizeof(iTSS));
        memset(ESP0,0,sizeof(ESP0));
        memset(ESP3,0,sizeof(ESP3));
        VirtualLock(iTSS,28);
        VirtualLock(ESP0,0x1000);
        VirtualLock(ESP3,0x1000);
        dwESP = 0;
        dwCS = 0;
        dwCR3 = 0;
    
        iTSS[1] = (DWORD)(ESP0+0x900);    // ESP
        iTSS[2] = 0x10;                    // SS0
        iTSS[8] = (DWORD)Call;            // EIP
        iTSS[14] = (DWORD)(ESP3+0x900); // ESP3
        iTSS[18] = 0x23;    // ES
        iTSS[19] = 0x08;    // CS
        iTSS[20] = 0x10;    // SS
        iTSS[21] = 0x23;    // DS
        iTSS[22] = 0x30;    // FS
    
        printf("iTSS:%x ESP3:%x ESP0:%x\n",iTSS,(ESP3+0x900),(ESP0+0x900));
        printf("input cr3:");
        scanf("%x",&dwCR3);
        iTSS[7] = dwCR3;        // cr3
    
        char buf[6] = {0,0,0,0,0x48,0};
        _asm{
            int 0x20;
        }
        printf("ESP:%x CS:%x\n",dwESP,dwCS);
        return 0;
        return 0;
    }

    windbg 修改
    其根據任務門屬性來進行如下修改:
    eq 8003f500  0000e500`00480000 (任務門,通過int 0x20觸發,找到48選擇子處)
    eq 8003f048 0000e943`2c680068 (TSS內存地址構造TSS段描述符)
 填寫進程的CR3地址,之后就可以看見運行成功。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM