您的位置:首页 > 其它

总结进入RING0的方法

2005-09-15 13:49 204 查看
  关于进入RING0层的方法,大家一定听说过不少,我在复习保护模式编程中将一些进RING0的方法;总结了一下,包括调用门,任务门,中断门,陷阱
门等,这些方法都是直接利用IA32的方法,所以和操作系统应该没有多大关系,当然由于NT内核对GDT,IDT,的保护所以我们不能用这些方法,不过如
果一旦突破了NT的保护,那么所有的方法就都可以使用了,其他的还有SEH等方法,我在前面的文章中也有介绍。

-----------------------------------------------------------Code---

;========================================

;      WOWOCOCK  编写      ;

;======================================== 

   .586p

   .model flat, stdcall

   option casemap :none  ; case sensitive

   include /masm32/include/windows.inc

   include /masm32/include/kernel32.inc

   include /masm32/include/user32.inc

   includelib /masm32/lib/kernel32.lib

   includelib /masm32/lib/user32.lib

;;--------------

TSS       STRUC

TRLink     dw   0   ;链接字段

        dw   0   ;不使用,置为0

TRESP0     dd   0   ;0级堆栈指针

TRSS0      dw   0   ;0级堆栈段寄存器

        dw   0   ;不使用,置为0

TRESP1     dd   0   ;1级堆栈指针

TRSS1      dw   0   ;1级堆栈段寄存器

        dw   0   ;不使用,置为0

TRESP2     dd   0   ;2级堆栈指针

TRSS2      dw   0   ;2级堆栈段寄存器

        dw   0   ;不使用,置为0

TRCR3      dd   0   ;CR3

TREIP      dd   0   ;EIP

TREFlag     dd   0   ;EFLAGS

TREAX      dd   0   ;eax

TRECX      dd   0   ;ecx

TREDX      dd   0   ;edx

TREBX      dd   0   ;ebx

TRESP      dd   0   ;esp

TREBP      dd   0   ;ebp

TRESI      dd   0   ;esi

TREDI      dd   0   ;edi

TRES      dw   0   ;ES

        dw   0   ;不使用,置为0

TRCS      dw   0   ;CS

        dw   0   ;不使用,置为0

TRSS      dw   0   ;ss

        dw   0   ;不使用,置为0

TRDS      dw   0   ;DS

        dw   0   ;不使用,置为0

TRFS      dw   0   ;FS

        dw   0   ;不使用,置为0

TRGS      dw   0   ;GS

        dw   0   ;不使用,置为0

TRLDTR     dw   0   ;LDTR

        dw   0   ;不使用,置为0

TRTrip     dw   0   ;调试陷阱标志(只用位0)

TRIOMap     dw   $+2  ;指向I/O许可位图区的段内偏移

TSS       ENDS

  .data

sztit   db "Gate Test",0

CTEXTCall db "call gate to Ring0!继续?",0

CTEXTInt  db "int gate to Ring0 By int 5 !继续?",0

CTEXTIntx db "int gate to Ring0 By int X !继续?",0

CTEXTTrap db "Trap gate to Ring0 By int 1!继续?",0

CTEXTFault db "Fault gate to Ring0!继续?",0

CTEXTTask db "Task gate to Ring0!继续?",0

temp1 db "Cr3的内容是:%8X",0

temp2 db 100 dup(?)

Freq db 08h    ;发声频率

gdtR df 0

idtR df 0

ldtR dw 0     

trR  dw 0     ;the contents of GDTR,IDTR,LDTR,TR

ldtDes dw 0    

    dw 0    ;LDT Limit  

    dd 0    ;LDT Base

Callgt dq 0    ;call gate's sel

ff

TrDes dw 0    

    dw 0    ;TR Limit  

    dd 0    ;TR Base

Tss1Sel dw ?   ;TSS

Call32  dd 0

Tss1Gate dw ?   ;任务门

TSS1 TSS <>

Tss1Limit equ $-TSS1

TSS2 TSS <>

TestCR3 dd 4

MyCall MACRO Selector,Offsetv

 db 09ah

 dd Offsetv

 dw Selector

ENDM

;;-----------------------------------------

  .code

