首先完成这个: 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;
}