CN110046497B - 一种函数挂钩实现方法、装置和存储介质 - Google Patents
一种函数挂钩实现方法、装置和存储介质 Download PDFInfo
- Publication number
- CN110046497B CN110046497B CN201810041219.4A CN201810041219A CN110046497B CN 110046497 B CN110046497 B CN 110046497B CN 201810041219 A CN201810041219 A CN 201810041219A CN 110046497 B CN110046497 B CN 110046497B
- Authority
- CN
- China
- Prior art keywords
- function
- hooked
- instructions
- address
- method object
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/50—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems
- G06F21/52—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems during program execution, e.g. stack integrity ; Preventing unwanted data erasure; Buffer overflow
- G06F21/54—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems during program execution, e.g. stack integrity ; Preventing unwanted data erasure; Buffer overflow by adding security routines or objects to programs
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y02—TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
- Y02D—CLIMATE CHANGE MITIGATION TECHNOLOGIES IN INFORMATION AND COMMUNICATION TECHNOLOGIES [ICT], I.E. INFORMATION AND COMMUNICATION TECHNOLOGIES AIMING AT THE REDUCTION OF THEIR OWN ENERGY USE
- Y02D10/00—Energy efficient computing, e.g. low power processors, power management or thermal management
Landscapes
- Engineering & Computer Science (AREA)
- Computer Security & Cryptography (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Executing Machine-Instructions (AREA)
Abstract
本发明实施例公开了一种函数挂钩实现方法、装置和存储介质;本发明实施例采用在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至方法对象中,函数信息包括被挂钩函数的头两条指令;将被挂钩函数中的头两条指令修改为跳转指令,跳转指令用于指示跳转至执行自定义挂钩函数;在方法对象中设置回调指令,回调指令位于头两条指令之后,用于指示跳转执行被挂钩函数中头两条指令的后续指令;当调用被挂钩函数时,根据跳转指令跳转至执行自定义挂钩函数;在自定义挂钩函数执行完成时,跳转至执行方法对象中的头两条指令,并根据回调指令跳转至执行被挂钩函数中的后续指令。该方案可以提高终端系统的安全性。
Description
技术领域
本发明涉及计算机技术领域,具体涉及一种函数挂钩实现方法、装置和存储介质。
背景技术
ART模式英文全称为Android runtime,是谷歌Android 4.4系统新增的一种应用运行模式。ART模式中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。
目前,android(安卓)系统在ART模式下的函数替换操作方案即hook(挂钩)方案主要包括以xpose为代表的方案。xpose方案虽然能够比较好的hook以及回调到原函数,但是在实际操作中需要使用xpose提供的libart.so文件替换系统已有的libart.so文件,这样就需要对终端进行root,使得用户获取系统的超级用户权限。然而,对终端进行root,会降低终端系统的安全性。
发明内容
本发明实施例提供一种函数挂钩实现方法、装置和存储介质,可以提高终端系统的安全性。
本发明实施例提供一种函数挂钩实现方法,包括:
在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;
将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
相应的,本发明实施例还提供了一种函数挂钩实现装置,包括:
备份单元,用于在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;
修改单元,用于将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
回调设置单元,用于在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
函数调用单元,用于当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
函数回调单元,用于在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
相应的,本发明实施例还提供一种存储介质,所述存储介质存储有指令,所述指令被处理器执行时实现本发明实施例任一提供的函数挂钩实现方法。
本发明实施例采用在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至方法对象中,函数信息包括被挂钩函数的头两条指令;将被挂钩函数中的头两条指令修改为跳转指令,跳转指令用于指示跳转至执行自定义挂钩函数;在方法对象中设置回调指令,回调指令位于头两条指令之后,用于指示跳转执行被挂钩函数中头两条指令的后续指令;当调用被挂钩函数时,根据跳转指令跳转至执行自定义挂钩函数;在自定义挂钩函数执行完成时,跳转至执行方法对象中的头两条指令,并根据回调指令跳转至执行被挂钩函数中的后续指令。该方案可以非root模式下不用替换libart.so文件即可实现函数挂钩操作以及函数回调操作,其无需对终端进行root,因此,可以提高终端系统的安全性。
附图说明
为了更清楚地说明本发明实施例中的技术方案,下面将对实施例描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1a是本发明实施例提供的函数挂钩实现方法的流程示意图;
图1b是本发明实施例提供的ArtMethod组示意图;
图1c是本发明实施例提供的安卓系统的架构示意图;
图1d是本发明实施例提供的安卓系统的另一架构示意图;
图2a是本发明实施例提供的inline hook示意图;
图2b是本发明实施例提供的ArtMethod结构示意图;
图3a是本发明实施例提供的第一函数调用逻辑关系示意图;
图3b是本发明实施例提供的第二函数调用逻辑关系示意图;
图3c是本发明实施例提供的第三函数调用逻辑关系示意图;
图3d是本发明实施例提供的第四函数调用逻辑关系示意图;
图4是本发明实施例提供的函数挂钩实现方法的另一流程示意图;
图5a是本发明实施例提供的函数挂钩实现装置的第一种结构示意图;
图5b是本发明实施例提供的函数挂钩实现装置的第二种结构示意图;
图5c是本发明实施例提供的函数挂钩实现装置的第三种结构示意图;
图5d是本发明实施例提供的函数挂钩实现装置的第三种结构示意图;
图5e是本发明实施例提供的函数挂钩实现装置的第四种结构示意图
图6是本发明实施例提供的终端的结构示意图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
本发明实施例提供一种函数挂钩实现方法和装置。以下分别进行详细说明。
本实施例将从函数挂钩实现装置的角度进行描述,该函数挂钩实现装置具体可以集成在终端等设备中,该终端具体可以为手机、笔记本电脑或平板电脑等设备。
在一实施例中,一种函数挂钩实现方法,如图1a所示该方法的具体流程如下:
101、在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至方法对象中,函数信息包括被挂钩函数的头两条指令。
其中,被挂钩函数为需要挂钩(Hook)的函数,即原函数。本实施例中,函数可以为方法对象,比如,在ART系统被挂钩函数可以为被挂钩ArtMethod对象。
该方法对象是一个回调函数对应的方法对象,用于保存被挂钩函数的函数信息,以实现对被挂钩函数的回调。其可以为一个ArtMethod对象,在本实施例中称为方法对象。
比如,在ART模式下或者ART系统中,可以创建空的ArtMethod对象,用于保存被挂钩函数的函数信息,以实现对被挂钩函数的回调。该方法对象即为ArtMethod对象。
其中,被挂钩函数的函数信息可以包括:被挂钩函数的头两条指令(即第一条指令和第二条指令)、函数头信息、函数结构(如ArtMethod对象结构)信息等等。
在一实施例中,可以基于被挂钩函数的结构大小来构建空的方法对象。但是,由于不同厂商可能对ArtMethod对象的结构进行修改,导致不同系统中方法对象的结构大小不相同,因此,被挂钩函数的结构大小也不一样,不能按照统一或固定结构大小来构建方法对象。
比如,在一实施例中,为了能够获取被挂钩函数的实际结构大小,以构建相应的方法对象,可以在创建一个新的类如在java层设计一个类,并在该类中创建两个空函数(即测试函数),利用这个两个空函数确定对象的结构大小。也即,步骤“在ART系统中创建空的方法对象”,可以包括:
在ART系统创建一个类,并在类中创建两个空的测试方法对象;
获取测试方法对象之间的地址差;
根据地址差在ART系统中创建空的方法对象。
其中,测试方法对象之间的地址差即为方法对象的结构大小,比如,参考图1b为ArtMethod对象的空间结构,从图1b中可以看出ArtMethod是紧密排列的,所以一个ArtMethod的大小就是相邻两个ArtMethod地址差,这样就可以得到artsize。此时ArtMethod的大小即为被Hook函数的结构大小。然后,基于ArtMethod的大小创建一个用于函数回调的方法对象。在一实施例中,该空的方法对象的结构大小为地址差。
在安卓系统中一般包括本地层(即Native层)和应用层(如java层),本发明实施例可以在应用层(如java层)创建空的方法对象。
由于不同版本的系统java层和和Native层之间的ArtMethod结构对应关系不同,以安卓5.0和6.0系统为例,参考图1c和图1d,可以看出对于5.0和6.0系统存在java层ArtMethod结构和Native层的ArtMethod结构对应;而6.0系统却没有,在相关的AbstractMethod结构中,6.0系统只是存储了native层ArtMethod对象的地址。其中,在Java层中AbstractMethod下面的ArtMethod为long类型,是native层中ArtMethod的指针。因此,如果在Native层创建备份信息的方法对象,还需要在Java层保存该方法对象的指针。
此时,步骤“在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至方法对象中”,可以包括:
在ART系统的本地层创建空的方法对象;
将被挂钩函数的函数信息备份至本地层的方法对象;
将方法对象对应的指针信息保存在应用层。
比如,可以基于前述方式获取ArtMethod的结构大小,然后,基于ArtMethod的结构大小在Native层创建一空的ArtMethod对象,接着,在Java层保存该方法对象的指针。这样后续根据应用层中的指针信息跳转到备份方法对象,从而实现函数的回调。
考虑到在回调机制如invoke中,对于非静态的函数,如果是非直接函数(直接函数为私有、静态、构造)的会通过虚表等方式重新获取Artmethod对象,将传入的对象替换,导致回调失败。因此,在一实施例中,为了保证回调成功,可以将回调函数即创建的方法对象的函数属性设置为私有(private)属性。比如,可以将构造的回调函数的access_flag设置存在private属性类型。
102、将被挂钩函数中的头两条指令修改为跳转指令,跳转指令用于指示跳转至执行自定义挂钩函数。
其中,自定义挂钩函数为一个自定义函数,即Hook函数。自定义函数可以为Artmethod对象。Hook指的是:实现从被挂钩函数(被Hook函数,也即原函数)跳转到执行自定义挂钩函数(自定义Hook函数)。
其中,跳转指令的构造方式有多种,比如,由于arm指令带立即数的跳转范围只有4M,thumb的跳转范围只有256字节。因此,可以采用LDR PC,[PC,?]指令实现跳转。
LDR跳转指令的格式如下:
LDR PC,[PC,#-4]
addr。
LDR PC,[PC,#-4]指的从pc-4指向的指令地址中读取指令代码到PC(寄存器,或者程序计数器)中;addr为要跳转的地址。本实施例中由于需要跳转到自定义挂钩函数,此时addr可以为自定义挂钩函数的函数入口地址。
103、在方法对象中设置回调指令,回调指令位于头两条指令之后,用于指示跳转执行被挂钩函数中头两条指令的后续指令。
其中,后续指令为头两条指令的下一条指令,比如,当头两条指令分别为指令一和指令二时,后续指令即为指令三。
其中,回调指令为一个跳转指令,用于指示跳转执行被挂钩函数中头两条指令的后续指令。该跳转指令可以为LDR指令。具体地,该回调指令的格式如下:
LDR PC,[PC,#-4]
后续指令的地址,比如原指令三的地址。
其中,方法对象的头两条指令为被挂钩函数的头两条指令(即第一条和第二条指令)。
本发明实施例中,可以采用inline hook实现函数的Hook和回调。在实际应用中,考虑到art下代码格式和elf一样,每个java函数都有对应的二进制代码段,且有相对应的指针来指向函数入口,这个指向函数入口的指针就有点内置elf中间的符号表,所以在知道一个elf文件中函数入口指针的情况下,可以使用inline hook的方式对函数进行hook处理。inline hook的介绍如下:
参考图2a,Inline hook通过三级跳转实现了函数的hook以及回调。inline hook的原理介绍如下:
Inline hook中构造出一块内存空间,将func函数(即被挂钩函数)的头两条指令拷贝到该空间中,并在该两条指令后,设置回调指令。Inline hook采用LDR PC,[PC,?]指令实现跳转,即该回调指令为LDR指令。具体地,通过修改pc(寄存器),使得pc为pc-4位置的值,就可以(在pc-4的位置记录原函数第三条指令的地址)跳转到func函数。这就完成回调原函数的trampoline的构建。
LDR跳转指令的格式如下:
LDR PC,[PC,#-4]
addr。
LDR PC,[PC,#-4]指的从PC-4指向的指令地址中读取指令代码到PC(寄存器,或者程序计数器)中;addr为要跳转的地址。本实施例中由于需要跳转到自定义挂钩函数,此时addr可以为自定义挂钩函数的函数入口地址。
将func函数的头两条指令修改为跳转到自定义函数my_func(即自定义挂钩函数)的跳转指令,修改方式也是利用对pc的修改处理,该跳转指令可以为LDR指令。
在my_fuc函数的末尾通过跳转到构建的内存空间位置就可以实现回调原函数的操作。
如图2a所示,在经过inline hook处理后,可以通过func函数中的跳转指令跳转到my_fuc函数,在my_fuc函数执行结束时跳转到mmap的空间即trampoline执行原来的头两条指令(指令一和二),然后,根据回调指令跳转到执行func函数的原指令三,从而实现了函数hook和回调操作。
参考图2b,ART系统中,相对于传统的elf文件的函数,在art编译后的函数还存在一个函数头的信息,该头中存储了该函数符号表偏移(二进制代码对dalvik代码的关联,在堆栈解析、函数调试会有用)、运行时候栈空间大小(堆栈追溯用)、使用寄存器信息、gc列表信息等。因此,本发明实施例还需要将被挂钩函数的函数头信息备份至回调函数中,具体地,将被挂钩函数的函数头信息作为回调函数的函数头信息,也即,此时,函数信息还包括被挂钩函数的函数头信息,方法对象的函数头信息为被挂钩函数的函数头信息。
其中,函数符号表偏移可以包括:应用层映射到虚拟机层的函数符号表偏移(符号表相对于代码起始位置的偏移),虚拟机层映射到代码层的函数符号表偏移(符号表相对于代码起始位置的偏移)。
比如,java层映射到虚拟机层的函数符号表偏移为:
vmap_table_offset_diff=code_offset-1-vampping_table_offset;
比如,虚拟机层映射到代码层的函数序号表偏移为:
mapping_table_offset_diff=code_offset-1-mapping_table_offset。
考虑到,在执行回调函数时,函数的头地址变为回调函数的头地址,如果采用之前被挂钩函数头信息中的符号表偏移,会出现找不到函数符号表。因此,为了保证在一些情况下如堆栈解析等情况下能够找函数符号表,需要对函数符号表偏移进行修正,使得函数符号表能够被找到。
在一实施例中,在将被挂钩函数的函数信息备份至方法对象中之后,函数挂钩实现方法还可以包括:
根据被挂钩函数的函数入口地址和方法对象的函数入口地址,对方法对象的函数头信息中的函数符号表偏移进行修正。
比如,可以将函数符号表偏移设置为原始偏移值+(方法对象的函数入口地址值-被挂钩函数的函数入口地址值)。
例如,被挂钩函数的函数入口地址为0X1000,方法对象即回调函数的函数入口地址为0X3000
mapping_table_offset_diff=0X100,vmap_table_offset_diff=0X200;那么修正后的:
mapping_table_offset_diff=0X100+(0X3000-0X1000)=0X2100;
vmap_table_offset_diff=0X200+(0X3000-0X1000)=0X2200。
104、当调用被挂钩函数时,根据跳转指令跳转至执行自定义挂钩函数。
比如,通过LDR跳转指令跳转到执行自定义挂钩函数。
本发明实施例中步骤101-103的时序关系可以有多种,不受序号限制。
105、在自定义挂钩函数执行完成时,跳转至执行方法对象中的头两条指令,并根据回调指令跳转至执行被挂钩函数中的后续指令。
比如,可以在自动挂钩函数的末尾处设置方法对象的调用指令,当执行完自定义挂钩函数时可以根据该调用指令跳转至执行方法对象即回调函数的头两条。然后,在根据方法对象中的回调指令跳转到执行被挂钩函数中头两条指令的后续指令。
在一实施例中,可以根据应用层如java层上的指针信息查找对应的方法对象,然后,跳转到执行该方法对象内的头两条指令。
参考图3a,为本发明实施例提供的Hook处理后函数的调用逻辑关系图。其中,Called_func为被挂钩函数、Hook_func为自定义挂钩函数、trampoline为构建的回调函数,该回调函数为一个Artmethod对象。
图3a所示,基于inline hook方式可以将Called_func的头两条指令(即指令一和二)以及函数头信息备份至trampoline;并对函数头信息中函数符号表偏移修正。
将Called_func内的头两条指令修改为LDR跳转指令,在Hook_func的末尾处设置trampoline调用指令,在trampoline的指令一和指令二后设置LDR跳转指令。
在调用Called_func时,通过LDR跳转指令跳转执行Hook_func,然后,通过Hook_func中的trampoline调用指令跳转执行trampoline的原指令一和原指令二,在指令一和二执行完成是通过LDR跳转指令跳转到执行Called_func的原指令三,从而实现函数Hook和回调。
在一实施例中,考虑到实际应用中可能自定义挂钩函数出现异常时需要函数入口地址获取堆栈信息,此时的函数入口系统默认为被挂钩函数的入口地址,此时,sought_offset可能超出了范围,在符号表中找不到,无法获取堆栈信息。因此,为了能够保证自定义挂钩函数出现异常时能够获取堆栈信息,还可以对被挂钩函数的函数入口地址修改。
其中,ART系统中,函数的入口地址都保存在函数的调用地址属性中,因此,本发明实施例还可以在调用挂钩函数之前,还可以包括:
将被挂钩函数的调用地址属性修改为自定义函数的调用地址属性,调用地址属性保存有被挂钩函数的函数入口地址。
其中,调用地址属性存储有原函数的调用地址信息(即入口地址信息)。比如,该地址属性可以为entry_point_from_quick_compiled_code_,其是函数或者ArtMehod对象的属性,保存了code_offset(代码偏移位置)_地址和参数base之和,也即为真实执行的二进制代码的地址。
例如,参考图3b,如果hook_func崩溃了,pc在0x5300,那么这时候根于之前的分析会获取entry_point为0x1000,他们的算出来的sought_offset为0x4300这个时候在符号表中找不到,会崩溃并报出异常。
所以这里必须将called_func的entry_point_from_quick_compiled_code_做修改,将其设置为hook的entry_point_from_quick_compiled_code_。
在一实施例中,考虑各个厂商会修改ArtMethod导致获取属性偏移异常的问题,因此为了能够正常获取调用地址属性,可以基于函数位置属性相对于被挂钩函数头的地址偏移获取调用地址属性。具体地,步骤“将被挂钩函数的调用地址属性修改为被挂钩函数的调用地址属性”可以包括:
获取被挂钩函数的函数位置属性相对于被挂钩函数头的第一地址偏移;
根据第一地址偏移、以及被挂钩函数的调用地址属性相对于函数位置属性的第二偏移值,获取被挂钩函数的调用地址属性相对于被挂钩函数头的第三地址偏移;
根据第三地址偏移获取被挂钩函数的调用地址属性;
将被挂钩函数的调用地址属性修改为被挂钩函数的调用地址属性。
其中,函数位置属性用于指示函数在所属类中的位置,比如,该函数位置属性可以包括method_idx;method_idx表示函数在所属类中的第几个函数。
可以函数位置属性值(如method_idx值)获取函数位置属性相对于函数头的第一地址偏移,然后,根据第一地址偏移以及调用地址属性(如entry_point_from_quick_compiled_code_)相对于该函数位置属性的第二偏移值获取调用地址属性(如entry_point_from_quick_compiled_code_)相对于函数头的第三地址偏移,最后,通过该第三地址即可获取调用地址属性(如entry_point_from_quick_compiled_code_)。
本发明实施例中,考虑到厂商对方法对象结构进行修改,但是,一般结构内部的属性之间的相对位置关系是不会变更的。因此,其他函数属性如调用地址属性可以设计为相对于函数位置属性的偏移,从而可以正常获取调用地址属性。
在一实施例中,在回到原函数时候,当前函数入口地址变为了回调函数的入口地址,一旦有异常获取堆栈情况出现时,那么可能会导致堆栈获取失败和异常。比如,参考图3c,当前入口变为了trampoline的入口即0x3000,这时候trampoline和called_func的内存块也是分离的,一旦有异常获取堆栈时候,sought_offset为0x1100-0x3000是一个负数,从而无法获取堆栈信息。
因此,除了修改entry_point_from_quick_compiled_code_和代码块连续性外,还可以对处理堆栈信息的操作时候修改其pc参数的值,将pc参数修正为在trampoline为函数入口情况下的偏移。也即,函数挂钩实现方法还可以包括:
在处理堆栈信息时,判断寄存器参数值是否落入被挂钩函数的指令地址范围内;
若是,则根据方法对象与被挂钩函数之间的入口地址差,对寄存器参数值进行修正。
比如,将寄存器参数值设置为原始值+方法对象与被挂钩函数之间的入口地址差值。
参考图3d,例如,被挂钩函数called_func的函数入口地址为0X1000,方法对象即回调函数trampoline的函数入口地址为0X3000。
在处理堆栈信息时可以将pc修改为pc’;该pc’=pc+(0x3000-0x1000)。
在一实施例中,可以对pc值获取函数如ToDexPc这个函数做hook操作,使得在进入该函数时候跳转到执行pc修改函数,从而判断pc是否落在源函数的指令地址范围内,若是,则根据方法对象与被挂钩函数之间的入口地址差,对寄存器参数值进行修正,并返回执行pc值获取函数。
其中,PC值获取函数的hook过程可以参考上述hook的过程,比如,可以采用inlinehook,可以将PC值获取函数的头两条指令修改为用于跳转到pc修改函数的跳转指令,并在PC修改函数中设置用于跳转到pc值获取函数的回调指令;该pc修改函数用于判断pc是否落在源函数的指令地址范围内,若是,则根据方法对象与被挂钩函数之间的入口地址差,对寄存器参数值进行修正。
由上可知,本发明实施例采用在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至方法对象中,函数信息包括被挂钩函数的头两条指令;将被挂钩函数中的头两条指令修改为跳转指令,跳转指令用于指示跳转至执行自定义挂钩函数;在方法对象中设置回调指令,回调指令位于头两条指令之后,用于指示跳转执行被挂钩函数中头两条指令的后续指令;当调用被挂钩函数时,根据跳转指令跳转至执行自定义挂钩函数;在自定义挂钩函数执行完成时,跳转至执行方法对象中的头两条指令,并根据回调指令跳转至执行被挂钩函数中的后续指令。该方案可以非root模式下不用替换libart.so文件即可实现函数挂钩操作以及函数回调操作,其无需对终端进行root,因此,可以提高终端系统的安全性。
此外,本发明实施例还对符号表偏移、函数入口地址以及pc参数值进行修正,保证了在函数调用过程中符号表正常获取、以及堆栈信息的正常获取,从而,提升了函数Hook的稳定性。
在一实施例,根据上述所描述的方法,将作进一步详细说明。
如图4所示,一种函数挂钩实现方法,具体流程如下:
201、在ART系统创建一个类,并在类中创建两个空的测试ArtMethod对象。
考虑到不同厂商可能对ArtMethod对象的结构进行修改,导致不同系统中方法对象的结构大小不相同,因此,为了能够获取当前系统下的ArtMethod对象的结构大小,可以创建两个空的ArtMethod对象来获取方法对象结构大小。
由于在ART系统中,初始化一个类时会给类中每个ArtMethod对象分配空间,此时,可以通过两个测试ArtMethod对象分配的地址空间来确定当前系统中ArtMethod对象的结构大小。
在一实施例中,还可以先获取当前终端安卓系统的版本信息,对于没有ART模式的安卓系统不做Hook。
202、根据两个测试ArtMethod对象之间的地址差,并根据地址差在ART系统中创建空的回调方法对象。
其中,测试方法对象之间的地址差即为方法对象的结构大小,比如,参考图1b为ArtMethod对象的空间结构,从图1b中可以看出ArtMethod是紧密排列的,所以一个ArtMethod的大小就是相邻两个ArtMethod地址差,这样就可以得到artsize。此时ArtMethod的大小即为被Hook函数的结构大小。然后,基于ArtMethod的大小创建一个用于函数回调的方法对象。在一实施例中,该空的方法对象的结构大小为地址差。
在安卓系统中一般包括本地层(即Native层)和应用层(如java层),本发明实施例可以根据地址差在应用层(如java层)创建空的方法对象。
由于不同版本的系统java层和和Native层之间的ArtMethod结构对应关系不同,以安卓5.0和6.0系统为例,参考图1c和图1d,可以看出对于5.0和6.0系统存在java层ArtMethod结构和Native层的ArtMethod结构对应;而6.0系统却没有,在相关的AbstractMethod结构中,6.0系统只是存储了native层ArtMethod对象的地址。其中,在Java层中AbstractMethod下面的ArtMethod为long类型,是native层中ArtMethod的指针。因此,如果根据地址差值在Native层创建备份信息的回调方法对象,还需要在Java层保存该方法对象的指针。
203、将PC值获取函数Hook到自定义的PC值修改函数。
比如,可以将ToDexPc hook到自定义的my_ToDexPc中,在自定义函数my_ToDexP里面对已hook函数的pc参数进行修正。
具体地,pc修改函数用于判断pc是否落在源函数的指令地址范围内,若是,则根据方法对象与被挂钩函数之间的入口地址差,对寄存器参数值进行修正,并返回执行pc值获取函数。
比如,可以将寄存器参数值设置为原始值+方法对象与被挂钩函数之间的入口地址差值。
在一实施例中,如果需要对ToDexPc进行hook操作那么在执行hook之前还需要获取到libart.so的文件路径,比如,可以通过当前进程的内存映像来获取。
204、获取被挂钩ArtMethod对象以及自定义挂钩ArtMethod对象。
在ART系统中,被挂钩方法对象即为被挂钩函数对应的方法对象,自定义挂钩对象为自定义挂钩函数对应的方法对象。
205、当被挂钩ArtMethod对象没有被挂钩时,将被挂钩ArtMethod对象以及自定义挂钩ArtMethod对象的加载类设置为一致。
本实施例对于已经Hook的函数不做任何处理,对没有Hook的函数做Hook处理。
206、将回调ArtMethod对象的结构设置与被挂钩ArtMethod对象的结构一致。
其中,回调ArtMethod对象的头信息与被挂钩ArtMethod对象的头信息相同,并且,回调ArtMethod对象的头两条指令与被挂钩ArtMethod对象头两条指令相同。
比如,构造一个回调函数(6.0系统需要在native层构建ArtMethod对象结构),然后将原函数的结构备份到回调函数中。
比如,可以将被挂钩ArtMethod对象中的头两条指令、函数头信息拷贝到被挂钩ArtMethod对象中。
207、通过inline hook对被挂钩ArtMethod对象进行hook操作。
具体地,将被挂钩函数中的头两条指令修改为跳转指令,跳转指令用于指示跳转至执行自定义挂钩函数;在方法对象中设置回调指令,回调指令位于头两条指令之后,用于指示跳转执行被挂钩函数中头两条指令的后续指令。
Inline hook通过三级跳转实现了函数的hook以及回调。inline hook的原理介绍如下:
Inline hook中构造出一块内存空间,将func函数(即被挂钩函数)的头两条指令拷贝到该空间中,并在该两条指令后,设置回调指令。Inline hook采用LDR PC,[PC,?]指令实现跳转,即该回调指令为LDR指令。具体地,通过修改pc(寄存器),使得pc为pc-4位置的值,就可以(在pc-4的位置记录原函数第三条指令的地址)跳转到func函数。这就完成回调原函数的trampoline的构建。
LDR跳转指令的格式如下:
LDR PC,[PC,#-4]
addr。
LDR PC,[PC,#-4]指的从PC-4指向的指令地址中读取指令代码到PC(寄存器,或者程序计数器)中;addr为要跳转的地址。本实施例中由于需要跳转到自定义挂钩函数,此时addr可以为自定义挂钩函数的函数入口地址。
将func函数的头两条指令修改为跳转到自定义函数my_func(即自定义挂钩函数)的跳转指令,修改方式也是利用对pc的修改处理,该跳转指令可以为LDR指令。
在my_fuc函数的末尾通过跳转到构建的内存空间位置就可以实现回调原函数的操作。
208、对回调ArtMethod对象的头信息中函数符号表偏移进行修正。
考虑到,在执行回调函数时,函数的头地址变为回调函数的头地址,如果采用之前被挂钩函数头信息中的符号表偏移,会出现找不到函数符号表。因此,为了保证在一些情况下如堆栈解析等情况下能够找函数符号表,需要对函数符号表偏移进行修正,使得函数符号表能够被找到。
在一实施例中,在将被挂钩函数的函数信息备份至方法对象中之后,函数挂钩实现方法还可以包括:
根据被挂钩函数的函数入口地址和方法对象的函数入口地址,对方法对象的函数头信息中的函数符号表偏移进行修正。
比如,可以将函数符号表偏移设置为原始偏移值+(方法对象的函数入口地址值-被挂钩函数的函数入口地址值)。
例如,被挂钩ArtMethod对象的函数入口地址为0X1000,方法对象即回调函数的函数入口地址为0X3000
mapping_table_offset_diff=0X100,vmap_table_offset_diff=0X200;那么修正后的:
mapping_table_offset_diff=0X100+(0X3000-0X1000)=0X2100;
vmap_table_offset_diff=0X200+(0X3000-0X1000)=0X2200。
209、将被挂钩ArtMethod对象的调用地址属性修改为自定义挂钩ArtMethod对象的调用地址属性。
其中,调用地址属性存储有原函数的调用地址信息(即入口地址信息)。比如,该地址属性可以为entry_point_from_quick_compiled_code_,其是函数或者ArtMehod对象的属性,保存了code_offset(代码偏移位置)_地址和参数base之和,也即为真实执行的二进制代码的地址。
例如,参考图3b,如果hook_func崩溃了,pc在0x5300,那么这时候根于之前的分析会获取entry_point为0x1000,他们的算出来的sought_offset为0x4300这个时候在符号表中找不到,会崩溃并报出异常。
所以这里必须将called_func的entry_point_from_quick_compiled_code_做修改,将其设置为hook的entry_point_from_quick_compiled_code_。
210、保存被挂钩ArtMethod对象、自定义挂钩ArtMethod对象以及回调ArtMethod对象。
通过上述的函数Hook处理,在调用被挂钩函数时可以跳转到执行自定义挂钩函数,在自定义挂钩函数执行完成时跳转到回调函数执行被挂钩函数中被修改的指令,然后,跳转到被挂钩函数执行后续指令,从而实现函数的Hook和回调。比如,参考图3a至图3d。
由上可知,本发明实施例可以采用inline hook实现函数的hook以及回调在。该方案可以非root模式下不用替换libart.so文件即可实现函数挂钩操作以及函数回调操作,其无需对终端进行root,因此,可以提高终端系统的安全性。
此外,本发明实施例还对符号表偏移、函数入口地址以及pc参数值进行修正,保证了在函数调用过程中符号表正常获取、以及堆栈信息的正常获取,从而,提升了函数Hook的稳定性。
为了便于更好的实施本发明实施例提供的函数挂钩实现方法,在一实施例中还提供了一种函数挂钩实现装置。其中名词的含义与上述函数挂钩实现方法中相同,具体实现细节可以参考方法实施例中的说明。
在一实施例中,还提供了一种函数挂钩实现装置,如图5a所示,该函数挂钩实现装置可以包括:备份单元301、修改单元302、回调设置单元303、函数调用单元304以及函数回调单元305。其中:
备份单元301,用于在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;
修改单元302,用于将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
回调设置单元303,用于在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
函数调用单元304,用于当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
函数回调单元305,用于在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
在一实施例中,所述函数信息还包括所述被挂钩函数的函数头信息,所述方法对象的函数头信息为所述被挂钩函数的函数头信息;参考图5b,函数挂钩实现装置还可以包括:偏移修正单元306;
所述偏移修正单元306,用于在所述备份单元301将被挂钩函数的函数信息备份至所述方法对象中之后;根据所述被挂钩函数的函数入口地址和所述方法对象的函数入口地址,对所述方法对象的函数头信息中的函数符号表偏移进行修正。
在一实施例中,参考图5c,函数挂钩实现装置还可以包括:地址属性修改单元307;
所述地址属性修改单元307,用于在所述函数调用单元304调用所述被挂钩函数之前,将所述被挂钩函数的调用地址属性修改为所述自定义挂钩函数的调用地址属性,所述被挂钩函数的调用地址属性保存有所述被挂钩函数的函数入口地址。
在一实施例中,参考图5d,所述地址属性修改单元307,包括:属性获取子单元3071和属性修改子单元3072;
属性获取子单元3071,用于:
获取所述被挂钩函数的函数位置属性相对于所述被挂钩函数头的第一地址偏移;
根据所述第一地址偏移、以及所述被挂钩函数的调用地址属性相对于所述函数位置属性的第二偏移值,获取所述被挂钩函数的调用地址属性相对于所述被挂钩函数头的第三地址偏移;
根据所述第三地址偏移获取所述被挂钩函数的调用地址属性;
所述属性修改子单元3072,用于将所述被挂钩函数的调用地址属性修改为所述被挂钩函数的调用地址属性。
在一实施例中,参考图5e,函数挂钩实现装置还可以包括:参数修改单元308;
所述参数修改单元308,用于在处理堆栈信息时,判断寄存器参数值是否落入所述被挂钩函数的指令地址范围内;若是,则根据所述方法对象与被挂钩函数之间的入口地址差,对所述寄存器参数值进行修正。
在一实施例中,备份单元301可以用于:
在ART系统创建一个类,并在所述类中创建两个空的测试方法对象;
获取所述测试方法对象之间的地址差;
根据所述地址差在所述ART系统中创建空的方法对象。
在一实施例中,备份单元301可以用于:
在ART系统的本地层创建空的方法对象;
将所述被挂钩函数的函数信息备份至本地层的所述方法对象;
将所述方法对象对应的指针信息保存在所述应用层。
具体实施时,以上各个单元可以作为独立的实体来实现,也可以进行任意组合,作为同一或若干个实体来实现,以上各个单元的具体实施可参见前面的方法实施例,在此不再赘述。
该函数挂钩实现装置具体可以集成在终端等设备中,该终端具体可以为手机或平板电脑等设备。
由上可知,本发明实施例授权管理装置可以采用备份单元301在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;由修改单元302将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;由回调设置单元303在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;由函数调用单元304当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;由函数回调单元305在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。该方案可以非root模式下不用替换libart.so文件即可实现函数挂钩操作以及函数回调操作,其无需对终端进行root,因此,可以提高终端系统的安全性。
在一实施例中,为了更好地实施以上方法,本发明实施例还提供了一种终端,如手机、笔记本电脑等。
本发明实施例提供了一种终端400,如图4所示,该终端可以包括射频(RF,RadioFrequency)电路401、包括有一个或一个以上计算机可读存储介质的存储器402、输入单元403、显示单元404、传感器405、音频电路406、无线保真(WiFi,Wireless Fidelity)模块407、包括有一个或者一个以上处理核心的处理器408、以及电源409等部件。本领域技术人员可以理解,图4中示出的终端结构并不构成对终端的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件布置。其中:
RF电路401可用于收发信息或通话过程中,信号的接收和发送,特别地,将基站的下行信息接收后,交由一个或者一个以上处理器408处理;另外,将涉及上行的数据发送给基站。通常,RF电路401包括但不限于天线、至少一个放大器、调谐器、一个或多个振荡器、用户身份模块(SIM,Subscriber Identity Module)卡、收发信机、耦合器、低噪声放大器(LNA,Low Noise Amplifier)、双工器等。此外,RF电路401还可以通过无线通信与网络和其他设备通信。所述无线通信可以使用任一通信标准或协议,包括但不限于全球移动通讯系统(GSM,Global System of Mobile communication)、通用分组无线服务(GPRS,GeneralPacket Radio Service)、码分多址(CDMA,Code Division Multiple Access)、宽带码分多址(WCDMA,Wideband Code Division Multiple Access)、长期演进(LTE,Long TermEvolution)、电子邮件、短消息服务(SMS,Short Messaging Service)等。
存储器402可用于存储软件程序以及模块,处理器408通过运行存储在存储器402的软件程序以及模块,从而执行各种功能应用以及数据处理。存储器402可主要包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序(比如声音播放功能、图像播放功能等)等;存储数据区可存储根据终端的使用所创建的数据(比如音频数据、电话本等)等。此外,存储器402可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他易失性固态存储器件。相应地,存储器402还可以包括存储器控制器,以提供处理器408和输入单元403对存储器402的访问。
输入单元403可用于接收输入的数字或字符信息,以及产生与用户设置以及功能控制有关的键盘、鼠标、操作杆、光学或者轨迹球信号输入。具体地,在一个具体的实施例中,输入单元403可包括触敏表面以及其他输入设备。触敏表面,也称为触摸显示屏或者触控板,可收集用户在其上或附近的触摸操作(比如用户使用手指、触笔等任何适合的物体或附件在触敏表面上或在触敏表面附近的操作),并根据预先设定的程式驱动相应的连接装置。可选的,触敏表面可包括触摸检测装置和触摸控制器两个部分。其中,触摸检测装置检测用户的触摸方位,并检测触摸操作带来的信号,将信号传送给触摸控制器;触摸控制器从触摸检测装置上接收触摸信息,并将它转换成触点坐标,再送给处理器408,并能接收处理器408发来的命令并加以执行。此外,可以采用电阻式、电容式、红外线以及表面声波等多种类型实现触敏表面。除了触敏表面,输入单元403还可以包括其他输入设备。具体地,其他输入设备可以包括但不限于物理键盘、功能键(比如音量控制按键、开关按键等)、轨迹球、鼠标、操作杆等中的一种或多种。
显示单元404可用于显示由用户输入的信息或提供给用户的信息以及终端的各种图形用户接口,这些图形用户接口可以由图形、文本、图标、视频和其任意组合来构成。显示单元404可包括显示面板,可选的,可以采用液晶显示器(LCD,Liquid Crystal Display)、有机发光二极管(OLED,Organic Light-Emitting Diode)等形式来配置显示面板。进一步的,触敏表面可覆盖显示面板,当触敏表面检测到在其上或附近的触摸操作后,传送给处理器408以确定触摸事件的类型,随后处理器408根据触摸事件的类型在显示面板上提供相应的视觉输出。虽然在图4中,触敏表面与显示面板是作为两个独立的部件来实现输入和输入功能,但是在某些实施例中,可以将触敏表面与显示面板集成而实现输入和输出功能。
终端还可包括至少一种传感器405,比如光传感器、运动传感器以及其他传感器。具体地,光传感器可包括环境光传感器及接近传感器,其中,环境光传感器可根据环境光线的明暗来调节显示面板的亮度,接近传感器可在终端移动到耳边时,关闭显示面板和/或背光。作为运动传感器的一种,重力加速度传感器可检测各个方向上(一般为三轴)加速度的大小,静止时可检测出重力的大小及方向,可用于识别手机姿态的应用(比如横竖屏切换、相关游戏、磁力计姿态校准)、振动识别相关功能(比如计步器、敲击)等;至于终端还可配置的陀螺仪、气压计、湿度计、温度计、红外线传感器等其他传感器,在此不再赘述。
音频电路406、扬声器,传声器可提供用户与终端之间的音频接口。音频电路406可将接收到的音频数据转换后的电信号,传输到扬声器,由扬声器转换为声音信号输出;另一方面,传声器将收集的声音信号转换为电信号,由音频电路406接收后转换为音频数据,再将音频数据输出处理器408处理后,经RF电路401以发送给比如另一终端,或者将音频数据输出至存储器402以便进一步处理。音频电路406还可能包括耳塞插孔,以提供外设耳机与终端的通信。
WiFi属于短距离无线传输技术,终端通过WiFi模块407可以帮助用户收发电子邮件、浏览网页和访问流式媒体等,它为用户提供了无线的宽带互联网访问。虽然图6示出了WiFi模块407,但是可以理解的是,其并不属于终端的必须构成,完全可以根据需要在不改变发明的本质的范围内而省略。
处理器408是终端的控制中心,利用各种接口和线路连接整个手机的各个部分,通过运行或执行存储在存储器402内的软件程序和/或模块,以及调用存储在存储器402内的数据,执行终端的各种功能和处理数据,从而对手机进行整体监控。可选的,处理器408可包括一个或多个处理核心;优选的,处理器408可集成应用处理器和调制解调处理器,其中,应用处理器主要处理操作系统、用户界面和应用程序等,调制解调处理器主要处理无线通信。可以理解的是,上述调制解调处理器也可以不集成到处理器408中。
终端还包括给各个部件供电的电源409(比如电池),优选的,电源可以通过电源管理系统与处理器408逻辑相连,从而通过电源管理系统实现管理充电、放电、以及功耗管理等功能。电源409还可以包括一个或一个以上的直流或交流电源、再充电系统、电源故障检测电路、电源转换器或者逆变器、电源状态指示器等任意组件。
尽管未示出,终端还可以包括摄像头、蓝牙模块等,在此不再赘述。具体在本实施例中,终端中的处理器408会按照如下的指令,将一个或一个以上的应用程序的进程对应的可执行文件加载到存储器402中,并由处理器408来运行存储在存储器402中的应用程序,从而实现各种功能:
在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;
将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
在一实施例中,所述函数信息还包括所述被挂钩函数的函数头信息,所述方法对象的函数头信息为所述被挂钩函数的函数头信息;处理器401还可以具体执行以下步骤:
在将被挂钩函数的函数信息备份至所述方法对象中之后,根据所述被挂钩函数的函数入口地址和所述方法对象的函数入口地址,对所述方法对象的函数头信息中的函数符号表偏移进行修正。
在一实施例中,在调用所述被挂钩函数之前,处理器401还可以具体执行以下步骤:
将所述被挂钩函数的调用地址属性修改为所述自定义挂钩函数的调用地址属性,所述被挂钩函数的调用地址属性保存有所述被挂钩函数的函数入口地址。
在一实施例中,在将所述被挂钩函数的调用地址属性修改为所述被挂钩函数的调用地址属性时,处理器401可以具体执行以下步骤:
获取所述被挂钩函数的函数位置属性相对于所述被挂钩函数头的第一地址偏移;
根据所述第一地址偏移、以及所述被挂钩函数的调用地址属性相对于所述函数位置属性的第二偏移值,获取所述被挂钩函数的调用地址属性相对于所述被挂钩函数头的第三地址偏移;
根据所述第三地址偏移获取所述被挂钩函数的调用地址属性;
将所述被挂钩函数的调用地址属性修改为所述被挂钩函数的调用地址属性。
在一实施例中,在ART系统中创建空的方法对象时,处理器401可以具体执行以下步骤:
在ART系统创建一个类,并在所述类中创建两个空的测试方法对象;
获取所述测试方法对象之间的地址差;
根据所述地址差在所述ART系统中创建空的方法对象。
在一实施例中,处理器401还可以具体执行以下步骤:
在处理堆栈信息时,判断寄存器参数值是否落入所述被挂钩函数的指令地址范围内;
若是,则根据所述方法对象与被挂钩函数之间的入口地址差,对所述寄存器参数值进行修正。
在一实施例中,在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中时,处理器401可以具体执行以下步骤:
在ART系统的本地层创建空的方法对象;
将所述被挂钩函数的函数信息备份至本地层的所述方法对象;
将所述方法对象对应的指针信息保存在所述应用层。
由上可知,本发明实施例终端可以在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令;将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。该方案可以非root模式下不用替换libart.so文件即可实现函数挂钩操作以及函数回调操作,其无需对终端进行root,因此,可以提高终端系统的安全性。
本领域普通技术人员可以理解上述实施例的各种方法中的全部或部分步骤是可以通过程序来指令相关的硬件来完成,该程序可以存储于一计算机可读存储介质中,存储介质可以包括:只读存储器(ROM,Read Only Memory)、随机存取记忆体(RAM,RandomAccess Memory)、磁盘或光盘等。
以上对本发明实施例所提供的一种函数挂钩实现方法、装置和存储介质进行了详细介绍,本文中应用了具体个例对本发明的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本发明的方法及其核心思想;同时,对于本领域的技术人员,依据本发明的思想,在具体实施方式及应用范围上均会有改变之处,综上所述,本说明书内容不应理解为对本发明的限制。
Claims (9)
1.一种函数挂钩实现方法,其特征在于,所述方法包括:
在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令,所述ART系统为安卓应用运行系统;
将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
获取所述被挂钩函数的函数位置属性相对于所述被挂钩函数头的第一地址偏移;
根据所述第一地址偏移、以及所述被挂钩函数的调用地址属性相对于所述函数位置属性的第二偏移值,获取所述被挂钩函数的调用地址属性相对于所述被挂钩函数头的第三地址偏移;
根据所述第三地址偏移获取所述被挂钩函数的调用地址属性;
将所述被挂钩函数的调用地址属性修改为所述自定义挂钩函数的调用地址属性,所述被挂钩函数的调用地址属性保存有所述被挂钩函数的函数入口地址;
当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
2.如权利要求1所述的函数挂钩实现方法,其特征在于,所述函数信息还包括所述被挂钩函数的函数头信息,所述方法对象的函数头信息为所述被挂钩函数的函数头信息;
在将被挂钩函数的函数信息备份至所述方法对象中之后,所述函数挂钩实现方法还包括:
根据所述被挂钩函数的函数入口地址和所述方法对象的函数入口地址,对所述方法对象的函数头信息中的函数符号表偏移进行修正。
3.如权利要求1所述的函数挂钩实现方法,其特征在于,在ART系统中创建空的方法对象,包括:
在ART系统创建一个类,并在所述类中创建两个空的测试方法对象;
获取所述测试方法对象之间的地址差;
根据所述地址差在所述ART系统中创建空的方法对象。
4.如权利要求1所述的函数挂钩实现方法,其特征在于,所述函数挂钩实现方法还包括:
在处理堆栈信息时,判断寄存器参数值是否落入所述被挂钩函数的指令地址范围内;
若是,则根据所述方法对象与被挂钩函数之间的入口地址差,对所述寄存器参数值进行修正。
5.如权利要求1所述的函数挂钩实现方法,其特征在于,所述ART系统包括本地层和应用层;所述在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,包括:
在ART系统的本地层创建空的方法对象;
将所述被挂钩函数的函数信息备份至本地层的所述方法对象;
将所述方法对象对应的指针信息保存在所述应用层。
6.一种函数挂钩实现装置,其特征在于,包括:
备份单元,用于在ART系统中创建空的方法对象,并将被挂钩函数的函数信息备份至所述方法对象中,所述函数信息包括所述被挂钩函数的头两条指令,所述ART系统为安卓应用运行系统;
修改单元,用于将所述被挂钩函数中的头两条指令修改为跳转指令,所述跳转指令用于指示跳转至执行自定义挂钩函数;
回调设置单元,用于在所述方法对象中设置回调指令,所述回调指令位于所述头两条指令之后,用于指示跳转执行所述被挂钩函数中所述头两条指令的后续指令;
地址属性修改单元,用于获取所述被挂钩函数的函数位置属性相对于所述被挂钩函数头的第一地址偏移;根据所述第一地址偏移、以及所述被挂钩函数的调用地址属性相对于所述函数位置属性的第二偏移值,获取所述被挂钩函数的调用地址属性相对于所述被挂钩函数头的第三地址偏移;根据所述第三地址偏移获取所述被挂钩函数的调用地址属性;将所述被挂钩函数的调用地址属性修改为所述自定义挂钩函数的调用地址属性,所述被挂钩函数的调用地址属性保存有所述被挂钩函数的函数入口地址;
函数调用单元,用于当调用所述被挂钩函数时,根据所述跳转指令跳转至执行所述自定义挂钩函数;
函数回调单元,用于在所述自定义挂钩函数执行完成时,跳转至执行所述方法对象中的所述头两条指令,并根据所述回调指令跳转至执行所述被挂钩函数中的所述后续指令。
7.如权利要求6所述的函数挂钩实现装置,其特征在于,所述函数信息还包括所述被挂钩函数的函数头信息,所述方法对象的函数头信息为所述被挂钩函数的函数头信息;
所述函数挂钩实现装置还包括:偏移修正单元;
所述偏移修正单元,用于在所述备份单元将被挂钩函数的函数信息备份至所述方法对象中之后;根据所述被挂钩函数的函数入口地址和所述方法对象的函数入口地址,对所述方法对象的函数头信息中的函数符号表偏移进行修正。
8.如权利要求6所述的函数挂钩实现装置,其特征在于,还包括:参数修改单元;
所述参数修改单元,用于在处理堆栈信息时,判断寄存器参数值是否落入所述被挂钩函数的指令地址范围内;若是,则根据所述方法对象与被挂钩函数之间的入口地址差,对所述寄存器参数值进行修正。
9.一种存储介质,其特征在于,所述存储介质存储有指令,所述指令被处理器执行时实现如权利要求1-5任一项所述函数挂钩实现方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201810041219.4A CN110046497B (zh) | 2018-01-16 | 2018-01-16 | 一种函数挂钩实现方法、装置和存储介质 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201810041219.4A CN110046497B (zh) | 2018-01-16 | 2018-01-16 | 一种函数挂钩实现方法、装置和存储介质 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN110046497A CN110046497A (zh) | 2019-07-23 |
CN110046497B true CN110046497B (zh) | 2023-06-20 |
Family
ID=67273459
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201810041219.4A Active CN110046497B (zh) | 2018-01-16 | 2018-01-16 | 一种函数挂钩实现方法、装置和存储介质 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN110046497B (zh) |
Families Citing this family (8)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN111352673B (zh) * | 2020-01-02 | 2023-10-03 | 上海域幂信息科技有限公司 | 一种新型Hook方法、存储介质及电子装置 |
CN111914251A (zh) * | 2020-07-03 | 2020-11-10 | 上海理想信息产业(集团)有限公司 | 一种基于混合控制技术的智能终端安全保护方法及系统 |
CN112148388A (zh) * | 2020-10-22 | 2020-12-29 | 北京嘀嘀无限科技发展有限公司 | 一种计算机程序的挂钩方法和系统 |
CN113378123A (zh) * | 2021-06-10 | 2021-09-10 | 福建省天奕网络科技有限公司 | 一种安卓端抽取壳的实现方法及系统 |
CN113590419A (zh) * | 2021-07-23 | 2021-11-02 | 北京沃东天骏信息技术有限公司 | 一种函数管理方法和装置 |
CN114168489B (zh) * | 2022-02-08 | 2022-12-30 | 统信软件技术有限公司 | 一种函数信息获取方法、计算设备及存储介质 |
CN118094536A (zh) * | 2024-01-08 | 2024-05-28 | 中金金融认证中心有限公司 | 恶意软件检测方法及装置 |
CN118152044A (zh) * | 2024-05-10 | 2024-06-07 | 海马云(天津)信息技术有限公司 | 非根权限挂钩Java方法的方法与装置 |
Citations (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102109975A (zh) * | 2009-12-24 | 2011-06-29 | 华为技术有限公司 | 确定函数调用关系的方法、装置及系统 |
Family Cites Families (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN103530118B (zh) * | 2013-09-30 | 2017-01-11 | 广州华多网络科技有限公司 | 将自定义dll注入目标进程的方法及装置 |
CN105656860A (zh) * | 2014-11-20 | 2016-06-08 | 中兴通讯股份有限公司 | Android系统的安全管控方法、装置及其系统 |
CN104598809B (zh) * | 2015-02-13 | 2017-04-19 | 北京奇虎科技有限公司 | 程序的监控方法及其防御方法以及相关装置 |
CN106547580B (zh) * | 2015-09-22 | 2020-08-28 | 腾讯科技(深圳)有限公司 | 挂钩函数的方法、装置、移动终端及存储介质 |
CN106919458B (zh) * | 2015-12-25 | 2020-09-01 | 腾讯科技(深圳)有限公司 | Hook目标内核函数的方法及装置 |
CN106502703B (zh) * | 2016-10-27 | 2020-07-03 | 腾讯科技(深圳)有限公司 | 一种函数调用方法和装置 |
CN107358103A (zh) * | 2017-07-20 | 2017-11-17 | 国网上海市电力公司 | 基于敏感函数调用插桩的安卓敏感行为监控方法和系统 |
-
2018
- 2018-01-16 CN CN201810041219.4A patent/CN110046497B/zh active Active
Patent Citations (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102109975A (zh) * | 2009-12-24 | 2011-06-29 | 华为技术有限公司 | 确定函数调用关系的方法、装置及系统 |
Also Published As
Publication number | Publication date |
---|---|
CN110046497A (zh) | 2019-07-23 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN110046497B (zh) | 一种函数挂钩实现方法、装置和存储介质 | |
US10186244B2 (en) | Sound effect processing method and device, plug-in unit manager and sound effect plug-in unit | |
CN106502703B (zh) | 一种函数调用方法和装置 | |
US10628271B2 (en) | Method for information processing and related device | |
CN107273160A (zh) | 一种版本升级的方法及装置 | |
CN112055424B (zh) | 电子装置以及切换电子装置的方法 | |
CN106775827B (zh) | 一种应用程序更新方法及装置、计算机设备 | |
CN108595218B (zh) | 一种加载系统动态库的方法和装置 | |
CN110058850B (zh) | 一种应用的开发方法、装置以及存储介质 | |
WO2015078342A1 (en) | Method for acquiring memory information, and terminal | |
CN103455343A (zh) | 一种更新应用程序的方法和装置 | |
WO2014173211A1 (en) | Code coverage testing method, device and system | |
WO2014161353A1 (en) | Method for starting process of application and computer system | |
CN106919458B (zh) | Hook目标内核函数的方法及装置 | |
CN110968508B (zh) | 一种小程序的加载时间确定方法、装置、终端及存储介质 | |
US20140304720A1 (en) | Method for starting process of application and computer system | |
CN110837343B (zh) | 处理快照的方法、装置及终端 | |
CN111966491B (zh) | 统计占用内存的方法及终端设备 | |
US20220255639A1 (en) | Radio frequency parameter processing method and device, and mobile terminal and storage medium | |
EP2869604A1 (en) | Method, apparatus and device for processing a mobile terminal resource | |
CN108984374B (zh) | 一种数据库性能的测试方法和系统 | |
CN106933636B (zh) | 启动插件服务的方法、装置和终端设备 | |
US9928134B2 (en) | Method and apparatus for repairing dynamic link library file | |
CN105278942B (zh) | 组件管理方法及装置 | |
CN109145598B (zh) | 脚本文件的病毒检测方法、装置、终端及存储介质 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |