| 站点地图 | 联系我
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | 书签 | ASP.Net书签 | 上善若水 厚德载物
 现在位置 :: 主页 >> 资料中心 >> ROOT / CODE / C/C++ /
 

令 Win32 应用程序跳入系统零层 (C++ Builder)

来源(安全矩阵(Security Matrix)学术与技术论坛)

From: http://www.smatrix.org/bbs/simple/index.php?t74.html

令 Win32 应用程序跳入系统零层

众所周知 , 在 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 <conio.h>
#include <iostream.h>
#include <windows.h>
#include <vmm.h>    // 若无 DDK 带下划线的可略去 , 这些语句演示了调用 VMM/VXD 服务
DWORDLONG IDTR,SavedGate;
WORD OurGate[4]={0,0x0028,0xee00,0x0000};
// 中断门描述符格式如下 : 图 1

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<<endl;
    cout<<"EAX received in Ring0="<<_eax<<" ECX received in Ring 0="<<_ecx<<endl;
    cout<<"VMM Ver="<<vmmver<<endl;
    cout<<"SYSTEM VM="<<sysvm<<endl;
    cout<<"Press any key to continue."<<endl;
    do{} while(_kbhit()==0);
    if(0==_getch())
    _getch();
}


运行结果 :

图 2

此方法的好处一是回避了奇特的 VxD 文件格式 , 不用使用汇编语言编程 , 二是应用程序不用带一个单独的 VxD 文件 , 干净利索。

值得一提的是 , 许多文章描述著名的 CIH 病毒都说其利用了 VxD 技术 , 是说它带一个单独的 VxD 文件吗 ? 显然不可能 , 实际上 CIH 病毒使用的就是以上技巧 , 进入 Ring0 后调用 VMM 服务分配一块内存 , 把自身拷贝进去 , 然后用 IFS VxD 的 IFSMgr_InstallFileSystemApiHook 服务安装文件系统监视以感染其他文件 , 只不过 CIH 病毒安装的是 Int 3 中断 , 这跟在 DOS 下没什么两样。我们也可以对此了解以更好地防范 CIH 病毒。

最后还要指出其缺陷 , 这个技巧仅能用在 Windows95/97/98 下 , 在 Windows NT 下行不通。不过听说 CIH 病毒的作者已经开发了 NT 版的 CIH 病毒 , 说明 NT 中也有类似的 " 后门 " 。

Link: http://www.asm32.net/article_details.aspx?id=1898


浏览次数 364 发布时间 2006/8/25 5:02:12 从属分类 C/C++ 【评论】【 】【打印】【关闭
 
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | 书签 | ASP.Net书签 | 京ICP备09029108号-1