Last active
April 25, 2025 14:17
-
-
Save supechicken/4c26ae331b404ea309c2ebb3e0d93c02 to your computer and use it in GitHub Desktop.
Execute embedded program with custom ld-linux
This file contains hidden or 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
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <linux/limits.h> | |
#include <sys/mman.h> | |
extern const char _binary_executable_start, _binary_executable_end; | |
bool verbose = false; | |
int main(int argc, char **argv) { | |
char *new_args[argc + 4], fd_path[PATH_MAX], *interp_path; | |
// enable verbose logging if requested | |
if (strcmp(getenv("LD_WRAPPER_VERBOSE") ?: "0", "1") == 0) verbose = true; | |
// get interpreter path from environment | |
interp_path = getenv("LD_WRAPPER_INTERPRETER_PATH") ?: "/usr/local/bin/ld.so"; | |
if (verbose) fprintf(stderr, "[+] ELF interpreter set to %s\n", interp_path); | |
// create a memfd for the executable | |
int memfd = memfd_create("real-executable", 0), | |
executable_size = &_binary_executable_end - &_binary_executable_start; | |
if (memfd == -1) { | |
fprintf(stderr, "memfd_create() failed: %s\n", strerror(errno)); | |
exit(errno); | |
} | |
// full path of memfd | |
snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%i", memfd); | |
// command line arguments for ld.so | |
new_args[0] = "ld.so"; | |
new_args[1] = "--argv0"; | |
new_args[2] = argv[0]; | |
new_args[3] = fd_path; | |
// copy all argument pointers to new array | |
for (int i = 1; i < argc; i++) new_args[3 + i] = argv[i]; | |
new_args[argc + 3] = NULL; | |
if (verbose) { | |
fprintf(stderr, "[+] New command line:\n[+]\n[+] "); | |
for (int i = 0; i < argc + 3; i++) { | |
fprintf(stderr, "%s ", new_args[i]); | |
} | |
fprintf(stderr, "\n[+]\n"); | |
} | |
// load executable into memfd | |
if (write(memfd, &_binary_executable_start, executable_size) == -1) { | |
fprintf(stderr, "Failed to write into memfd: %s\n", strerror(errno)); | |
exit(errno); | |
} | |
if (verbose) fprintf(stderr, "[+] Now re-exec with %s...\n", interp_path); | |
// execute the memfd with our dynamic linker | |
if (execv(interp_path, new_args) == -1) { | |
fprintf(stderr, "execv() failed: %s\n", strerror(errno)); | |
exit(errno); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment