前叙
众所周知,目前各大APP的安全模块几乎都会使用自实现的libc函数,如open,read等函数,通过自实现svc方式来实现系统调用。因此我们如果想要hook系统调用,只能通过扫描厂商自实现的代码段,定位svc指令所在地址,再通过inline hook方式来进行hook操作,但是这种方式需要涉及内存修改,很容易被检测到内存篡改行为。
本文将利用seccomp方式来监听系统调用,以达到劫持svc调用的目的。
什么是seccomp
Seccomp是一个Linux内核安全模块,它可以使进程限制可以进行的系统调用数量,从而提高进程的安全性和可靠性。Seccomp提供了一种轻量级的进程隔离方式,可以在限制进程的能力的同时,不会影响操作系统的整体功能,是现代容器和虚拟化技术中广泛使用的安全保障机制之一。
Seccomp的主要工作流程是通过在进程中使用prctl()
系统调用来指定一个过滤规则集,该规则集称为“过滤器”,它定义了该进程允许使用的系统调用类型和参数。当进程调用系统调用时,过滤器会拦截该调用并进行验证,以判断其是否符合规则集中指定的条件。如果系统调用不符合规则,Seccomp将拒绝该操作,并终止进程。
Seccomp的过滤器有两种类型:全局过滤器和线程过滤器。全局过滤器是在prctl()
系统调用时设置的,它会对整个进程使用的所有线程都生效。而线程过滤器是在线程创建时设置的,只会对该线程生效。通常情况下,Seccomp的使用者只需要使用全局过滤器即可,因为它可以在进程创建时就应用到所有的线程中。
过滤器的具体设置可以使用在C语言中定义的BPF程序宏来完成,也可以使用SECCOMP_MODE_FILTER模式下的seccomp()
库函数来设置。BPF程序宏和seccomp()函数都需要将过滤器规则集以二进制方式指定,并将其传递给prctl()
系统调用来启用过滤器。下面是一个简单的示例,演示如何使用BPF程序宏来在全局范围内应用过滤器:
#include <stddef.h> #include <linux/seccomp.h> #include <sys/prctl.h> #define FILTER_SYSCALLS \ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr)), \ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, __NR_getpid, 0, 1), \ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), \ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE) int main(int argc, char *argv[]) { struct sock_fprog filter = {