问题标签 [position-independent-code]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
1508 浏览

buffer-overflow - 当我们有 execstack 时,与位置无关的可执行文件 (PIE) 有什么意义?

我正在阅读Hacking: The art of exploit,它显然充满了过时的信息(不考虑金丝雀、不可执行堆栈、ASLR)。我试图了解即使在现代系统上是否(以及如何)堆栈溢出攻击也是可能的。到目前为止,我发现的最好的论文是Stack 在现代 Linux 系统上的粉碎,至少是从 2012 年开始的。

似乎真正阻碍堆栈溢出攻击执行任意代码的是金丝雀和位置无关可执行文件(在 gcc 中禁用标志-fno-stack-protector-fPIE)。PIE 使堆栈不可执行,因此即使设法用堆栈地址覆盖返回地址,程序也会崩溃,因为堆栈上的代码不允许执行。

显然,Linux 终端命令readelf -l <filename>允许知道是否使用 PIE 编译了可执行文件。标题GNU_STACK是我们应该查看的:如果是RWE,则允许执行,如果E缺少,则不是。因此,检查堆栈是否可执行很简单。(值得指出的是,在不反汇编或使软件崩溃的情况下,检查文件是否使用金丝雀保护编译并不容易)

但是,据我了解,可以通过一个名为execstackGNU_STACK的小工具轻松调整标题。这很容易。它甚至不需要 root 权限(当然,只要文件的所有者不是 root)。RWEexecstack -s <filename>

现在,我的问题是:如果我们可以如此轻松地更改它的设置,那么 PIE 的意义何在?禁用金丝雀需要重新编译整个文件,因为金丝雀检查内置在汇编代码中,但GNU_STACK标题似乎很容易出错......我错过了什么?

更新:如果攻击者可以修改标头,那么这意味着攻击者已经实现了代码注入。 ”我不确定这是真的。如果攻击者想要利用可执行文件中的缺陷,他很可能需要另一个可执行文件。例如,在《黑客:剥削的艺术》一书中,漏洞notesearch是通过 exploit notesearch_exploit。即使notesearch有不可执行的堆栈,也可以通过对 execstack in 的 apt 调用轻松使其可执行notesearch_exploit(鉴于没有 root 权限的事实),从而绕过 PIE 限制。这不正确吗?

0 投票
1 回答
19292 浏览

assembly - ARM 汇编中 ADRP 和 ADRL 指令的语义是什么?

ADRP

PC 相对偏移处的 4KB 页的地址。

ADRL

将 PC 相对地址加载到寄存器中。它类似于 ADR 指令。ADRL 可以加载比 ADR 更广的地址范围,因为它生成两条数据处理指令。

具体来说,

ADRL 汇编成两条指令,一条 ADRP 后跟 ADD。如果汇编器不能在两条指令中构造地址,它会产生一个重定位。然后链接器生成正确的偏移量。ADRL 产生与位置无关的代码,因为地址是相对于 PC 计算的。

做什么ADRPADRL指示做什么?更重要的是,如何ADRP构造ADD一个PC相对地址?

0 投票
1 回答
923 浏览

assembly - 在位置无关代码中引用链接器定义的符号

我有一个使用 -fpie 为 ARM 编译的代码模块,我想在第一次执行时清除 BSS。但是,当我为 BSS 部分的开头和结尾引用链接器脚本符号时,我得到的代码包含局部变量中的绝对地址。

这是我的程序集入口点:

输出如下:

Readelf 表示我的 ELF 文件没有重定位。

我认为链接器符号只是永远是绝对地址的整数是否正确?如果是这样,有没有办法在加载或执行时修复地址?或者是否有其他正确的方法来清除此代码的 BSS?

编辑:添加一些 readelf -s 输出。这是相关的 .S 文件以及与 BSS 有关的所有内容。

0 投票
1 回答
57 浏览

gcc - 为什么代码段的地址为零?

