fangpsh's blog

为何无法杀死阿里云盾

输错 PID,给云盾进程发送了kill signal:

root     26689  0.3  0.1 113180  9420 ?        S<sl 10:34   0:08 /usr/local/aegis/aegis_client/aegis_11_83/AliYunDun
...

# kill -9 26689
-bash: kill: (26689) - Operation not permitted

咦,怎么啥不死,我是 root 呀。再尝试下systemctl stop aegis,状态是inactive了,但是进程还在 👻。

● aegis.service - Aegis Service
   Loaded: loaded (/etc/systemd/system/aegis.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Wed 2024-01-10 14:46:43 HKT; 24h ago
   CGroup: /system.slice/aegis.service
           ├─26627 /usr/local/aegis/aegis_update/AliYunDunUpdate
           ├─26689 /usr/local/aegis/aegis_client/aegis_11_83/AliYunDun
           └─26700 /usr/local/aegis/aegis_client/aegis_11_83/AliYunDunMonitor

好奇心来了,咋实现的呢?😯

strace 一下 strace kill -9 26689 没什么收获,

open("/usr/lib/locale/UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
kill(26689, SIGKILL)                    = -1 EPERM (Operation not permitted)
write(2, "kill: ", 6kill: )                   = 6
write(2, "sending signal to 26689 failed", 30sending signal to 26689 failed) = 30
write(2, ": ", 2: )                       = 2
write(2, "Operation not permitted\n", 24Operation not permitted
) = 24

云盾的二进制文件也删不掉:

# rm -f /usr/local/aegis/aegis_client/aegis_11_81/AliYunDun
rm: cannot remove 'AliYunDun': Operation not permitted

也对,这是个安全软件(HIDS),要是能这么简单被干掉,也太弱了。 想起有网友介意这类程序的,那我看大家的卸载清理指南不就可以了?

找到卸载脚本:

http://update.aegis.aliyun.com/download/uninstall.sh

stop_aegis_pkill() 就是普通的 kill 发个信号,不过接着执行的wait_aegis_exit() 里面的语句:

    echo "wait AliYunDun process exit fail, possibly due to self-protection, please uninstall aegis or disable self-protection from the aegis console."

意思就是在控制台关闭掉就可以被 kill 了,那这应该是云盾进程自己控制的。 再往下看如何清理文件,看到了kprobe:

    kprobeArr=(
        "/sys/kernel/debug/tracing/instances/aegis_do_sys_open/set_event"
        "/sys/kernel/debug/tracing/instances/aegis_inet_csk_accept/set_event"
        "/sys/kernel/debug/tracing/instances/aegis_tcp_connect/set_event"
        "/sys/kernel/debug/tracing/instances/aegis/set_event"
        "/sys/kernel/debug/tracing/instances/aegis_/set_event"
        "/sys/kernel/debug/tracing/instances/aegis_accept/set_event"
        "/sys/kernel/debug/tracing/kprobe_events"
        "/usr/local/aegis/aegis_debug/tracing/set_event"
        "/usr/local/aegis/aegis_debug/tracing/kprobe_events"
    )

看着眼熟,之前看动态调试相关的文章见过,没深入了解忘记了,原来如此。

# lsmod  |grep -i ali
AliSecGuard            22400  2

果然有一个配套的内核模块。

检查一下event:

# trace-cmd list   |grep -i aegis
kprobes:aegis_cn_netlink_send
kprobes:aegis_sys_execve
kprobes:aegis_proc_fork_connector

v2ex这个帖子中,网友提到了用kprobe 检测系统调用是HIDS 的主流实现方式,是我菜鸡了。

既然如此,那找一个开源的 HIDS 学习一下。

看到了字节开源的:elkeid,看这个原理介绍

AgentSmith是LKM(可加载内核模块)的方式hook住Linux内核一些函数。由于它是使用kprobe的方式,它hook的函数不只是系统调用,还可以hook内核内部一些函数,而这些内部函数是某些系统调用的关键点调用。

kill 对kill/tkill系统调用挂钩,记录程序终止某个进程操作, 记录信息: 执行程序 目标进程 信号

先看这篇文章学习了下怎么写一个简单的 kprobe 例子,以便能略微看懂代码:
《Linux内核调试技术——kprobe使用与实现》

翻了下Elkeid/driver/LKM/src/ 找到了 kill_kprobe

struct kprobe kill_kprobe = {
        .symbol_name = P_GET_SYSCALL_NAME(kill),
        .pre_handler = kill_pre_handler,
};

struct kprobe tkill_kprobe = {
        .symbol_name = P_GET_SYSCALL_NAME(tkill),
        .pre_handler = tkill_pre_handler,
};

再顺着就可以找到register_kill_kprobekill_pre_handler() 等。

大概明白了逻辑,云盾是hook 了 kill 的系统调用,在里面实现了自保的逻辑。

也可以参考这个文章《 linux源码解读(十三):内核驱动module加载kprobe&字节跳动Elkied简要分析》

这两篇译文写的也非常好,可以补充下 ftrace 的技能: