检测非法程序的方法和装置转让专利

申请号 : CN201810502710.2

文献号 : CN108898012B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 王智通毛俊鸿陈岑

申请人 : 华为技术有限公司

摘要 :

本申请实施例提供了一种检测非法程序的方法和装置,属于计算机技术领域。所述方法包括:确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容;调用所述第一读取函数,获取所述内核空间中第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;当所述第一内核数据结构的初始结构内容与当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。采用本申请,可以检测内核空间中的非法程序。

权利要求 :

1.一种检测非法程序的方法,其特征在于,所述方法包括:

确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容,所述第一读取函数和所述第二读取函数位于所述内核空间中;

调用所述第一读取函数,获取所述内核空间中所述第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;

当所述第一内核数据结构的初始结构内容与所述当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。

2.根据权利要求1所述的方法,其特征在于,所述方法还包括:

获取所述第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;

根据所述对应关系和所述第一内核数据结构的标识,确定所述第一内核数据结构所属的内核数据结构类型。

3.根据权利要求2所述的方法,其特征在于,所述确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,包括:获取内核数据结构类型与读取函数的标识的对应关系;

根据所述第一内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;

根据所述两个读取函数的标识中有第一标记的读取函数的标识,确定所述内核空间中第一内核数据结构对应的第一读取函数,并根据所述两个读取函数的标识中有第二标记的读取函数的标识,确定所述第一内核数据结构对应的第二读取函数,其中,所述第一标记用于指示读取函数用于读取当前结构内容,所述第二标记用于指示读取函数用于读取初始结构内容。

4.根据权利要求1至3任一所述的方法,其特征在于,所述方法还包括:当确定所述内核空间中存在目标模块结构体时,确定所述目标模块结构体为非法程序,其中,所述目标模块结构体用于删除内核数据结构链表中的结点,所述结点是所述目标模块结构体在所述内核空间中能加载的内核数据结构的标识。

5.根据权利要求1所述的方法,其特征在于,所述方法还包括:

接收目标系统调用,其中,所述目标系统调用用于指示进行非法程序检测;

当所述目标系统调用对应有预设标识时,确定进行非法程序检测。

6.根据权利要求1所述的方法,其特征在于,所述内核空间包括核心程序,所述核心程序运行在高于预设等级的权限上,拥有访问主机的硬件的所有权限。

7.一种检测非法程序的方法,其特征在于,所述方法包括:

确定内核空间中目标内核数据结构对应的目标读取函数,其中,所述目标读取函数用于读取当前结构内容,所述目标读取函数位于所述内核空间中;

调用所述目标读取函数,获取所述内核空间中所述目标内核数据结构的当前结构内容;

当所述目标内核数据结构的当前结构内容中存在预设结构时,确定所述目标内核数据结构中存在非法程序,其中,所述预设结构为用于执行非法处理的结构。

8.根据权利要求7所述的方法,其特征在于,所述方法还包括:

获取所述目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;

根据所述对应关系和所述目标内核数据结构的标识,确定所述目标内核数据结构所属的内核数据结构类型。

9.根据权利要求8所述的方法,其特征在于,所述确定内核空间中目标内核数据结构对应的目标读取函数,包括:获取内核数据结构类型与读取函数的标识的对应关系;

根据所述目标内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;

根据所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定所述目标内核数据结构对应的目标读取函数。

10.根据权利要求7至9任一所述的方法,其特征在于,所述预设结构包括改变执行路径的指令、键盘记录列表中的结点。

11.一种主机,其特征在于,所述主机包括存储器和处理器,所述存储器中存储有计算机程序,当所述处理器调用所述存储器中的计算机程序时,使得所述处理器执行上述权利要求1-10任一所述的检测非法程序的方法。

12.一种检测非法程序的装置,其特征在于,所述装置包括:确定模块,用于确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容,所述第一读取函数和所述第二读取函数位于所述内核空间中;

获取模块,用于调用所述第一读取函数,获取所述内核空间中所述第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;

所述确定模块,还用于当所述第一内核数据结构的初始结构内容与当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。

13.根据权利要求12所述的装置,其特征在于,所述获取模块,还用于:获取所述第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;

所述确定模块,还用于根据所述对应关系和所述第一内核数据结构的标识,确定所述第一内核数据结构所属的内核数据结构类型。

14.根据权利要求13所述的装置,其特征在于,所述确定模块,用于:获取内核数据结构类型与读取函数的标识的对应关系;

根据所述第一内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;

根据所述两个读取函数的标识中有第一标记的读取函数的标识,确定所述内核空间中第一内核数据结构对应的第一读取函数,并根据所述两个读取函数的标识中有第二标记的读取函数的标识,确定所述第一内核数据结构对应的第二读取函数,其中,所述第一标记用于指示读取函数用于读取当前结构内容,所述第二标记用于指示读取函数用于读取初始结构内容。

15.根据权利要求12至14任一所述的装置,其特征在于,所述确定模块,还用于:当确定所述内核空间中存在目标模块结构体时,确定所述目标模块结构体为非法程序,其中,所述目标模块结构体用于删除内核数据结构链表中的结点,所述结点是所述目标模块结构体在所述内核空间中能加载的内核数据结构的标识。

16.根据权利要求12所述的装置,其特征在于,所述装置还包括:接收模块,用于接收目标系统调用,其中,所述目标系统调用用于指示进行非法程序检测;

所述确定模块,还用于当所述目标系统调用对应有预设标识时,确定进行非法程序检测。

17.一种检测非法程序的装置,其特征在于,所述装置包括:

确定模块,用于确定内核空间中目标内核数据结构对应的目标读取函数,其中,所述目标读取函数用于读取当前结构内容,所述目标读取函数位于所述内核空间中;

获取模块,用于调用所述目标读取函数,获取所述内核空间中所述目标内核数据结构的当前结构内容;

所述确定模块,还用于当所述目标内核数据结构的当前结构内容中存在预设结构时,确定所述目标内核数据结构中存在非法程序,其中,所述预设结构至少包括改变执行路径的指令、恶意钩子函数。

18.根据权利要求17所述的装置,其特征在于,所述获取模块,还用于:获取所述目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;

所述确定模块,还用于根据所述对应关系和所述目标内核数据结构的标识,确定所述目标内核数据结构所属的内核数据结构类型。

19.根据权利要求18所述的装置,其特征在于,所述确定模块,用于:获取内核数据结构类型与读取函数的标识的对应关系;

根据所述目标内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;

根据所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定所述目标内核数据结构对应的目标读取函数。

20.一种包含指令的计算机程序产品,其特征在于,当所述计算机程序产品在主机上运行时,使得所述主机执行所述权利要求1-10中任一权利要求所述的方法。

21.一种计算机可读存储介质,其特征在于,所述计算机可读存储介质存储有指令,当所述计算机可读存储介质在主机上运行时,使得所述主机执行所述权利要求1-10中任一权利要求所述的方法。

说明书 :

检测非法程序的方法和装置

技术领域

[0001] 本申请涉及计算机技术领域,特别涉及一种检测非法程序的方法和装置。

背景技术

[0002] 非法程序(如Rootkits等)是一种在攻击操作系统时,用于隐藏踪迹和保留root访问权限的工具。非法程序可以分为应用级非法程序和内核级非法程序,应用级非法程序主要修改操作系统应用层的系统文件,比较容易预防和检测,内核级非法程序主要攻击操作系统内核空间,比较难预防和检测,所以需要提供在内核空间中检测非法程序的方法。
[0003] 然而相关技术中,技术人员在用户空间中设置检测程序,对用户空间中的应用级非法程序进行检测。
[0004] 这样,由于内核级非法程序仅在内核空间中可见,用户空间中的检测程序仅对应用级非法程序进行检测,无法检测到内核级非法程序。

发明内容

[0005] 为了解决无法检测内核级非法程序的问题,本申请实施例提供了一种检测非法程序的方法和装置。所述技术方案如下:
[0006] 第一方面,提供了一种检测非法程序的方法,该方法包括:
[0007] 确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容;调用所述第一读取函数,获取所述内核空间中所述第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;当所述第一内核数据结构的初始结构内容与当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。
[0008] 其中,第一内核数据结构可以有系统调用表、中断描述符表、某些函数的函数指针和处理函数(如虚拟文件系统劫持等)等。
[0009] 本申请实施例所示的方案,主机中安装有检测程序,检测程序的代码可以被主机中的中央处理器(Central Processing Unit,CPU)所运行,该检测程序一部分是安装在主机的Linux操作系统的用户空间,一部分是安装在主机的Linux操作系统的内核空间,安装在用户空间的部分运行于用户空间,安装在内核空间的部分运行于内核空间,用于检测内核空间中的非法程序。检测程序中还设置有第一内核数据结构的标识列表,在检测非法程序时,会遍历标识列表,对标识列表中的每个内核数据结构的标识对应的内核数据结构进行检测。内核空间包括核心程序,核心程序运行在高于预设等级的权限上,拥有访问主机的硬件的所有权限。用户空间中包括Linux操作系统中除核心程序之外的程序,该程序仅能访问Linux操作系统允许用户空间使用的系统资源,且不能直接访问内核空间和主机的硬件。
[0010] 主机在检测内核空间中的非法程序时,可以由主机中的CPU执行检测程序在内核空间中的代码,获取标识列表中的任一内核数据结构的标识(后续可以称为是第一内核数据结构的标识),确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,第一读取函数用于读取内核数据结构的当前结构内容,第二读取函数用于读取内核数据结构的初始结构内容。例如,在Linux操作系统中,第一读取函数可以是probe_kernel_read函数,第二读取函数可以是kallsyms_lookup_name函数。
[0011] 然后通过CPU运行检测程序在内核空间中的代码,调用第一读取函数,将第一内核数据结构的标识作为第一读取函数的输入,运行第一读取函数的代码,获取到第一内核数据结构的当前结构内容,并且可以调用第二读取函数,将第一内核数据结构的标识,作为第二读取函数的输入,运行第二读取函数的代码,获取到第一内核数据结构的初始结构内容。
[0012] 然后对第一内核数据结构的当前结构内容和初始结构内容进行对比,当存在不相同的内容时,确定第一内核数据结构中存在非法程序。
[0013] 这样,检测程序设置在内核空间中,可以对所有可能存在检测程序的内核数据结构进行检测,检测能力比较强。
[0014] 在一种可能的方式中,获取所述第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;根据所述对应关系和所述第一内核数据结构的标识,确定所述第一内核数据结构所属的内核数据结构类型。
[0015] 本申请实施例所示的方案,主机通过CPU运行检测程序在内核空间中的代码,确定第一内核数据结构的第一读取函数和第二读取函数之前,还可以在标识列表中,获取第一内核数据结构的标识,并获取检测程序中内核数据结构的标识和内核数据结构类型的对应关系。使用第一内核数据结构的标识,在该对应关系中,查找到第一内核数据结构标识,对应的第一类型,将第一类型确定为第一内核数据结构的内核数据结构类型。其中,第一类型用于指示通过对比的方式确定非法程序,也即要获取内核数据结构的初始结构内容和当前结构内容。这样,通过判断内核数据结构类型,即可确认出是否要获取第一读取函数和第二读取函数。
[0016] 在一种可能的方式中,获取内核数据结构类型与读取函数的标识的对应关系;根据所述第一内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;根据所述两个读取函数的标识中有第一标记的读取函数的标识,确定所述内核空间中第一内核数据结构对应的第一读取函数,并根据所述两个读取函数的标识中有第二标记的读取函数的标识,确定所述第一内核数据结构对应的第二读取函数,其中,所述第一标记用于指示读取函数用于读取当前结构内容,所述第二标记用于指示读取函数用于读取初始结构内容。
[0017] 本申请实施例所示的方案,主机可以通过CPU运行检测程序在内核空间中的代码,来获取检测程序中内核数据结构类型与读取函数的标识的对应关系,然后使用第一类型在该对应关系中,查找第一类型对应的两个读取函数的标识。对于两个读取函数的标识,如果在读取函数的标识中有第一标记,则可以确定是第一读取函数的标识,可以使用该标识,在内核空间中确定第一读取函数,如果在读取函数的标识中有第二标记,则可以确定是第二读取函数的标识,可以使用该标识在内核空间中,确定第二读取函数。例如,在Linux操作系统中,第一读取函数的标识是probe_kernel_read,第二读取函数的标识是kallsyms_lookup_name,第一标记可以是kernel,第二标记可以是kallsyms。
[0018] 在一种可能的方式中,当确定所述内核空间中存在目标模块结构体时,确定所述目标模块结构体为非法程序,其中,所述目标模块结构体用于删除内核数据结构链表中的结点,所述结点是所述目标模块结构体在所述内核空间中能加载的内核数据结构的标识。
[0019] 本申请实施例所示的方案,目标模块结构体用于删除内核数据结构链表中的结点,该结点是目标模块结构体在内核空间中能加载的内核数据结构的标识。主机可以通过CPU运行检测程序在内核空间中的代码,获取到module_kset结构体和module结构体,然后对module_kset结构体和module结构体进行对比,确定出其中不相同的内容,将该不相同的内容,确定为目标模块结构体,目标模块结构体为非法程序。这样,就可以确定出隐藏结点的非法程序。
[0020] 在一种可能的方式中,在进行非法程序检测前,还会判定对于检测的系统调用是否有权限,接收目标系统调用,其中,所述目标系统调用用于指示进行非法程序检测;当所述目标系统调用对应有预设标识时,确定进行非法程序检测。
[0021] 本申请实施例所示的方案,主机通过CPU运行检测程序在内核空间中的代码时,一般会通过系统调用的方式进行调用,该系统调用可以称为是目标系统调用,可以判断目标系统调用是否对应有预设标识,如果有则进行非法程序检测,如果没有则不进行非法程序检测。
[0022] 判断方式可以是通过白名单的方式确定,在白名单中设置有预设标识对应的系统调用的标识,可以获取白名单。如果在白名单中有目标系统调用的标识,则确定目标系统调用对应有预设标识,如果在白名单中没有目标系统调用的标识,则确定目标系统调用未对应有预设标识。或者是,直接判断目标系统调用中是否包含预设标记,如果包含有预设标记,则确定对应有预设标识。这样,可以防止检测程序的非法访问。
[0023] 在一种可能的方式中,第一内核数据结构为第一预设函数,当第一预设函数的初始函数指针和当前函数指针不相同时,确定第一预设函数中存在非法程序。
[0024] 其中,第一预设函数可以是一个也可以是多个,一般情况下是多个,例如,第一预设函数可以是proc_reg_open、proc_root_readdir、tcp4_seq_show、con_open中任意一个等,函数指针指函数代码的存储地址。
[0025] 本申请实施例所示的方案,主机可以通过检测程序获取到第一预设函数的初始结构内容和当前结构内容,初始结构内容中包括初始函数指针,当前结构内容中包括当前函数指针。
[0026] 主机可以通过CPU运行检测程序在内核空间中的代码,对第一预设函数的初始函数指针和当前函数指针进行比对,在当前函数指针与初始函数指针不一样时,确定第一预设函数中存在Rootkits。
[0027] 在一种可能的方式中,第一内核数据结构可以为第二预设函数,当第二预设函数的初始处理函数和当前处理函数不相同时,确定第二预设函数中存在非法程序。
[0028] 其中,第二预设函数可以是一个也可以是多个,一般情况下是多个,例如,sys_getdents64,sys_getdents、compat_sys_getdents64、compat_sys_getdents等。在执行第二预设函数时,实际执行的是第二预设函数的处理函数的代码,第二预设函数的初始处理函数是指初始的没有被Rootkits修改的函数,第二预设函数的当前处理函数是指当前要执行第二预设函数时,获取到的处理函数。
[0029] 本申请实施例所示的方案,主机可以通过CPU运行检测程序在内核空间中的代码,获取到第二预设函数初的始结构内容和当前结构内容,初始结构内容中包括初始处理函数,当前结构内容中包括当前处理函数。
[0030] 主机可以通过CPU运行检测程序在内核空间中的代码,对初始处理函数和当前处理函数进行比对,在该当前处理函数与初始处理函数不一样时,确定第二预设函数中存在Rootkits。
[0031] 在一种可能的方式中,第一内核数据结构可以为网络过滤函数,当当前网络过滤函数与白名单不相同时,将不相同的函数,确定为网络过滤函数中的非法程序。
[0032] 其中,网络过滤函数是用于对主机的收发内容进行过滤的函数,白名单可以预先设置,并且存储至主机的存储器(该存储器可以是主机中的非易失性存储器)中,白名单中可以包括预先设置的网络过滤函数,也就是说白名单中设置的网络过滤函数是正常存在的,如iptable_filter_hook、ipv4_conntrack_defrag等,也即白名单是网络过滤函数的初始结构内容,当前结构内容为当前获取到的网络过滤函数。
[0033] 本申请实施例所示的方案,主机可以通过CPU运行检测程序在内核空间中的代码,获取内存中预先存储的网络过滤函数的白名单,然后将当前的网络过滤函数和白名单中的网络过滤函数进行对比,如果当前获取到的网络过滤函数中有不属于白名单的网络过滤函数,则网络过滤函数中存在Rootkits。
[0034] 第二方面,提供了一种检测非法程序的方法,该方法包括:
[0035] 确定内核空间中目标内核数据结构对应的目标读取函数,其中,所述目标读取函数用于读取当前结构内容;调用所述目标读取函数,获取所述内核空间中所述目标内核数据结构的当前结构内容;当所述目标内核数据结构的当前结构内容中存在预设结构时,确定所述目标内核数据结构中存在非法程序,其中,所述预设结构为用于执行非法处理的结构。
[0036] 其中,预设结构可以预设,并且存储在检测程序中,预设结构可以是用于执行非法处理的结构,如改变执行路径的指令、键盘记录列表中的结点等。
[0037] 本申请实施例所示的方案,主机在检测内核空间中的非法程序时,可以由主机中的CPU运行检测程序在内核空间中的代码,获取目标读取函数的标识列表中的任一内核数据结构(后续可以称为是目标内核数据结构),确定目标内核数据结构的目标读取函数,目标读取函数用于读取内核数据结构的当前结构内容。例如,在Linux操作系统中,目标读取函数可以是probe_kernel_read函数。
[0038] 然后通过CPU运行检测程序在内核空间中的代码,调用目标读取函数,将目标内核数据结构的标识作为目标读取函数的输入,运行目标读取函数的代码,获取到目标内核数据结构的当前结构内容。
[0039] 然后对目标内核数据结构的当前结构内容进行检测,当存在预设结构时,可以确定目标内核数据结构中存在非法程序。
[0040] 可选的,上述目标读取函数可以与上述的第一读取函数是同一函数。
[0041] 在一种可能的方式中,该方法还包括:获取所述目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;根据所述对应关系和所述目标内核数据结构的标识,确定所述目标内核数据结构所属的内核数据结构类型。
[0042] 本申请实施例所示的方案,主机通过CPU运行检测程序在内核空间中的代码,确定目标内核数据结构的目标读取函数之前,还可以在标识列表中,获取目标内核数据结构的标识,并获取检测程序中内核数据结构的标识和内核数据结构类型的对应关系。使用目标内核数据结构的标识,在该对应关系中,查找到目标内核数据结构标识对应的目标类型,将目标类型确定为目标内核数据结构的内核数据结构类型。其中,目标类型用于指示通过判断的方式确定非法程序。
[0043] 在一种可能的方式中,获取内核数据结构类型与读取函数的标识的对应关系;根据所述目标内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;根据所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定所述目标内核数据结构对应的目标读取函数。
[0044] 本申请实施例所示的方案,主机通过CPU运行检测程序在内核空间中的代码,可以获取内核数据结构类型与读取函数的标识的对应关系。在该对应关系中,使用目标类型查找到对应的读取函数的标识,然后使用该读取函数的标识,从内核空间中,获取读取函数的标识对应的读取函数,将该读取函数,确定为目标读取函数。这样,可以通过内核数据结构类型,即可确定出目标读取函数。
[0045] 在一种可能的方式中,内核数据结构为键盘记录列表,获取键盘记录列表,当键盘记录表中存在结点,确定键盘记录表中存在Rootkits。
[0046] 本申请实施例所示的方案,主机通过CPU运行检测程序在内核空间中的代码,获取到键盘记录列表(keyboard_notifier_list)当前结构内容后,通过CPU运行检测程序在内核空间中的代码,确定keyboard_notifier_list中是否包括有内容(也就是判断keyboard_notifier_list是否是空的),如果keyboard_notifier_list有内容,将该内容确定为notifier结点,确定keyboard_notifier_list中包括notifier结点,确定keyboard_notifier_list中存在Rootkits。如果keyboard_notifier_list没有内容,则确定keyboard_notifier_list没有Rootkits。
[0047] 在一种可能的方式中,目标内核数据结构为第三预设函数,当第三预设函数的处理函数的入口处有改变执行路径的指令时,确定第三预设函数有Rootkits。
[0048] 本申请实施例所示的方案,主机可以通过CPU运行检测程序在内核空间中的代码,获取第三预设函数的处理函数,然后通过CPU运行检测程序在内核空间中的代码,识别第三预设函数的处理函数的入口处的指令,判断第三预设函数的处理函数的入口处的指令是否包括改变执行路径的指令(如call、jump等指令),如果第三预设函数的处理函数的入口处包括,则确定第三预设函数有Rootkits。这样,可以对Inline hook型的Rootkits进行检测。
[0049] 第三方面,提供了一种主机,该主机包括处理器和存储器,所述存储器中存储有计算机程序,当所述处理器调用所述存储器中的计算机程序时,使得所述处理器执行如下内容:
[0050] 确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容;
[0051] 调用所述第一读取函数,获取所述内核空间中所述第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;
[0052] 当所述第一内核数据结构的初始结构内容与当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。
[0053] 在一种可能的方式中,所述处理器,还用于:
[0054] 获取所述第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;
[0055] 根据所述对应关系和所述第一内核数据结构的标识,确定所述第一内核数据结构所属的内核数据结构类型。
[0056] 在一种可能的方式中,所述处理器,用于:
[0057] 获取内核数据结构类型与读取函数的标识的对应关系;
[0058] 根据所述第一内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;
[0059] 根据所述两个读取函数的标识中有第一标记的读取函数的标识,确定所述内核空间中第一内核数据结构对应的第一读取函数,并根据所述两个读取函数的标识中有第二标记的读取函数的标识,确定所述第一内核数据结构对应的第二读取函数,其中,所述第一标记用于指示读取函数用于读取当前结构内容,所述第二标记用于指示读取函数用于读取初始结构内容。
[0060] 在一种可能的方式中,所述处理器,还用于:
[0061] 当确定所述内核空间中存在目标模块结构体时,确定所述目标模块结构体为非法程序,其中,所述目标模块结构体用于删除内核数据结构链表中的结点,所述结点是所述目标模块结构体在所述内核空间中能加载的内核数据结构的标识。
[0062] 在一种可能的方式中,所述处理器,还用于:
[0063] 接收目标系统调用,其中,所述目标系统调用用于指示进行非法程序检测;
[0064] 当所述目标系统调用对应有预设标识时,确定进行非法程序检测。
[0065] 在一种可能的方式中,所述内核空间包括核心程序,所述核心程序运行在高于预设等级的权限上,拥有访问主机的硬件的所有权限。
[0066] 在一种可能的方式中,确定内核空间中目标内核数据结构对应的目标读取函数,其中,所述目标读取函数用于读取当前结构内容;
[0067] 调用所述目标读取函数,获取所述内核空间中所述目标内核数据结构的当前结构内容;
[0068] 当所述目标内核数据结构的当前结构内容中存在预设结构时,确定所述目标内核数据结构中存在非法程序,其中,所述预设结构为用于执行非法处理的结构。
[0069] 在一种可能的方式中,所述处理器,还用于:
[0070] 获取所述目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;
[0071] 根据所述对应关系和所述目标内核数据结构的标识,确定所述目标内核数据结构所属的内核数据结构类型。
[0072] 在一种可能的方式中,所述处理器,用于:
[0073] 获取内核数据结构类型与读取函数的标识的对应关系;
[0074] 根据所述目标内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;
[0075] 根据所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定所述目标内核数据结构对应的目标读取函数。
[0076] 第四方面,提供了一种检测非法程序的装置,该装置包括一个或多个模块,该一个或多个模块通过执行指令来实现上述第一方面和第二方面所提供的检测非法程序的方法。
[0077] 第五方面,提供了一种计算机可读存储介质,计算机可读存储介质存储有指令,当计算机可读存储介质在主机上运行时,使得主机执行上述第一方面和第二方面所提供的检测非法程序的方法。
[0078] 第六方面,提供了一种包含指令的计算机程序产品,当其在主机上运行时,使得主机执行上述第一方面和第二方面所提供的检非法程序的方法。
[0079] 本申请实施例提供的技术方案带来的有益效果至少包括:
[0080] 本申请实施例中,由于可以通过第一读取函数和第二读取函数,分别获取内核空间中第一内核数据结构的初始结构内容和当前结构内容,通过对比的方式,即可确定第一内核数据结构中是否存在非法程序,所以可以对内核空间中的非法程序进行检测。

