diff --git a/manip-exe.h b/manip-exe.h index 095bb98..a7c8195 100644 --- a/manip-exe.h +++ b/manip-exe.h @@ -6,9 +6,9 @@ #include #include -#if (sizeof(ElfW(Ehdr)) != sizeof(Elf64_Ehdr)) +/*#if sizeof(ElfW(Ehdr)) != sizeof(Elf64_Ehdr) #error "Need 64-bit ELF for now, sorry" -#endif +#endif*/ static bool manip_elf(ElfW(Ehdr)* elf, const char* symname) { if (elf->e_ident[0] != ELFMAG0 || elf->e_ident[1] != ELFMAG1 @@ -33,13 +33,23 @@ static bool manip_elf(ElfW(Ehdr)* elf, const char* symname) { ElfW(Phdr)* phdr = (ElfW(Phdr)*)(elf->e_phoff + (size_t)elf), *ph_loadexec; ElfW(Dyn)* dyn = NULL; + bool textrel = false; + enum { + libc_unk, libc_g /* glibc */, libc_musl, libc_uc /* uclibc */ + } libc = libc_unk; + // first, try to determine the libc used for (size_t i = 0; i < elf->e_phnum; ++i, phdr = (ElfW(Phdr)*)((size_t)phdr + elf->e_phentsize)) { - if (phdr->p_type == PT_LOAD) { - // need this at runtime for the relocs to work (yeah, sorry) - if (phdr->p_flags & PF_X) { - ph_loadexec = phdr; - phdr->p_flags |= PF_W; + if (phdr->p_type == PT_INTERP) { + const char* str = (char*)elf + phdr->p_offset; + if (!strcmp(str, "/lib64/ld-linux-x86-64.so.2")) { + libc = libc_g; + printf("\tglibc\n"); + } else if (!strcmp(str, "/lib/ld-musl-x86_64.so.1")) { + libc = libc_musl; + printf("\tmusl\n"); + } else { + printf("\tunknown libc: '%s'\n", str); } } @@ -49,6 +59,55 @@ static bool manip_elf(ElfW(Ehdr)* elf, const char* symname) { } } + if (libc == libc_unk) { + ElfW(Dyn)* dd = dyn; + const char* ddstr = NULL; + for (size_t i = 0; dd->d_tag != DT_NULL; ++i, ++dd) { + if (dd->d_tag == DT_STRTAB) + ddstr = (const char*)((size_t)elf + dd->d_un.d_ptr); + } + dd = dyn; + for (size_t i = 0; dd->d_tag != DT_NULL; ++i, ++dd) { + if (dd->d_tag == DT_NEEDED) { + const char* s = ddstr + dd->d_un.d_val; + + if (strstr(s, "libc.so") != s) continue; + + if (!strcmp(s, "libc.so.6")) { + libc = libc_g; + printf("\tglibc\n"); + break; + } else if (!strcmp(s, "libc.so.0")) { + libc = libc_uc; + printf("\tuclibc\n"); + break; + } else if (!strcmp(s, "libc.so")) { + libc = libc_musl; + printf("\tmusl\n"); + break; + } else { + printf("\tunknown libc: '%s'\n", s); + } + } + } + } + + phdr = (ElfW(Phdr)*)(elf->e_phoff + (size_t)elf); + for (size_t i = 0; i < elf->e_phnum; + ++i, phdr = (ElfW(Phdr)*)((size_t)phdr + elf->e_phentsize)) { + if (phdr->p_type == PT_LOAD) { + // need this at runtime for the relocs to work (yeah, sorry) + if (phdr->p_flags & PF_X) { + ph_loadexec = phdr; + if (libc == libc_g || libc == libc_uc) { + textrel = true; + } else { + phdr->p_flags |= PF_W; + } + } + } + } + if (dyn == NULL) { fprintf(stderr, "No DYNAMIC table! bailing out...\n"); return true; @@ -63,6 +122,7 @@ static bool manip_elf(ElfW(Ehdr)* elf, const char* symname) { ElfW(Addr) relaoff = 0; for (size_t i = 0; dyn->d_tag != DT_NULL; ++i, ++dyn) { + if (dyn->d_tag == DT_TEXTREL) textrel = false; if (dyn->d_tag == DT_RELA) { relatab = (ElfW(Rela)*)((size_t)elf + dyn->d_un.d_ptr); relaoff = dyn->d_un.d_ptr; @@ -80,6 +140,10 @@ static bool manip_elf(ElfW(Ehdr)* elf, const char* symname) { if (dyn->d_tag == DT_SYMENT) syment = dyn->d_un.d_val; if (dyn->d_tag == DT_STRSZ ) strsz = dyn->d_un.d_val; } + if (textrel) { + dyn->d_tag = DT_TEXTREL; // need this one + dyn[1].d_tag = DT_NULL; + } if (!relasz || !relaent || !relatab) { fprintf(stderr, "No RELA/RELASZ/RELAENT in DYN!\n");