Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16498238
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:59:17

下载本文示例代码
  一、引言  80x86系列CPU具有四级保护机制。在Windows 9X操作系统只使用0级和3级,以便于移植到精简指令集的计算机上,如RS4000等,这些处理器一般只有两个特权级,即系统级和用户级。在Windows 9X系统环境,应用程序运行在Ring3(3级),如果要运行特权指令就必须进入Ring0(0级)。在同一任务内,实现特权级从外层到内层变换的普通途径是使用段间调用指令CALL,通过调用门进行转移;实现特权级从内层向外层变换的普通途径是使用段间返回指令RET。注意,不能用JMP指令实现任务内不同特权级的变换。调用门描述符转移的入口点包含目标地址的段及偏移量的48位全指针。在执行通过任务门的段间转移指令JMP或段间调用指令CALL时,指令所含指针内的选择子用于确定调用门,而偏移被丢弃;把调用门内的48位全指针作为目标地址指针进行转移。  二、基本思路  取得全局描述符表,搜索该表找到一个暂时为空的描述符,安装调用门,进行远程调用即可实现特权指令操作。  三、所用到的数据结构  ①全局描述符GDT的格式:   在VC中定义全局描述符如下: struct GDT_DESCRIPTOR{ WORD LimitL;//段界限低16位 WORD BaseL;//基地址低16位 BYTE BaseM;//基地址中间8位 BYTE AttriB;//段属性 BYTE LimitH;//段界限的高4位(包括段属性的高4位) BYTE BaseH;//基地址的高8位}  ②门描述符的一般格式:   当TYPE的低4位值为0xC时,这是一个386调用门(CallGate)。在VC中定义"门"如下:struct GATE{ //门结构类型定义 WORD OffsetL; // 32位偏移的低16位WORD Selector; //选择子BYTE Dcount; //双字计数字段BYTE Gtype; //当低4位值为0xC是,这是一个调用门WORD LimitH; //32位偏移的高16位}  ③全局描述符表寄存器GDTR  GDTR长48位,其中高32位为基地址,低16位为界限,GDTR中的段界限以字节为单位。在VC中定义如下: struct GDTR{ WORD wGDTLimit; DWORD dwGDTBase;};  四、具体实现  使用MFC AppWizard新建一个基于对话框的应用程序,工程名为MyRing0。在对话框中添加一个按钮,修改ID为ID_GETCR0,修改Caption为取CR0的值,同时添加该按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()。新建一个头文件Ring0.h并添加到工程中,添加下面的代码到Ring0.h中。 #pragma pack(1)struct GDT_DESCRIPTOR{ WORD LimitL; //段界限低16位 WORD BaseL; //基地址低16位 BYTE BaseM; //基地址中间8位 BYTE AttriB; //段属性 BYTE LimitH; //段界限的高4位(包括段属性的高4位) BYTE BaseH; //基地址的高8位}; struct GATE_DESCRIPTOR{ WORD OffsetL; // 32位偏移的低16位 WORD Selector; //选择子 BYTE Dcount; //双字计数字段 BYTE Gtype; //当低4位值为0xC是,这是一个调用门 WORD LimitH; //32位偏移的高16位};struct GDTR{ WORD wGDTLimit; DWORD dwGDTBase;};#pragma pack()  在MyRing0Dlg.cpp中最后一个include语句后添加#include "Ring0.h",在按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()前面添加下面两个函数: __declspec(naked) void GetCR0_Ring0(){ _asm{ mov ebx,cr0 //特权指令 mov [EAX],ebx retf}}bool CallRing0(PVOID pvRing0FuncAddr,PWORD pVal){  struct GDT_DESCRIPTOR *pGDTDescriptor; struct GDTR gdtr; WORD CallgateAddr[3]; WORD wGDTIndex = 1; //取得全局描述符表GDT _asm Sgdt [gdtr] // 空选择子有特殊用途,跳过它,从第二个选择子开始搜索 pGDTDescriptor = (struct GDT_DESCRIPTOR *)(gdtr.dwGDTBase 8); for (wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex ) {  if (pGDTDescriptor->AttriB == 0)  {   struct GATE_DESCRIPTOR *pGate;   pGate = (struct GATE_DESCRIPTOR *) pGDTDescriptor;   pGate->OffsetL = LOWORD(pvRing0FuncAddr);   //选择子0x28总是指向Ring0的代码段   pGate->Selector = 0x28;   pGate->Dcount = 0;   pGate->Gtype = 0xEC;   pGate->OffsetH = HIWORD(pvRing0FuncAddr);   //准备远程调用参数   CallgateAddr[0] = 0x0;   CallgateAddr[1] = 0x0;   CallgateAddr[2] = (wGDTIndex << 3) | 3;   //进入Ring0   _asm Mov EAX,[pVal]   _asm call FWORD PTR [CallgateAddr]   //归还刚才使用的全局描述符   memset(pGDTDescriptor, 0, 8);   return true;  }  //下一个全局描述符  pGDTDescriptor ;  } //没有空闲的全局描述符 return false;}  为按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()添加代码如下: void CMyRing0Dlg::OnGetcr0() { // TODO: Add your control notification handler code here WORD Val=0; char str[16]; if(!CallRing0((PVOID)GetCR0_Ring0,&Val)){  AfxMessageBox("系统资源不够!");  return; }; sprintf(str,"CR0==",Val); AfxMessageBox(str); }   程序在VC6下编译通过,操作系统为Windows98。   一、引言  80x86系列CPU具有四级保护机制。在Windows 9X操作系统只使用0级和3级,以便于移植到精简指令集的计算机上,如RS4000等,这些处理器一般只有两个特权级,即系统级和用户级。在Windows 9X系统环境,应用程序运行在Ring3(3级),如果要运行特权指令就必须进入Ring0(0级)。在同一任务内,实现特权级从外层到内层变换的普通途径是使用段间调用指令CALL,通过调用门进行转移;实现特权级从内层向外层变换的普通途径是使用段间返回指令RET。注意,不能用JMP指令实现任务内不同特权级的变换。调用门描述符转移的入口点包含目标地址的段及偏移量的48位全指针。在执行通过任务门的段间转移指令JMP或段间调用指令CALL时,指令所含指针内的选择子用于确定调用门,而偏移被丢弃;把调用门内的48位全指针作为目标地址指针进行转移。  二、基本思路  取得全局描述符表,搜索该表找到一个暂时为空的描述符,安装调用门,进行远程调用即可实现特权指令操作。  三、所用到的数据结构  ①全局描述符GDT的格式:   在VC中定义全局描述符如下: struct GDT_DESCRIPTOR{ WORD LimitL;//段界限低16位 WORD BaseL;//基地址低16位 BYTE BaseM;//基地址中间8位 BYTE AttriB;//段属性 BYTE LimitH;//段界限的高4位(包括段属性的高4位) BYTE BaseH;//基地址的高8位}  ②门描述符的一般格式:   当TYPE的低4位值为0xC时,这是一个386调用门(CallGate)。在VC中定义"门"如下:struct GATE{ //门结构类型定义 WORD OffsetL; // 32位偏移的低16位WORD Selector; //选择子BYTE Dcount; //双字计数字段BYTE Gtype; //当低4位值为0xC是,这是一个调用门WORD LimitH; //32位偏移的高16位}  ③全局描述符表寄存器GDTR  GDTR长48位,其中高32位为基地址,低16位为界限,GDTR中的段界限以字节为单位。在VC中定义如下: struct GDTR{ WORD wGDTLimit; DWORD dwGDTBase;};  四、具体实现  使用MFC AppWizard新建一个基于对话框的应用程序,工程名为MyRing0。在对话框中添加一个按钮,修改ID为ID_GETCR0,修改Caption为取CR0的值,同时添加该按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()。新建一个头文件Ring0.h并添加到工程中,添加下面的代码到Ring0.h中。 #pragma pack(1)struct GDT_DESCRIPTOR{ WORD LimitL; //段界限低16位 WORD BaseL; //基地址低16位 BYTE BaseM; //基地址中间8位 BYTE AttriB; //段属性 BYTE LimitH; //段界限的高4位(包括段属性的高4位) BYTE BaseH; //基地址的高8位}; struct GATE_DESCRIPTOR{ WORD OffsetL; // 32位偏移的低16位 WORD Selector; //选择子 BYTE Dcount; //双字计数字段 BYTE Gtype; //当低4位值为0xC是,这是一个调用门 WORD LimitH; //32位偏移的高16位};struct GDTR{ WORD wGDTLimit; DWORD dwGDTBase;};#pragma pack()  在MyRing0Dlg.cpp中最后一个include语句后添加#include "Ring0.h",在按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()前面添加下面两个函数: __declspec(naked) void GetCR0_Ring0(){ _asm{ mov ebx,cr0 //特权指令 mov [EAX],ebx retf}}bool CallRing0(PVOID pvRing0FuncAddr,PWORD pVal){  struct GDT_DESCRIPTOR *pGDTDescriptor; struct GDTR gdtr; WORD CallgateAddr[3]; WORD wGDTIndex = 1; //取得全局描述符表GDT _asm Sgdt [gdtr] // 空选择子有特殊用途,跳过它,从第二个选择子开始搜索 pGDTDescriptor = (struct GDT_DESCRIPTOR *)(gdtr.dwGDTBase 8); for (wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex ) {  if (pGDTDescriptor->AttriB == 0)  {   struct GATE_DESCRIPTOR *pGate;   pGate = (struct GATE_DESCRIPTOR *) pGDTDescriptor;   pGate->OffsetL = LOWORD(pvRing0FuncAddr);   //选择子0x28总是指向Ring0的代码段   pGate->Selector = 0x28;   pGate->Dcount = 0;   pGate->Gtype = 0xEC;   pGate->OffsetH = HIWORD(pvRing0FuncAddr);   //准备远程调用参数   CallgateAddr[0] = 0x0;   CallgateAddr[1] = 0x0;   CallgateAddr[2] = (wGDTIndex << 3) | 3;   //进入Ring0   _asm Mov EAX,[pVal]   _asm call FWORD PTR [CallgateAddr]   //归还刚才使用的全局描述符   memset(pGDTDescriptor, 0, 8);   return true;  }  //下一个全局描述符  pGDTDescriptor ;  } //没有空闲的全局描述符 return false;}  为按钮的消息处理函数void CMyRing0Dlg::OnGetcr0()添加代码如下: void CMyRing0Dlg::OnGetcr0() { // TODO: Add your control notification handler code here WORD Val=0; char str[16]; if(!CallRing0((PVOID)GetCR0_Ring0,&Val)){  AfxMessageBox("系统资源不够!");  return; }; sprintf(str,"CR0==",Val); AfxMessageBox(str); }   程序在VC6下编译通过,操作系统为Windows98。 下载本文示例代码


用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作用Visual C 实现CPU特权指令操作
阅读(196) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~