一种应用于Linux系统中动态库API的拦截方法及装置与流程

文档序号:12596443阅读:315来源:国知局
一种应用于Linux系统中动态库API的拦截方法及装置与流程

本发明涉及计算机API拦截技术领域,特别是涉及一种应用于linux系统中动态库API的拦截方法及装置。



背景技术:

为了实现对计算机应用程序的调试以及拓展原有的功能,现有计算技术领域普遍采用钩子技术用来拦截不同API的调用,拦截api的技术有很多种,大体分为用户层和内核层的拦截,其中,对于用户层的拦截技术,一般是直接修改要拦截的api的内存以及程序流程,使程序跳转到指定的地址执行,然后再返回到原地址。但是上述的拦截方法中,由于不同动态库服务调用的同一API所执行的钩子函数有所区别,因此在某一调用的API未完成对应的动态库服务时,其它同样需要调用该指令的动态库服务就要延迟推后执行,不能支持对同一API的重复多次挂钩以及卸钩操作。



技术实现要素:

本发明所要解决的技术问题是:提供一种应用于linux系统中动态库API的拦截方法及装置,利用双级拦截映射表可以实现对API及其钩子函数的多次挂钩和卸钩。

本发明解决上述技术问题所采用的技术方案是:

本发明提供了一种应用于linux系统中动态库API的拦截方法,包括:获取待执行的动态库服务所调用的API及钩子函数;根据API从预设的双级拦截映射表中查找相应的API,将钩子函数与API的原函数挂钩,以钩子 函数替换原函数执行动态库服务;在动态库服务执行完成后,卸钩API并恢复原函数。

进一步的,双级拦截映射表包括一级映射表和二级映射表,其中,一级映射表的键为ELF文件的句柄集,值为API名称集;二级映射表的键为API名称,值为原函数和钩子函数。

进一步的,根据API从预设的双级拦截映射表中查找相应的API的过程包括:调用dlopen函数打开对应API的ELF文件,并获取ELF文件的句柄,从一级映射表的句柄集中查找和匹配对应的句柄;取出匹配成功的句柄所对应的API名称集,并递增ELF文件的引用计数。

进一步的,在调用dlopen函数打开ELF文件并获取所述ELF文件的句柄后,判断句柄是否满足句柄调用条件;判断句柄是否满足句柄调用条件的过程包括:判断句柄是否为空,若否,则判断ELF文件的路径名是否为空;若路径名不为空,则满足句柄调用条件,否则,从伪文件系统中读取文件路径名,其中,读取的文件路径名为/proc/self/exe;以只读方式调用open函数并返回fd,判断fd是否为-1,若否,则满足句柄调用条件。

进一步的,当句柄未从所述句柄集中查找和匹配成功时,在一级映射表中新建句柄;在一级映射表中新建句柄的过程包括:读取句柄对应的所述ELF文件的文件头,计算ELF文件的基地址,将句柄插入至一级映射表的句柄集中。

进一步的,计算确定ELF文件的映像基地址的过程包括:获取ELF文件的程序头部表,判断ELF文件的类型,在ELF文件为DYN文件时,读取DYN文件的动态链接符号节头和字符串节头;根据动态链接符号节头确定DYN文件的动态链接符号表,根据字符串节头确定DYN文件的动态链接符号字符串表;从动态链接符号表中重复取下一个符号sym并获取sym的偏移量,判断是否达到动态链接符号表的末尾,若否,则判断sym是否为外部 函数且偏移量非0;若sym为外部函数且偏移量非0,则从动态链接符号字符串表中获取sym的函数名称,并调用库函数返回fun;判断fun是否为非空,fun为通过dlopen函数所获取的对应符号的函数地址,若fun非空,则设置ELF文件的映像基地址为fun和sym偏移量的差。

