段界限检查
有个项目在困扰着我,因为是别人遗留的项目,因此只得自己参详(也没有具体源码),具体如下:========
例子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、如果以上都不对的话,那想请教该如何理解段界限的检测? 回复 1# shellmic
顶
页:
[1]