AgentSmith HIDS
是字节跳动开源的HIDS,采用内核驱动方式进行入侵检测,可以检测各种rootkit/bootkit
,具有实时,高性能,无感知的优势。由于它是基于内核,只对2.6.32+内核支持,且rootkit的检测必须要在3.10.0+内核才支持。同时,由于它是监控内核函数的调用,事件和消息,并不提供软件管理,用户管理,系统管理,网络管理之类的基线。
虽然目前总体代码只是2500行左右,但实现功能却非常多,多得作者Will大佬的指点,在撸一把5.12.0内核的代码,才勉强清楚这些检测点的应用场景。感谢Will大佬。Will大佬在内核造诣非常深厚。
AgentSmith在检测信息时,这些信息是每个场景都采集的。详情见kprobe_print.h
AgentSmith是LKM(可加载内核模块)的方式hook住Linux内核一些函数。由于它是使用kprobe的方式,它hook的函数不只是系统调用,还可以hook内核内部一些函数,而这些内部函数是某些系统调用的关键点调用。
下面按照这样格式列举各个钩子:内核版本:该钩子支持的内核版本 作用:该钩子对应syscall的作用 危害:黑客可以利用相应syscall所造成的危害 实现原理:该钩子的实现方式 不足:该钩子还没有覆盖的情况
内核版本:
1.0+
作用
这个系统调用对当前进程内存段设置保护
危害
恶意软件把当前进程的数据段设置为可执行,从而绕过DEP 恶意软件把当前进程的代码段设置为可写,从而注入恶意代码
实现原理
对mprotect系统调用挂钩,记录任何把进程内存段改为**执行权限(
PROT_EXEC
)**的操作。记录信息:
执行程序 执行程序的进程树 目标进程 目标进程所属的程序 操作
不足
仅处理了执行权限(
PROT_EXEC
), 没有处理可写权限(PROT_WRITE
)
内核版本:
1.0+
作用
打开并且有可能创建新的文件或设备
危害
恶意软件隐藏自身文件, 躲避检测
实现原理
对open系统调用挂钩,记录程序打开文件操作,记录信息:
执行程序 文件 打开标志 打开模式
内核版本:
2.0+
作用
进程休眠一定时间再执行,高精度的休眠
危害
恶意软件hook
nanosleep
系统调用,可以延迟执行,从而逃避HIDS软件的检测。详情请见https://reyammer.io/publications/2018_oakland_linuxmalware.pdf
实现原理
对nanosleep系统调用挂钩,记录程序进程休眠操作,记录信息:
执行程序 秒 纳秒
内核版本
kill: 1.0+
tkill: 2.4.22, 2.6+
作用
kill: 向某个进程发送信号
tkill: 向某个线程发送信号
危害
服务进程被恶意终止,造成DOS攻击
实现原理
对kill/tkill系统调用挂钩,记录程序终止某个进程操作,
记录信息:
执行程序 目标进程 信号
内核版本
exit: 1.0+
exit_group: 2.6+
作用
exit: 进程退出
exit_group: 所有进程所在线程组的线程都退出
危害
服务线程被退出,造成服务不可用
实现原理
对exit/exit_group系统调用挂钩,记录程序退出进程操作,记录信息:
执行程序
内核版本
rmdir: 1.0+
unlink: 1.0+
作用
rmdir: 删除一个目录
unlink: 删除链接,并且有可能删除引用的文件
危害
服务依赖的问题被删除,导致服务无法启动
实现原理
对rmdir/unlink系统调用挂钩,记录程序删除文件或目录操作,记录信息:
执行程序 被删除的路径
内核版本
rename: 1.0+
renameat: 2.6.16+
作用
rename: 重命名或移动文件
renameat: 基于某个目录重命名或移动文件
危害
恶意文件伪装成合法文件
实现原理
对rename/renameat系统调用挂钩,记录程序对目录和文件改名操作,记录信息:
执行程序 当前工作路径 旧路径名 新路径名
内核版本
link: 1.0+
linkat: 2.6.16+
作用
link: 给文件建立链接
linkat: 基于某个目录给文件建立链接
危害
恶意文件伪装成合法文件
实现原理
对link/linkat系统调用挂钩,记录程序链接文件操作,记录信息:
执行程序 当前工作路径 旧路径名 新路径名
内核版本
setsid: 1.0+
作用
setsid: 创建会话并设置进程组ID
危害
恶意本地提权
实现原理
对setsid系统调用挂钩,记录程序执行文件权限提升操作,记录信息:
执行程序
内核版本
prctl: 2.2+
作用
prctl: 对进程的属性操作
危害
进程伪装,躲避HIDS的检测 允许进程被恶意代码注入 允许进程自修改(病毒多态)
实现原理
对prctl系统调用挂钩,记录程序对进程和线程进行名称设置(
PR_SET_NAME
2.6.9+内核支持)操作,记录信息:
执行程序 改名 新名称
不足
没有对 PR_SET_PTRACER
处理,这个会允许恶意软件调试该进程,从而进行代码注入。PR_SET_PTRACER
在3.4+内核支持没有对 PR_SET_MM
监控,恶意程序可以对自身进行自修改,PR_SET_MM
在3.3+内核支持
内核版本
connect: 2.0+
作用
connect: 启动一个连接
危害
外连行为
实现原理
对connect系统调用挂钩,记录程序连接远程服务操作,记录信息:
数据类型 目标IP 目标端口 执行文件 源IP 源端口 返回结果
内核版本
bind: 2.0+
作用
bind: 绑定socket
危害
高危端口,增加攻击面
实现原理
对bind系统调用挂钩,记录程序绑定端口提供服务操作,记录信息:
执行程序 IP地址 端口 返回结果
内核版本
open: 1.0+
creat: 1.0+
作用
open: 打开并且有可能创建新的文件或设备
creat: 创建新的文件或设备
危害
恶意软件创建并隐藏自身文件,躲避检测
实现原理
对creat/open系统调用挂钩,记录不在白名单的程序创建文件操作,记录信息:
执行程序 路径
内核版本
execve: 1.0+
作用
execve: 执行文件
危害
执行恶意程序
实现原理
对execve系统调用挂钩,记录程序执行文件操作,记录信息:
执行目录 执行程序 父程序 参数 标准输入 标准输出 进程树 终端名称 ssh连接 ld_preload标志 返回结果 目标IP 目标端口 源IP 源端口 socket所属进程 socket名称
内核版本
ptrace: 1.0+
作用
调试进程
危害
恶意代码注入正常程序,可以达到无落地文件的内存级注入
实现原理
对ptrace系统调用挂钩,记录程序调试进程操作,记录信息:
POKETEXT
/POKEDATA
进程ID 内存地址 拷贝的数据 执行程序 进程树
不足
PTRACE_GETREGSET
,PTRACE_SETREGSET
,PTRACE_SYSCALL
没有处理,无法阻止ROP攻击
内核版本
recvmsg: 2.0+
作用
recvmsg: 接收消息
危害
DNS污染
实现原理
对recvmsg系统调用挂钩,记录程序dns查询消息处理,记录信息:
目标端口 目标地址 执行程序 源IP 源端口 消息类型 操作码 返回码
不足
没有对sendmsg挂钩,对DNS的响应,检测DNS反射放大攻击
内核版本
init_module: 1.0+
作用
init_module: 加载内核模块
危害
加载内核态rootkit或bootkit
实现原理
对init_module系统调用挂钩,记录程序加载内核模块操作,记录信息:
执行程序 模块名 进程树 当前工作目录
内核版本
capset: 2.2+
setgroups: 2.4+
fork: 1.0+
execve: 1.0+
setns: 3.0+
setregid: 1.0+
setgid: 1.0+
setreuid: 1.0+
setuid: 1.0+
setresuid: 2.2+
setresgid: 2.2+
setfsuid: 1.2+
setfsgid: 1.2+
keyctl: 2.6.11+
add_key: 2.6.11+
request_key: 2.6.11+
作用
capset: 设置线程权限特性
setgroups:给进程设置后补组
fork: 创建子进程
execve: 执行程序
setns: 关联线程到某个命名空间
setregid: 设置有效组id
setgid:设置真实组id
setreuid: 设置有效用户id
setuid: 设置真实用户id
setresuid: 设置真实,有效和保存用户id
setresgid:设置真实,有效和保存组id
setfsuid: 设置用于文件系统检查的用户id
setfsgid:设置用于文件系统检查的组id
keyctl: 操作内核密钥管理工具
add_key: 增加一个密钥到内核密钥管理工具
request_key: 从内核密钥管理工具中请求一个密钥
危害
恶意文件提权
实现原理
对capset/setgroup/fork/execve/setns/setregid/setgid/setreuid/setuid/setresuid/setresgid/setfsuid/setfsgid/keyctl/add_key/request_key系统调用涉及的update_creds函数挂钩,记录程序进程权限提升操作,记录信息:
执行程序 进程树 旧uid 设置结果