本申请属于计算机系统开发,具体涉及一种基于二进制重写的系统调用挂钩方法、设备及介质。
背景技术:
1、现有的类unix系统内核支持的钩子机制(例如,ptrace、syscall user dispatch(sud)以及int3信令)所使用的传统二进制重写技术导致应用钩子的用户空间程序在性能上出现不可接受的降级。其他二进制重写机制(例如,指令双关语、e9patch和xcontainers中应用的技术)和函数调用替换(例如,ld_preload机制)无法彻底对系统调用进行挂钩。因此,它们不能用于对可靠性有要求的操作系统。
技术实现思路
1、为了解决现有技术的问题,本专利为x86-64cpu提出了一种新颖的系统调用挂钩操作方法,该方法基于二进制重写技术,它通过取代syscall和sysenter这两个用于触发系统调用的字节指令(汇编操作码分别为0x0f0x05和0x0f0x34),来跳转到任意钩子函数地址。该方法没有上面提到的所有缺点,解决了性能损耗高的问题,实现了将用户空间操作系统子系统透明地应用于用户空间程序的要求。其技术方案为:
2、一种基于二进制重写的系统调用挂钩方法,包括以下步骤:
3、s1.操作系统的环境配置:配置系统环境变量,将虚拟地址0设为可用;
4、s2.蹦床代码的设置:在虚拟地址0处分配内存,用nop指令序列和跳转代码填充分配的内存空间;
5、s3.二进制重写:获取内存映射信息,遍历内存上的指令,进行指令替换操作,完成二进制重写;
6、s4.加载钩子函数库:加载库文件,并为其指定新的命名空间;获取指向钩子函数核心实现的指针,挂载调用钩子函数。
7、优选的,操作系统环境配置还包括:
8、(1)设置操作系统环境变量:在linux系统环境变量中,将ld_preload的值设置为专用共享库的路径;
9、(2)在linux系统环境变量中增加自定义环境变量,并将其设置为钩子函数库的路径。
10、优选的,蹦床代码和二进制重写在专用共享库中实现,在用户空间程序的主函数启动之前执行设置过程;
11、专用共享库在通过ld_preload机制加载并在动态链接应用程序二进制文件时使用,ld_preload允许专用共享库在用户空间程序的主函数启动之前运行设置过程。
12、优选的,蹦床代码设置过程首先使用 mmap 系统调用在虚拟地址 0 处分配内存;然后,它用 nop 指令序列和跳转代码填充分配的内存区域。
13、优选的,二进制重写过程首先利用procfs文件系统获取内存映射信息;然后,遍历可执行内存区域上的中央处理器指令,并用指令替换 syscall/sysenter指令。
14、优选的,蹦床代码和用户空间程序的代码的存储区域在该设置阶段被配置为可写,并且在设置过程退出之前将它们恢复为不可写;设置完成后,用户空间程序的主函数照常启动,实现相应的挂钩操作。
15、优选的,通过利用dlmopen函数解决钩子函数在调用重写前原本就是要执行syscall/sysenter 的函数时会陷入无限循环的问题,因为替换的指令将执行流程带回到了钩子函数;为了使用 dlmopen 函数,假设用户将钩子函数构建为共享库,在设置阶段,专用共享库使用dlmopen函数在钩子函数专用的命名空间中加载该共享库文件,并使用dlsym函数获取指向钩子函数核心实现的指针,在专用命名空间中加载的共享库中实现的钩子函数可以通过获得的钩子函数核心实现的指针来调用,从而避免不必要的自动关联,进而避免陷入无限循环。
16、优选的,null指针访问终止如下:
17、终止null的读取和写入:为了终止null读写,将蹦床代码配置为仅可执行内存;尝试对配置为仅可执行的内存进行读/写访问的用户空间程序将因故障而被内核终止;
18、终止 null执行:为了捕获非故意的null执行动作,需要收集syscall/sysenter的虚拟地址,syscall/sysenter的虚拟地址在设置阶段被替换,并在钩子函数的入口点检查钩子函数的调用者是否是被替换的虚拟地址之一;如果不是,终止用户空间程序,如果是执行钩子函数。
19、优选的,为了维护替换的虚拟地址,同时实现低开销的null执行检查,使用覆盖x86-64cpu中常见的整个256tb虚拟地址范围的位图,位图允许通过一些位操作来执行null 执行检查。
20、一种电子设备,包括:处理器、存储器及存储在所述存储器上并可在所述处理器上运行的计算机程序,所述计算机程序被所述处理器执行时实现本申请所述的系统调用挂钩方法的步骤。
21、一种计算机可读存储介质,所述计算机可读存储介质上存储有计算机程序,所述计算机程序被处理器执行时实现本申请所述的系统调用挂钩方法的步骤。
22、与现有技术相比,本申请有益效果如下:
23、通过与现有钩子机制的比较来评估本专利提出的方法,特别是,量化了本专利提出方法的挂钩操作开销,以及由本专利提出的方法绑定的应用程序和用户空间操作系统子系统所经历的性能损失。
24、相较于基于ptrace、syscall user dispatch(sud)以及int3信令等技术的系统调用钩子技术,本专利实现的基于二进制重写的x86-64架构系统调用低耗费挂钩方法具有一下优势:
25、(1)比基于ptrace的技术快100倍。
26、(2)可实现对系统调用的100%覆盖挂钩,即可以通过穷举所有的系统调用实现挂钩操作。
27、(3)不需要改动用户空间程序的源代码。
28、(4)无需更改操作系统内核,也无需内核模块。
1.一种基于二进制重写的系统调用挂钩方法,其特征在于,包括以下步骤:
2.根据权利要求1所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,操作系统环境配置还包括:
3.根据权利要求2所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,蹦床代码和二进制重写在专用共享库中实现,在用户空间程序的主函数启动之前执行设置过程;
4.根据权利要求3所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,蹦床代码设置过程首先使用 mmap 系统调用在虚拟地址 0 处分配内存;然后,它用 nop 指令序列和跳转代码填充分配的内存区域;
5.根据权利要求3所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,二进制重写过程首先利用procfs文件系统获取内存映射信息;然后,遍历可执行内存区域上的中央处理器指令,并用指令替换 syscall/sysenter指令。
6.根据权利要求1所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,通过利用dlmopen函数解决钩子函数在调用重写前原本就是要执行 syscall/sysenter 的函数时会陷入无限循环的问题,因为替换的指令将执行流程带回到了钩子函数;为了使用 dlmopen 函数,假设用户将钩子函数构建为共享库,在设置阶段,专用共享库使用dlmopen函数在钩子函数专用的命名空间中加载该共享库文件,并使用dlsym函数获取指向钩子函数核心实现的指针,在专用命名空间中加载的共享库中实现的钩子函数可以通过获得的钩子函数核心实现的指针来调用,从而避免不必要的自动关联,进而避免陷入无限循环。
7.根据权利要求1所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,null指针访问终止如下:
8.根据权利要求7所述的一种基于二进制重写的系统调用挂钩方法,其特征在于,为了维护替换的虚拟地址,同时实现低开销的null执行检查,使用覆盖x86-64cpu中整个256tb虚拟地址范围的位图,位图允许通过相关位操作来执行 null 执行检查。
9.一种电子设备,其特征在于,包括:处理器、存储器及存储在所述存储器上并可在所述处理器上运行的计算机程序,所述计算机程序被所述处理器执行时实现如权利要求1至7之中任一项所述的系统调用挂钩方法的步骤。
10.一种计算机可读存储介质,其特征在于,所述计算机可读存储介质上存储有计算机程序,所述计算机程序被处理器执行时实现如权利要求1至7之中任一项所述的系统调用挂钩方法的步骤。