在入侵检测的过程中,进程创建监控是必不可少的一点,因为攻击者的绝大多数攻击行为都是以进程的方式呈现,所以及时获取到新进程创建的信息能帮助我们快速地定位攻击行为。
本文将介绍一些常见的监控进程创建的方式,包括其原理、Demo、使用条件和优缺点。行文仓促,如果有哪些错误和不足,还望大家批评指正。
目前来看,常见的获取进程创建的信息的方式有以下四种:
下面我们就从原理、Demo、使用条件和优缺点来了解一下这四种方式。
首先跟大家介绍两点基础知识:
1.Linux 中大部分的可执行程序是动态链接的,常用的有关进程执行的函数例如 execve均实现在 libc.so 这个动态链接库中。
2.Linux 提供了一个 so preload 的机制,它允许定义优先加载的动态链接库,方便使用者有选择地载入不同动态链接库中的相同函数。
结合上述两点不难得出,我们可以通过 so preload 来覆盖 libc.so 中的 execve等函数来监控进程的创建。
下面我们就来实现一个简单的 demo 。
1.创建文件 hook.c ,内容如下:
#define _GNU_SOURCE
#include
该文件的主要部分就是重新定义了 execve函数,在原始的 execve执行之前打印可执行文件的名字。
2.生成动态链接库:gcc hook.c-fPIC-shared-o hook.so
3.将上面生成的动态链接库注册成 preload :echo'/path/to/hook.so'>/etc/ld.so.preload
4.退出当前 shell 并重新登录(下面会讲原因),执行命令即可看到我们编写的代码已被执行:

