shellmic 发表于 2011-08-15 12:31

段界限检查

有个项目在困扰着我,因为是别人遗留的项目,因此只得自己参详(也没有具体源码),具体如下:
========
例子1
========

编写一个函数库,提供对特殊代码的处理,且这个函数库里的函数可以被其他应用程序调用。遗留的设计(下面通过例子简要说明)如下:

假设待编写的函数库名为 obj_lib,使用obj_lib的应用程序名为 host_app ,待处理的代码名为 un_code 和 其处理后的结果 obj_code。当host_app要处理un_code时,它会调用obj_lib里的函数在host_app的内存空间里动态创建2个段,一个用来存放un_code,另一个用来存放obj_code。这2个段对应的描述符都将保存于LDT里。处理过程中,host_app会分析un_code,并将分析结果放入obj_code中(即放入第二个段里)。最后,host_app执行obj_code里的代码。
问题如下:

1、为何要动态创建2个段来存放un_code及obj_code?按设计上说是这样可以进行段边界检测。即在执行obj_code的过程中,如果存在jmp的转移指令,则可以通过段界限去检测这个转移是否合法。对于段界限的检测,我以前只是知道有这么一回事,但从来没有去试验过。翻了一下资料,找到了一个例子,如下:
========
例子2
========

//定义
L_G        :        DESC                0,             0,        0
L_CODE        :        DESC                0, lencode - 1,        DA_C + DA_32
L_VIDEO        :         DESC          0B8000h,        0ffffh,        DA_DRW

GLEN        equ        $ - L_G
GPTR        dw        GLEN - 1
        dd        0

selector_v        equ        L_VIDEO        - L_G

........

//配置
        mov        ax, cs
        movzx        eax, ax
        shl        eax, 4
        add        eax, L_CODE
        mov        word , ax
        shr        eax, 16
        mov        byte , al
        mov        byte , ah

......

//加载GDT
        xor        eax, eax
        mov        ax, ds
        shl        eax, 4
        add        eax, L_G                ; eax <- gdt 基地址
        mov        dword , eax        ; <- gdt 基地址

        lgdt       

.....

//在保护模式里,配置视频段
        mov        ax, selector_v
        mov        gs, ax

.....

//用于测试视频段的函数片段
......
        xor        edi, edi
......
.1:
        lodsb
        test        al, al
        jz        .2
        mov        , ax
        add        edi, 2
        jmp        .1
.2:        ; 显示完毕

......
       
例子2对于视频段,对应的描述符为L_VIDEO,选择子为selector_v,而配置给视频段的是段寄存器gs,而显示输出的偏移为edi。由于显示的范围在描述符里已设定,即 0 <= edi <= 0ffffh。因此,edi不能显示0b8000:0ffff之后的内容(如果edi大于0ffffh,是简单的不显示还是出现异常报错?这个我还没有测试过)。视频段的例子与之前的un_code的段应该是差不多的,都是对数据的检测。不知道我理解的对不对?


2、例子2的代码段,其描述符为L_CODE,对应的段寄存器为CS,其段界限为lencode - 1。则对于代码段里的每条指令,其唯一的检索是CS:EIP。如果存在指令 JMP A,则A的范围为 cs:0 <= A <= cs:lencode - 1。那也就是在算界限的时候,必须使用到CS,不能简单地像视频段一样使用gs或fs。再说的清楚一点,对于之前的例子里的 obj_code段来说(跟这里的代码段是类似的),obj_code段必须是可以单独获得CPU调度的段,它的EIP是从0开始算的。即,如果host_app是系统里众多进程里的一个,那obj_code则是它的一个线程,可以被单独调度,拥有单独的EIP。否则,如果obj_code不是被单独调度的话,那它的首指令的EIP就不是0,而是obj_code首指令基于host_app的偏移。这样的偏移是无法通过obj_code里的段界限去约束obj_code段里的转移语句是否合法的。

也就是说,例子1成立的前提是运行在多线程环境里,且obj_code段对应一个线程,是可以被单独调度的。是这样吗?

3、如果以上都不对的话,那想请教该如何理解段界限的检测?

shellmic 发表于 2011-08-15 12:34

回复 1# shellmic


    顶
页: [1]
查看完整版本: 段界限检查