__Start:

  sgdt  fword ptr gdtR

  sidt  fword ptr idtR

  sldt  word ptr ldtR   

  str   word ptr trR  ;save them for later use

    ;-----------------------

    ; get the ldt mes

    ;-----------------------

    movzx esi,ldtR

    add  esi,dword ptr [gdtR+2] ;esi->ldt descriptor

    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

    or  eax,ebx

    mov  dword ptr [ldtDes+4],eax    ;get ldt Base

    ;-----------------------

    ; get the tr mes

    ;-----------------------    

    movzx esi,trR

    add  esi,dword ptr [gdtR+2]

    mov  ax,word ptr [esi]

    mov  word ptr [TrDes],ax

    mov  ax,word ptr [esi+6]

    and  ax,0fh

    mov  word ptr [TrDes+2],ax     ;get tr Limit

    

    mov  eax,[esi+2]

    and  eax,0ffffffh

    mov  ebx,[esi+4]

    and  ebx,0ff000000h

    or  eax,ebx

    mov  dword ptr [TrDes+4],eax;get tr Base

    ;-------------------------------------

    ; 这里演示在GDT中寻找空白表项来制造调用门

    ;-------------------------------------

    mov  esi,dword ptr [gdtR+2] ;esi->gdt base

    movzx eax,word ptr [gdtR]  ;eax=gdt limit

    call  Search_XDT

                        ;esi==gdt Base

    mov  esi,dword ptr [gdtR+2]

    push  offset myring0_prc_callgt    ;set callgate in gdt

    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,dpl=3,and attribute ->386 call gate!

    and  dword ptr Callgt,0

    or   al,3h

    mov  word ptr [Callgt+4],ax

    call  fword ptr [Callgt]      ;use callgate to Ring0!

    ;--------------------------------------------

    ; 这里演示在Ldt中制造调用门

    ;--------------------------------------------

    invoke  MessageBoxA,0, addr CTEXTCall,addr sztit,MB_YESNO

    cmp  eax,IDNO

    jz   @xit000           ;继续演示?

    mov  esi,dword ptr [ldtDes+4]   ;esi->ldt base

    mov  eax,dword ptr [ldtDes]    ;eax=ldt limit

    call  Search_XDT          ;eax返回找到的空白选择子

    mov  esi,dword ptr [ldtDes+4]

    push  offset myring0_prc_callgt  ;set callgate in ldt

    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,dpl=3,and attribute ->386 call gate!

    and  dword ptr Callgt,0

    or   al,7h            ;所以选择子一定要指向LDT

    mov  word ptr [Callgt+4],ax

    call  fword ptr [Callgt]      ;use callgate to Ring0! 

; *通过中断门进入ring0,像在Dos下一样,我们只要替换中断向量表的地址以指向我们

; *自己的程序就可以了,不过在win下中断向量表变为IDT(中断描述符表),其第0~1保存

; *中断处理程序偏移的低16位,6~7字节保存偏移的高16位,我们必须使用描述符具有DPL=3

; *的中断门以便在ring3下转入中断程序,而int 03h,04h,05h,10h,13h,30h等本来就是

; *DPL=3,我们可以方便地利用之,注意中断处理程序返回用iretd

    ;---------------------------

    ; 下面利用int 5进入ring0

    ;---------------------------

    invoke  MessageBoxA,0,addr CTEXTInt,addr sztit,MB_YESNO

    cmp  eax,IDNO

    jz   @xit000           ;继续演示?

    mov  esi,dword ptr [idtR+2]    ;esi->idt base

    push  dword ptr [esi+8*5+0]

    push  dword ptr [esi+8*5+4]    ;保存INT 5,中断描述符

    push  offset myring0_prc_Intgt   ;替换原来INT5的入口地址

    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]    ;恢复,int 5,中断描述符

    pop  dword ptr [esi+8*5+0]

; *当然,上面使用的全部是DPL=3的int如1,3,5等,如果我们准备使用任意int 来达到

; *目的该怎么办?这就需要自己改int descriptor 的属性值,使DPL=3,sel=28h

; *如下面使用int 255

