Last active
August 25, 2024 04:40
-
-
Save x-projs/6820491646f9d01980a7eadb16564ddf to your computer and use it in GitHub Desktop.
Make the executable file can be loaded by dlopen() after glibc>=2.30.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
There is a behavior change in glibc>=2.30. dlopen() will fail if the file is | |
position independent executable. This code will clean up the PIE flag in the | |
file to bypass the dlopen() check. | |
MIT License (c) 2020 Yubo Xie, [email protected] | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <elf.h> | |
#define EXEC(x, err_msg) \ | |
if (!(x)) { \ | |
perror(err_msg); \ | |
err = -1; \ | |
goto ex; \ | |
} | |
int main(int argc, char* argv[]) { | |
int err = 0; | |
if (argc != 2) { | |
printf("Usage: mkexeloadable <executable-elf64-file>\n"); | |
return -1; | |
} | |
FILE* fp = fopen(argv[1], "r+b"); | |
EXEC(fp != NULL, "Can't open file"); | |
// Read elf header. | |
Elf64_Ehdr elf_header; | |
EXEC(fread(&elf_header, sizeof(elf_header), 1, fp) == 1, "Read elf64_ehdr failed"); | |
// Is it a elf64 file? | |
EXEC(strncmp((char*)elf_header.e_ident, "\177ELF\002", 5) == 0, "It is not a valid elf64 file"); | |
// Find out dynamic section | |
Elf64_Shdr section_header; | |
Elf64_Dyn dyn; | |
EXEC(fseek(fp, elf_header.e_shoff, SEEK_SET) == 0, "Seek file failed"); | |
for (int i = 0; i < elf_header.e_shnum; ++i) { | |
EXEC(fread(§ion_header, elf_header.e_shentsize, 1, fp) == 1, "Read section header failed"); | |
if (section_header.sh_type == SHT_DYNAMIC) { | |
EXEC(fseek(fp, section_header.sh_offset, SEEK_SET) == 0, "Seek file failed"); | |
while (1) { | |
EXEC(fread(&dyn, sizeof(Elf64_Dyn), 1, fp) == 1, "Read section entry failed"); | |
EXEC(dyn.d_tag != 0, "Can't find flags_1"); | |
if (dyn.d_tag == 0x6ffffffb) { | |
// Clear PIE flag. | |
dyn.d_un.d_val &= ~DF_1_PIE; | |
EXEC(fseek(fp, -sizeof(Elf64_Dyn), SEEK_CUR) == 0, "Seek flags_1 failed"); | |
EXEC(fwrite(&dyn, sizeof(Elf64_Dyn), 1, fp) == 1, "Write back flags_1 failed"); | |
// Success! | |
goto ex; | |
} | |
} | |
} | |
} | |
// Can't find required flags, something might be wrong. | |
EXEC(0, "Can't find required flags"); | |
ex: | |
if (fp) { | |
fclose(fp); | |
} | |
return err; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks man, I was facing the same problem until I hit your blog while "researching" the reason why, the only thing that changed in my builds was the GCC version.