总结进入RING0的方法

关于进入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:off

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:ptr TSS
     push word ptr ldtR
     pop word ptr[esi].TRLDTR ;设置LDT SELECTOR(WINDOWS98的TSS中LDT 为0???)

    lea edi,TSS1
     assume edi:ptr 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...___________

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值