我翻译成Delphi的。我测试过你的程序在BCB中可以通过,但是在Delphi中,sidt 指令却不能编译,那位高手知道如何修改?我可以单独开贴子送分!
const IntNo=9;var
IDTR,SavedGate:int64;
OurGate:array[0..3] of word=(0,$0028,$ee00,$0000);procedure Ring0Proc;  // 在Ring0中执行你自已的代码
begin
    // .......
    asm
    mov eax,CR0;  // 试验一下Ring3不能执行的特权指令
    end;
end;
// =====================================================
procedure   NewInt(); //新中断
begin
      Ring0Proc();
      asm
      iretd;
      end;
end;procedure  GotoRing0;
begin
      asm
            mov  eax,offset NewInt;
            mov  word ptr[OurGate],ax;
            shr  eax,16;
            mov  word ptr[OurGate+6],ax;
            sidt fword ptr IDTR;//此处不能通过!如何修改?
            mov  ebx,dword ptr [IDTR+2];
            add  ebx,IntNo*8;
            mov  edi,offset SavedGate;
            mov  esi,ebx;
            movsd;
            movsd;
            mov  edi,ebx;
            mov  esi,offset OurGate;
            movsd;
            movsd;
            int  IntNo;
            mov  edi,ebx;  // 开始恢复原中断门
            mov  esi,offset SavedGate;
            movsd;
            movsd;
        end;
end;
// ===================================================procedure TForm1.Button1Click(Sender: TObject);
begin
 gotoring0;
end;

解决方案 »

  1.   

    换成
    lea ebx, idtr;
    sidt [ebx]
      

  2.   

    为了优化,对原程序改动,取消OurGate数组, 
    直接修改原中断门,程序就出错,原来数组中
    第三项0ee00h是门属性,不能不设,不太明白;
    IDTR与SavedGate可以合二为一成Buf,注意:
    此Buf可以须是全局或静态变量,不能是栈中
    分配的动态变量,原因可能是传送指令movsd的
    操作数不是相对于栈段;
    void Ring0Proc()  // 在Ring0中执行你自已的子程序
    {
         asm mov eax,CR0;  // 测验Ring3不能执行的特权指令
    }
    // =====================================================
    void  __declspec(naked) NewInt() //新中断
    {
          Ring0Proc();
          asm  iretd;
    }
    #define IntNo  3void  GotoRing0()
    {
          static DWORDLONG Buf;      //静态或全局变量
          asm
             {
                mov    edi,offset Buf;
                sidt   [edi];       // 取IDT->Buf
                mov    ebx,[edi+2]; // 求中断门基址
                add    ebx,IntNo*8;
                mov    esi,ebx;
                push   edi;
                push   esi;
                movsd;        //保存原中断门->Buf
                movsd;            cli;
                mov    eax,offset NewInt;
                mov    [ebx],ax;
                shr    eax,16;
                mov    [ebx+6],ax;  // 修改新中断门
                mov    ax,0ee00h;
                mov    [ebx+4],ax;  // 设置门属性            int    IntNo;            pop    edi;
                pop    esi;
                movsd;              // 恢复原中断门
                movsd;
                sti;
             }
    }
    // ===================================================void __fastcall TForm1::Button1Click(TObject *Sender)
    {
         GotoRing0();
    }改动后的程序,若有新问题,请再贴!!!!!!
      

  3.   

    to BCB:
        $EE00代表:已经映射到物理内存的访问等级为3的386中断门。
        我在2K下,没有调试。不过,不觉得你这样写程序有什么好。虽然是少用了4字节的存储空间,且不说代码却多了2条。而且使得程序流程晦涩难懂,这在汇编程序中是致命的问题。
      

  4.   

                            push   eax                                   
                            sidt    [esp-02h]       
                            pop     ebx 
    这样如何?
      

  5.   

    在Ring3能执行API函数吗?,难道又只能用汇编?
      

  6.   

    非常感谢GoodHope等热心的网友指点!
    对于门属性,未改前好象是8e00h,要改成0ee00h,才能成功,不知为什么?
    代码重改的理由,不是针对几个字节或指令,主要是针对OurGate 数组:
        OurGate[1]是选择子,它设成0028h,没有必要;所以取消
    OurGate数组是应该的,改动后的流程还能算符合常理:
       取IDT->取中断门地址->保存旧中断门(且暂存源、目)-> 修改中断门->
    执行中断->取出源、目且恢复旧门
       修改后如果仍能正常,就满意了!
    最后一个问题:
       取得了特权ring0,我们能搞些什么应用????看了原文章,主要:
      1.能执行特权指令了;
      2.能执行BIOS了;
      3.能执行VMM(虚拟管理器)管理了;
      4.能执行DPMI服务了;
    除了共知的CIH外,似乎“用处”大得“狠”,请高手解释!!!!!!!!!
     
      

  7.   

    能不能封装两个函数出来?EnableRing0();DisableRing0();我在Delphi中测试,一运行就重新启动,或者出现蓝屏!
      

  8.   

    $8e00是已经映射到物理内存的访问等级为0的386中断门。自己的应用初始等级是3,是无法访问这段内存的。
    Win9x下所有的选择子的基址像都一样,所以修改了也没关系。不然,你只修改了入口地址,却没有把门的段选择子改为自己代码段选择子,也是有问题的。如果要保险起见,可以将CS也填入到OurGate中去。取得Ring0其实最重要的作用是执行特权指令,以便随意访问硬件资源(主要是内存),从而可以修改Windwos的核心。2~3的内容在NT下都废除了,用处不大。另外,Ring0下CLI然后HLT,可就真的死机了,只能Reset了^_^。
      

  9.   

    to Kingron:
    是你“改进”后出现“兰屏”,还是本人提供的程序就出现“兰屏”?
    在RING0下,也就是一会儿,又回到Ring3,象你用“开关”式的切换
    可能较困难.
      

  10.   

    to GoodHope:
     经测试:选择子,修改前后,都是0028H,我原想就不设定了;
     另外,你的意思int 3前加一条 STI,
    ok!
      

  11.   

    to Kingron:
       你要常调用GotoRing0(),可将原Ring0Proc 稍改到一下,用函数名
    做参数如:
        GotoRing0(Ring0Proc1);
        .....
        GotoRing0(Ring0Proc2);
        .....
    就没必要做成“开关”式的切换了,拥有
    “特权”的时间不宜太长.
      

  12.   

    这段代码只是在自己中断处理程序中拥有RING0权限,出来了就没了。要想长期拥有Ring0,必须在中断中趁拥有Ring0权限,修改原程序段的属性,这个操作就复杂了。to:BCB
      我的意思是只有Ring0下才能轻易让机器彻底死掉。所以一般不要切过来,在Ring0下,程序错误的后果会非常严重。
      

  13.   

    哦,IC。
    ***********************************************
    你要常调用GotoRing0(),可将原Ring0Proc 稍改到一下,用函数名
    做参数如:
        GotoRing0(Ring0Proc1);
                  ~~~~~~~~~~
        .....
        GotoRing0(Ring0Proc2);
                  ~~~~~~~~~~~
        .....
    就没必要做成“开关”式的切换了,拥有
    “特权”的时间不宜太长.
    ****************************************