附图说明

[0081] 图1a是本申请实施例提供的一种主机的结构示意图;
[0082] 图1b是本申请实施例提供的一种用户空间与内核空间的结构示意图;
[0083] 图2是本申请实施例提供的各种类型的Rootkits的特征;
[0084] 图3是本申请实施例提供的检测非法程序的方法的流程示意图;
[0085] 图4是本申请实施例提供的检测程序的设置示意图;
[0086] 图5是本申请实施例提供的检测非法程序的方法的流程示意图;
[0087] 图6是本申请实施例提供的检测Rootkits的系统示意图;
[0088] 图7是本申请实施例提供的一种检测Rootkits的装置结构示意图;
[0089] 图8是本申请实施例提供的一种检测Rootkits的装置结构示意图;
[0090] 图9是本申请实施例提供的一种检测Rootkits的装置结构示意图。

具体实施方式

[0091] 为使本申请的目的、技术方案和优点更加清楚,下面将结合附图对本申请实施方式作进一步地详细描述。
[0092] 本申请实施例提供了一种检测非法程序的方法,该方法的执行主体可以是安装有Linux操作系统的主机,主机可以是终端,也可以是服务器。
[0093] 图1a示出了本申请实施例中主机的结构框图,该主机至少可以包括接收器101、处理器102、存储器103和发送器104。其中,接收器101可以用于实现数据的接收,发送器104可以用于数据的发送,具体可以用于内核空间中的非法程序的发送,存储器103可以用于存储软件程序以及模块,具体可以用于存储本申请实施例中断描述符表、系统调用表等,处理器102通过运行存储在存储器103中的软件程序以及模块,从而执行各种功能应用以及数据处理。存储器103可主要包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序等;存储数据区可存储根据检测程序的使用所创建的数据等。
此外,存储器103可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他易失性固态存储器件。相应地,存储器103还可以包括存储器控制器,以提供处理器102、接收器101和发送器104对存储器103的访问。处理器102是主机的控制中心,利用各种接口和线路连接整个邻位干扰识别设备的各个部分,通过运行或执行存储在存储器103内的软件程序和/或模块,以及调用存储在存储器103内的数据,执行主机的各种功能和处理数据,从而对主机进行整体监控。
[0094] 可选的,处理器102可包括一个或多个处理核心;优选的,处理器102可集成应用处理器和调制解调处理器,其中,应用处理器主要处理操作系统、用户界面和应用程序等。可以理解的是,上述调制解调处理器也可以不集成到处理器102中。
[0095] 为了便于对本申请实施例的理解,下面首先介绍本申请实施例涉及的系统架构、应用场景、以及所涉及到名词的概念。
[0096] 本申请实施例可以适用于安装有Linux操作系统的主机,主机可以是终端,如移动终端(如手机、平板电脑等)、台式电脑和笔记本电脑等,也可以是服务器,包括但不限于:独立服务器、计算服务器、存储服务器、云服务器等。如图1b所示,Linux操作系统包括用户空间与内核空间,用户空间对用户可见,内核空间对用户不可见,用户空间与内核空间可以相互通信。内核空间中包括核心程序,该核心程序独立于普通应用程序,运行在较高的特权级别上,拥有访问主机的硬件的所有权限,用户空间中包括Linux操作系统中除核心程序之外的程序,该程序仅能访问Linux操作系统允许用户空间使用的系统资源,且不能直接访问内核空间和主机的硬件。当主机运行一个程序时,该程序所创建的进程一开始是运行在用户空间的,当它执行某些处理(如通过网络发送数据等)时,必须系统调用write、send等系统调用函数来完成,这些系统调用会去调用内核空间中的系统调用函数的代码来完成用户空间的请求操作,在内核空间中执行代码完成操作后,又返回到用户空间,也可以称为是返回到用户态。
[0097] 非法程序,也可以被称为是恶意程序,在内核空间能够隐藏自身和内核空间中的指定文件、进程等,并且长期驻留,拥有最高访问权限。如Rootkits等。Rootkits是攻击者在攻击时用来隐藏自己的踪迹和保留root访问权限的工具,Linux操作系统中的Rootkits可以分为应用级Rootkits和内核级Rootkits,应用级Rootkits主要修改操作系统应用层的系统文件,比较容易预防和检测,内核级Rootkits主要攻击操作系统内核空间,比较难预防和检测。
[0098] 系统调用表(System Call Table,SCT),是一个包含有系统调用的二维表,在该二维表中,每一行均包含系统调用编号和对应执行函数的函数指针(也可以称为是系统调用函数的函数指针),Linux操作系统的内核空间接收到用户空间的系统调用后,可以根据系统调用编号,查找到对应执行函数的函数指针。
[0099] 中断描述符表(Interrupt Descriptor Table,IDT),是x86用于实现中断向量表的数据结构,用于记录确定执行代码中断或异常时,基于中断号查找到对应的中断处理函数的函数指针。
[0100] 虚拟文件系统(Virtual File System,VFS),是Linux操作系统建立在各种不同文件系统之上的抽象层,基于该抽象层,应用程序可以透明的访问文件系统上的文件,而不需要知道文件是什么类型。例如,虚拟文件系统可以是在EXT2、EXT3、NFS、FAT32之上设置的抽象层。
[0101] 本申请实施例中,以非法程序为Rootkits为例进行方案的说明,在进行实施前,首先介绍一下,本申请实施例中内核空间中所涉及到的各种Rootkits:
[0102] 如图2所示,常见的Rootkits一般是出现在以下几种内核数据结构中:
[0103] 修改或重定向系统调用表,特征是修改系统调用表中某些系统调用函数的指针,使其执行恶意函数,或者是重定向到执行恶意函数的代码,在执行恶意函数的代码的同时或之后执行原来系统调用函数的代码。这样,在进行某些系统函数的调用时,会执行恶意函数的代码。例如,在调用sys_write时,使之指向evil_sys_write,evil_sys_write再调用sys_write,同时执行恶意函数的代码。
[0104] 虚拟文件系统劫持,特征是篡改虚拟文件系统的结构体指针(如proc_reg_open、proc_root_readdir、tcp4_seq_show、con_open等),使其执行恶意函数的代码等。
[0105] 中断描述符表劫持,通过中断描述符表寄存器,获取到中断描述符的指针后,可以修改中断描述符的指针,或者编写中断描述符的处理函数的代码,并在系统调用入口处设置中断,每当有系统调用,恶意函数的代码就会被执行,例如,首先用rootkit_system_call(在系统调用表)替换原有的system_call函数,实现篡改set_uid()系统调用,在rootkit_system_call入口处设置中断,篡改IDT的中断处理函数的函数指针或者中断处理函数的代码,此后每当有set_uid()系统调用产生时,恶意函数的代码就会被执行。
[0106] 网络过滤器(Netfilter)劫持,特征是在nf_hooks(用于记录对收发内容进行过滤的网络过滤函数)中添加恶意钩子函数,这样,本来应该是拦截的内容,但是被恶意钩子函数放行侵入主机。
[0107] 键盘记录器(Keylogger)劫持,特征是在keyboard_notifier_list(键盘记录列表,获取键盘的输入的函数)添加notifer记录键盘输入,这样,用户输入的密码、账号等会被复制。
[0108] 修改系统调用函数的代码,特征是直接在系统调用函数的代码中添加恶意函数的处理函数(也就是实际被执行的代码)。
[0109] 修改某些关键函数的执行流程,特征是一般通过插入jmp(跳转)、call(调用)等指令篡改函数的执行流程,使其执行恶意函数的代码。例如,在执行主流程时,使其跳转至执行恶意函数的代码,执行完之后,再返回主流程,或使其调用某个恶意函数,执行完之后,再返回主流程。
[0110] 通过对上述几种常见的Rootkits进行分析,基于Rootkits类型不同,检测方式也不一样,这样,可以将内核数据结构分为以下两种内核数据结构类型:
[0111] 第一类型:将内核数据结构初始结构内容与当前结构内容进行对比,才能确定Rootkits的这类内核数据结构。例如,系统调用表、中断描述符表、某些函数的函数指针和代码(如虚拟文件系统劫持等)等。其中,对于第一类型对应的某个内核数据结构,该内核数据结构的初始结构内容是开发出来未被Rootkits感染的结构内容,该内核数据结构的当前结构内容是现在使用时,获取到的结构内容。
[0112] 第二类型(也可以称为是目标类型):通过判断内核数据结构当前结构内容是否存在某些预设结构,来确定Rootkits的这类内核数据结构。例如,键盘记录器劫持、网络过滤器劫持、某些被插入jmp、call等指令的函数等。预设结构可以是改变执行路径的指令(如jmp、call等指令)、键盘记录列表中的结点等。
[0113] 本申请实施例提供了一种检测非法程序的方法,下面将结合具体实施方式,对该方法的处理流程进行详细的说明,如图3所示,内容可以如下:
[0114] 步骤301,确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,第一读取函数用于读取当前结构内容,第二读取函数用于读取初始结构内容。
[0115] 其中,第一内核数据结构是内核空间中的内核数据结构,容易被感染Rootkits,第一内核数据结构的标识被编译在检测程序中,组成内核数据结构的标识列表,如第一内核数据结构有系统调用表、中断描述符表等。
[0116] 在实施中,编写检测程序的代码,该检测程序的代码可以被主机中的处理器(该处理器可以是主机的中央处理器)所运行,然后将检测程序安装在主机上,该检测程序一部分是安装在主机的Linux操作系统的用户空间,一部分是安装在主机的Linux操作系统的内核空间,安装在用户空间的部分运行于用户空间,安装在内核空间的部分运行于内核空间,用于检测内核空间中的Rootkits。例如,如图4所示,检测程序可以是图4中Gra_dbg,用户空间中是Gra_dbg用户态接口部分,内核空间中是Gra_dbg内核检测部分。
[0117] 在需要检测内核空间中的rootkits时,可以启动主机中的检测程序,例如,可以是用户点击检测程序的界面上显示的Rootkits选项,主机则会检测到该选项的点击指令,通过系统调用的方式,调用检测程序在内核空间的部分检测内核空间中的Rootkits。处理过程可以是:主机可以通过检测程序安装在内核空间的部分,获取检测程序中设置的内核数据结构的标识列表,从中获取任一内核数据结构的标识(后续可以称为第一内核数据结构的标识),根据第一内核数据结构的标识,获取第一内核数据结构的第一读取函数和第二读取函数,第一读取函数用于读取当前结构内容,第二读取函数用于读取初始结构内容。
[0118] 可选的,在获取第一读取函数和第二读取函数之前,首先要确定第一内核数据结构所属的内核数据结构类型,相应的处理可以如下:
[0119] 获取第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;根据对应关系和第一内核数据结构的标识,确定第一内核数据结构所属的内核数据结构类型。
[0120] 其中,在内核数据结构的标识与内核数据结构类型的对应关系中,可以是多个内核数据结构的标识对应一种内核数据结构类型,也可以是每个内核数据结构的标识,都分别对应有内核数据结构类型,只不过每个内核数据结构的标识分别对应的内核数据结构类型有相同的。
[0121] 在实施中,检测程序中编译有内核数据结构的标识与内核数据结构类型的对应关系。主机可以通过CPU运行检测程序在内核空间中的代码,从上述标识列表中,获取第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系。然后使用第一内核数据结构的标识,从对应关系中,确定第一内核数据结构的标识对应的第一类型,将第一类型确定为第一内核数据结构所属的内核数据结构类型。后续可以使用第一类型,来获取第一读取函数和第二读取函数。
[0122] 可选的,主机可以基于第一类型,来确定第一内核数据结构对应的第一读取函数和第二读取函数,相应的处理可以如下:
[0123] 获取内核数据结构类型与读取函数的标识的对应关系;根据第一内核数据结构所属的内核数据结构类型以及内核数据结构类型与读取函数的标识的对应关系,确定第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;根据两个读取函数的标识中有第一标记的读取函数的标识,确定内核空间中第一内核数据结构对应的第一读取函数,并根据两个读取函数的标识中有第二标记的读取函数的标识,确定第一内核数据结构对应的第二读取函数。
[0124] 其中,第一标记用于指示读取函数用于读取当前结构内容,第二标记用于指示读取函数用于读取初始结构内容。
[0125] 在实施中,检测程序中编译有内核数据结构类型与读取函数的标识的对应关系,主机确定出第一内核数据结构所属的内核数据结构类型为第一类型后,可以通过CPU运行检测程序的代码,获取检测程序编译的内核数据结构类型与读取函数的标识的对应关系。从该对应关系中,确定出第一类型对应的两个读取函数的标识,然后判断两个读取函数的标识中,是否包含第一标记,如果包含第一标记,则确定包含第一标记的读取函数的标识,为第一读取函数的标识,可以使用该标识,在内核空间中确定第一读取函数。并且可以判断两个读取函数的标识中,是否包含第二标记,如果包含第二标记,则确定包含第二标记的读取函数的标识,为第二读取函数的标识,可以使用该标识,在内核空间中确定第二读取函数。
[0126] 例如,在Linux操作系统中,第一读取函数的标识是probe_kernel_read,第二读取函数的标识是kallsyms_lookup_name,第一标记可以是kernel,第二标记可以是kallsyms。
[0127] 另外,在获取第一内核数据结构对应的第一读取函数和第二读取函数时,还可以通过CPU运行检测程序在内核空间中的代码,获取检测程序中内核数据结构与读取函数的标识的对应关系,使用第一读取函数的标识,从该对应关系中,获取到第一内核数据结构的标识对应的两个读取函数的标识,然后判断两个读取函数的标识中,是否包含第一标记。如果包含第一标记,则确定包含第一标记的读取函数的标识,为第一读取函数的标识,可以使用该标识,在内核空间中确定第一读取函数。并且可以判断两个读取函数的标识中,是否包含第二标记,如果包含第二标记,则确定包含第二标记的读取函数的标识,为第二读取函数的标识,可以使用该标识,在内核空间中确定第二读取函数。
[0128] 另外,在获取第一内核数据结构对应的第一读取函数和第二读取函数时,还可以通过CPU运行检测程序在内核空间的代码,获取检测程序中内核数据结构类型、读取函数的标识和指示标记的对应关系,(在该对应关系中,指示标记有第一标记和第二标记,与前面的含义相同)。可以从该对应关系中,确定出第一类型对应的两个读取函数的标识、以及两个标识分别对应的指示标记,将指示标记为第一标记的读取函数的标识,确定为第一读取函数的标识,可以使用该标识,在内核空间中确定第一读取函数。并且可以将指示标记为第二标记的读取函数的标识,确定为第二读取函数的标识,可以使用该标识,在内核空间中确定第二读取函数。
[0129] 可选的,第一内核数据结构可以有系统调用表、中断描述符表、第一预设函数和第二预设函数。
[0130] 在实施中,第一内核数据结构可以有系统调用表、中断描述符表、第一预设函数和第二预设函数。系统调用表和中断描述符表见后面的描述。第一预设函数可以是常见的易感染Rootkits的函数指针,例如,虚拟文件系统的结构体指针,包括但不限于函数con_open/pty、函数tcp_seq_show或函数proc_reg_mmap/proc_root_readdir等。第二预设函数可以是预先统计出的常见代码易感染Rootkits的函数。第一预设函数与第一预设函数可以相同。
[0131] 步骤302,调用第一读取函数,获取内核空间中第一内核数据结构的当前结构内容,并且调用第二读取函数,获取内核空间中预先存储的第一内核数据结构的初始结构内容。
[0132] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,将第一内核数据结构的标识,作为第一读取函数的输入,运行第一读取函数的代码,查找到第一内核数据结构的标识对应的实际地址,然后使用第一内核数据结构的标识对应的实际地址,从实际地址对应的存储区域中,读取第一内核数据结构的当前结构内容。并且调用内核空间中的第二读取函数,将第一内核数据结构的标识作为第二读取函数的输入,查找到第一内核数据结构的标识对应的初始地址,然后使用第一内核数据结构的标识对应的初始地址,从初始地址对应的存储区域中,读取第一内核数据结构的初始结构内容。这样,就可以获取到当前结构内容和初始结构内容。
[0133] 例如,在Linux操作系统中,对于第一内核数据结构,可以调用probe_kernel_read函数(即第一读取函数为probe_kernel_read函数),将第一内核数据结构的标识作为probe_kernel_read函数的输入,查找到第一内核数据结构的标识对应的实际地址Addr_current,从该实际地址对应的存储区域中,获取第一内核数据结构的当前结构内容。并且可以调用kallsyms_lookup_name函数(即第二读取函数为kallsyms_lookup_name函数),将第一内核数据结构的标识作为kallsyms_lookup_name函数的输入,查找到第一内核数据结构的标识对应的初始地址Addr_orig,从初始地址对应的存储区域中,获取第一内核数据结构的初始结构内容。
[0134] 例如,第一内核数据结构可以有系统调用表、中断描述符表等,系统调用表包括两列,初始结构内容如表一所示:
[0135]系统调用编号 系统调用函数的函数指针
0 sys_read
1 sys_write
… …
332 sys_ststx
512 compat_sys_rt_sigaction
… …
547 compat_sys_rt_pwriterv64v2
[0136] 表一
[0137] 中断描述符表包括两列,初始结构内容如表二所示:
[0138]
[0139]
[0140] 表二
[0141] 步骤303,当第一内核数据结构的初始结构内容与当前结构内容不相同时,确定第一内核数据结构中存在非法程序。
[0142] 在实施中,主机通过CPU运行检测程序在内核空间中的代码,获取到第一内核数据结构的初始结构内容与当前结构内容后,可以将初始结构内容与当前结构内容进行对比,如果有不相同的内容,确定被非法程序篡改,可以确定第一内核数据结构中存在非法程序。例如,上述表一中系统调用表的初始结构内容中,512对应的系统调用函数指针为compat_sys_rt_sigaction,在系统调用表的当前结构内容中,512对应的系统调用函数指针为compat_sys_rt_action,这样,第一内核数据结构的Rootkits为compat_sys_rt_action。
[0143] 需要说明的是,主机在对第一内核数据结构进行检测时,可以通过检测程序中的一个总进程,每次获取标识列表中一个内核数据结构的标识,然后从内核数据结构的标识与内核数据结构类型的对应关系中,确定该内核数据结构的标识对应的内核数据结构类型。根据确定出的内核数据结构类型,确定Rootkits检测方式,按照该Rootkits检测方式,确定内核数据结构中是否存在Rootkis。在确定出该内核数据结构的检测结果后,再获取标识列表中剩余内核数据结构的标识中的一个内核数据结构的标识,按照上述方法,确定该内核数据结构中是否存在Rootkis。依此类推,直到遍历完上述标识列表中所有的内核数据结构的标识。
[0144] 主机可以通过检测程序中的一个总进程,控制多个线程,分别从标识列表中获取一个内核数据结构的标识,分别确定自身获取的内核数据结构的标识对应的内核数据结构类型。分别根据确定出的内核数据结构类型,确定Rootkits检测方式,按照该Rootkits检测方式,确定内核数据结构中是否存在Rootkis。总进程可以随时查看每个线程的运行进度,如果确定所有进程都执行完成,可以确定多个线程获取到的内核数据结构已经检测完成,总进程可以控制多个线程,检测上述标识列表中剩余的内核数据结构的标识对应的内核数据结构,直到遍历完上述标识列表中所有的内核数据结构的标识。
[0145] 可选的,第一内核数据结构为系统调用表,相应的检测Rootkits方法可以如下:
[0146] 第一内核数据结构为系统调用表,那么获取到的初始结构内容为初始系统调用表,当前结构内容为当前系统调用表。主机可以通过CPU运行检测程序在内核空间中的代码,将相同系统调用编号在两个系统调用表中分别对应的系统调用函数的函数指针进行对比,如果有不相同的函数指针,则将当前系统调用表中不相同的函数指针,确定为第一内核数据结构的Rootkits,如果函数指针均相同,则确定系统调用表中没有Rootkits。
[0147] 可选的,第一内核数据结构可以为中断描述符表,相应的检测Rootkits方法可以如下:
[0148] 第一内核数据结构包括中断描述符表,那么获取到的初始结构内容为初始中断描述符表,当前结构内容为当前中断描述符表。主机可以通过CPU运行检测程序在内核空间中的代码,将相同中断号在两个中断描述符表中分别对应的中断处理函数的函数指针进行对比,如果有不相同的函数指针,则将当前中断描述符表中不相同的函数指针,确定为第一内核数据结构的Rootkits,如果函数指针均相同,则确定中断描述符表中没有Rootkits。
[0149] 可选的,第一内核数据结构为第一预设函数,相应的检测Rootkits方法可以如下:
[0150] 当第一预设函数的初始函数指针和当前函数指针不相同时,确定第一预设函数中存在非法程序。
[0151] 其中,第一预设函数可以是一个也可以是多个,一般情况下是多个,例如,proc_reg_open函数、proc_root_readdir函数、tcp4_seq_show函数、con_open函数中任意一个等,函数指针指函数代码的存储地址。
[0152] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,获取到第一预设函数的初始结构内容和当前结构内容,初始结构内容中包括初始函数指针,当前结构内容中包括当前函数指针。
[0153] 主机可以通过CPU运行检测程序在内核空间中的代码,对第一预设函数的初始函数指针和当前函数指针进行比对,在当前函数指针与初始函数指针不一样时,确定第一预设函数中存在Rootkits。
[0154] 可选的,第一内核数据结构可以为第二预设函数,相应的检测Rootkits方法可以如下:
[0155] 当第二预设函数的初始处理函数和当前处理函数不相同时,确定第二预设函数中存在非法程序。
[0156] 其中,第二预设函数可以是一个也可以是多个,一般情况下是多个。例如,sys_getdents64,sys_getdents、compat_sys_getdents64、compat_sys_getdents等。在执行第二预设函数时,实际执行的是第二预设函数的处理函数的代码,第二预设函数的初始处理函数是指原始的没有被Rootkits修改的函数,第二预设函数的当前处理函数是指当前要执行第二预设函数时,获取到的处理函数。
[0157] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,获取到每个第二预设函数的初始结构内容和当前结构内容,初始结构内容中包括初始处理函数,当前结构内容中包括当前处理函数。
[0158] 主机可以通过CPU运行检测程序在内核空间中的代码,对初始处理函数和当前处理函数进行比对,在该当前处理函数与初始处理函数不一样时,确定第二预设函数中存在Rootkits。
[0159] 需要说明的是,上述提到的第一预设函数与第二预设函数可以相同。
[0160] 可选的,第一内核数据结构可以为网络过滤函数,相应的检测Rootkits方法可以如下:
[0161] 当当前网络过滤函数与白名单不相同时,将不相同的函数,确定为网络过滤函数中的非法程序。
[0162] 其中,网络过滤函数是用于对主机的收发内容进行过滤的函数,白名单可以预先设置,并且存储至主机的存储器(该存储器可以是主机中的非易失性存储器)中,白名单中可以包括预先设置的网络过滤函数,也就是说白名单中设置的网络过滤函数是正常存在的。例如,iptable_filter_hook、ipv4_conntrack_defrag等,也即白名单是网络过滤函数的初始结构内容,当前结构内容为当前获取到的网络过滤函数。
[0163] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,获取内存中预先存储的网络过滤函数的白名单,然后将当前的网络过滤函数和白名单中的网络过滤函数进行对比,如果当前获取到的网络过滤函数中,有不属于白名单的网络过滤函数,则网络过滤函数中存在Rootkits。
[0164] 例如,主机可以通过CPU运行检测程序在内核空间中的代码,检测Netfilter的nf_hooks中是否有白名单(如iptable_filter_hook、ipv4_conntrack_defrag等)以外的恶意函数,这样,可以实现对Netfilter型的rootkits的检测。
[0165] 可选的,一般内核空间检测Rootkits是在接收到系统调用(用于运行检测程序在内核空间中的代码)之后进行,为了降低非法访问检测程序在内核空间中的代码,可以进行如下处理:
[0166] 接收目标系统调用,其中,目标系统调用用于指示进行非法程序检测;当目标系统调用对应有预设标识时,确定进行非法程序检测。
[0167] 在实施中,主机通过内核空间接收到目标系统调用时(目标系统调用用于指示运行检测程序在内核空间中的代码),可以查看目标系统调用是否对应有预设标识(如该预设标识用于指示系统调用有Netlink访问权限,该预设标识可以是CAP_NET_ADMIN的标识)。如果有预设标识,则确定目标系统调用有Netlink访问权限,目标系统调用对应用户为root用户,可以进行非法程序检测,也即可以运行检测程序在内核空间中的代码。
[0168] 另外,如果目标系统调用没有预设标识,则确定目标系统调用没有Netlink访问权限,可以拒绝运行检测程序在内核空间中的代码。这样,可以防止检测程序的非法访问。
[0169] 可选的,可以通过白名单的方式确定目标系统调用是否有预设标识,在白名单中设置有预设标识对应的系统调用的标识,如果在白名单中有目标系统调用的标识,则确定目标系统调用对应有预设标识,如果在白名单中没有目标系统调用的标识,则确定目标系统调用未对应有预设标识。
[0170] 可选的,还可以对模块结构体进行检测,相应的处理方式可以如下:
[0171] 当确定内核空间中存在目标模块结构体时,确定目标模块结构体为非法程序,其中,目标模块结构体用于删除内核数据结构链表中的结点,结点是目标模块结构体在内核空间中能加载的内核数据结构的标识。
[0172] 在实施中,目标模块结构体用于删除内核数据结构链表中的结点,该结点是目标模块结构体在内核空间中能加载的内核数据结构的标识。主机可以通过CPU运行检测程序在内核空间中的代码,获取到module_kset结构体和module结构体,然后对module_kset结构体和module结构体进行对比,确定出其中不相同的内容,将该不相同的内容,确定为目标模块结构体,目标模块结构体为非法程序。这样,通过对module_kset结构体和module结构体的对比,可以确定出隐藏可加载内核数据结构的结点的Rootkits,该Rootkits的作用是删除Rootkits在内核空间中可加载内核模块链表中的结点。
[0173] 本申请实施例中,由于可以通过第一读取函数和第二读取函数,分别获取内核空间中第一内核数据结构的初始结构内容和当前结构内容,通过对比的方式,即可确定第一内核数据结构中是否存在非法程序,所以可以对内核空间中的非法程序进行检测。
[0174] 如图5所示,本申请另一实施例,还提供了通过判断的方式,检测目标内核数据结构的方法,相应的处理可以如下:
[0175] 步骤501,确定内核空间中目标内核数据结构对应的目标读取函数,其中,目标读取函数用于读取当前结构内容。
[0176] 其中,目标内核数据结构是内核空间中的内核数据结构,容易被感染Rootkits,目标内核数据结构的标识被编译至检测程序中,组成内核数据结构的标识列表,如目标内核数据结构有第三预设函数、键盘记录表等。
[0177] 在实施中,在需要检测内核空间中的rootkits时,可以启动主机中的检测程序。例如,可以是用户点击检测程序的界面上显示的Rootkits选项,主机则会检测到该选项的点击指令,通过系统调用的方式,调用检测程序在内核空间的部分检测内核空间中的Rootkits。处理过程可以是:主机可以通过检测程序安装在内核空间的部分,获取检测程序中设置的内核数据结构的标识列表,从中获取任一内核数据结构的标识(后续可以称为目标内核数据结构的标识),根据目标内核数据结构的标识,获取目标内核数据结构的目标读取函数,目标读取函数用于读取当前结构内容。
[0178] 需要说明的是,此处的目标读取函数可以与前面提到的第一读取函数相同。
[0179] 可选的,在获取目标读取函数之前,首先要确定目标内核数据结构所属的内核数据结构类型,相应的处理可以如下:
[0180] 获取目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;根据对应关系和目标内核数据结构的标识,确定目标内核数据结构所属的内核数据结构类型。
[0181] 其中,在内核数据结构的标识与内核数据结构类型的对应关系中,可以是多个内核数据结构的标识对应一种内核数据结构类型,也可以是每个内核数据结构的标识都分别对应有内核数据结构类型,只不过每个内核数据结构的标识分别对应的内核数据结构类型有相同的。
[0182] 在实施中,检测程序中编译有内核数据结构的标识与内核数据结构类型的对应关系,主机可以通过CPU运行检测程序在内核空间中的代码,获取目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系。然后使用目标内核数据结构的标识,从对应关系中,确定目标内核数据结构的标识对应的目标类型,将目标类型确定为目标内核数据结构所属的内核数据结构类型。后续可以通过目标类型,获取到目标读取函数。
[0183] 可选的,主机可以基于目标类型,来确定目标内核数据结构对应的目标读取函数,相应的处理可以如下:
[0184] 获取内核数据结构类型与读取函数的标识的对应关系;根据目标内核数据结构所属的内核数据结构类型以及内核数据结构类型与读取函数的标识的对应关系,确定目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;根据目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定目标内核数据结构对应的目标读取函数。
[0185] 在实施中,检测程序中编译有内核数据结构类型与读取函数的标识的对应关系,主机确定出目标内核数据结构所属的内核数据结构类型为目标类型后,可以获取检测程序编译的内核数据结构类型与读取函数的标识的对应关系。从中确定目标类型对应的读取函数的标识,将该标识确定为目标读取函数的标识,基于目标读取函数的标识,就可以确定出目标读取函数。例如,在Linux操作系统中,目标读取函数的标识可以是probe_kernel_read。
[0186] 另外,在获取目标内核数据结构对应的目标读取函数时,还可以获取检测程序中内核数据结构与读取函数的标识的对应关系,使用目标读取函数的标识,从该对应关系中,获取到目标内核数据结构的标识对应的读取函数的标识,将该标识确定为目标读取函数的标识。然后可以使用该标识,在内核空间中确定目标读取函数。
[0187] 步骤502,调用目标读取函数,获取目标内核数据结构的当前结构内容。
[0188] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,将目标内核数据结构的标识,作为目标读取函数的输入,运行目标读取函数的代码,查找到目标内核数据结构的标识对应的实际地址,然后使用目标内核数据结构的标识对应的实际地址。从实际地址对应的存储区域中,读取目标内核数据结构的当前结构内容。例如,在Linux操作系统中,对于目标内核数据结构,可以调用probe_kernel_read函数(即目标读取函数为probe_kernel_read函数),将目标内核数据结构的标识作为probe_kernel_read函数的输入,查找到目标内核数据结构的标识对应的实际地址Addr_current。从该实际地址对应的存储区域中,获取目标内核数据结构的当前结构内容。
[0189] 步骤503,当目标内核数据结构的当前结构内容中存在预设结构时,确定目标内核数据结构中存在非法程序。
[0190] 其中,预设结构为用于执行非法处理的结构,如改变执行路径的指令、键盘记录列表中的结点等。
[0191] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,确定目标内核数据结构中的当前结构内容中是否存在预设结构,如果存在,则确定目标内核数据结构中存在非法程序。
[0192] 可选的,目标内核数据结构为键盘记录列表,相应的检测Rootkits方法可以如下:
[0193] 获取键盘记录列表,当键盘记录表中存在结点,确定键盘记录表中存在Rootkits。
[0194] 在实施中,主机通过检测程序获取到键盘记录列表(keyboard_notifier_list)当前结构内容后,通过CPU运行检测程序在内核空间中的代码,确定keyboard_notifier_list中是否包括有内容(也就是判断keyboard_notifier_list是否是空的)。如果keyboard_notifier_list有内容,将该内容确定为notifier结点,确定keyboard_notifier_list中包括notifier结点,确定keyboard_notifier_list中存在Rootkits。如果keyboard_notifier_list没有内容,则确定keyboard_notifier_list没有Rootkits。
[0195] 可选的,目标内核数据结构为第三预设函数,相应的检测Rootkits方法可以如下:
[0196] 当第三预设函数的处理函数的入口处有改变执行路径的指令时,确定第三预设函数有Rootkits。
[0197] 在实施中,主机可以通过CPU运行检测程序在内核空间中的代码,获取第三预设函数的处理函数。然后通过CPU运行检测程序在内核空间中的代码,识别第三预设函数的处理函数的入口处的指令,判断第三预设函数的处理函数的入口处的指令是否包括改变执行路径的指令(如call、jump等指令)。如果第三预设函数的处理函数的入口处包括,则确定第三预设函数有Rootkits。如果第三预设函数的处理函数的入口处不包括,则确定第三预设函数没有Rootkits。这样,可以对Inline hook型的Rootkits进行检测。
[0198] 本申请实施例中,由于可以通过目标读取函数,分别获取内核空间中目标内核数据结构的当前结构内容,通过判断的方式,即可确定目标内核数据结构中是否存在非法程序,所以可以对内核空间中的非法程序进行检测。
[0199] 另外,针对本申请的上述两个实施例,主机确定出第一内核数据结构中的Rootkits和目标内核数据结构中的Rootkits后,可以将其确定为内核空间中的Rootkits。这样,通过内核空间中的检测程序可以检测到内核空间中的Rootkits。
[0200] 另外,主机可以通过netlink协议,将检测到的Rootkits发送至用户空间,主机可以对检测到的Rootkits进行显示,这样,更方便用户查看检测结果。可选的,可以分别对第一内核数据结构和目标内核数据结构中的Rootkits进行发送。
[0201] 可选的,本申请实施例中,还提供了从服务器获取主机上的Linux操作系统内核空间中的Rootkits的方法,相应的处理可以如下:
[0202] 通过检测程序,将内核空间中的Rootkits,发送至用户空间;通过用户空间,向服务器发送内核空间中的Rootkits。
[0203] 在实施中,主机通过检测程序,确定内核空间中的Rootkits后,可以通过用户空间与内核空间之间的Netlink(网链接)协议,将内核空间中的Rootkits,发送至用户空间,然后主机可以通过用户空间向检测程序的后台服务器(此处可以简称为服务器)发送内核空间的Rootkits。该过程可以由主机的CPU和发送器共同实现,CPU通过运行检测程序在内核空间中的代码,将内核空间中的Rootkits,发送至用户空间,由主机的发送器,通过无线网络或有线网络,将内核空间中的Rootkits发送至服务器。
[0204] 这样,后续可以从服务器上获取主机的内核空间Rootkits检测结果,进而对主机进行Rootkits进行清理。
[0205] 另外,本申请实施例中,还可以统一管理服多个安装有Linux操作系统的主机,处理过程可以如下:
[0206] 如图6所示,在安装有Linux操作系统的主机上,均安装检测程序,通过服务器向管理的每个主机,周期性(如每天00:00点等)发送Rootkits检测指令。主机接收到Rootkits检测指令后,可以经过系统调用,通过运行检测程序在内核空间中的代码进行Rootkits检测(检测方法与前面的方式相同此处不再赘述)。在通过内核空间中的检测程序得到内核空间中Rootkits后,主机可以通过用户空间与内核空间之间的Netlink协议,将检测到的Rootkits发送至用户空间,然后主机可以通过用户空间将检测到的Rootkits发送至服务器。
[0207] 可选的,检测程序中编译有预设内核数据结构对应的用于清理Rootkits的代码,在确定出某种内核数据结构中有Rootkits之后,可以使用该内核数据结构的标识,查找到对应的用于清理Rootkits的代码,运行该代码,对该内核数据结构中的Rootkits进行清理。或者是另外编译一个清理程序,将清理程序安装在主机上,可以通过检测程序,启动清理程序,对内核数据结构中的Rootkits进行清理。在清理完成后,可以使用前面检测Rootkits的方式重新检测,对于某个内核数据结构,如果重新检测不存在Rootkits,则确定该内核数据结构中不存在Rootkits,在上报Rootkits检测结果时,不进行上报。如果重新检测存在Rootkits,则确定该内核数据结构中还存在Rootkits,在上报Rootkits检测结果时,上报该内核数据结构中存在Rootkits。
[0208] 另外,还可以将本申请实施例应用于安卓系统,安卓(Android)系统是基于Linux操作系统搭建的,检测Rootkits的方式与Linux操作系统检测Rootkits的方式类似,比如系统调用表、网络过滤函数等内核数据结构的检测方式一致。
[0209] 另外,还可以将本申请实施例的思想应用于ios系统,在ios系统的内核空间中设置检测程序,检测ios内核空间中的Rootkits。
[0210] 需要说明的是,本申请上述两个实施例中,Linux操作系统中的第一读取函数、目标读取函数可以是probe_kernel_read函数,第二读取函数可以是kallsyms_lookup_name函数,这仅是一种举例的方式,不管是在Linux操作系统中,还是在其它操作系统中,凡是可以用于读取当前结构内容的函数都可以是第一读取函数,凡是可以用于读取内核空间中,初始结构内容的函数都可以是第二读取函数,本申请实施例不做限定。
[0211] 图7是本申请实施例提供的检测非法程序的装置的结构图。该装置可以通过软件、硬件或者两者的结合实现成为装置中的部分或者全部。本申请实施例提供的主机可以实现本申请实施例图3所示的流程,该装置包括:确定模块710、获取模块720,其中:
[0212] 确定模块710,用于确定内核空间中第一内核数据结构对应的第一读取函数和第二读取函数,其中,所述第一读取函数用于读取当前结构内容,所述第二读取函数用于读取初始结构内容;具体可以实现上述步骤301中的确定功能,以及其它隐含步骤。
[0213] 获取模块720,用于调用所述第一读取函数,获取所述内核空间中所述第一内核数据结构的当前结构内容,并且调用所述第二读取函数,获取所述内核空间中预先存储的所述第一内核数据结构的初始结构内容;具体可以实现上述步骤302中的获取功能,以及其它隐含步骤。
[0214] 所述确定模块710,还用于当所述第一内核数据结构的初始结构内容与当前结构内容不相同时,确定所述第一内核数据结构中存在非法程序。具体可以实现上述步骤303中的确定功能,以及其它隐含步骤。
[0215] 可选的,所述获取模块720,还用于:
[0216] 获取所述第一内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;
[0217] 所述确定模块710,还用于根据所述对应关系和所述第一内核数据结构的标识,确定所述第一内核数据结构所属的内核数据结构类型。
[0218] 可选的,所述确定模块710,用于:
[0219] 获取内核数据结构类型与读取函数的标识的对应关系;
[0220] 根据所述第一内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述第一内核数据结构所属的内核数据结构类型对应的两个读取函数的标识;
[0221] 根据所述两个读取函数的标识中有第一标记的读取函数的标识,确定所述内核空间中第一内核数据结构对应的第一读取函数,并根据所述两个读取函数的标识中有第二标记的读取函数的标识,确定所述第一内核数据结构对应的第二读取函数,其中,所述第一标记用于指示读取函数用于读取当前结构内容,所述第二标记用于指示读取函数用于读取初始结构内容。
[0222] 可选的,所述确定模块710,还用于:
[0223] 当确定所述内核空间中存在目标模块结构体时,确定所述目标模块结构体为非法程序,其中,所述目标模块结构体用于删除内核数据结构链表中的结点,所述结点是所述目标模块结构体在所述内核空间中能加载的内核数据结构的标识。
[0224] 可选的,如图8所示,所述装置还包括:
[0225] 接收模块730,用于接收目标系统调用,其中,所述目标系统调用用于指示进行非法程序检测;
[0226] 所述确定模块710,还用于当所述目标系统调用对应有预设标识时,确定进行非法程序检测。
[0227] 本申请实施例中,由于可以通过第一读取函数和第二读取函数,分别获取内核空间中第一内核数据结构的初始结构内容和当前结构内容,通过对比的方式,即可确定第一内核数据结构中是否存在非法程序,所以可以对内核空间中的非法程序进行检测。
[0228] 需要说明的是:上述实施例提供的检测非法程序的装置在检测非法程序时,仅以上述各功能模块的划分进行举例说明,实际应用中,可以根据需要而将上述功能分配由不同的功能模块完成,即将装置的内部结构划分成不同的功能模块,以完成以上描述的全部或者部分功能。另外,上述实施例提供的检测非法程序的装置与检测非法程序的方法实施例属于同一构思,其具体实现过程详见方法实施例,这里不再赘述。
[0229] 图9是本申请实施例提供的检测非法程序的装置的结构图。该装置可以通过软件、硬件或者两者的结合实现成为装置中的部分或者全部。本申请实施例提供的主机可以实现本申请实施例图5所示的流程,该装置包括:确定模块910、获取模块920,其中:
[0230] 确定模块910,用于确定内核空间中目标内核数据结构对应的目标读取函数,其中,所述目标读取函数用于读取当前结构内容;
[0231] 获取模块920,用于调用所述目标读取函数,获取所述内核空间中所述目标内核数据结构的当前结构内容;
[0232] 所述确定模块910,还用于当所述目标内核数据结构的当前结构内容中存在预设结构时,确定所述目标内核数据结构中存在非法程序,其中,所述预设结构至少包括改变执行路径的指令、恶意钩子函数。
[0233] 可选的,所述获取模块920,还用于:
[0234] 获取所述目标内核数据结构的标识,并获取内核数据结构的标识与内核数据结构类型的对应关系;
[0235] 所述确定模块910,还用于根据所述对应关系和所述目标内核数据结构的标识,确定所述目标内核数据结构所属的内核数据结构类型。
[0236] 可选的,所述确定模块910,用于:
[0237] 获取内核数据结构类型与读取函数的标识的对应关系;
[0238] 根据所述目标内核数据结构所属的内核数据结构类型以及所述内核数据结构类型与读取函数的标识的对应关系,确定所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识;
[0239] 根据所述目标内核数据结构所属的内核数据结构类型对应的读取函数的标识,确定所述目标内核数据结构对应的目标读取函数。
[0240] 可选的,所述预设结构包括改变执行路径的指令、键盘记录列表中的结点。
[0241] 本申请实施例中,由于可以通过目标读取函数,分别获取内核空间中目标内核数据结构的当前结构内容,通过判断的方式,即可确定目标内核数据结构中是否存在非法程序,所以可以对内核空间中的非法程序进行检测。
[0242] 需要说明的是:上述实施例提供的检测非法程序的装置在检测非法程序时,仅以上述各功能模块的划分进行举例说明,实际应用中,可以根据需要而将上述功能分配由不同的功能模块完成,即将装置的内部结构划分成不同的功能模块,以完成以上描述的全部或者部分功能。另外,上述实施例提供的检测非法程序的装置与检测非法程序的方法实施例属于同一构思,其具体实现过程详见方法实施例,这里不再赘述。
[0243] 在上述实施例中,可以全部或部分地通过软件、硬件、固件或者其任意组合来实现,当使用软件实现时,可以全部或部分地以计算机程序产品的形式实现。所述计算机程序产品包括一个或多个计算机指令,在装置上加载和执行所述计算机程序指令时,全部或部分地产生按照本申请实施例所述的流程或功能。所述计算机指令可以存储在计算机可读存储介质中,或者从一个计算机可读存储介质向另一个计算机可读存储介质传输,例如,所述计算机指令可以从一个网站站点、计算机、服务器或数据中心通过有线(例如同轴光缆、光纤、数字用户线)或无线(例如红外、无线、微波等)方式向另一个网站站点、计算机、服务器或数据中心进行传输。所述计算机可读存储介质可以是装置能够存取的任何可用介质或者是包含一个或多个可用介质集成的服务器、数据中心等数据存储设备。所述可用介质可以是磁性介质(如软盘、硬盘和磁带等),也可以是光介质(如数字视盘(Digital Video Disk,DVD)等),或者半导体介质(如固态硬盘等)。
[0244] 以上所述仅为本申请的一个实施例,并不用以限制本申请,凡在本申请的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本申请的保护范围之内。