Skip to content

Instantly share code, notes, and snippets.

@atejeda
Forked from x-projs/mkexeloadable.c
Created June 10, 2020 22:22
Show Gist options
  • Select an option

  • Save atejeda/3d6ca5fba255bfa5731f92e591ceec42 to your computer and use it in GitHub Desktop.

Select an option

Save atejeda/3d6ca5fba255bfa5731f92e591ceec42 to your computer and use it in GitHub Desktop.

Revisions

  1. @xieyubo xieyubo revised this gist Feb 23, 2020. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions mkexeloadable.c
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,9 @@
    /* There is a behavior change in glibc>=2.30. dlopen() will fail if the file is position independent executable.
    This tool will clean up the PIE flag in the file to bypass the dlopen() check.
    /*
    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, xyb@xyb.name
    */

    #include <stdio.h>
  2. @xieyubo xieyubo created this gist Feb 23, 2020.
    65 changes: 65 additions & 0 deletions mkexeloadable.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    /* There is a behavior change in glibc>=2.30. dlopen() will fail if the file is position independent executable.
    This tool will clean up the PIE flag in the file to bypass the dlopen() check.
    */

    #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(&section_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;
    }