Linux上隐藏进程名(初级版)
緣起
上一篇博文 模仿nginx修改進程名 中提到了一種修改進程名的方法,就像 nginx 一樣,給不同進程命名為 master 以及 worker 等。那么能不能把新進程名設置為空字符串呢?如果能,又會有哪些應用場景呢?
答案可能是能的,設置新進程的名字為空,通常用來隱藏進程,用于攻擊或者反攻擊。
prctl 函數
上一篇博文 模仿nginx修改進程名 文章末尾提到了 prctl 這個函數,它也可以用來修改進程名。
只不過如果單單使用 prctl 來修改進程名的話,使用 ps 或者 top 等工具看到的可能還是原來的名字。
源代碼可以在我的 github 找到:
https://github.com/smaugx/setproctitle/blob/main/hidden_process/prctl_main.cc
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/prctl.h>int main(int argc, char* argv[], char *envp[])
{const char *new_title = "prctl_new_name";prctl(PR_SET_NAME, new_title, NULL, NULL, NULL);while (true) {sleep(2);}return 0;
}
編譯運行:
# g++ prctl_main.cc -o prctl_main -std=c++11
# ./prctl_main
然后我們查看一下進程的名字:
# ps -ef |grep prctl
root 20758 12289 0 17:39 pts/3 00:00:00 ./prctl_main
root 20791 20422 0 17:39 pts/1 00:00:00 grep --color=auto prctl
可以看到 ps 看到的進程名依然是 prctl_main 而不是 prctl_new_name。那么 prctl 函數到底修改了哪里呢? ps 命令又是從哪里讀取的進程名呢?
/proc/<pid> 虛擬文件夾
linux 上一切皆文件,啟動一個進程,就會在系統的 /proc 這個虛擬文件系統下創建這個進程相關的文件夾,里面記錄了這個進程的數據。
# ls /proc/20758
attr cgroup comm cwd fd io map_files mountinfo net oom_adj pagemap projid_map schedstat smaps statm task wchan
autogroup clear_refs coredump_filter environ fdinfo limits maps mounts ns oom_score patch_state root sessionid stack status timers
auxv cmdline cpuset exe gid_map loginuid mem mountstats numa_maps oom_score_adj personality sched setgroups stat syscall uid_map
關注一下這兩個虛擬文件:
# cat /proc/20758/cmdline
./prctl_main
以及
# cat /proc/20758/status
Name: prctl_new_name
Umask: 0022
State: S (sleeping)
Tgid: 20758
Ngid: 0
Pid: 20758
PPid: 12289
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0...(省略)
細心的同學應該發現上面的不一致了吧, /proc/<pid>/cmdline 這個文件記錄的進程名是 prctl_main,而 /proc/<pid>/status 中 Name 值記錄的進程名是 prctl_new_name。而 ps 命令正好是讀取了 cmdline 這個文件,導致即便使用 prctl 修改了進程名,但 ps 依然看到的是老的進程名。
另外要注意,prctl() 這個函數有個限制,新進程的名字長度不能超過 16 字節(包括最后的 ‘\0’),詳見手冊:
https://man7.org/linux/man-pages/man2/prctl.2.html
prctl 結合 argv[0]
上面的分析看到,不論是修改 argv[0] 還是使用 prctl,均有其局限性,那么通常可以結合兩者來進行。
源碼可以在我的 github 找到:
https://github.com/smaugx/setproctitle/blob/main/hidden_process/hidden_main.cc
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/prctl.h>#include "../setproctitle.h"char **smaug_os_argv;int main(int argc, char* argv[], char *envp[])
{smaug_os_argv = argv;// set new process NULL to hide processconst char *new_title = "hidden_main_new";if (smaug_init_setproctitle() == SMAUG_PROCTITLE_OK) {smaug_setproctitle(new_title);}// set new process NULL to hide processprctl(PR_SET_NAME, new_title, NULL, NULL, NULL);while (true) {sleep(1);}return 0;
}
編譯運行:
# ps -ef |grep hidd
root 21753 12289 0 17:55 pts/3 00:00:00 hidden_main_new
root 21760 20422 0 17:55 pts/1 00:00:00 grep --color=auto hidd# cat /proc/21753/cmdline
hidden_main_new[root@Jiao ~]## cat /proc/21753/status |grep Name
Name: hidden_main_new
可以看到,無論是通過 ps 命令還是直接查看 /proc/<pid>/ 下的文件的方式,均能看到修改后的名字: hidden_main_new。
隱藏進程
經過上一步,已經可以完美的修改進程名了,那么再進一步,如何隱藏進程呢?
const char *new_title = "";
只需要修改上述的一行代碼,重新編譯即可,然后用 ps 或者 top 看一下,能不能找到這個進程:
# ps -ef |grep hidden
root 22022 20422 0 17:59 pts/1 00:00:00 grep --color=auto hidden
可以看到 ps 無法找到 hidden* 相關的進程,那么 top 呢?
top - 18:01:06 up 16 days, 4:16, 9 users, load average: 0.00, 0.01, 0.05
Tasks: 121 total, 1 running, 120 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3879952 total, 3579624 free, 95660 used, 204668 buff/cache
KiB Swap: 5242876 total, 5164352 free, 78524 used. 3272224 avail MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31038 root 20 0 115800 372 368 S 0.0 0.0 0:00.70 bash
22081 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/1:0
22078 root 20 0 162140 2252 1548 R 0.0 0.1 0:00.04 top
22013 root 20 0 11124 1068 908 S 0.0 0.0 0:00.00
21859 root 20 0 115892 244 240 S 0.0 0.0 0:00.46 bash
21725 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/1:2
20811 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0
運行 top 命令,并且以 pid 倒敘排序,注意第四行的進程,可以看到 COMMAND 為空,這個進程就是剛才的這個進程,但是看不到進程名了,達到了簡單的、初級的隱藏進程的目的。
擴展一下
上述相關代碼均可以在我的 github 找到:
https://github.com/smaugx/setproctitle/tree/main/hidden_process
上面的討論可以看到,能實現初級的,簡單的進程隱藏,但是使用 top 命令還是能看到這個無名進程,那么這點改怎么解決呢?
這里就不展開了,我沒有這方面的經驗。不過通常來說有兩種辦法:
- 修改進程名為常見的一些進程名,比如 bash, top, nginx 等以達到混淆的目的
- 想辦法把 /proc/<pid>/ 這個虛擬文件夾隱藏或者達到隱藏類的效果(不太擅長)
Blog:
-
rebootcat.com
-
email: linuxcode2niki@gmail.com
2020-10-25 于杭州
By 史矛革
總結
以上是生活随笔為你收集整理的Linux上隐藏进程名(初级版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模仿nginx修改进程名
- 下一篇: free not return memo