特权级--ring3到ring0

来源:互联网 发布:samba windows 无权限 编辑:程序博客网 时间:2024/05/21 10:22

还记得吗?我们用调用门和lcall指令实现特权级由低到高的转移.

假设我们想由代码A转移到代码B,运用一个调用门G,即调用门G中的目标选择子指向代码B的段。实际上我们要考虑4个要素:CPL、RPL、DPL_B(代码B的DPL)、DPL_G(调用门G的DPL)。

第一步,当A访问调用门G时,规则相当于访问一个数据段,要求CPL和RPL都小于或者等于DPL_G.也就是CPL和RPL需要在更高的特权级上。

第二步,除了上面系统还将比较CPL和DPL_B。如果是一致代码段的话,要求DPL_B<=CPL;如果是非一致代码段的话,call指令要求DPL_B<=CPL;jmp指令要求DPL_B==CPL.

 

当我们用call和调用门实现从ring3到ring0的转移时,会从TSS加载ring0的堆栈STACKR0,然后将调用者ring3的ss、esp压入新堆栈STACKR0,然后从调用者堆栈STACKR3中复制Param Count个参数并入栈,然后将当前ring3的cs和ip入栈,然后加载调用门中的新的cs和ip,开始执行被调用者的过程。

 

TSS结构如下:

[plain] view plain copy
  1. LABEL_TSS:  
  2.     .4byte  0           # Back  
  3.     .4byte  TopOfStack      # 0 级堆栈  
  4.     .4byte  SelectorStack          
  5.     .4byte  0           # 1 级堆栈  
  6.     .4byte  0           #   
  7.     .4byte  0           # 2 级堆栈  
  8.     .4byte  0           #   
  9.     .4byte  0           # CR3  
  10.     .4byte  0           # EIP  
  11.     .4byte  0           # EFLAGS  
  12.     .4byte  0           # EAX  
  13.     .4byte  0           # ECX  
  14.     .4byte  0           # EDX  
  15.     .4byte  0           # EBX  
  16.     .4byte  0           # ESP  
  17.     .4byte  0           # EBP  
  18.     .4byte  0           # ESI  
  19.     .4byte  0           # EDI  
  20.     .4byte  0           # ES  
  21.     .4byte  0           # CS  
  22.     .4byte  0           # SS  
  23.     .4byte  0           # DS  
  24.     .4byte  0           # FS  
  25.     .4byte  0           # GS  
  26.     .4byte  0           # LDT  
  27.     .2byte  0           # 调试陷阱标志  
  28.     .2byte  . - LABEL_TSS + 2   # I/O位图基址  
  29.     .byte   0xff                            # I/O位图结束标志  
  30. .set     TSSLen,(. - LABEL_TSS)  




不过我想在一个引导扇区内搞定,而我们只用到了0级堆栈,所有我写成了这样:

[plain] view plain copy
  1. LABEL_TSS:  
  2.     .4byte  0           /* Back Link */  
  3.     .4byte  TopOfStackR0  /* ESP0 */  
  4.     .4byte  SelectorStackR0 /* SS0 */  
  5. .set    TSSLen, (. - LABEL_TSS)  


添加ring0的堆栈:

[plain] view plain copy
  1. LABEL_STACKR0:  
  2. .space  20, 0  
  3. .set    TopOfStackR0, (. - LABEL_STACKR0)  


 

添加ring0堆栈的描述符和TSS的描述符以及对应的选择子,然后初始化
Descriptor_STACKR0:Descriptor(0,TopOfStackR0, (DA_DRWA + DA_32))
LABEL_DESC_TSS: Descriptor(0,       (TSSLen - 1), DA_386TSS)

.set  SelectorStackR0,  (Descriptor_STACKR0  - GDT_START)
.set    SelectorTSS,    (LABEL_DESC_TSS - GDT_START)

InitDescrptor(Descriptor_STACKR0,LABEL_STACKR0);
InitDescrptor(LABEL_DESC_TSS,LABEL_TSS);

将调用门描述符的DPL改为DA_DPL3,将其选择子的RPL改为SA_RPL3
Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_DPL3)) 
.set  Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START+ SA_RPL3)

添加加载TSS的代码:
movw     $(SelectorTSS), %ax    /* Load TSS to TR register */
ltr     %ax

在ring3代码中打印完字符‘3’后添加
lcall $Selector_Gate_Call,$0
回到ring0

代码如下:

[plain] view plain copy
  1. #define Descriptor(base,lim,attr)\  
  2. .word lim&0xffff;\  
  3. .word base&0xffff;\  
  4. .byte (base>>16)&0xff;\  
  5. .word ((lim>>8)&0xf00)|(attr&0x0f0ff);\  
  6. .byte ((base>>24)&0xff)    
  7.     
  8. /*    
  9. *InitDescrptor(Descriptor,SegBase)初始化描述符函数    
  10. *Descriptor:要初始化的描述符    
  11. *SegBase:段基址    
  12. */    
  13. #define InitDescrptor(Descriptor,SegBase)\  
  14. xor     %eax,%eax; \  
  15. mov     %cs,%ax  ; \  
  16. shl     $4,%eax  ; \  
  17. addl    $(SegBase), %eax ;\  
  18. movw    %ax, (Descriptor + 2);\  
  19. shr     $16, %eax;\  
  20. movb    %al, (Descriptor + 4);\  
  21. movb    %ah, (Descriptor + 7)    
  22.   
  23. #define Gate(Selector,Offset,PCount,Attr)\  
  24. .2byte (Offset&0xffff);\  
  25. .2byte (Selector);\  
  26. .2byte (PCount&0x1f)|((Attr<<8)&0xff00);\  
  27. .2byte ((Offset>>16)&0xffff)    
  28.   
  29. DA_386CGate = 0x8c  
  30. DA_C   = 0x98    
  31. DA_32  = 0x4000    
  32. DA_DRW = 0x92   
  33. DA_DRWA=0x93   
  34. SA_TIL = 0x4    
  35. DA_LDT = 0x82   
  36.   
  37. SA_RPL3 = 3  
  38. DA_DPL0=0x00  
  39. DA_DPL1=0x20  
  40. DA_DPL2=0x40  
  41. DA_DPL3=0x60   
  42.    
  43. DA_386TSS=0x89    
  44. .text    
  45. .globl start    
  46. .code16    
  47. start:    
  48.  jmpl $0x0, $code     
  49.      
  50. /**-----------------------------------------------------------------    
  51.  * 全局描述符表: GDT    
  52.  *-------------------------------*/         
  53. GDT_START:      
  54. Descriptor_DUMMY: Descriptor(0x0,0x0,0x0)    
  55. Descriptor_CODE32:Descriptor(0x0,0xffffffff,DA_C+DA_32)   
  56. Descriptor_STACKR0:Descriptor(0,TopOfStackR0, (DA_DRWA + DA_32))  
  57. Descriptor_VIDEO: Descriptor(0xb8000,0x0ffff,DA_DRW + DA_DPL3)    
  58. Descriptor_CODE_GATE:Descriptor(0x0,CodeGLen,DA_C+DA_32)  
  59. Descriptor_CODE3:Descriptor(0x0,0xffffffff,DA_C+DA_32+DA_DPL3)  
  60. Descriptor_STACKR3:Descriptor(0,TopOfStackR3, (DA_DRWA + DA_32 + DA_DPL3))  
  61. LABEL_DESC_TSS: Descriptor(0,       (TSSLen - 1), DA_386TSS)  
  62.   
  63. /*门描述符*/   
  64. Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_DPL3))    
  65. GDT_END:    
  66.     
  67. GdtPtr:    
  68.     .word (GDT_END-GDT_START)-1 # so does gdt     
  69.     .long GDT_START     # This will be rewrite by code.    
  70.   
  71. /**-----------------------------------------------------------------    
  72.  * GDT中的选择子  
  73.  *-------------------------------*/   
  74. .set    selector_Code32,(Descriptor_CODE32-GDT_START)  
  75. .set  SelectorStackR0,  (Descriptor_STACKR0  - GDT_START)  
  76. .set    Selector_Video,(Descriptor_VIDEO-GDT_START)       
  77. .set  Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START+ SA_RPL3)  
  78. .set    selector_CodeR3,(Descriptor_CODE3-GDT_START+SA_RPL3)  
  79. .set    SelectorStackR3,(Descriptor_STACKR3- GDT_START + SA_RPL3)  
  80. .set    SelectorTSS,    (LABEL_DESC_TSS - GDT_START)  
  81. /*调用门选择子*/  
  82. .set    Selector_Gate_Call,(Descriptor_Gate_Call-GDT_START)  
  83.   
  84.   
  85. /* 32-bit ring 3 stack segment. */  
  86. .align  4  
  87. LABEL_STACKR0:  
  88. .space  20, 0  
  89. .set    TopOfStackR0, (. - LABEL_STACKR0)  
  90.   
  91.   
  92. LABEL_STACKR3:  
  93. .space  20, 0  
  94. .set    TopOfStackR3, (. - LABEL_STACKR3)  
  95.   
  96. LABEL_TSS:  
  97.     .4byte  0           /* Back Link */  
  98.     .4byte  TopOfStackR0  /* ESP0 */  
  99.     .4byte  SelectorStackR0 /* SS0 */  
  100. .set    TSSLen, (. - LABEL_TSS)  
  101.   
  102. /******************************************  
  103. *程序从这里开始  
  104. */  
  105. code:    
  106.     mov     %cs,%ax       
  107.     mov     %ax,%ds     
  108.     mov     %ax,%es        
  109.     mov     %ax,%ss      
  110.     mov  $0x8000,%sp      
  111.        
  112. /*初始全局描述符Descriptor_CODE32*/    
  113. InitDescrptor(Descriptor_CODE32,LABEL_SEG_CODE32);   
  114.    
  115. /*初始全局描述符Descriptor_CODE_GATE*/    
  116. InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);    
  117.   
  118. /*初始全局描述符LABEL_STACKR0  ring0堆栈*/  
  119. InitDescrptor(Descriptor_STACKR0,LABEL_STACKR0);  
  120.   
  121. /*初始全局描述符LABEL_STACKR3  ring3堆栈*/  
  122. InitDescrptor(Descriptor_STACKR3,LABEL_STACKR3);  
  123.   
  124.   
  125.   
  126. /*初始全局描述符Descriptor_CODE3*/    
  127. InitDescrptor(Descriptor_CODE3,LABEL_CODE_3);  
  128.   
  129. InitDescrptor(LABEL_DESC_TSS,LABEL_TSS);  
  130.   
  131.   
  132. /*加载gdtr即将全局描述符表gdt的首地址和gdt的界限赋给gdtr寄存器*/           
  133.     lgdt GdtPtr    
  134.     
  135. /*关中断*/    
  136.     cli    
  137.     
  138. /*打开地址线A20*/    
  139.     inb $0x92,%al    
  140.     or  $0x02,%al    
  141.     outb %al,$0x92    
  142.     
  143. /*设置cr0寄存器,切换到保护模式*/    
  144.     movl %cr0,%eax    
  145.     or   $1,%eax    
  146.     movl %eax,%cr0    
  147.     
  148.     
  149. /*真正进入保护模式,执行此命令后CS=0x8,IP=0*/    
  150.     ljmp $selector_Code32,$0    
  151.     
  152.   
  153.   
  154. LABEL_SEG_CODE32:    
  155. .align  32    
  156. .code32   
  157.         movw     $(SelectorStackR0), %ax  
  158.     movw     %ax, %ss   
  159.     movl     $(TopOfStackR0), %esp   
  160.       
  161.     movw $Selector_Video,%ax    
  162.     movw %ax,%gs/* 视频段选择子(目的)*/   
  163.       
  164.        
  165.     movl $((80*11+79)*2),%edi/*第11行,79列*/    
  166.     movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/    
  167.     movb $'P',%al/*显示的字符*/    
  168.     movw %ax,%gs:(%edi)    
  169.       
  170.     #ljmp $selector_CodeR3,$0  
  171.     movw     $(SelectorTSS), %ax    /* Load TSS to TR register */  
  172.     ltr     %ax   
  173.     #lcall $Selector_Gate_Call,$0  
  174.     pushl $SelectorStackR3  
  175.     pushl $TopOfStackR3  
  176.     pushl $selector_CodeR3  
  177.     pushl $0  
  178.     lret    
  179.       
  180.     lcall $Selector_Gate_Call,$0    
  181.     
  182.       
  183.    
  184.         
  185. jmp .    
  186.         
  187. LABEL_CODE_G:  
  188.   
  189.     movl $((80*12+0)*2),%edi/*第10行,0列*/    
  190.     movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/    
  191.     movb $'G',%al/*要显示的字符*/    
  192.     movw %ax,%gs:(%edi)    
  193.           
  194.         lret  
  195. .set CodeGLen,(. - LABEL_CODE_G)    
  196.   
  197. LABEL_CODE_3:  
  198.     movw $Selector_Video,%ax  
  199.     movw %ax,%gs/* 视频段选择子(目的)*/  
  200.     movl $((80*12+10)*2),%edi/*第10行,0列*/  
  201.     movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/  
  202.     movb $'3',%al/*要显示的字符*/  
  203.     movw %ax,%gs:(%edi)  
  204.       
  205.     lcall $Selector_Gate_Call,$0  
  206.   
  207. jmp .  
  208. .set Code3Len,(. - LABEL_CODE_3)  
  209.     
  210. .org 0x1fe, 0x90     
  211. .word 0xaa55   


 

0 0
原创粉丝点击