; *__________________________________________

    invoke  MessageBoxA,0,addr CTEXTIntx,addr sztit,MB_YESNO

    cmp  eax,IDNO

    jz   @xit000           ;继续演示?

    movzx ebx,word ptr [idtR] ;ebx=idt limit

    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 ;P=1,386中断门,DPL=3

    pop word ptr [esi+ebx+6]

    

    ;mov eax,ebx

    ;shl eax,5

    ;add eax,90C300CDh

    ;push eax

    ;call ss:esp ; 在堆栈中形成指令 int 5Fh ret直接转入执行!

    int 5fh

    ;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  MessageBoxA,0,addr CTEXTTrap,addr sztit,MB_YESNO

    cmp  eax,IDNO

    jz   @xit001           ;继续演示?

    ;---------------------------------

    ; 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     ; set TF=1

    nop      ; ring0!

    pop dword ptr [esi+(8*1)+4]; restore IDT entry 

    pop dword ptr [esi+(8*1)+0]

    ;--------------------------------------------

    ; 这里演示故障门,除法错误

    ;--------------------------------------------

    @xit001:invoke  MessageBoxA,0,addr CTEXTFault,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!

    ;-----------------------------------------

    invoke  MessageBoxA,0,addr CTEXTTask,addr sztit,MB_YESNO

    cmp  eax,IDNO

    jz   @xit000

    ;-------------------------------------

    ; 这里演示在GDT中寻找空白表项来制造TSS

    ;-------------------------------------

    mov  esi,dword ptr [gdtR+2]

    movzx eax,word ptr [gdtR]

    call  Search_XDT

    and  ax,0fff8h

    mov  Tss1Sel,ax   ;save Tss1 selector ,esi==gdt Base

    mov  esi,dword ptr [gdtR+2]

    mov  ebx,offset TSS1

    mov  word ptr [esi+eax+0],Tss1Limit    

    mov  dword ptr [esi+eax+2],ebx    ;offset

    mov  word ptr [esi+eax+5],89h

    shr  ebx,24

    mov  byte ptr [esi+eax+7],bl ;set mytss

    ;--------------------------------------------

    ; 这里演示在Ldt中制造任务门

    ;--------------------------------------------

    mov  esi,dword ptr [ldtDes+4]

    mov  eax,dword ptr [ldtDes]

    call  Search_XDT          ;eax返回找到的空白选择子

    push  eax

    or   ax,7h

    mov  Tss1Gate,ax

    pop  eax

    mov  esi,dword ptr [ldtDes+4]

    mov  word ptr [esi+eax+0],0    

    mov  word ptr [esi+eax+6],0    ;offset

    push  word ptr Tss1Sel

    pop  word ptr [esi+eax+2]

    mov  word ptr [esi+eax+4],0E500h ;Tss Gate

    mov esi,dword ptr [TrDes+4]

    assume esi

tr TSS

    push word ptr ldtR

    pop word ptr[esi].TRLDTR ;设置LDT SELECTOR(WINDOWS98的TSS中LDT 为0???)

    lea edi,TSS1

    assume edi

tr TSS

    push word ptr trR

    pop word ptr [edi].TRLink  ;返回TSS选择子,设置联接字

    push dword ptr[esi].TRESP0  ;设置SP0

    pop dword ptr[edi].TRESP0

  

    push word ptr[esi].TRSS0   ;设置SS0

    pop word ptr[edi].TRSS0

    push dword ptr[esi].TRCR3  

       ;设置CR3寄存器,即设置好转换以后所有的段及页转换相关寄存器

    pop dword ptr[edi].TRCR3

    push offset Ring0

    pop dword ptr[edi].TREIP

    mov word ptr[edi].TRCS,28h  ;CS=28

    mov word ptr[edi].TRSS,30h  ;ss=30

    push word ptr ldtR      ;设置LDTR

    pop word ptr[edi].TRLDTR

    push ds

    pop dword ptr[edi].TRDS

    mov word ptr[edi+54h+2],0

    call fword ptr Call32

    mov ebx,dword ptr [TestCR3]

   @xit000:

    invoke wsprintf,addr temp2,addr temp1,TestCR3

    invoke MessageBoxA,0,addr temp2,addr sztit,0

    mov eax,dword ptr [ldtDes+4];恢复GDT,LDT中的空选择子。

    movzx esi,Tss1Gate

    and  esi,0fffffff8h

    add eax,esi

    mov dword ptr [eax],0

    mov dword ptr [eax+4],0

    mov eax,dword ptr [gdtR+2]

    movzx esi,Tss1Sel

    add eax,esi

    mov dword ptr [eax],0

    mov dword ptr [eax+4],0

    invoke  ExitProcess,0

    ;-----------------------------------------

Ring0Code_div proc far                            

                                       

    pushad                                  

    mov  ecx,10     ;EIP

   ambalance002:         ;cs

    push  ecx      ;EFLAGS

    call  Beeps

    pop  ecx

    loop  ambalance002                                

    popad                                   

                                       

    add dword ptr [esp],2 ; 修改Eip,略过除错指令(div eax)2个字节长,继续执行             

                                       

    iretd                                   

                                       

Ring0Code_div endp                              

myring0_prc_Trapgt  proc  far

    pushad         ;注意压栈结构为

    mov  ecx,10      ;esp->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

    pushfd

    pop eax 

    or eax,3000h 

    push eax

    popfd

    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    ;ebx=limit

    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         ; eax=free GDT entry selector

    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

  Ring0:

  mov ebx,cr3

  mov TestCR3,ebx

  iretd

END  __Start

;___________________________________________________Over...___________
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息