我找到了一个有趣的文章关于如何从进程监控工具(如ps
、top
、lsof
、 ... )中隐藏 Linux 上的特定进程
Person 指出有几种可能的方法来隐藏进程:
- 使用适当的框架:有很多非常好的框架,例如
SELinux
和Grsecurity
,除其他外,正是这样做的。在生产系统中,我绝对会考虑这些,尽管今天我想亲自动手并享受从头开始创建一些东西的乐趣。- 修改
top/ps/...
二进制文件:我可以获取每个工具的源代码,实现我自己的“隐藏linux进程” 逻辑、重新编译并替换二进制文件。非常低效且耗时。- 调整
libc
:我可以修改readdir()
里面的函数libc
并输入代码以排除对某些/proc
文件的访问。但重新编译libc
是一种负担,更不用说libc
代码往往很难理解。- 修改内核中的系统调用:这是最先进的,它可以通过
getdents()
使用自定义模块直接在内核中拦截和修改系统调用来工作。这绝对很诱人,但我今天不会遵循这条路线,因为我已经非常熟悉系统调用拦截在 中的工作原理sysdig
,所以我想做一些新的事情。我决定寻求一种中间解决方案,一种有趣且简单的解决方案,可以在一个小时左右的时间内实现:它是 “修改libc”基于提供的一个棘手的功能Linux 动态链接器(负责在运行时加载程序所需的各种库的组件),称为预加载。
和预加载Linux 非常友善地为我们提供了在加载其他常规系统库之前加载自定义共享库的选项。这意味着,如果自定义库导出的函数与系统库中的函数具有相同的签名,那么我们实际上可以使用库中的自定义代码覆盖它,并且所有进程都会自动选择我们的自定义函数!
这听起来像是我的问题的解决方案,因为我可以编写一个非常简单的自定义库来覆盖 libc's
readdir()
,并编写逻辑来隐藏进程!逻辑也相当简单:每次我看到目录/proc/PID
(其中PID是个进程PID正在读取名称"evil_script"
),我只是以干净的方式阻止该访问,从而隐藏整个目录!我继续用代码实现了这些想法。您可以在以下位置获取来源: https://github.com/gianlucaborello/libprocesshider/blob/master/processhider.c (实际上,包括注释在内,代码不到 100 行,所以请阅读它!)。代码编写完成后,我们将其编译为共享库,并将其安装在系统路径中。
源代码:进程隐藏器.c
所以步骤是:
make
=>gcc -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl
mv libprocesshider.so /usr/local/lib/
(作为根)echo /usr/local/lib/libprocesshider.so >> /etc/ld.so.preload
现在回到我的问题/问题: 这里描述的是Linux系统。我在我的 Ubuntu 18.04(64 位)机器上测试了它,一切正常 - 进程现在从ps
.另外,我在另一台安装了 FreeBSD 11.0(64 位)的机器上测试了它。
首先我必须删除以下部分代码:
DECLARE_READDIR(dirent64, readdir64);
因为我收到一个错误(dirent64
未在中定义迪伦特.h- 我只是使用了locate dirent.h
代码并将其与一些互联网资源进行了比较):
processhider.c: In function 'readdir64':
processhider.c:87:37: error: dereferencing pointer to incomplete type 'struct dirent64'
get_process_name(dir->d_name, process_name) && \
^
processhider.c:97:1: note: in expansion of macro 'DECLARE_READDIR'
DECLARE_READDIR(dirent64, readdir64);
^
*** Error code 1
删除后,DECLARE_READDIR(dirent64, readdir64);
我收到另一个错误,抱怨-ldl
标志:
/usr/local/bin/gcc5 -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl
/usr/local/bin/ld: cannot find -ldl
collect2: error: ld returned 1 exit status
*** Error code 1
Stop.
我找到了一个解决方案可以-ldl
用-L/usr/local/lib
我的libdl.so
文件所在位置替换的位置(“的含义”collect2:错误:ld 返回 1 退出状态“ 错误)。
然后我就可以编译代码了。我将库放入/usr/local/lib/
并将其添加到/etc/ld.so.preload
.
然而,当我调用我的脚本时evil_script.py
(代码不同(不再有 UDP 数据包垃圾邮件),但我仍然有while true
循环,time.sleep(60)
因此进程应该在那里),它仍然出现在进程列表中 ( ps auxww
)。也许/etc/ld.so.preload
不工作?ld.so
共享库可能有问题吗?有什么方法可以测试此时出现的问题吗?
答案1
方法2和3(修改ps、top、library),很容易出现绕过漏洞。例如,攻击者可以只使用自己的ps
.
更好的方法是阻止这些工具访问其他用户进程的信息。然后以不同用户身份运行要隐藏的进程。
对于第一部分,编辑/etc/fstab
,包括
#protect /proc
proc /proc proc defaults,nosuid,nodev,noexec,relatime,hidepid=2,gid=admin 0 0