android免root hook框架legend

1、前言

Android中hook框架已经很是多了,最优秀的当属Xposed和Substrate了,这两个框架我在以前的文章都详细介绍过了,不了解的同窗,能够转战这里:http://www.wjdiankong.cn;可是这两个框架用于破解逆向是很是有用的,惋惜他们最大的局限性就是须要root权限,这个几乎现阶段可能阻碍了不少产品的商业化,毕竟国内人的安全意识愈来愈高了。因此这里就须要借助一个免root的hook框架了。而对于免root的框架最大的好处就在于无需root权限,可是弊端就是只能hook自身,对于系统其它app无能无力,就有人好奇了,只能hook本身有个卵用,的确是没什么用,可是也并不是一点用都没有。android

 

2、免root的hook功能用途

关于Android中的Hook机制,我在以前已经说得很是详细了,大体就两个方式:git

第一个方式:root权限,直接hook系统,能够干掉全部app。github

第二种方式:免root权限,可是只能hook自身。web

对于免root权限只能hook自身,并不是一点用都没有,好比我以前介绍到的自动破解签名校验工具kstools,就是借助这个原理实现,不了解原理的同窗能够看这里:Android中自动破解签名校验工具kstools,咱们在破解逆向app的时候,须要反编译,二次打包,那么这时候其实咱们想针对于这个app作点手脚,就能够借助这个技术,好比如今想改一个app,使得他获取系统的imei值是随机的,有这种需求的,有的游戏有的功能会用设备的imei值作惟一处理,随机imei值的话就能够跳过这个功能了。那么这时候咱们能够反编译这游戏,在游戏入口处加上hook代码,即hook游戏自身的imei值便可,这就是需求,只须要hook这一款游戏便可。这样无需在用xposed来编写外挂了。游戏二次打包便可使用了。api

 

3、以往hook框架原理分析

那么其实免root进行hook功能在以前我已经介绍过了一款阿里的开源框架Dexposed了,不过这个框架已经废弃了,取而代之的是AndFix,原理很简单在native层把Java层的方法强制改为native类型,而后在将方法的native标志指向自定义的native函数便可。这样原来的方法就会走到自定义的native函数中,这个框架是很是优秀的AOP框架,惋惜兼容性问题不能继续维护了。取而代之的是AndFix,关于它的原理就更简单了,他没有了AOP功能,直接将原始方法和自定义的新方法信息进行对换,这样原来方法执行的逻辑就是新的方法了。这个框架主要用于热修复,因此不必须要AOP功能了。而今天介绍的这款框架原理也是相似,只不过以为比较好的是,他把大部分的功能都放到了Java层,这样的兼容性就很是好了,并且自身的兼容也很优秀。缓存

 

4、Legend框架原理分析

下面就来介绍一下他的原理,代码量不是不少,框架下载地址能够去github上:https://github.com/asLody/legend,下载下来直接运行就ok了,咱们继续来分析它的代码吧:安全

进入这个方法查看:数据结构

到这里咱们会发现,他是编译传入进来的class类,而后编译他全部用到了Hook注解的方法,获取其须要hook的方法信息,具体样式为:类名::方法名@参数1#参数2#...架构

而后解析完了注解获取方法签名信息以后,开始调用hookMethod进行hook操做:app

这里看到,每一个hook方法必须是static类型的,而后会区分是art仍是dalvik的,分别处理,这里直接分析dalvik方法,后面的代码是有一个缓存池,用于缓存每次替换完以后的原始方法信息,为了后面会调用原始方法功能。下面继续来看dalvik方法的hook代码:

这里首先会获取原始方法和hook新方法对应的dalivk的数据结构信息,这个就是框架的核心点了,关于dalivk对应的方法结构体信息大体以下:

 

  • accessFlags: 各个不一样标志位表示此方法的多个属性,其中标志位0x00000100代表此方法是native的
  • registersSize: 该方法总共用到的寄存器个数,包含输入参数所用到的寄存器,还有方法内部另外使用到的寄存器,在调用方法时会为其申请栈内存
  • outsSize: 该方法调用其余方法时使用到的寄存器个数,注意:只有此方法为非native方法时,此值才有效.
  • insSize: 该方法输入参数用到的寄存器个数(registersSize包含此值)
  • insns: 若方法类型为1,这里指向实际的字节码首地址;若方法类型为2,这里指向实际的JNI函数首地址;若方法类型为3,这里为null
  • jniArgInfo: 当方法类型为2时有效,记录了一些预先计算好的信息(具体信息格式与实际CPU架构有关,但老是包含返回值类型),从而不须要在调用的时候再经过方法的参数和返回值实时计算了,提升了JNI调用的速度。若是第一位为1(即0x80000000),则Dalvik虚拟机会忽略后面的全部信息,强制在调用时实时计算
  • nativeFunc: 若方法类型为1,此值无效;若方法类型为2,这里指向dvmCallJNIMethod;若方法类型为3,这里指向实际的处理函数(DalvikBridgeFunc类型)
还记得最后一个参数吗?当初介绍Dexposed框架就是利用这个参数进行操做的,他对应的就是一个方法的native函数,对于AndFix框架,其实也就是直接替换方法的这些结构体信息便可。
 
替换新旧方法的结构体信息,作到移花积木的功能:
而后就把替换以后额数据写入到内存中,而这里咱们要注意的是,操做内存,Java实在不靠谱的,因此这里须要将工做移动到native层作,操做内存数据,指针是万能的,因此就跑到C++中干了:
这里看到,其实不是写入内存,而是对内存数据的一个替换,直接利用指针方便快捷。
 

5、案例用法

那么到这里,其实咱们就大体分析完了这个框架的功能,关于art类型的能够自行分析代码,原理都是同样的,这里的hook机制很是简洁,直接构造出新旧方法对应的虚拟机数据结构,而后替换信息,会写到内存中便可。和阿里的AndFix框架原理几乎同样。分析完了原理以后,接下来才是正事,演示一个案例,这里主要介绍两个案例,首先来看看如何hook系统的imei值:
这里须要用到注解,形式如:类名::方法名,由于这里没有参数信息,因此忽略,而后在定义一个新的hook方法,每一个hook方法第一个参数必须是hook方法所属的类类型,这里直接返回imei值为110,而后在获取imei值看看效果:
看到了,hook成功了,操做就是这么简单。
 
下面再来看一个例子,就是hook应用中全部的webview加载的url值,这个也是此次我要分析这个框架的缘由,由于项目须要,想拦截应用全部webview加载的url值:
这里看到了,咱们通常用WebView加载url都会走shouldOverrideUrlLoading方法,因此直接hook这个方法便可,看到这里的注解类型也好理解:类名::方法名@参数1#参数2...,这里还有一个重要的知识就是调用callSuper方法能够调用原来的方法,这样咱们只作了一层拦截,不要破坏原始方法的执行流程,而这里能够调用原始方法其实就是利用以前提到的原始方法缓存池功能便可实现,这里能够看出有AOP的意思了。运行看一下效果:
这里会把每一个页面加载请求的url进行拦截了,这就是我项目想要的功能。
 
由于上面分析了框架的原理,大部分功能都是在Java层作的,这样很大程度上可以作到兼容,由于这样,我也想尝试利用这个框架来操做项目,毕竟也算是一种尝试。
 
注意:
一、框架能够选择不使用注解的方式进行hook,直接使用api方式,具体用法参见github上说明。
二、hook的时机最好要早,通常在程序的入口处便可。
相关文章
相关标签/搜索