进一步的,将钩子函数与API的原函数挂钩的过程包括:根据动态链接符号节头确定API名称对应的索引,以及根据映象基地址和偏移量确定动态符号表和重定位链接过程表的位置,获取动态符号表和重定位链接过程表;以钩子函数替换重定位链接过程表的入口表项,并输出原函数;若替换失败,则以钩子函数替换动态符号表的入口表项,并输出原函数;判断钩子函数与原函数是否相同,若否,则判断是否为第一次挂钩该API;若为第一次挂钩该API,则将钩子函数和原函数插入至二级映射表并生成挂钩记录,否则,更新二级映射表中前次未卸钩的钩子函数为本次挂钩的钩子函数。

进一步的,卸钩API并恢复原函数的过程包括:从二级映射表中查找对应所述API的挂钩记录;以原函数为钩子函数,以钩子函数替换重定位链接过程表的入口表项,并输出原函数;判断钩子函数与原函数是否相同,若否,更新二级映射表中的钩子函数为原函数;将二级映射表中的挂钩记录删除。

进一步的,在动态库服务执行完成后,关闭ELF文件,其中,关闭ELF文件的过程包括:递减ELF文件的引用计数,判断递减后的引用次数是否为0,若是,则遍历二级映射表,卸钩API并恢复原函数;释放加载处理进程占用的内存,调用dlclose函数和close函数关闭ELF文件;将ELF文件从一级映射表中删除。

本发明还提供了一种应用该拦截方法的装置,包括:获取单元,用于获取待执行的动态库服务所对应API及钩子函数;挂钩单元,用于根据API 从预设的双级拦截映射表中查找相应的API,将钩子函数与API的原函数挂钩,以钩子函数替换所述原函数执行动态库服务;卸钩单元,用于在动态库服务执行完成后,卸钩API并恢复原函数。

本发明采用上述技术方案所具有的有益效果是:

本发明的拦截方法利用双级拦截映射表,建立不同动态库服务所调用的API与其对应的ELF文件、钩子函数和原函数的关联关系,根据钩子函数的区别可以在映射表中插入多个API调用记录,能够在动态库服务执行完成,根据调用记录将API复原为原始函数,方便不同动态库服务对同一API的多次重复调用。

附图说明

图1为本发明拦截方法的整体流程图;

图2为本发明一实施例中双级拦截映射表的结构示意图;

图3为本发明拦截方法中查找API的流程图;

图4为本发明拦截方法中基地址计算的流程图;

图5为本发明拦截方法中挂钩API的流程图;

图6为本发明拦截方法中卸钩API的流程图;

图7为本发明拦截方法中关闭ELF文件的流程图。

具体实施方式

为清楚的说明本发明中的方案,下面给出优选的实施例并结合附图详细说明。以下的说明本质上仅仅是示例性的而并不是为了限制本公开的应用或用途。应当理解的是,在全部的附图中,对应的附图标记表示相同或对应的部件和特征。

如图1所示,本发明提供了一种应用于linux系统中动态库API的拦 截方法,包括:

S101、获取待执行的动态库服务所调用的API及钩子函数;

S102、根据API从预设的双级拦截映射表中查找相应的API,将钩子函数与API的原函数挂钩,以钩子函数替换原函数执行动态库服务;

S103、在动态库服务执行完成后,卸钩API并恢复原函数。

钩子函数是外部输入的动态库服务函数,由于钩子函数是基于API的原函数基础上修改成的动态库服务函数,在原函数对应的动态库服务函数基础拓展了新的动态库服务内容,而本发明中API挂钩的即是将新的动态库服务函数与原函数挂钩,在上述过程中,钩子函数替换原函数执行完新的动态库服务后,可以根据双级拦截映射表恢复API与原函数的关联关系。

实施例中,如图2所示,双级拦截映射表包括一级映射表和二级映射表,其中,一级映射表的键为ELF文件的句柄集,值为API名称集;二级映射表的键为API名称,值为原函数和钩子函数;本发明对API的挂钩和卸钩操作即是根据该双级拦截映射表实现的,例如,某一映射表中的ELF文件的其中一个句柄为0xffff0001,API的名称为dlopen,该API的原函数为0xffff1234,外部输入的某一钩子函数为0xffff5678。

