Linux 内核创建了许多线程来帮助完成系统任务。这些线程可以用于调度磁盘 I/O 等。
当打印系统进程时,这些线程将显示为带有 [xxx],括号表示该进程没有命令行参数,它们是某种线程。而普通进程,通常不会以 [xxx] 显示。
有些恶意软件使进程的名称周围显示 [xxx] ,伪装成 Linux 内核线程来隐藏其运行时的状态。比如,设置可执行文件名称为 [ksample],然后伪装为内核线程运行。
针对可疑内核线程的排查,第一种方法是查看/proc/<PID>/maps下是否有任何内容。/proc/<PID>/maps通常是进程显示链接到的库以及在内存中映射到的位置。对于真正的内核线程,其映射为空。
伪装为内核线程的 [ksample],则打印出内存中的映射信息。
可以快速遍历所有进程/线程,并查看哪些以括号命名,且具有映射信息。任何显示数据的进程/线程都应该进一步调查。
ps -aux | grep \\[ | awk '{print $2}' | xargs -I % sh -c 'echo PID: %; cat /proc/%/maps' 2> /dev/null
另一种方法,查看它是否指向正在运行的进程的可执行文件。查看/proc/PID/exe,真正的内核线程不会有指向的可执行文件。
伪装的内核线程则会指向可执行文件。
可以复制进程的二进制文件。保留启动该线程的二进制文件的快照。也可以计算哈希检测已知恶意软件。
ps -aux | grep \\[ | awk '{print $2}' | xargs -I % sh -c 'echo PID: %; sha1sum /proc/%/exe' 2> /dev/null
proc 目录下的文件 comm 和 cmdline 将显示系统启动进程/线程时的命令和命令行。真正的内核线程,comm 中一般为没有括号的线程名称,伪装的内核线程,comm 中一般带有括号。
进程名称两边的括号,表示该进程没有命令行参数,这通常表示它是作为线程产生的。所以真正的内核线程,cmdline 为空。
当启动一个进程时,通常会附加环境变量列表。查看 /proc/<PID>/environ,真正的内核线程,内容为空。
https://sandflysecurity.com/blog/detecting-linux-kernel-process-masquerading-with-command-line-forensics/