1

我试图.text使用. 该命令正常执行,没有任何错误。elfobjcopy --writable-text executable_name

通过检查部分权限,readelf我可以看到文本部分仍然只有读取和执行权限。

在浏览objcopy此特定选项的手册页时,提到该选项对所有二进制格式都没有意义。(这是我不能这样做的原因吗?)。

谁能指出我在这里缺少的东西。

谢谢

(Ubuntu x86_64 位机器,GNU objcopy(用于 Ubuntu 的 GNU Binutils)2.22.90.20120924)

4

3 回答 3

2

在浏览此特定选项的 objcopy 手册页时,提到该选项对所有二进制格式都没有意义。(这是我不能这样做的原因吗?)。

是的。

在ELF 格式的特殊部分的这个相当详细的描述中,您会看到它.text 具有SHF_ALLOC + SHF_EXECINSTR属性(为它分配了空间并且该空间中包含可执行代码),但没有SHF_WRITE(可以写入空间)。您要求objcopy做的事情对 ELF.text部分无效。

于 2014-02-08T00:12:28.443 回答
1

在 Debian 上,我可以只链接 -N 并生成一个带有可写 .text 的可执行文件

所以:ld -N obj.o

于 2014-05-21T08:34:49.833 回答
1

首先完成这个: objcopy --writable-text --set-section-flags .text=CONTENTS,ALLOC,LOAD,CODE

然后 objdump -x 或 readelf -a 查看加载节表,通常在程序头之后。请参阅 ELF 的手册页。对于 32 位可执行文件,例如:

使用 hexedit 打开二进制文件并查看文件偏移量 0x1C(通常为 0x34)处的值,然后遍历 0x20 字节结构(在文件偏移量 0x2a 处列出的大小),直到找到在上一个转储中标识为包含.text 部分。倒数第二个长值将是 00000005 (05 00 00 00) 并且需要添加写入,从而变为 00000007 (07 00 00 00)。现在它将按预期工作,没有任何限制,例如 -Wl,--omagic 的共享库问题。有点技术性,但需要几秒钟才能完成。

无论如何,这一位标志已经引起了无数的问题,没有任何解释可以澄清这个让它完美工作的小点。

可以使用 GCC 轻松编译代码解决方案以进行更改,如果定期进行更改,这可能会更容易和更好的解决方案:

#include <stdlib.h>
#include <stdio.h>
#include <elf.h>

int main(int argc, char** argv)
{
    if (argc <= 1) return -1;
    FILE* fp = fopen(argv[1], "r+");
    Elf64_Ehdr teh;
    fread(&teh, sizeof(teh), 1, fp);
    fseek(fp, 0, SEEK_SET);
    if (teh.e_ident[EI_CLASS] == ELFCLASS64) {
        Elf64_Ehdr eh;
        fread(&eh, sizeof(eh), 1, fp);
        Elf64_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize);
        Elf64_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize);
        fseek(fp, eh.e_phoff, SEEK_SET);
        fread(ph, eh.e_phentsize, eh.e_phnum, fp);
        fseek(fp, eh.e_shoff, SEEK_SET);
        fread(sh, eh.e_shentsize, eh.e_shnum, fp);
        for (int i = 0; i < eh.e_phnum; i++) {
            if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) {
            fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf64_Phdr*)0)->p_flags, SEEK_SET);
            ph[i].p_flags |= PF_W;
            fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp);
            }
        }
        for (int i = 0; i < eh.e_shnum; i++) {
            if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) {
            fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf64_Shdr*)0)->sh_flags, SEEK_SET);
            sh[i].sh_flags |= SHF_WRITE;
            fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp);
            }       
        }
        free(ph);
        free(sh);
    } else {
        Elf32_Ehdr eh;
        fread(&eh, sizeof(eh), 1, fp);
        Elf32_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize);
        Elf32_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize);
        fseek(fp, eh.e_phoff, SEEK_SET);
        fread(ph, eh.e_phentsize, eh.e_phnum, fp);
        fseek(fp, eh.e_shoff, SEEK_SET);
        fread(sh, eh.e_shentsize, eh.e_shnum, fp);
        for (int i = 0; i < eh.e_phnum; i++) {
            if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) {
            fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf32_Phdr*)0)->p_flags, SEEK_SET);
            ph[i].p_flags |= PF_W;
            fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp);
            }
        }
        for (int i = 0; i < eh.e_shnum; i++) {
            if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) {
            fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf32_Shdr*)0)->sh_flags, SEEK_SET);
            sh[i].sh_flags |= SHF_WRITE;
            fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp);
            }       
        }
        free(ph);
        free(sh);
    }
    fflush(fp);
    fclose(fp);
    return 0;
}
于 2017-07-09T04:56:07.403 回答