`dlopen` 可以用于加载和映射静态 ELF 可执行文件(不是库)吗?
Can `dlopen` be used to load and mmap a static ELF executable (not library)?
如果文件anexe
是静态编译的,没有符号,没有导出,ELF,dlopen("anexe", RTLD_LAZY)
可以用来映射到内存吗?
我的目标不是能够引用符号——没有符号。相反,我的目标是能够在给定地址(固定地址,而不是 PIC)的情况下调用其函数,并在给定地址的情况下读取其数据。我本来打算通过 mmap
来完成这一切,但意识到 dlopen
虽然不是为此而设计的,但也许可以为我完成这一切。
dlopen可以那样用吗?
当我尝试时,我得到 dlerror
:cannot dynamically load executable
- 有什么解决方法吗?
If file anexe is static compiled, no symbols, no exports, ELF, can dlopen("anexe", RTLD_LAZY) be used to map it into memory?
否(但见下文)。
My goal isn't to be able to reference symbols -- there are no symbols. Rather, my goal is to be able to call its functions given their addresses (which are fixed, not PIC), and to read its data given address.
请注意,non-PIE 可执行文件只能 加载到它链接的地址。您可以通过检查其程序头(以编程方式或使用 readelf -Wl
)找到哪个地址。
一旦您知道应该将其加载到哪个地址(并假设该地址尚未被您自己的可执行文件占用),那么您可以执行一系列 mmap
调用以将该可执行文件“加载”到内存,之后就可以调用它的函数,读取它的数据了。
一个复杂的问题是可执行文件的初始化程序不会有 运行(你没有调用它的 _start
,你也不想),因此其中的函数可能不会 运行正确,可能会崩溃等
例如,给定这个二进制文件:
$ echo "int main() { return 0; }" | gcc -xc - -static -no-pie -o a.out
$ readelf -Wl a.out | egrep 'Type|LOAD'
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000518 0x000518 R 0x1000
LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x07fd01 0x07fd01 R E 0x1000
LOAD 0x081000 0x0000000000481000 0x0000000000481000 0x026660 0x026660 R 0x1000
LOAD 0x0a7928 0x00000000004a8928 0x00000000004a8928 0x0059c8 0x007298 RW 0x1000
您需要执行 4 次 mmap
调用(每个 LOAD
段调用一次),其中 MAP_FIXED
。 mmap
的地址、文件偏移量、大小和保护参数很明显。
最后一段的 mmap
参数可能不是:您需要将地址和偏移向下舍入到 Align
,并将大小扩展 0x928
以解决这个问题四舍五入。
如果文件anexe
是静态编译的,没有符号,没有导出,ELF,dlopen("anexe", RTLD_LAZY)
可以用来映射到内存吗?
我的目标不是能够引用符号——没有符号。相反,我的目标是能够在给定地址(固定地址,而不是 PIC)的情况下调用其函数,并在给定地址的情况下读取其数据。我本来打算通过 mmap
来完成这一切,但意识到 dlopen
虽然不是为此而设计的,但也许可以为我完成这一切。
dlopen可以那样用吗?
当我尝试时,我得到 dlerror
:cannot dynamically load executable
- 有什么解决方法吗?
If file anexe is static compiled, no symbols, no exports, ELF, can dlopen("anexe", RTLD_LAZY) be used to map it into memory?
否(但见下文)。
My goal isn't to be able to reference symbols -- there are no symbols. Rather, my goal is to be able to call its functions given their addresses (which are fixed, not PIC), and to read its data given address.
请注意,non-PIE 可执行文件只能 加载到它链接的地址。您可以通过检查其程序头(以编程方式或使用 readelf -Wl
)找到哪个地址。
一旦您知道应该将其加载到哪个地址(并假设该地址尚未被您自己的可执行文件占用),那么您可以执行一系列 mmap
调用以将该可执行文件“加载”到内存,之后就可以调用它的函数,读取它的数据了。
一个复杂的问题是可执行文件的初始化程序不会有 运行(你没有调用它的 _start
,你也不想),因此其中的函数可能不会 运行正确,可能会崩溃等
例如,给定这个二进制文件:
$ echo "int main() { return 0; }" | gcc -xc - -static -no-pie -o a.out
$ readelf -Wl a.out | egrep 'Type|LOAD'
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000518 0x000518 R 0x1000
LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x07fd01 0x07fd01 R E 0x1000
LOAD 0x081000 0x0000000000481000 0x0000000000481000 0x026660 0x026660 R 0x1000
LOAD 0x0a7928 0x00000000004a8928 0x00000000004a8928 0x0059c8 0x007298 RW 0x1000
您需要执行 4 次 mmap
调用(每个 LOAD
段调用一次),其中 MAP_FIXED
。 mmap
的地址、文件偏移量、大小和保护参数很明显。
最后一段的 mmap
参数可能不是:您需要将地址和偏移向下舍入到 Align
,并将大小扩展 0x928
以解决这个问题四舍五入。