繁体   English   中英

objcopy --writable-text不能使elf二进制文本节可写吗?

[英]Objcopy --writable-text not making elf binary text section writable?

我试图使用objcopy --writable-text executable_name使elf二进制文件的.text部分可写。 该命令正常执行,没有任何错误。

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

在遍历objcopy手册页时,提到该选项对于所有二进制格式都没有意义。 (这是我无法执行此操作的原因吗?)。

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

谢谢

(Ubuntu x86_64位计算机,GNU objcopy(适用于Ubuntu的GNU Binutils)2.22.90.20120924)

在遍历objcopy手册页时,提到该选项对于所有二进制格式都没有意义。 (这是我无法执行此操作的原因吗?)。

是。

ELF格式的特殊部分的详细说明中 ,您可以看到.text具有SHF_ALLOC + SHF_EXECINSTR属性(为其分配了空间,并且该空间具有可执行代码),但没有SHF_WRITE (可以写入空间)。 您要求objcopy进行的操作仅对ELF .text部分无效。

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

所以:ld -N obj.o

首先完成此操作:objcopy --writable-text --set-section-flags .text = CONTENTS,ALLOC,LOAD,CODE

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

使用hexedit打开二进制文件,查看文件偏移量0x1C(通常为0x34)处的值,然后遍历0x20字节结构(文件偏移量0x2a处列出的大小),直到找到在上一个转储中标识为包含以下内容的字节结构为止。 .text部分。 倒数第二个long值将是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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM