better libc detection, use DT_TEXTREL when possible instead of making a segment RWX
This commit is contained in:
parent
00632e9548
commit
c3248c6801
78
manip-exe.h
78
manip-exe.h
|
@ -6,9 +6,9 @@
|
|||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#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");
|
||||
|
|
Loading…
Reference in New Issue