gpt4 book ai didi

linux - 无法使代码段只执行(不可读)

转载 作者:太空宇宙 更新时间:2023-11-04 09:20:35 26 4
gpt4 key购买 nike

我试图让代码段只执行(不可读)。

但在我尝试了手册告诉我的所有操作后,我失败了。这是我使代码段不可读的方法。

>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

首先,我在“Intel(R)64 and IA-32 Architectures Software Developer's Manual(Combined Volumes 1,2A,2B,2C,2D,3A,3B,3C and 3D)": Set read-enable bit to enable readSegment Types .(抱歉,我仍然不允许在我的帖子中嵌入图片,所以链接代替)

所以,我想如果我更改 %CS,并让它指向一个将读取启用位设置为 0 的段描述符,我应该使代码段不可读。

然后,我使用下面的代码将一个新的段插入到 LDT.entry[2] 中,并将代码段类型设置为 8,即 1000B,根据“段类型”,这意味着“仅执行”上面发布的链接:

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));

之后,我使用 ljmp 将 %CS 更改为 0x17(00010111B,表示 LDT 中的条目 2)。

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 成功。

所以,我想知道,我在测试过程中是否犯了任何错误?或者这只是英特尔手册中的一个错误?

最佳答案

在执行(unsigned int)a[0] 时,您仍在通过DS 访问代码。

只写段不存在(如果存在,将 DS 设置为只写将不是一个好主意)。

如果你做的一切都正确 mov eax, [cs:...] (NASM 语法)将失败(但是 mov eax, [ds:...]不会)。


快速浏览英特尔手册后,只执行页面不应该存在(至少直接),所以使用 mprotect使用 PROT_EXEC 可能用途有限(代码仍然可读)。
不过值得一试。

可以通过三种方式解决这个问题。
但是,如果没有操作系统的帮助,这些都无法实现,因此它们的理论性多于实践性。

保护键

如果 CPU 支持它们(参见 Intel 手册 3 的 4.6.2 节),它们会在读取代码和数据的方式上引入不对称。

读取数据受 key 保护。然而,获取不是:

How a linear address’s protection key controls access to the address depends on the mode of a linear address:

  • A linear address’s protection controls only data accesses to the address. It does not in any way affect instructions fetches from the address.

因此可以为应用程序的 PKRU 寄存器中没有的代码页设置保护 key 。
您仍然可以执行代码,但不能阅读它。

取消 TLB 的同步

如果您的应用程序从未接触过要读取的代码页,它们将占用 ITLB 中的一些条目,但不会占用 DTLB 中的一些条目。
如果然后,操作系统将它们映射为仅管理器而不刷新 TLB,则在作为数据访问时将阻止对它们的访问(因为不存在这些页面的 DTLB 条目,强制在内存上走动),但感谢 ITLB,代码仍然可以获取。

这更多地涉及到实践,因为代码跨越多个页面并且实际上被操作系统读取为数据。

EPT

扩展数据页在虚拟化过程中用于将客户物理地址转换为主机物理地址。
尽管它们看起来只是另一个间接级别,但它们具有独立的读取、写入和执行控制位

A paper has been written关于防止内核代码泄露(抵消动态返回导向编程)。

关于linux - 无法使代码段只执行(不可读),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42368380/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com