分享

调用门的使用

 astrotycoon 2013-08-31

         Windows的调用门保存在GDT中。GDT称为全局描述符表,其中不但有调用门,还有其他种类的描述符存在。一个调用门的结构如下,注意,这里有两个32位数据,一共是64位.。

调用门的使用 - prince_william@126 - Never  compromise `

        在这里要明确一个概念,就是“段选择子”。选择段子所选择的是一个描述符,在这里只考虑全局描述符表的时候,也可以认为一个段选择子就选择了一个GDT中的描述符。

      所有的全局描述符都存在全局描述符表中,结构和上面的调用门类似。其中P表示这个描述符是否有效,DPL表示调用门的特权级,段选择子指出要访问的代码段,偏移量指出在代码段中的入口点,参数计数给出的是要传递的参数的数量。主程序通过堆栈把入口参数传递给子程序。如果利用调用门调用子程序时,引起特权级的转换和堆栈的改变,那么就需要将外层堆栈中的参数复制到内存堆栈,而复制的数量则由参数计数决定。

调用门的使用 - prince_william@126 - Never  compromise `

问题在于:sysenter虽然可以在R3下执行,但是跳转的目的地址却一定要在R0下指定。换句话说,我可以在R3下调用sysenter,却无法控制我要跳转的地址。

跳转地址是由Windows预先设置的,下面介绍这个地址的设置方法。这些地址保存在3个特殊的寄存器中。

调用门的使用 - prince_william@126 - Never  compromise `

 

设置方法为调用wrmsr指令,这是特权指令。方法如下:把寄存器代号放入ecx中,把要设置的内容放在eds:eax中。

      mov  ecx,0x8                        ;Windows xp下代码段选择子为8

      mov dword ptr eds:[eax],0x8?????       ;固定跳转到某个内核地址

      wrmsr                                     ;写入

以上代码当然是Windows系统执行的。然而如果编写了R0代码也可以执行,但是在R3下不能执行。

值得注意的是,SYSENTER_CS_MSR总是被设置为8。Windows中所有的内核代码段都公用这个描述符-----实际计算得到的段基地址总数全0,这就是为何在Windows下虚地址总是线性地址的原因。

此外,sysenter执行后的堆栈段,以及sysexit返回后的代码段和堆栈段也需要确定段选择子。这个在指令手册上已经有规定,所以只需要设置一个SYSENTER_CS_MSR就可以了。剩下的这个选择子之后连续排列。

调用门的使用 - prince_william@126 - Never  compromise `
总而言之,sysenter的过程可以概述如下:
1、装载SYSENTER_CS_MSR到cs寄存器
2、装载SYSENTER_EIP_MSR到eip寄存器
3、装载SYSENTER_CS_MSR+8到SS寄存器
4、装载SYSENTER_ESP_MSR到esp寄存器
5、切换到R0层
6、清除eflags寄存器中的VM标志
7、执行eip开始的R0例程
而sysexit返回的过程除了用到上面表格中的两个段选择子之外,还要加载edx到eip中,加载ecx的值到esp中。换句话说,在执行sysexit之前,要返回的地址应保存在edx中,概述如下
1、SYSENTER_CS_MSR+16装载到cs寄存器
2、将edx的值送人eip
3、SYSENTER_CS_MSR+24装载到ss寄存器
4、将ecx的值送入ESP
5、切换回R3层
6、执行eip处的R3指令

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多