实施例中,如图3所示,根据API从预设的双级拦截映射表中查找相应的API的过程包括:调用dlopen函数打开对应API的ELF文件,并获取ELF文件的句柄,从一级映射表的句柄集中查找和匹配对应的句柄;取出匹配成功的句柄所对应的API名称集,并递增ELF文件的引用计数,引用计数可以用于记录同一ELF文件被打开及使用的次数。

实施例中,在调用dlopen函数打开ELF文件并获取ELF文件的句柄后,判断句柄是否满足句柄调用条件,具体判断过程为:

S201、判断句柄是否为空,若否,则判断ELF文件的路径名是否为空;

S202、若路径名不为空,则满足句柄调用条件,否则,从伪文件系统 中读取文件路径名,其中,读取的文件路径名为/proc/self/exe;

S203、以只读方式调用open函数并返回fd,判断fd是否为-1,fd为文件描述符,在fd=-1时,即ELF文件打开失败;若否,则满足句柄调用条件。

实施例中,当句柄未从句柄集中查找和匹配成功时,在一级映射表中新建句柄,具体新建的过程包括:读取句柄对应的ELF文件的文件头,计算ELF文件的基地址,将句柄插入至一级映射表的句柄集中。

如图4所示,计算确定ELF文件的映像基地址的过程包括:

S301、获取ELF文件的程序头部表,判断ELF文件的类型,在ELF文件为DYN文件时,读取DYN文件的动态链接符号节头和字符串节头;

S303、根据动态链接符号节头确定DYN文件的动态链接符号表,根据字符串节头确定DYN文件的动态链接符号字符串表;

S304、从动态链接符号表中重复取下一个符号sym并获取sym的偏移量,判断是否达到动态链接符号表的末尾,若否,则判断sym是否为外部可见的导出函数且偏移量非0;

S305、若sym为外部可见的导出函数且偏移量非0,则从动态链接符号字符串表中获取sym的函数名称,并调用库函数返回fun;

S306、判断fun是否为非空,fun为通过dlopen函数所获取的对应符号的函数地址,若fun非空,则设置ELF文件的映像基地址为fun和sym偏移量的差。

如图5所示,将钩子函数与API的原函数挂钩的过程包括:

S401、根据动态链接符号节头确定API名称对应的索引,索引是指在动态符号表或重定位链接过程表中的表项位置;比如,1、2、3等;以及根据映象基地址和偏移量确定动态符号表和重定位链接过程表的位置,获取动态符号表和重定位链接过程表;

S402、以钩子函数替换重定位链接过程表的入口表项,入口表项存储有API的地址,比如dlopen索引为1时,在表项1处的内容为地址0xffff1234,地址0xffff1234的内容为dlopen的地址;并输出原函数;若替换失败,则以钩子函数替换动态符号表的入口表项,并输出原函数;

S403、判断钩子函数与原函数是否相同,若否,则判断是否为第一次挂钩该API;

S404、若为第一次挂钩该API,则将钩子函数和原函数插入至二级映射表并生成挂钩记录,否则,更新二级映射表中前次未卸钩的钩子函数为本次挂钩的钩子函数。

如图6所示,卸钩API并恢复原函数的过程包括:

S501、从二级映射表中查找对应API的挂钩记录;

S502、以原函数为钩子函数,重新调用挂钩API的流程,以原函数作为钩子函数替换重定位链接过程表的入口表项,并输出原函数;

S503、判断钩子函数与原函数是否相同,若否,更新二级映射表中的钩子函数为原函数;

S504、将二级映射表中的挂钩记录删除。

如图7所示,在动态库服务执行完成后,关闭ELF文件,关闭ELF文件的具体过程包括:

S601、递减ELF文件的引用计数,判断递减后的引用次数是否为0,若是,则遍历二级映射表,卸钩API并恢复原函数;

S602、释放加载处理进程占用的内存,调用dlclose函数和close函数关闭ELF文件;

