Last active
October 4, 2024 16:25
-
-
Save whit3rabbit/6a6d4c6f29be194878abf7e0ab0ad5d4 to your computer and use it in GitHub Desktop.
hide_process_name.c
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 <string.h> | |
| #include <unistd.h> | |
| #include <sys/prctl.h> | |
| #include <sys/mman.h> | |
| #include <errno.h> | |
| #include <dirent.h> | |
| #include <sys/mount.h> | |
| #include <sys/stat.h> | |
| #include <libgen.h> | |
| #include <stdlib.h> | |
| #include <limits.h> | |
| #ifdef __FreeBSD__ | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| #endif | |
| #ifndef PR_SET_MM | |
| #define PR_SET_MM 35 | |
| #endif | |
| #ifndef PR_SET_MM_ARG_START | |
| #define PR_SET_MM_ARG_START 8 | |
| #endif | |
| #ifndef PR_SET_MM_ARG_END | |
| #define PR_SET_MM_ARG_END 9 | |
| #endif | |
| #ifndef MS_BIND | |
| #define MS_BIND 4096 | |
| #endif | |
| #ifndef PATH_MAX | |
| #define PATH_MAX 4096 | |
| #endif | |
| static int try_bind_mount(void) { | |
| char proc_path[PATH_MAX]; | |
| if (snprintf(proc_path, sizeof(proc_path), "/proc/%d", getpid()) >= sizeof(proc_path)) { | |
| fprintf(stderr, "Error: Process path too long\n"); | |
| return 0; | |
| } | |
| DIR *proc_dir = opendir("/proc"); | |
| if (proc_dir == NULL) { | |
| perror("Failed to open /proc directory"); | |
| return 0; | |
| } | |
| struct dirent *entry; | |
| while ((entry = readdir(proc_dir)) != NULL) { | |
| struct stat st; | |
| char full_path[PATH_MAX]; | |
| if (snprintf(full_path, sizeof(full_path), "/proc/%s", entry->d_name) >= sizeof(full_path)) { | |
| fprintf(stderr, "Error: Full path too long for %s\n", entry->d_name); | |
| continue; | |
| } | |
| if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) { | |
| int pid = atoi(entry->d_name); | |
| if (pid > 0 && pid < 1000) { | |
| char mount_source[PATH_MAX]; | |
| if (snprintf(mount_source, sizeof(mount_source), "/proc/%s", entry->d_name) >= sizeof(mount_source)) { | |
| fprintf(stderr, "Error: Mount source path too long for %s\n", entry->d_name); | |
| continue; | |
| } | |
| if (mount(mount_source, proc_path, NULL, MS_BIND, NULL) == 0) { | |
| printf("Process hidden using bind mount: %s -> %s\n", mount_source, proc_path); | |
| closedir(proc_dir); | |
| return 1; | |
| } | |
| } | |
| } | |
| } | |
| closedir(proc_dir); | |
| return 0; | |
| } | |
| void change_process_name(const char *new_name, int argc, char **argv) { | |
| if (new_name == NULL || *new_name == '\0') { | |
| fprintf(stderr, "Invalid process name\n"); | |
| return; | |
| } | |
| char *base_name = basename(argv[0]); | |
| char combined_name[PATH_MAX]; | |
| if (snprintf(combined_name, sizeof(combined_name), "%s (%s)", new_name, base_name) >= sizeof(combined_name)) { | |
| fprintf(stderr, "Error: Combined name too long\n"); | |
| return; | |
| } | |
| int name_changed = 0; | |
| #ifdef __FreeBSD__ | |
| setproctitle("%s", combined_name); | |
| name_changed = 1; | |
| #else | |
| if (prctl(PR_SET_NAME, combined_name, 0, 0, 0) == 0) { | |
| printf("Thread name changed using prctl PR_SET_NAME\n"); | |
| } else { | |
| perror("prctl PR_SET_NAME failed"); | |
| } | |
| if (geteuid() == 0) { | |
| if (try_bind_mount()) { | |
| printf("Process hidden using bind mount\n"); | |
| name_changed = 1; | |
| } else { | |
| size_t new_name_len = strlen(combined_name) + 1; | |
| char *new_argv = mmap(NULL, new_name_len, PROT_READ | PROT_WRITE, | |
| MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
| if (new_argv != MAP_FAILED) { | |
| if (snprintf(new_argv, new_name_len, "%s", combined_name) >= new_name_len) { | |
| fprintf(stderr, "Error: New argv string truncated\n"); | |
| } else if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long)new_argv, 0, 0) == 0 && | |
| prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long)(new_argv + new_name_len), 0, 0) == 0) { | |
| name_changed = 1; | |
| printf("Process name changed using PR_SET_MM\n"); | |
| } else { | |
| perror("prctl PR_SET_MM failed"); | |
| } | |
| if (!name_changed) { | |
| munmap(new_argv, new_name_len); | |
| } | |
| } else { | |
| perror("mmap failed"); | |
| } | |
| } | |
| } | |
| if (!name_changed) { | |
| size_t arg_len = 0; | |
| for (int i = 0; i < argc; i++) { | |
| arg_len += strlen(argv[i]) + 1; | |
| } | |
| if (arg_len > 0) { | |
| memset(argv[0], 0, arg_len); | |
| if (snprintf(argv[0], arg_len, "%s", combined_name) >= arg_len) { | |
| fprintf(stderr, "Warning: Process name truncated in argv\n"); | |
| } | |
| for (int i = 1; i < argc; i++) { | |
| argv[i] = NULL; | |
| } | |
| printf("Process name changed using argv modification\n"); | |
| name_changed = 1; | |
| } else { | |
| fprintf(stderr, "Error: Invalid argument length\n"); | |
| } | |
| } | |
| #endif | |
| if (name_changed) { | |
| printf("Process name successfully changed to: %s\n", combined_name); | |
| } else { | |
| printf("Failed to change process name\n"); | |
| } | |
| } | |
| int main(int argc, char **argv) { | |
| printf("Original process name: %s\n", argv[0]); | |
| printf("Effective UID: %d\n", geteuid()); | |
| change_process_name("hidden_process", argc, argv); | |
| printf("Process renamed. Check 'ps' output in another terminal.\n"); | |
| pause(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment