- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我在引用这篇论文:
二进制搅拌:的自随机指令地址
旧版x86二进制代码
https://www.utdallas.edu/~hamlen/wartell12ccs.pdf
代码与数据交织:现代编译器积极地交织
PE和ELF二进制文件中的代码段中的静态数据
性能原因。在编译的二进制文件中,通常没有
从代码中区分数据字节的方法。无意间
将数据与代码随机化会破坏二进制文件,
给指令级随机化器带来了困难。可行的
解决方案必须以某种方式保留数据,同时将所有
可达代码。
但是我有一些问题:
如何提高程序速度?我只能想象这只会使cpu的执行更加复杂吗?
CPU如何区分代码和数据?因为据我所知,除非存在跳转类型的指令,否则cpu将以线性方式依次执行每个指令,那么cpu怎么知道代码中的哪些指令是代码,哪些指令是数据?
考虑到代码段是可执行的,并且CPU可能会错误地将恶意数据作为代码执行,因此这对安全性是否非常不利? (也许攻击者将程序重定向到该指令?)
最佳答案
是的,他们提出的二进制随机化器需要处理这种情况,因为可能存在混淆的二进制文件,或者手写代码可能会执行任意操作,因为作者并不了解或出于某种奇怪的原因。
但是,不,普通编译器不会针对x86执行此操作。该答案针对书面提出的SO问题,而不是包含这些主张的论文:
出于性能原因,现代编译器在PE和ELF二进制文件的代码段中积极插入静态数据
需要引用!在我使用GCC和clang之类的编译器的经验中,对于x86来说,这完全是错误的,并且有些经验是从MSVC和ICC看asm输出的。
普通的编译器将静态只读数据放入section .rodata
(ELF平台)或section .rdata
(Windows)。 .rodata
节(和.text
节)被链接为文本段的一部分,但是整个可执行文件或库的所有只读数据都被分组在一起,而所有代码则被分别分组在一起。 What's the difference of section and segment in ELF file format(或者最近,即使在单独的ELF段中,也可以将.rodata
映射为noexec。)
Intel's optimization guide表示不要混合代码/数据,尤其是读写数据:
汇编/编译器编码规则50。(M影响,L通用性)如果(希望是只读的)数据必须
与代码出现在同一页面上,请避免在间接跳转之后立即将其放置。例如,
跟随间接跳转及其最可能的目标,然后将数据放在无条件分支之后。
汇编/编译器编码规则51。(对H的影响,对L的一般性)始终将代码和数据放在
单独的页面。尽可能避免自我修改代码。如果要修改代码,请尝试在以下位置进行所有操作
一次并确保执行修改的代码和正在修改的代码处于打开状态
单独的4 KB页面或单独的对齐的1 KB子页面。
(有趣的事实:Skylake实际上具有用于自修改代码管道核的高速缓存行粒度;在最近的高端用户中,将读/写数据放在64字节的代码内是安全的。)
在同一页面中混合使用代码和数据在x86上具有接近零的优势,并且浪费了代码字节的data-TLB覆盖范围,浪费了数据字节的指令-TLB覆盖范围。在64字节高速缓存行中也是如此,以浪费L1i / L1d中的空间。唯一的优势是统一缓存(L2和L3)的代码+数据局部性,但是通常不会这样做。 (例如,在代码提取将一行插入L2之后,从同一行中提取数据可能会进入L2,而不得不从另一缓存行进入RAM来获取数据。)
但是,使用分离的L1iTLB和L1dTLB,以及将L2 TLB作为统一的受害者缓存(maybe I think?),x86 CPU并未为此进行优化。从现代Intel CPU上的同一高速缓存行读取字节时,在获取“冷”功能时出现iTLB丢失并不能防止dTLB丢失。
x86上的代码大小优势为零。 x86-64的PC相对寻址模式为[RIP + rel32]
,因此它可以寻址当前位置+ -2GiB之内的任何内容。 32位x86甚至没有PC相关的寻址模式。
也许作者想到的是ARM,ARM附近的静态数据允许相对PC的负载(具有较小的偏移量)将32位常量存储到寄存器中? (在ARM上,这称为“文字池”,您将在函数之间找到它们。)
我认为它们并不意味着立即数据,例如mov eax, 12345
,其中32位12345
是指令编码的一部分。这不是要通过加载指令加载的静态数据。立即数据是另一回事。
显然,它仅用于只读数据;在指令指针附近进行写操作将触发清除管道以处理自修改代码的可能性。而且,您通常希望W ^ X(写或exec,而不是两者)用于内存页面。
CPU如何区分代码和数据?
逐渐增加。 CPU在RIP上提取字节,并将其解码为指令。从程序入口点开始之后,执行将在已执行的分支之后进行,并落入未执行的分支等。
从体系结构上讲,它不关心当前正在执行的字节或指令正在将其作为数据加载/存储的字节。如果再次需要,最近执行的字节将保留在L1-I高速缓存中,并且与L1-D高速缓存中的数据相同。
在无条件分支或ret
之后立即拥有数据而不是其他代码并不重要。函数之间的填充可以是任何东西。在极少数情况下,如果数据具有某种模式,则数据可能会暂停预解码或解码阶段(例如,由于现代CPU以16或32字节的宽块为单位进行取/解码),但随后的CPU阶段都是仅查看来自正确路径的实际解码指令。 (或者由于分支的错误推测...)
因此,如果执行到达一个字节,则该字节是指令的一部分。这对于CPU完全没问题,但对于想要查看可执行文件并将每个字节分类为“或”的程序无济于事。
代码提取总是检查TLB中的权限,因此,如果RIP指向不可执行的页面,它将导致错误。 (页表条目中的NX位)。
但是实际上就CPU而言,并没有真正的区别。 x86是冯·诺依曼架构。如果需要,一条指令可以加载自己的代码字节。
例如movzx eax, byte ptr [rip - 1]
将EAX设置为0x000000FF,加载rel32 = -1 = 0xffffffff位移的最后一个字节。
考虑到代码段是可执行的,并且CPU可能会错误地将恶意数据作为代码执行,因此这对安全性是否非常不利? (也许攻击者将程序重定向到该指令?)
可执行页面中的只读数据可以用作Spectre小工具,也可以用作面向返回编程(ROP)攻击的小工具。但是我认为通常在真实代码中已经有足够多的小工具了,这没什么大不了的。
但是,是的,与您的其他观点不同,这实际上是一个次要的反对。
最近(2019年或2018年末),GNU Binutils ld
已开始将.rodata
部分与.text
部分放在单独的页面中,因此无需执行权限即可将其只读。这使得静态只读数据在x86-64之类的ISA上不可执行,而exec权限与读取权限是分开的。即在单独的ELF细分中。
您可以使不可执行的事情越多越好,并且将代码+常量混合在一起将要求它们是可执行的。
关于x86 - 为什么编译器将数据放在PE和ELF文件的.text(code)部分中,并且CPU如何区分数据和代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55607052/
我当前项目中的许多类都有几个只能从类本身内部调用的属性和方法。此外,根据类(class)的当前状态,它们可能会扰乱类(class)的工作。 目前,所有这些接口(interface)都在 .h 文件的主
我想使用ngbTabSet将nav-pills in card-header 和tab-content in card-body。但我不知道该怎么做。 这是我尝试实现的示例(使用 bootstrap.
我正在浏览文档以查找如何允许放置在停靠栏图标上。据我所知,建议您使用 LSItemContentTypes,因为 CFBundleTypeOSTypes 已弃用。但是,我无法让 LSItemConte
我正在尝试在书签中使用 jquery UI 作为 slider 。并且 jquery ui 要求在普通 jquery 文件之后包含该文件。 所以到目前为止我所尝试的只是将脚本附加到 header ,同
您好,我尝试了广泛的谷歌搜索,但似乎没有任何帮助。 这是我的场景: 公司 Logo 存储在外部域/网址(矩形)中。 带有谷歌地图的 Ionic 应用程序,将这些 Logo 作为标记放置在 map 上。
我今天在阅读我的一些 C# 代码时发现了这一行: if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Pr
我刚遇到this question在 Go FAQ 中,它让我想起了困扰我一段时间的事情。不幸的是,我真的不明白答案是什么。 似乎几乎所有非 C 类语言都将类型放在变量名之后,如下所示: var :
这是有效的 HTML 吗? 最佳答案 作为元素可以包含 phrasing content ,以及属于该组,则有效。 从语义上(并且具有一些常识),如果唯一的内容是 , 不;如果它同时包含文本和图像
这是有效的 HTML 吗? 最佳答案 作为元素可以包含 phrasing content ,以及属于该组,则有效。 从语义上(并且具有一些常识),如果唯一的内容是 , 不;如果它同时包含文本和图像
我有两本 T.Parr 写的关于 ANTLR 的书,我到处都看到美元符号和符号的引用。它也对我有用: term : IDENT -> { new TokenNode($IDENT) }; 或更复杂的东
我在实现段控制时遇到了一些问题。因为我希望它是一个固定的标题,所以当我滚动时我总是可以看到它,我已经在 - (UIView *)tableView:(UITableView *)tableView v
我有一个 20x36px (10x18pt) 的箭头图像,当我选择一个 UIImageView 时,将它拖到我的 View Controller 上然后设置图像,它总是模糊的。我只在我的项目中包含 @
How can I put background image when I hover a link Insert Bg in this a when hov
我需要在我的 .container 中添加(最新的第一个)新分区,但在 .controls (按钮)之后。可能吗? 注意:添加新的分区来保存按钮下方的前置控件对我来说不是一个选择。 HTML 需要保持
我是一名优秀的程序员,十分优秀!