动态执行的 ARM ASM 系统调用,可从C++重新定位

Dynamically executed ARM ASM syscall with relocations from C++

本文关键字:新定位 定位 C++ 可从 执行 ARM ASM 系统调用 动态      更新时间:2023-10-16

我想从C++调用ARM/ARM64 ASM代码。ASM 代码包含系统调用和对外部函数的重新定位。 ARM架构在这里不是那么重要,我只是想从概念上了解如何解决我的问题。

我有以下ASM系统调用(objdump -d输出),它在共享库中调用:

198:   d28009e8    mov x8, #0x4f                   // #79
19c:   d4000001    svc #0x0
1a0:   b140041f    cmn x0, #0x1, lsl #12
1a4:   da809400    cneg    x0, x0, hi
1a8:   54000008    b.hi    0 <__set_errno_internal>
1ac:   d65f03c0    ret

这段代码调用fstatat64系统调用,并通过外部__set_errno_internal函数设置errnoreadelf -r显示了__set_errno_internal功能的以下重新定位:

00000000000001a8 R_AARCH64_CONDBR19  __set_errno_internal

我想从C++调用这段代码,所以我将其转换为缓冲区:

unsigned char machine_code[] __attribute__((section(".text"))) =
"xe8x09x80xd2"
"x01x00x00xd4"
"x1fx04x40xb1"
"x00x94x80xda"
"x08x00x00x54"   // Here we have mentioned relocation
"xc0x03x5fxd6";

编辑:重要细节 - 我选择使用缓冲区(不是内联程序集等),因为我想在这个缓冲区上运行额外的处理(例如字符串文字上的解密函数作为软件保护机制,但这在这里并不重要)在它被评估为机器代码之前。

之后,可以将缓冲区转换为函数并直接调用以执行机器代码。显然,搬迁存在问题,它不会自动修复,我必须手动修复它。但是在运行时我不能这样做.text因为该部分是只读和可执行的。

虽然我几乎完全控制源代码,但我不能关闭堆栈保护和其他功能以使该部分可写(不要问为什么)。因此,似乎应该以某种方式在链接阶段执行重新定位修复。据我所知,共享库包含链接器修复重定位后的相对偏移量(对于类似的外部函数调用),二进制 *.so 文件应包含正确的偏移量(无需运行时重定位工作),因此在链接期间修复machine_code该缓冲区应该是可能的。

我正在使用手动构建的Clang 7编译器,并且可以完全控制LLVM传递,因此我认为也许可以编写某种在链接期间执行的LLVM传递。虽然看起来ld最终被调用了,所以也许 LLVM 通行证在这里无济于事(不是这里的专家)。

不同的想法也将不胜感激。 如您所见,问题非常复杂。也许您有一些方向/想法如何解决这个问题?谢谢!

已经有一个有效的打包机制来处理重新定位。它被称为dlsym(). 虽然它不直接为您提供函数指针,但所有主要的C++编译器都支持reinterpret_castdlsym到任何普通函数指针的结果。(成员函数完全是另一个问题,但这在这里无关紧要)