不抽烟,少喝酒,多运动,多思考,多努力

仅仅是为了记录自己想记下的一些东西,方便自己以后查看
几种门调用

再看nt下无驱执行ring0代码

(在不考虑正误的前提下,胡说八道一番有点罗嗦没办法。。。)

Author:icelord@ustb@05/11/19

(这仅是一篇日记而已

大二时看网上的“无驱执行ring0代码”看得我一头雾水,今天重新拿起来看了几遍,有点收获,将想法记录一下….

X86平台上,cpu可以工作在三个特权级别下,ring0—ring3,其中ring0具有最高权限,可以执行任何指令而无限制,ring3受到cpu保护机制限制,只能执行非特权指令。当在ring3下执行特权指令如lgdtiret等时,会触发general protection异常(也就是出错啦,跳转到相应得错误处理程序)。

nt平台下,普通应用程序运行在ring3下,操作系统运行于ring0。如果在程序中需要执行一些特权指令的话,程序必须转入到ring0。由于用户程序执行特权指令可能会破坏系统资源,故出于保护和稳定的目的,操作系统通过“门”机制向用户态程序提供必要的服务。在x86种有四种门:中断门、陷阱门、调用门、任务门。

先描述一下门的概念,个人认为就是两种不同状态之间的通道,换句话说,也就是不同环(特权级)之间切换的通道。

一般在操作系统初始化时,由real mode进入保护模式(pmode)后,cpu就处于ring0状态,在完成各种初始化后,系统转入用户态并创建用户进程。用户程序需要特权服务时,通过系统调用进入ring0,由系统完成指定的、在提供的服务范围内的请求。这样可以避免恶意程序破坏系统。但是如果我们想执行一些“特殊的”操作时怎么办?

这个问题有几个解决方法,第一种方法是安装驱动;驱动程序作为内核的辅助模块为用户程序提供服务,它与操作系统一样工作在ring0,而且他是可以根据自己需编写。所以可以通过编写一个“自定义的”驱动程序来执行ring0代码,这种方法在nt下和linux下应该都可,(不好意思,本人没实践过,忙着“好好学习”,有时间再说)。第二种限定于nt平台,通过“自定义门”来实现执行ring0代码。

由于nt平台的特性,导致用户可以通过操作Section对象""device"PhysicalMemory来操作物理内存。这样就可通过找到全局描述符表GDT或中断描述符表IDT并修改其内容来构造自己的“门”,甚至使用自定义代码来覆盖内核代码,。。。通过这些方法来达到执行ring0代码的目的。说得有点混乱下面将一些预备知识,以便为后面理解作基础….

还有几个寄存器,这里就不乱说了….下面给出相应得结构:

 

/* 中断描述符结构 */

typedef struct IDT_ITEM__

{

 unsigned short offset_low ;        // 偏移量的0~15位

 unsigned short seg_selector ;      // 段选择符

 unsigned char reserved1 ;          // 未使用,须设为全零

 unsigned char saved_1_1_0 : 3 ;    // 类型/中断门14/陷阱门15

 unsigned char d : 1 ;          // D

 unsigned char reserved2 : 1 ; // 保留,需设为0

 unsigned char dpl : 2 ;        // 特权ring3

 unsigned char p : 1 ;          // P 位存在/有效

 unsigned short offset_high ;   // 偏移量的16~31位

}IDT_ITEM ;

/* 调用门结构 */

typedef struct InvokeGate__

{

unsigned short Offset_0_15 ;/* 偏移量的 0~15 位 */

unsigned short SegSelector ;/* 段选择符 */

unsigned char reserved1;   

unsigned char Type : 4 ;    /* 类型字段,调用门需为 1100 ( 0xC ) */

unsigned char DT_0 : 1 ;    /* 需为 0 , 以表明这是一个系统用的描述符 */

unsigned char DPL : 2 ;     /* 特权级 */ ring3

unsigned char P : 1 ;       /* 存在位 */

unsigned short Offset_16_31 ; /* 偏移量的 16~31 位 */

}INT_GATE;

讲到这里,问题好像还没解决的样子.

预备知识:

1)   Windows NT将开始512MB物理内存连续映射到0x8000 0000 开始到0xa000 0000处(暂时不考虑大于/小于512MB)//这里在暂时对winnt 5.0 和 5.1

2)   ZwMapViewOfSection()函数可以将物理内存映射到当前进程地址空间,并返回映射的虚拟地址

3)   Sidt指令和sgdt指令是非特权及指令,用户态可执行

4)   Windows Nt使用平坦模式的内存段,即段基址为0

说到这里,问题的基本可以解决了,这就是网上流传的“无驱执行ring0代码” 的基础。

预备知识:

预备知识:

ring3“使用”门要求门的描述符特权级=3,这样这个门才能被用户态程序所使用,

也就是上面结构中DPL域的值=3

构造中断门:

将中断描述符指向你的中断处理程序,里面填写你的ring0代码,至于参数可以通过寄存器eax/ebx/ecx…/esi/edi传递,就跟linux系统调用类似

调用时:

Mov eax,param1

Mov ebx,param2

…..

Int 中断向量号

构造陷阱门与中断门类似。。。。。

构造调用门:

将描述符指向你的ring0要执行的函数

word sel[3];

Sel[0]=sel[1]=0;

Sel[2]=调用门选择子

_Asm call fword ptr [sel]           //调用调用门,进入ring0

//这里没有试验过

//估计 ushort[3]è 

//struct

//{

//    Ulong offset;

//    Ushort selector;

//};

这里糊涂啊….有待研究….

到这里,你应该基本了解了为什么“无驱执行ring0了,流程图如下:

到这里问题因该很简单了,代码我就不贴了,老早以前的东西了…..

本次只是更新一下本人对这这些的认识,上面有很多错误,暂时摆到这里,以后有时间再修改吧,懒啊….

需要代码在百度查:无驱执行ring0代码就可以查到…..

posted on 2009-04-28 13:46  adward  阅读(380)  评论(0编辑  收藏  举报