在我更新了我的 kali linux 之后,我使用 gcc 来编译我的程序。更新系统之前,我用objdump反汇编程序,.text地址从0x08048... 6.3,怎么了?为什么会这样?

0 投票
2 回答
845 浏览

c - 混合 fPIC 和非 fPIC 对象模块

环境:Ubuntu 16.04

在我的实验中,我运行了以下命令:

我需要公开的函数都是在 2.c 中通过extern "C"声明定义的。这些函数在内部调用 1.c 中定义的其他函数。

请注意,我没有申请-fPIC1.c。仍然一切似乎编译/链接正常,没有任何警告。

我们是否可以得出结论,-fPIC必须只应用于那些公开外部函数的源文件?

在更大的图片中,我有一堆可能没有使用-fPIC标志编译的存档 (.a) 文件。我需要创建一个与这些存档文件链接的自定义共享库。如果我的假设是有效的,我认为可以链接到这些存档文件。欣赏你的想法。问候。

0 投票
0 回答
1854 浏览

c++ - 为 CMake 中的链接禁用 PIC

我在 CMake(32 位共享库)和 gcc 编译器中有一个 C++ 项目。我为我的项目设置了POSITION_INDEPENDENT_CODE属性OFF,所以-fPIC它只在源编译时删除,而不是链接阶段。如何禁用链接?

我知道有一种方法-fno-PICin LINK_FLAGS。而且我也可以设置CMAKE_SHARED_LIBRARY_CXX_FLAGS"". 但这些方式看起来很脏。

0 投票
1 回答
836 浏览

llvm - llc:符号上不支持的重定位

问题

llc给我以下错误:

LLVM 错误:符号上不支持的重定位

详细编译流程

我正在为编译器的中级 IR (MIR) 实现 LLVM 前端,在将各种方法转换为许多位码文件后,我将它们链接 ( llvm-link)、优化它们 ( opt)、将它们转换为机器码 ( llc)、制作它们是一个共享库(clang因为它是链接器包装器),并动态加载它们。 llc对于我正在编译的某些方法,步骤失败了!

步骤 1: llvm-link: 合并许多位码文件

我可能有许多相互调用的函数,所以我llvm-link使用了可能相互交互的不同位码文件。这一步没有问题。例子:

llvm-link function1.bc function2.bc -o lnk.bc

步骤 2: opt: 运行优化通道

现在我正在使用以下内容:

opt -O3 lnk.bc -o opt.bc

这一步没有问题,但这就是导致问题的原因!此外,这是必要的,因为将来我将需要这一步来通过额外的通行证,例如loop-unroll

第三步llc::生成机器码(PIC)

我正在使用以下命令:

llc -march=thumb -arm-reserve-r9 -mcpu=cortex-a9 -filetype=obj -relocation-model pic opt.bc -o obj.o

我保留了我设置的拱形特定标志,以防它们导致问题。我正在使用Position Independent Code,因为下一步我将构建一个shared object. 此命令失败,并出现我在此答案之上编写的错误。

第 4 步clang::生成共享对象

对于Step 3失败的情况,未达到此步骤。如果llc成功,这一步也将成功!

附加信息

配置

以下在arm设备上运行的 llvm3.6 上运行。

我注意到的事情

  • 如果我在步骤中省略-O3(或任何其他级别)opt,那么llc就可以了。
  • 如果我不这样做,而是从 中省略它们llcllc仍然会失败。这让我认为这opt -O<level>是造成问题的原因。
  • 如果我llc直接使用它会起作用,但我将无法运行opt允许我的特定通行证,所以这不是我的选择。
  • 到目前为止,我使用我编译的 2 个函数(来自它们的原始 MIR)遇到了这个问题,这些函数使用循环。其他人产生工作代码!
  • 如果我不使用pic模型 at llc,它可以生成obj.o,但是我将无法从中创建一个.so