该方法没有什么条件限制,只需有 root 权限即可(做入侵监控程序 root 权限是必需的,后面的几种方法默认也都是在 root 权限下)。
优点
缺点
对于使用方法的第四步,可能大家会有疑问:为什么一定要重新获取 shell 才可以看到效果呢?这是因为其实在当前 shell 下执行命令(也就是执行 execve)的实际上是当前的 shell 可执行程序,例如 bash ,而 bash 所需的动态链接库在其开始运行时就已确定,所以我们后续添加的 preload 并不会影响到当前 bash ,只有在添加 preload 之后创建的进程才会受 preload 的影响。这也就得出了该方法的第一个缺点:
除此之外还有以下几点缺点:
在介绍 Netlink Connector 之前,首先了解一下 Netlink 是什么,Netlink 是一个套接字家族(socket family),它被用于内核与用户态进程以及用户态进程之间的 IPC 通信,我们常用的 ss命令就是通过 Netlink 与内核通信获取的信息。
Netlink Connector 是一种 Netlink ,它的 Netlink 协议号是 NETLINK_CONNECTOR,其代码位于 9f9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6@1L8%4u0$3j5h3I4V1M7#2)9J5c8X3I4A6L8Y4g2^5i4K6u0r3N6s2u0W2k6g2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8X3c8J5K9i4k6W2M7Y4y4Q4x3V1k6U0L8$3&6F1k6h3y4@1L8%4t1`. 中,其中 connectors.c 和 cnqueue.c 是 Netlink Connector 的实现代码,而 cnproc.c 是一个应用实例,名为进程事件连接器,我们可以通过该连接器来实现对进程创建的监控。
系统架构:
(图片来源:296K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2K6L8r3W2V1k6i4y4Z5j5i4u0W2i4K6u0W2L8X3g2@1i4K6u0r3K9$3g2J5L8X3g2D9N6r3I4$3i4K6u0r3K9$3g2J5L8X3g2D9i4K6u0V1M7s2u0G2j5#2)9J5k6r3y4G2L8X3&6W2j5%4c8G2M7W2)9J5k6r3q4F1k6q4)9J5k6r3y4G2L8Y4c8S2K9h3&6W2M7Y4y4Q4c8f1k6Q4b7V1y4Q4z5o6V1`.

具体流程:
(图片来源:6bdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1j5@1K9r3!0#2i4K6u0W2N6$3W2F1i4K6u0r3N6$3!0J5k6s2m8J5k6i4y4K6i4K6u0r3i4K6y4r3M7q4)9K6c8o6t1&6y4e0R3$3i4@1g2r3i4@1u0o6i4K6R3&6

图中的 ncp 为 Netlink Connector Process,即用户态我们需要开发的程序。
在 Github 上已有人基于进程事件连接器开发了一个简单的进程监控程序:682K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Y4k6%4u0S2L8X3c8W2M7#2)9J5k6r3y4D9L8$3&6W2M7#2)9J5c8Y4m8E0L8$3&6Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3M7%4u0U0i4K6u0r3M7r3#2G2L8W2)9J5k6h3x3`. ,其核心函数为以下三个:
其执行流程正如上图所示。
我们通过 gcc pmon.c-o pmon生成可执行程序,然后执行该程序即可看到效果:

获取到的 pid 之后,再去 /proc/<pid>/目录下获取进程的详细信息即可。
内核支持 Netlink Connector
优点
缺点
Linux Audit 是 Linux 内核中用来进行审计的组件,可监控系统调用和文件访问,具体架构如下(图片来源:900K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6L8r3q4U0K9#2)9J5k6h3g2F1k6$3W2F1k6h3g2J5K9h3&6Y4i4K6u0r3M7%4W2K6j5$3q4D9L8q4)9J5k6r3q4#2k6r3W2@1K9h3&6Y4i4K6u0V1j5i4c8Q4x3X3c8K6j5$3q4D9k6g2)9J5k6r3f1$3j5e0y4U0j5e0S2S2j5K6q4T1z5q4!0q4c8W2!0n7b7#2)9^5z5g2!0q4c8W2!0n7b7#2)9&6b7b7`.`.

1.用户通过用户态的管理进程配置规则(例如图中的 go-audit ,也可替换为常用的 auditd ),并通过 Netlink 套接字通知给内核。
2.内核中的 kauditd 通过 Netlink 获取到规则并加载。
3.应用程序在调用系统调用和系统调用返回时都会经过 kauditd ,kauditd 会将这些事件记录下来并通过 Netlink 回传给用户态进程。
4.用户态进程解析事件日志并输出。
从上面的架构图可知,整个框架分为用户态和内核态两部分,内核空间的 kauditd 是不可变的,用户态的程序是可以定制的,目前最常用的用户态程序就是 auditd ,除此之外知名的 osquery 在底层也是通过与 Audit 交互来获取进程事件的(d72K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0k6h3c8A6N6h3#2Q4x3X3g2U0L8$3#2Q4x3V1k6H3j5h3I4S2L8Y4c8A6M7W2)9J5c8X3q4#2k6r3W2@1K9h3&6Y4i4K6u0V1N6$3W2@1K9q4)9J5k6r3!0K6M7i4g2W2M7Y4W2Q4x3X3c8H3j5i4u0@1i4K6u0V1L8$3&6W2i4K6u0V1K9h3&6@1M7X3!0V1N6h3y4@1K9h3!0F1i4K6u0V1N6r3!0Q4x3X3c8@1K9r3g2Q4x3X3c8D9K9h3&6#2P5q4)9J5k6r3q4#2k6r3W2@1i4K6u0V1k6Y4u0S2L8h3g2%4L8%4u0C8i4K6u0V1x3U0p5%4z5e0j5%4j5$3g2U0y4o6l9$3i4@1g2r3i4@1u0o6i4K6R3&6i4@1f1K6i4K6R3H3i4K6R3J5i4@1f1@1i4@1t1^5i4K6S2n7i4@1f1&6i4K6W2p5i4@1p5J5i4@1f1$3i4K6R3^5i4K6V1I4i4@1f1@1i4@1u0n7i4@1q4o6i4@1f1#2i4@1t1H3i4@1t1I4i4@1f1%4i4@1q4q4i4K6R3H3i4@1f1#2i4K6S2p5i4K6V1#2i4@1f1@1i4@1u0n7i4K6S2n7i4@1f1%4i4@1u0n7i4K6S2p5i4@1f1@1i4@1t1^5i4K6R3H3i4@1f1@1i4@1t1^5i4K6S2n7i4@1f1#2i4@1p5$3i4K6R3J5i4@1f1@1i4@1u0p5i4K6V1#2i4@1f1&6i4K6R3H3i4K6W2m8i4@1f1^5i4@1u0r3i4K6R3%4 auditd 来监控进程创建。
首先安装并启动 auditd :
auditd 软件包中含有一个命名行控制程序 auditctl,我们可以通过它在命令行中与 auditd 进行交互,用如下命令创建一个对 execve这个系统调用的监控:
再通过 auditd 软件包中的 ausearch来检索 auditd 产生的日志:
整个过程的执行结果如下:

至于其他的使用方法可以通过 man auditd和 man auditctl来查看。
内核开启 Audit
优点
缺点
上面的 Netlink Connector 和 Audit 都是 Linux 本身提供的监控系统调用的方法,如果我们想拥有更大程度的可定制化,我们就需要通过安装内核模块的方式来对系统调用进行 hook 。
目前常用的 hook 方法是通过修改 sys_call_table( Linux 系统调用表)来实现,具体原理就是系统在执行系统调用时是通过系统调用号在 sys_call_table中找到相应的函数进行调用,所以只要将 sys_call_table中 execve对应的地址改为我们安装的内核模块中的函数地址即可。
具体的实现细节可参考 YSRC 的这篇关于驭龙 HIDS 如何实现进程监控的文章:cedK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0M7q4)9J5k6i4N6W2K9i4S2A6L8W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7#2)9J5c8X3&6@1c8e0g2r3e0V1@1^5g2h3q4j5f1f1k6o6y4h3H3@1K9f1E0g2g2i4M7`. ,这里贴出文章里的一张图方便大家对整个流程有个直观地了解:

关于 Syscall hook 的 Demo ,我在 Github 上找了很多 Demo 代码,其中就包括驭龙 HIDS 的 hook 模块,但是这些都无法在我的机器上( Ubuntu 16.04 Kernel 4.4.0-151-generic )正常运行,这也就暴露了 Syscall hook 的兼容性问题。
最后我决定使用 Sysdig 来进行演示,Sysdig 是一个开源的系统监控工具,其核心原理是通过内核模块监控系统调用,并将系统调用抽象成事件,用户根据这些事件定制检测规则。作为一个相对成熟的产品,Sysdig 的兼容性做得比较好,所以这里用它来演示,同时也可以方便大家自己进行测试。
具体步骤如下:
1.通过官方的安装脚本进行安装:
curl-s 16cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6x3#2)9J5k6h3q4E0j5i4A6G2L8X3q4%4M7#2)9J5k6h3y4G2L8g2)9J5c8X3c8G2N6$3&6D9L8$3q4V1i4K6u0W2k6s2u0S2K9h3!0K6i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8S2j5X3I4W2i4K6u0r3K9h3&6K6N6r3q4D9L8q4)9J5k6s2y4&6M7$3c8A6k6H3`.`. | sudo bash
2.检测内核模块是否已经安全:lsmod|grep sysdig
3.启动对 execve的监控:sysdig evt.type=execve
最终的执行效果如下:

有关于 Sysdig 的更多信息可以访问其 wiki 进行获取,另外,Sysdig 团队推出了一个专门用于安全监控的工具 Falco ,Falco 在 Sysdig 的基础上抽象出了可读性更高的检测规则,并支持在容器内部署,同样,大家如果感兴趣可以访问其 wiki 获取更多信息。
优点
缺点
本文共讲了4种常见的监控进程创建的方法,这些方法本质上是对库函数或系统调用的监控,各有优劣,这里我再各用一句话总结一下:
对我个人来讲,单纯地看监控进程创建这方面,我还是更推荐使用 Netlink Connector 的方式,这种方式在保证从内核获取数据的前提下又足够轻量,方便进行定制化开发。如果是想要进行全方面的监控包括进程、网络和文件,Audit 是一个不错的选择。
另外本文是以 Demo 的形式对功能进行介绍,主要是想起到一个抛砖引玉的作用,至于各方法的稳定性并没有进行充分地测试,如果各位有这方面的测试数据欢迎在这里和大家分享讨论。
82dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1j5@1K9r3!0#2i4K6u0W2N6$3W2F1i4K6u0r3N6$3!0J5k6s2m8J5k6i4y4K6i4K6u0r3i4K6y4r3M7q4)9K6c8o6t1&6y4e0R3$3
ce2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6@1k6h3y4Z5i4K6u0W2L8h3g2A6N6s2g2S2L8W2)9J5k6h3y4G2L8g2)9J5c8U0t1H3x3e0W2Q4x3V1j5H3x3g2)9J5c8U0p5%4i4K6u0r3k6r3W2K6N6s2u0A6j5Y4g2@1k6h3c8Q4x3X3c8Z5K9h3c8K6i4K6u0V1j5$3I4#2M7%4c8W2M7W2)9J5k6r3q4J5j5$3S2A6N6r3g2U0N6s2g2J5k6g2)9J5k6r3c8W2M7$3W2Y4L8W2)9J5k6h3S2@1L8h3H3`.
e8cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2A6j5X3#2Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0%4L8%4u0C8M7#2)9J5c8X3y4F1i4K6u0r3L8r3W2F1N6i4S2Q4x3V1k6D9i4K6u0V1L8r3!0Q4x3X3c8#2M7$3g2Q4x3X3c8K6M7r3q4U0k6g2)9J5k6r3q4#2k6r3W2@1i4K6u0V1N6r3!0G2L8q4)9J5c8X3W2F1k6r3g2^5i4K6u0W2K9s2c8E0L8l9`.`.
c76K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9K9h3&6#2P5q4)9J5k6r3q4#2k6r3W2@1i4K6u0W2j5$3!0E0i4K6u0r3j5$3!0F1k6X3W2Y4N6i4u0A6L8X3N6Q4x3X3c8S2L8X3c8Q4x3X3c8S2N6h3c8A6N6r3W2F1k6#2)9J5k6r3I4A6L8Y4g2^5i4K6u0V1M7%4W2K6N6r3g2E0M7#2)9J5k6s2N6A6N6r3S2Q4x3X3c8S2N6h3c8A6N6q4)9J5k6r3c8S2k6h3#2G2L8W2)9J5c8R3`.`.
766K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0P5g2)9J5k6h3!0K6j5$3S2A6L8X3q4Q4x3X3g2F1k6i4c8Q4x3V1k6E0j5h3y4%4k6g2)9J5c8X3u0D9L8$3N6Q4x3V1j5$3x3o6x3#2z5o6x3`.
0b8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0M7q4)9J5k6i4N6W2K9i4S2A6L8W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7#2)9J5c8X3&6@1c8e0g2r3e0V1@1^5g2h3q4j5f1f1k6o6y4h3H3@1K9f1E0g2g2i4M7`.
93cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0M7q4)9J5k6i4N6W2K9i4S2A6L8W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7#2)9K6c8W2)9#2k6W2)9#2k6X3u0A6P5W2)9K6c8p5#2*7g2i4A6a6c8q4p5H3e0@1c8C8P5f1&6m8i4K6y4p5i4K6y4p5i4K6t1$3j5h3#2H3i4K6y4n7L8h3W2V1i4K6y4p5x3U0t1@1y4K6b7^5x3K6R3#2y4q4)9J5y4X3q4E0M7q4)9K6b7X3W2V1P5q4)9K6c8o6u0Q4x3U0k6S2L8i4m8Q4x3@1u0K6L8W2)9K6c8o6R3I4y4e0R3^5x3$3t1H3x3X3q4T1x3o6l9H3x3o6V1#2y4U0V1#2z5h3j5%4z5r3x3K6k6U0x3I4k6e0u0T1i4K6t1$3j5h3#2H3i4K6y4n7M7$3y4W2L8X3g2Q4x3@1b7J5x3b7`.`.
fb7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1M7X3q4A6L8%4y4Q4x3V1k6K6P5i4y4V1K9h3M7`.
8b6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3j5h3I4U0L8%4y4W2j5%4g2J5K9i4c8&6i4K6u0r3k6X3q4D9j5$3)9`.