如何改变进程名称

背景

之前在测试反弹shell时,测试发现:某厂商会根判断程命令是否是bash、sh等脚本解释器,如果修改bash、sh等文件名后反弹shell,就会绕过厂商的反弹shell防护。

需要注意的的是:”修改敏感文件名、复制敏感文件“本身非常有可能被hids当作一种”异常文件操作”行为。

还有一些场景下也会涉及到”进程名称的修改”:比如某些恶意软件会修改进程名称,伪装成”内核线程”。

所以可以说,在”进程名称的修改”这个点上是存在一些攻防对抗的。

本文研究:

  • 除了直接修改程序文件名,还有哪些方式来修改进程名称?
  • 作为防守方,怎么发现和检测这些”修改方式”?

本文应该适合 做应急响应、hids和”对linux后渗透感兴趣”的读者阅读,文章中给出了我对每种隐藏方式的效果验证,方便读者对隐藏效果做评估。

分析过程

  • 怎么查看”进程名称”?

    在 /proc/{pid} 目录下有好几个文件都存放有”进程名称”相关的信息,如下图:
    image

    更常见的情况下,我们是通过ps、top等命令来查看进程信息。

    ps命令也是基于 /proc/{pid}/stat、/proc/{pid}/status、/proc/{pid}/cmdline 等文件来获取进程信息。可以通过strace命令查看系统调用验证一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@instance-fj5pftdp ~]# strace ps aux 2>&1 |grep proc |grep 29224
    stat("/proc/29224", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
    open("/proc/29224/stat", O_RDONLY) = 6
    open("/proc/29224/status", O_RDONLY) = 6
    open("/proc/29224/cmdline", O_RDONLY) = 6
    readlink("/proc/29224/fd/2", "/42", 127) = 3
    [root@instance-fj5pftdp ~]#
    [root@instance-fj5pftdp ~]# strace ps -A 2>&1 |grep proc |grep 29224
    stat("/proc/29224", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
    open("/proc/29224/stat", O_RDONLY) = 6
    open("/proc/29224/status", O_RDONLY) = 6
    readlink("/proc/29224/fd/2", "/42", 127) = 3
  • 怎么修改”进程名称”?

    改变进程名包括以下方式:

    • execve系统调用
    • prctl系统调用
    • 修改进程argv
    • 软链接

通过”execve系统调用”改变进程名称

  • 怎么通过”execve系统调用”可以改变进程名称?

    execve系统调用的第二个参数可以指定cmdline,如下:

    image

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include<unistd.h>
    int main()
    {
    char * execve_str[] = {"test_sleep","10000"}; // 第一个参数会出现在/pro/{pid}/cmdline
    char * env[] = {NULL};
    if (execve("/usr/bin/sleep",execve_str,env) <0 ){
    perror("error on exec");
    }
    }

    更简便的方式是:通过bash的exec命令的-a参数改变进程名称

    1
    exec -a "xxx" sleep 10000
  • 效果

    image

    可以看到:ps -A可以看到sleep文件名信息,ps aux无法看到。

    image

    可以看到:只有cmdline被修改了。

通过”prctl系统调用”改变进程名称

  • 怎么通过”prctl系统调用”改变进程名称?

    Linux进程隐藏:初级篇 这篇文章有demo代码

  • 效果
    image

    可以看到虽然stat、comm、status文件已经修改,但是cmdline、exe等文件仍然有原程序名信息。

  • 怎么检测?

    字节hids hook了这个系统调用

通过”修改进程argv[0]”隐藏进程名称

  • 怎么通过”修改进程argv[0]”隐藏进程名称?

    Linux进程隐藏:初级篇 这篇文章有demo代码

  • 谁用了这种方式?

    恶意软件puppy 就用到了这种方式修改进程名为”[kworker/2:0]”。

    “[XXXX]”这种进程名都是内核线程

    image

  • 效果

    image

    可以看到:只有cmdline被修改了。

通过”软链接”改变进程名称

  • 是什么?

    两个主题:躲避execve与分析/proc/目录 这篇文章提到了:利用”软链接”可以改变进程信息,并且文件哈希和源文件不一致,这样可以用来躲避安全产品的监控。

  • 效果
    image

    可以看到:只有exe文件还有原程序信息,所以这种方式隐藏进程名的效果是最好的。

总结

可以有以下结论:

  • 单看四种隐藏方式,”软链接”这种方式隐蔽得最好;其他几种方式,comm、stat、cmdline、status文件中总会有原程序相关信息
  • 不论哪种方式,exe文件仍然有原程序相关信息
  • 像”prctl系统调用”这种方式应该避免使用