win2000下,
1.为什么在ring0无法执行一些api,比如messagebox之类?
2.ring0代码遭遇缺页,系统会是什么反应?
3.如何彻底解决ring0缺页??先给100分!!!谢谢先!!!!

解决方案 »

  1.   

    1. MessageBox是三级代码,如果调用必须通过中断门或者调用门实现ring0到ring3的转换才能调用
    2. 不是很清楚你说的“缺页”,即使在ring0下,系统的内存分配逻辑当然正常运行,不然系统内核不是挂了(不单单只有你在ring0里)!“缺页”是指当指定的虚拟内存不在物理内存里,那么如果发生的话,硬件会产生个中断,然后会进入系统缺页中断处理程序,处理完后退出来,再继续原程序运行!
    3. 缺页完全由系统内核来接管,不需要别的程序插手(也完全没有这个必要!!!除非你写的调度程序比微软好!)所以你看到的“缺页”可能是指针的非法操作引起的,而不是真正的“缺页”!换句话,任何时候程序都有可能发生内存“缺页”,但绝对不需要ring0程序去关心,除非一次分配的内存大于你机器的物理内存!
      

  2.   

    我所说的缺页就是不在ram中的时候,要由windows内核来进行页面调度,
    但由于通过调用门进入ring0,和系统的进入方式有一定区别,可能会和内核的调度
    产生冲突
    看看下面:
    PAGING ISSUES  While writing the callgate sample, we observed that there are certain issues regarding accessing the paged/swapped out data in the interrupt routine and also in the function called through callgate. All the existing interrupt handlers such as INT 2Eh were seen to follow certain entry and exit code before performing any real work. Some of the tasks performed by the entry code were: 
    1.Creates some space on stack. 
    2.Prepares a trap frame that will record the state of some of the CPU registers. 
    3.Saves away some of the fields in Thread Environment Block such as processor mode and one field in TEB, which SoftICE calls as "KSS EBP." We don’t know the exact meaning of this, but its seems that each interrupt handler should set this field to the trap frame created in previous step. 
    4.Saves away the contents of FS register and sets FS register to 0x30. 
     Out of all these steps, the first step is absolutely necessary and is related to the logic used by page fault handler of the operating system. The page fault handler does some arithmetic on the current stack pointer and the stack pointer at the time of ring transition from ring 3 to ring 0 and take some decisions. If at least a specific amount of stack space is not found between these two stack pointer values, then the system crashes with a Blue Screen.It is essential that you follow this while writing interrupt handlers or functions executed through callgate to successfully access paged out data. The fourth step of setting FS register to 0x30 is also necessary since the system expects FS register to point to Processor Control Region when the thread is executing in ring 0 and the selector 0x30 points to the descriptor with the base address equal to address of processor control region.Note: Note that you have to follow the same steps while hooking software interrupts. The second and third step seems to be only for bookkeeping information.
      

  3.   

    你是要自己写中断处理程序吗?代替系统中断?
    上面E文说了这个步骤,那么关键是堆栈的问题,其实即使是普通程序,也存在堆栈溢出的问题,堆栈不是无限大的!ring3程序还好,堆栈比较大,但是ring0程序就切记,堆栈很小的,写ring0比较要注意的就是:
    1. 不要定义太多的局部变量
    2. 还有函数嵌套调用不能太多
    只要注意了这些,上述的system crashes就不会了(别的原因还可能会!)
      

  4.   

    我不是要写handler,只是做了一个通过调用门进入ring0的函数,
    想作为dll,方便我以后使用,所以在这出了点小问题....
    e文说系统的中断处理在开始和结尾都有一段操作,这些操作是为了能够
    顺利的访问已经被page out的数据,估计也就是缺页处理在handler这段ring0程序执行时
    正常行使自己的权力,把换出的内存页重新调入内存,
    如果我进入ring0的程序没有这段预处理的话,可能缺页处理程序无法正常运行,我的
    代码也就访问不了已经被换出的内存页了,而访问时会出现兰屏
    所以我想知道由于缺页而产生的蓝屏是什么样的(我想试试这里的方法到底管不管用,还有其他的方法)
    怎样才能让我的程序顺利访问已换出的页面,按照这里说的步骤行不行呢?
      

  5.   

    FS改为0x30的意思是指向局部描述符表中的一个描述符,它是可以接管缺页异常的一个入口,其实这个机制在ring3里也有类似的,比如
    try() catch(...)就是,
    你打开VC的反汇编,可以看到它构造了一个异常处理,
    mov         eax,fs:[00000000]
    push        eax
    mov         dword ptr fs:[0],esp
    即SEH,如果程序把fs:[00000000]的值改为任意值,当程序出错时,系统是不会出“异常对话框”的,因为是ring3,所以不至于crash,但是内核的异常处理链不对的话,将会导致蓝屏,
    换句话,必须严格按照Windows的定义去写,否则将会蓝屏
      

  6.   

    ring0不太熟,不过这篇文章你可以参考以下:众 所 周 知, 在Windows95/98 的Win32 on Intel x86 体 系 中 利 用 了 处 理 器 的 三 环 保 护 模 型 中 的 零 环(Ring0, 最 高 权 限 级 别) 和 三 环(Ring3, 最 低 权 限 级 别)。 一 般 应 用 程 序 都 运 行 在Ring3 下, 受 到 严 格 的" 保 护", 只 能 规 矩 地 使 用Win32API。 如 果 我 们 想 进 行 一 些 系 统 级 的 操 作, 例 如 在 嵌 入 汇 编 中 使 用 诸 如"Mov EAX,CR0", 或 像 在DOS 下 那 样 调 用 一 些 必 不 可 少 的 系 统 服 务( 如BIOS,DPMI 服 务) 而 用"Int xx", 都 会 导 致" 非 法 操 作"。 但 这 种 能 力 有 时 是 必 不 可 少 的, 一 到 这 种 时 候Microsoft 就 " 建 议 编 写 一 个VxD"。VxD 大 家 早 有 所 闻 了, 在VxD 里, 不 但 可 以 执 行CPU 的 所 有 指 令, 而 且 可 以 调 用VMM( 虚 拟 机 管 理 器) 和 其 他VxD 提 供 的 上 千 个 系 统 级 服 务。 获 得 这 一 能 力 的 最 本 质 原 因 在 于 它 运 行 在Ring0, 与 系 统 内 核 同 一 级 别。 但 是 它 体 系 的 复 杂 性、 开 发 工 具 的 不 易 获 得、 帮 助 文 档 的 不 完 备, 使Microsoft 排 除 了 一 大 批 程 序 员 和 竞 争 对 手。 而 将 在Windows2000(Windows98 也 开 始 支 持) 中 取 代VxD 的WDM 对Win95 程 序 员 也 是 个 噩 梦, 它 需 要 了 解Windows NT 核 心 驱 动 模 型。 ----有 没 有 简 单 一 些 的 办 法 呢 ? 我 们 可 以 令 一 个 普 通Win32 应 用 程 序 运 行 在Ring0 下, 从 而 获 得VxD 的 能 力 吗 ? 答 案 是 肯 定 的。 下 面 我 们 就 简 述 一 下 这 一 技 巧, 有 关Intel x86 保 护 模 式 的 基 础 知 识 请 大 家 看 有 关 书 籍。 ----首 先 此 技 巧 基 于 以 下 理 论 根 据: ----一、SIDT 指 令( 将 中 断 描 述 符 表 寄 存 器 IDTR - -64 位 宽,16 ~47Bit 存 有 中 断 描 述 符 表IDT 基 地 址 - - 的 内 容 存 入 指 定 地 址 单 元) 不 是 特 权 指 令, 就 是 说 我 们 可 以 在Ring3 下 执 行 该 指 令, 获 得IDT 的 基 地 址, 从 而 修 改IDT, 增 加 一 个 中 断 门 安 置 我 们 的 中 断 服 务, 一 旦Ring3 程 序 中 产 生 此 中 断,VMM 就 会 调 用 此 中 断 服 务 程 序, 而 此 中 断 服 务 程 序 就 运 行 在Ring0 下 了。 这 一 点 与 在DOS 下 非 常 相 似。 ----二、Windows95 Win32 应 用 程 序 运 行 一 个 映 射 到 全 部4G 内 存 的 段 中, 选 择 子 为0137h,Ring0 中 的VxD 运 行 在 另 一 个 映 射 到 全 部4G 内 存 的 段 中, 选 择 子028h, 这 两 个 段 除 了 选 择 子 决 定 的 访 问 权 限 不 同 外, 没 什 么 不 同, 各 自 段 中 相 同 的 偏 移 量 对 应 了 相 同 的 线 性 地 址。 所 以 我 们 放 在Win32 应 用 程 序 中 的 中 断 服 务 程 序 可 以 以Ring3 的 段 偏 移 量 被Ring0 中 的VMM 寻 址。 ----下 面 我 们 以 具 体 例 子 进 一 步 说 明, 程 序 中 有 详 细 注 释。 ----这 是 一 个Win32 Console Program( 控 制 台 应 用 程 序), 虽 然 运 行 中 看 起 来 很 像DOS 筐 中 运 行 的 实 模 式DOS 程 序, 但 它 是 货 真 价 实 的 运 行 在Ring3 下 的Win32 程 序。 用Visual C + + 5.0 AppWizard 创 建 一 个Win32 Console Program 项 目, 添 加 以 下.CPP 文 件, 编 译 即 可。  #include
     #include
     #include
     #include 
      // 若 无DDK 带 下 划 线 的 可 略 去,
      这 些 语 句 演 示 了 调 用VMM/VXD 服 务
    DWORDLONG IDTR,SavedGate;
    WORD OurGate[4]={0,0x0028,0xee00,0x0000};
    // 中 断 门 描 述 符 格 式 如 下:
    DWORD _eax,_ecx,_cr0;
    WORD vmmver;
    HVM sysvm;void nothing()
    {
          //Used to test call in Ring0
          sysvm=Get_Sys_VM_Handle();
    }void __declspec( naked ) Ring0Proc(void)
      // 中 断 例 程, 运 行 在Ring0
    {
          _asm{
                mov   _eax,eax    //
                mov   _ecx,ecx    //
                mov   eax, CR0    
       // 测 试Ring3 中 不 能 执 行 的 特 权 指 令
                mov   _cr0,eax    //
          }
                VMMCall(Get_VMM_Version); 
      // 调 用VMM 服 务
          _asm{
                mov vmmver,ax
          }
          nothing();  
      // 测 试 在 运 行 于Ring0 的 
        中 断 例 程 中 调 用 子
          _asm  iretd   
      // 中 断 返 回, 与 在 实 模 式 
        编 程 无 本 质 区 别
    }
    void main() // 主 程 序
    {
          _asm{
          mov   eax, offset Ring0Proc
          mov   [OurGate], ax  // 将 中 断 函 数 的 地 址
          shr   eax, 16   // 填 入 新 造 的 中 断 门
          mov   [OurGate +6], ax // 描 述 符      sidt  fword ptr IDTR    
      // 将 中 断 描 述 符 表 寄 存 器(IDTR)
         的 内 容 取 出
          mov   ebx, dword ptr [IDTR +2]
      // 取 出 中 断 描 述 符 表(IDT) 基 地 址
          add   ebx, 8 *9  
       // 计 算Int 9 的 描 述 符 应 放 置 的 地 址 选 用
        Int9 是 因 为 它 在Win32 保 护 模 式 下 未 占 用      mov      edi, offset SavedGate
          mov      esi, ebx
          movsd   // 保 存 原 来 的Int 9 描 述 符 到
          movsd  //SavedGate 以 便 恢 复      mov      edi, ebx
          mov      esi, offset OurGate
          movsd  // 替 换 原 来 的 中 断 门 描 述 符
          movsd  // 以 安 装 中 断 服 务 例 程      mov   eax,0x6200 
       // 用 以 测 试 放 在EAX 中 的 数 据
         能 否 正 确 传 到Ring0 中 断
          mov   ecx,0 
       // 用 以 测 试 放 在ECX 中 的 数 据 
         能 否 正 确 传 到Ring0 中 断
          mov   ecx,0 
       // 用 以 测 试 放 在ECX 中 的 数 据 
         能 否 正 确 传 到Ring0 中 断
                   // 因 为 很 多VxD 服 务 都 用
                     此 二 寄 存 器 传 递 参 数
          int  9h  
         // 人 为 触 发 中 断, 平 时 会 出 现
           保 护 错 误 蓝 屏 或 非 法 操
                 // 作 对 话 框, 现 在 安 装 了
                 // 中 断 服 务 例 程 后, 就 会 通 过
                 //VMM 在Ring0 调 用 中 断 服 务 例 程
                    - -Ring0Proc      mov    edi, ebx
          mov    esi, offset SavedGate
          movsd // 恢 复 原 来 的 中 断 门 描 述 符
          movsd
          }
          cout<<"CR0="<<_cr0;
      

  7.   

    WIN98和2K对RING0的控制不一样,这篇文章基本无效
      

  8.   

    我按照e文的说法试了一下,可以正常运行,
    但我把该段代码去掉,也可以运行,
    可能是我的测试程序不够好,没有遇到缺页的情况
    怎么样才能让我的测试程序遇到缺页呢?30选择子在gdt中的基址是0xffdf000,该处是KPCR的位置
      

  9.   

    写个驱动运行想在ring0运行的代码,又方便又简单
      

  10.   

    很简单,就是不停的测试,反复的测试,可以写个自动测试程序,如果很长时间不出问题,可以近似的认为没有问题了(要知道微软测试windows都是动用的上千台机器同时测),而且这个缺页异常我觉得跟你的程序没多大关系,即使有也不会影响你的程序,那正确与否只有多测试了
      

  11.   

    程序写好了,马上开学了,试了几次没什么问题
    留着以后用的时候再测试吧
    谢谢roger_ding(海天一色)这几天与我讨论了这么多,
    帮了我很大的忙!!谢谢!
    谢谢其他热心回帖的朋友!!