S603、将ELF文件从一级映射表中删除。

本发明还提供了一种装置,该装置采用上述实施例中所公开的拦截方法,装置具体包括:

获取单元,用于获取待执行的动态库服务所对应API及钩子函数;

挂钩单元,用于根据API从预设的双级拦截映射表中查找相应的API,将钩子函数与API的原函数挂钩,以钩子函数替换原函数执行动态库服务;

卸钩单元,用于在动态库服务执行完成后,卸钩API并恢复原函数。

具体的,挂钩单元用于:调用dlopen函数打开对应API的ELF文件,并获取ELF文件的句柄,从一级映射表的句柄集中查找和匹配对应的句柄;取出匹配成功的句柄所对应的API名称集,并递增ELF文件的引用计数。

挂钩单元还用于:在调用dlopen函数打开ELF文件并获取ELF文件的句柄后,判断句柄是否满足句柄调用条件;判断句柄是否满足句柄调用条件的过程包括:判断句柄是否为空,若否,则判断ELF文件的路径名是否为空;若路径名不为空,则满足句柄调用条件,否则,从伪文件系统中读取文件路径名,其中,读取的文件路径名为/proc/self/exe;以只读方式调用open函数并返回fd,判断fd是否为-1,若否,则满足句柄调用条件。

挂钩单元还用于:当句柄未从句柄集中查找和匹配成功时,在一级映射表中新建句柄;在一级映射表中新建句柄的过程包括:读取句柄对应的ELF文件的文件头,计算ELF文件的基地址,将句柄插入至一级映射表的句柄集中。

挂钩单元还用于计算确定ELF文件的映像基地址,具体用于:获取ELF文件的程序头部表,判断ELF文件的类型,在ELF文件为DYN文件时,读取DYN文件的动态链接符号节头和字符串节头;根据动态链接符号节头确定DYN文件的动态链接符号表,根据字符串节头确定DYN文件的动态链接符号字符串表;从动态链接符号表中重复取下一个符号sym并获取sym的偏移量,判断是否达到动态链接符号表的末尾,若否,则判断sym是否为外部可见的导出函数且偏移量非0;若sym为外部可见的导出函数且偏移量非0,则从动态链接符号字符串表中获取sym的函数名称,并调用库函数返 回fun;判断fun是否为非空,fun为通过dlopen函数所获取的对应符号的函数地址,若fun非空,则设置ELF文件的映像基地址为fun和sym偏移量的差。

实施例中,挂钩单元还用于:根据动态链接符号节头确定API名称对应的索引,以及根据映象基地址和偏移量确定动态符号表和重定位链接过程表的位置,获取动态符号表和重定位链接过程表;以钩子函数替换重定位链接过程表的入口表项,并输出原函数;若替换失败,则以钩子函数替换动态符号表的入口表项,并输出原函数;判断钩子函数与原函数是否相同,若否,则判断是否为第一次挂钩该API;若为第一次挂钩该API,则将钩子函数和原函数插入至二级映射表并生成挂钩记录,否则,更新二级映射表中前次未卸钩的钩子函数为本次挂钩的钩子函数。

实施例中,卸钩单元具体用于:从二级映射表中查找对应API的挂钩记录;以原函数为钩子函数,以钩子函数替换重定位链接过程表的入口表项,并输出原函数;判断钩子函数与原函数是否相同,若否,更新二级映射表中的钩子函数为原函数;将二级映射表中的挂钩记录删除。

实施例中,卸钩单元还用于在动态库服务执行完成后,关闭ELF文件;具体用于:递减ELF文件的引用计数,判断递减后的引用次数是否为0,若是,则遍历二级映射表,卸钩API并恢复原函数;释放加载处理进程占用的内存,调用dlclose函数和close函数关闭ELF文件;将ELF文件从一级映射表中删除。

综上,以上内容仅为本发明的实施例,仅用于说明本发明的原理,并非用于限定本发明的保护范围。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1