问题

  1. 为什么会这样??!!

  2. 为什么opt-relocation-model选项?这不应该只是一llc件事吗?我已经尝试将其设置为 atoptllcto pic,但仍然失败。

  3. 我使用它是clang因为它有一个链接器的包装器来获取.so. 有没有办法用 LLVM 工具代替这一步?

0 投票
1 回答
1365 浏览

gcc - STM32,与位置无关的代码 - GOT 中没有函数指针?

我需要一个在 STM32F401 上工作的位置无关代码 (PIC)。但是我对指向在结构中使用的函数的指针有问题。

简短的例子:

拆卸后:

R3 中的分支地址对于偏移量不同于 0 的代码是错误的。我在这里看不到 GOT 的使用。这是一个错误还是缺少编译器/链接器选项?


我可能已经成功解决的事情:

  • 得到修复
  • 中断表修复
  • 使用适当的 cflags 编译的 Newlib

使用过的 CFLAGS:

-mlittle-endian -mthumb -mthumb-interwork -mcpu=cortex-m4 -fsingle-precision-constant -Wdouble-promotion -msoft-float -fpic -msingle-pic-base -mpic-data-is-text-relative -mpic -register=r10 -Wno-strict-aliasing -lc

并与

-fpic

0 投票
1 回答
3844 浏览

c - 为什么我不能用 -fPIE 编译,但可以用 -fPIC 编译?

我有一个有趣的编译问题。首先,请看要编译的代码。

我编译它并得到如下错误

在此之后,我修改了代码(删除了一行 [1]/使用 -fPIC 而不是 -PIE[2]),然后成功编译了这些代码。

为什么会发生这种现象?

我听说在使用 -fPIC 编译时通过 PLT 调用对象内的函数,但在使用 -fPIE 编译时直接跳转到函数来完成。我猜想带有 -fPIE 的函数调用机制会避免重定位。但我想知道准确和准确的解释。

你能帮我吗?

谢谢你们。

0 投票
1 回答
837 浏览

gcc - 使用 GCC 修复与位置无关的可执行文件中全局变量的重定位

我正在寻找一个gcc命令行标志或其他设置来为我的静态链接、与位置无关的 i386 可执行文件生成GOTOFF重定位而不是重定位。GOT有关我在下面尝试的更多详细信息。

我的源文件g1.s如下所示:

我的另一个源文件g2.s如下所示:

gcc -m32 -fPIE -Os -static -S -ffreestanding -fomit-frame-pointer -fno-unwind-tables -fno-asynchronous-unwind-tables g1.c我用i386编译它们。

我得到以下汇编输出:

以下是如何使用 GCC 7.2 在线重现此行为:https ://godbolt.org/g/XXkxJh

而不是GOT上面,我想得到GOTOFFmovl %(eax), %eax应该消失,所以函数的汇编代码应该是这样的:

我已经验证了这个GOTOFF程序集版本是有效的,而这个GOT版本不起作用(因为它有一个额外的指针间接)。

如何说服gcc生成GOTOFF版本?我尝试了-fPIC, -fpic, -fPIE, -fpie, -pie,的各种组合-fno-plt。他们都没有工作,他们都gcc制作了这个GOT版本。

我在https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html或任何通用标志上找不到任何 i386 特定标志: https ://gcc.gnu.org/onlinedocs/gcc/ Code-Gen-Options.html

事实上,我正在GOTOFF"..."字符串文字重新定位,我也想为extern变量获取它们。

最终输出是自定义二进制格式的静态链接可执行文件(我为此编写了 GNU ld 链接器脚本)。没有动态链接,也没有共享库。地址随机化由自定义加载器执行,该加载器可以自由地将可执行文件加载到任何地址。所以我确实需要与位置无关的代码。没有每段内存映射:整个可执行文件按原样连续加载。

我在网上找到的所有文档都在讨论动态链接的与位置无关的可执行文件,但我在那里找不到任何有用的东西。