将解释器添加到共享对象而不触及代码

问题描述 投票:0回答:1

我正在关注这篇文章,其中清楚地展示了如何将解释器添加到共享对象。

现在我正在尝试做同样的事情,但不添加行

const char interp_path[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";

即我希望代码是

#include <stdio.h>
#include <stdlib.h>
 
void print_version()
{
    printf("Library version 1.0\n");

    exit(0);
}

编译为

gcc -shared -fPIC -Wl,--entry=print_version -o lib.so lib.c

并为我的

lib.so
添加口译员。

我尝试了什么

  • 我尝试使用
    patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 lib.so
    。这会导致以下错误:
patchelf: cannot find section '.interp'. The input file is most likely statically linked

  • 然后我尝试添加该部分。注意到在标准可执行文件中我有
    A
    标志
  [ 1] .interp           PROGBITS        0000000000000318 000318 00001c 00   A  0   0  1

我试过了

echo -n /lib64/ld-linux-x86-64.so.2 > tempfile
objcopy --add-section .interp=tempfile --set-section-flags .interp=alloc,readonly lib.so libi.so

它抱怨告诉我

objcopy: libi.so: warning: allocated section `.interp' not in segment
。尽管使用
readelf
我得到了正确的标题部分,并且
patchelf
不再抱怨,但我无法按照我的意愿得到我的
libi.so

你能帮我吗?

c linux executable elf
1个回答
0
投票

正如我在评论中所说,

仅添加 .interp 部分是不够的,加载器将无法找到解释器,因为它不是可加载段的一部分,因此不会加载到内存中。除了该部分之外,您还必须添加/更新程序头并将其设为 PT_INTERP 类型,并根据解释器字符串的属性(现在位于 .interp 部分中)设置其值。

不幸的是,当我撰写评论时,我没有找到任何有用的工具来实现此目的...您可以使用像LIEF这样的库来添加自定义的

PT_INTERP
程序头(我不确定这个库是否支持它)不过)。

如果你想从头开始写if,概念上不会有困难。我假设您的代码是位置无关的(正如您所说,您的目标是共享对象)。您必须将新的

PT_INTERP
程序头附加到程序头表的末尾,然后相应地更新以下标头u200c(您可以使用
libbfd
提取标头信息):

ELF 标题

sizeof(Elf64_Phdr)
sizeof(Elf32_Phdr)
添加到
e_entry
e_shoff
,因为追加新的phdr后,入口点和节头表的基数将发生移动。还要将
1
添加到
e_phnum
(其中存储程序头的数量)。

章节标题

由于节和节头的数据通常放在程序头表之后,因此移位会影响节位置的正确偏移;因此,您还必须将

sizeof(Elf64_Phdr)
sizeof(Elf32_Phdr)
添加到每个节标题的
sh_offset
字段。

自定义程序头

要创建程序头本身,您可以使用

elf.h
Elf64_Phdr
Elf32_Phdr
)中提供的程序头结构。这样初始化结构体:

p_type   = 3       // Set p_type to PT_INTERP
p_flags  = PF_R    // Set permission for .interp to Readable
p_offset = (Your .interp offset)
p_vaddr  = (Your .interp virtual address)
p_paddr  = (Your .interp virtual address)
p_filesz = 28     // strlen(Interpreter string) + 1
p_memsz  = 28
p_align  = 1

然后您可以将初始化的结构写入文件中,然后将其注入程序头的末尾(正如我上面所说的)。

© www.soinside.com 2019 - 2024. All rights reserved.