Skip to content

Instantly share code, notes, and snippets.

@whit3rabbit
Last active October 4, 2024 16:25
Show Gist options
  • Select an option

  • Save whit3rabbit/6a6d4c6f29be194878abf7e0ab0ad5d4 to your computer and use it in GitHub Desktop.

Select an option

Save whit3rabbit/6a6d4c6f29be194878abf7e0ab0ad5d4 to your computer and use it in GitHub Desktop.
hide_process_name.c
#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