如何伪装进程信息
2021-10-19 16:25:09 Author: wiki.ioin.in(查看原文) 阅读量:54 收藏

如何改变进程名称 中提到了一些隐藏进程信息的方式,当时遗留有一个问题:不论哪种方式,exe文件仍然有原程序相关信息。

本文将总结两种"隐藏/proc/{pid}/exe文件"的方式,并浅析两种方式的隐藏效果。

两种方式包括:

  • mount命名空间
  • 修改软链接内容
  • 现象

    思路来源于基于Linux Namespaces 特性实现的消音

    先来看一个现象:/proc/31867/exe指向的可执行文件内容是一串文本。

    图一

    难道文本内容可以被当做二进制文件执行吗?

    答案当然是不行的。这里只是执行/tmp/sleep命令的方式比较特殊,如下:

    [root@instance-fj5pftdp ~]# echo 111 > /tmp/sleep
    [root@instance-fj5pftdp ~]# unshare -m bash -c "mount -t tmpfs xx /tmp/;cp /usr/bin/sleep /tmp/sleep;/tmp/sleep 1000" &
    [1] 31865
    [root@instance-fj5pftdp ~]# ps aux|grep sleep
    root      31867  0.0  0.0 108052   612 pts/74   S    10:01   0:00 /tmp/sleep 1000

    unshare -m命令创建了一个新的"mount命名空间",然后在这个空间中挂载了tmpfs文件系统,最后执行sleep程序。

  • "mount命名空间"是什么?

    "命名空间"是容器的核心原理之一。从效果上来看,"mount命名空间"可以让宿主机和容器中的"挂载信息"隔离。

    比如在上面例子中,宿主机上执行mount命令是是看不到"tmpfs文件系统被挂载在/tmp"目录下的。

    [root@instance-fj5pftdp ~]# mount | grep xx
    [root@instance-fj5pftdp ~]#
  • 这种方式的对抗效果怎么样?

    可以从两个场景来评估"对抗效果":

    1.和"应急分析人员"对抗:应急人员是否能够轻易发现异常?

    2.和"安全产品"对抗:安全产品是否能够轻易发现异常?安全产品的信息采集策略是否受此种方式影响?

    从"应急场景"的角度来看,应急分析人员如果很清楚/proc/{PID}/exe指向的文件不可信,可以通过 对比"可疑进程"和1号进程,验证mnt命名空间不同

    [root@instance-fj5pftdp ~]# ll /proc/31867/ns/mnt
    lrwxrwxrwx 1 root root 0 10月  1 23:42 /proc/31867/ns/mnt -> mnt:[4026533456]
    [root@instance-fj5pftdp ~]# ll /proc/1/ns/mnt
    lrwxrwxrwx 1 root root 0 10月  1 23:43 /proc/1/ns/mnt -> mnt:[4026531840]  // 和 4026533456 不同

    然后通过nsenter命令获取特定进程的挂载信息

    [root@instance-fj5pftdp ~]# nsenter -m -t 31867 mount|grep /tmp
    xx on /tmp type tmpfs (rw,relatime)

    从"安全产品对抗"的角度来看,可以有以下结论:

    1.hids可以监控mount系统调用来发现异常;不过不是所有的agent都会监控mount系统调用,比如字节hids[1]就没有。

    2.hids上报文件时,如果是读取软链接指向的文件(比如案例中的/tmp/sleep,而不是/proc/31867/exe),就有可能上报错误的文件。

  • 怎么修改软链接内容?

    Linux进程伪装:动态修改/proc/self/exe[2] 文章中总结了两种方法:

    1.execve函数

    2.prctl系统调用

    读者可直接阅读原文,这里我只记录一个自己看文章时的疑问:如果先创建线程A然后再调用execve,是否线程A还能继续执行?

    答案是不行。

    man 2 execve手册有说明:所有线程都被销毁

    Note the following further points:

      *  All threads other than the calling thread are destroyed during an execve().  Mutexes, condition variables, and other pthreads objects are not preserved.

    自己测试了一下,可以验证"线程会被销毁"的结论。

    测试代码[3],运行结果:

    [root@vm10-50-0-18 ~]# gcc y.c -lpthread && ./a.out
    hi
    hi
    hi
    [root@vm10-50-0-18 root]#
  • 这种方式的对抗效果怎么样?

    原文第一种execve方式,我不太清楚使用场景:既然都execve来替换程序了,为什么不直接退出程序呢?

    第二种"prctl系统调用"方式,对"应急响应人员"来说,迷惑性应该是很大的。对"hids产品"来说,prctl系统调用会是一个监控点。

    比如字节hids对prctl系统调用是有监控的,可以参考elkeid的系统调用hook列表[4]。不过目前只有prctl系统调用的参数是PR_SET_NAME时才上报数据。这里用到的是PR_SET_MM参数,所以会绕过字节hids。

    图五
  • 补充一种"修改软链接内容"的方式

    当使用umount -l卸载时,exe指向的路径也会修改,如下图

    图六

从上面分析可以看到,"/proc/{pid}/exe"文件相关信息似乎是不可信的:

  • "mount命名空间"会改变/proc/{pid}/exe对应文件的内容
  • 先知文章提到的两种方式会改变/proc/{pid}/exe指向的文件

个人感觉:这两种方式都有可能导致hids文件上报出现问题,也可能给"应急人员"的分析过程造成一定阻力。

其实这里存在一个缺陷导致隐藏效果打折:如果直接cat /proc/{pid}/exe,就能可以读到源二进制程序内容。

那怎么让/proc/{pid}/exe无法还原出二进制程序呢,这个问题留给读者思考。

本文提到的手段没有在真实的对抗中实践过,仅仅是我自己的研究,欢迎与我交流。

参考资料

[1]

字节hids: https://github.com/bytedance/Elkeid/tree/main/driver

[2]

Linux进程伪装:动态修改/proc/self/exe: https://xz.aliyun.com/t/10235

[3]

测试代码: https://gist.github.com/leveryd/277852e2e741eb24b0b4bb8dc0220ef2

[4]

elkeid的系统调用hook列表: https://github.com/bytedance/Elkeid/tree/main/driver


文章来源: http://wiki.ioin.in/url/QbRj
如有侵权请联系:admin#unsafe.sh