【发布时间】:2017-07-11 03:19:06
【问题描述】:
我正在尝试使代码段只执行(不可读)。
但是在我尝试了手册告诉我的所有操作之后,我失败了。这是我为使代码段不可读所做的操作。
>uname -a
Linux Emmet-VM 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015 i686 i686 i686 GNU/Linux
>lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.3 LTS
Release: 14.04
Codename: trusty
首先,我在“英特尔(R)64 和 IA-32 架构软件开发人员手册(组合卷 1、2A、2B、2C、2D、3A、3B、3C 和 3D)中找到了这个/em>": Set read-enable bit to enable read 和 Segment Types.(对不起,我的帖子中仍然不允许嵌入图片,所以用链接代替)
所以,我想如果我改变 %CS,让它指向一个读使能位设置为 0 的段描述符,我应该使代码段不可读。
然后,我使用下面的代码在 LDT.entry[2] 中插入一个新的 Segment,并且我将代码段类型设置为 8,即 1000B,这意味着根据“Segment Types”的“Execute-Only”上面发布的链接:
typedef struct user_desc UserDesc;
UserDesc *seg = (UserDesc*)malloc(sizeof(UserDesc));
seg->entry_number = 0x2;
seg->base_addr = 0x00000000;
seg->limit = 0xffffffff;
seg->seg_32bit = 0x1;
seg->contents = 0x02;
seg->read_exec_only = 0x1;
seg->limit_in_pages = 0x1;
seg->seg_not_present = 0x0;
seg->useable = 0x0;
int ret = modify_ldt(1, (void*)seg, sizeof(UserDesc));
之后,我将 %CS 更改为 0x17(00010111B,表示 LDT 中的条目 2)并使用 ljmp。
asm("ljmp $0x17, $reload_cs\n"
"reload_cs:");
但是,即使这样,我仍然可以读取代码段中的字节码:
void foo() {printf("foo\n");}
void test(){
char* a = (char*)foo;
printf("0x%x\n", (unsigned int)a[0]);// This prints 0x55
}
如果代码段不可读,上面的代码应该抛出一个segment fault 错误。但它会成功打印0x55。
所以,我想知道,我在测试期间是否犯了任何错误? 或者这只是英特尔手册中的一个错误?
【问题讨论】:
-
没错,你不能在 IA 中这样做。