另外,如果一个类不是接口如何实现Hook呢?我们可以先写一个类继承它,然后重写里面的方法,再使用反射替换就行了。hook 点必须满足以下的条件:需要 hook 的方法,所属的对象必须是静态的,因为我们是通过反射来获取对象的,我们获取的是系统的对象,所以不能够 new 一个新的对象,必须用系统创建的那个对象,所以只有静态的才能保证和系统的对象一致。
为什么说 queryLocalInterface方法也是一个Hook点呢?这里我以Hook queryLocalInterface方法的思路来阐述:
这个方法的意思就是:先查看本进程是否存在这个Binder对象,如果有那么直接就是本进程调用了;
如果不存在那么创建一个代理对象,让代理对象委托驱动完成跨进程调用。
观察这个方法,前面的那个if语句判空返回肯定动不了手脚;最后一句调用构造函数然后直接返回我们也是无从下手,
要修改asInterface方法的返回值,我们唯一能做的就是从这一句下手:
我们修改这个getService方法的返回值,让这个方法返回一个我们伪造过的IBinder对象;这样,
我们可以在自己伪造的IBinder对象的queryLocalInterface方法作处理,进而使得asInterface方法返回
在queryLocalInterface方法里面处理过的值,最终实现hook系统服务的目的。
在跟踪这个getService方法之前我们思考一下,由于系统服务是一系列的远程Service,它们的本体,
也就是Binder本地对象一般都存在于某个单独的进程,在这个进程之外的其他进程存在的都是这些Binder本地对象的代理。
因此在我们的进程里面,存在的也只是这个Binder代理对象,我们也只能对这些Binder代理对象下手。然后,
这个getService是一个静态方法,如果此方法什么都不做,拿到Binder代理对象之后直接返回;
那么我们就无能为力了:我们没有办法拦截一个静态方法,也没有办法获取到这个静态方法里面的局部变量(即我们希望修改的那个Binder代理对象)。
接下来就可以看这个getService的代码了:
不难发现,ServiceManager为了避免每次都进行跨进程通信,把这些Binder代理对象缓存在一张map里面。
我们可以替换这个map里面的内容为Hook过的IBinder对象,由于系统在getService的时候每次都会优先查找缓存,
因此返回给使用者的都是被我们修改过的对象。从而可以Hook掉前文中所说的queryLocalInterface方法,紧接着
又可以愉快的Hook IPM了。
我们可以自己反射 IPackageManager$Stub$Proxy 这个内部类产生一个IPM对象,来替换
APP原始被Hook了的PMS服务对象。代码如下所示:
获取真实PMS服务对象之前: recoverPMS(this, getIPackageManager());
之前有分析过kstools以及XX管理器的去签名校验功能,XX管理器普通版以及kstools的去签名校验使用动态代理PackageManagerService接口生成的对象替换系统原PMS服务,增强版Hook了Native层标准函数库里的open函数以及对Java层的各种IO类进行了继承重写,然后使用反射替换系统的IO。重写与构造虚假Context绕过一般签名校验的思路一样。
Android Hook技术目前非常火热,典型产品功能有App插件化,热修复等。在Android逆向破解方面就是注入了,不妨看看这篇:
上面提到的去签名校验以及替换系统PMS服务都源自于这篇这篇帖子,有详细介绍,下面也会简单带过一下。
Hook系统服务(修改系统API函数的执行逻辑),有全局Hook和单进程Hook,全局Hook需要Root权限,典型代表开源框架Xposed,Frida。单个进程Hook,代表开源框架Whale,爱奇艺的XHook。单个进程Hook就是自己Hook自己啦。前面提到的替换PMS服务对象就是。那么有人说不要Root权限能不能实现全局Hook呢?可以,你搞定SELinux就行。
我们知道JDK原生动态代理只能代理接口,因为代理接口后经过动态字节码技术生成的代理class是继承Proxy类的。那为什么代理类一定要继承Proxy类呢?这个问题我查看了许多答案,看的也不是特别明白。如大家有兴趣,可以去搜索一下。下面是一个动态字节码class命名:
public final class $Proxy0 extends Proxy implements MyInterface
$Proxy0有多少个代理类,0-N
MyInterface即我们需要代理的接口
其实我们知道Java平台还有一个动态代理框架:cglib,
它不仅仅能够代理接口,还可以代理非接口的类,并且还能够为类的非final方法提供代理,为JDK的动态代理提供了很好的补充。那为什么我们为什么不在Android平台上使用它呢?
cglib如此强大,但是,它有一个很致命的缺点是:cglib底层是采用著名的ASM字节码生成框架,使用字节码技术生成代理类,也就是通过操作字节码来生成的新的.class文件,而我们在android中加载的是优化后的.dex文件,也就是说我们需要可以动态生成.dex文件代理类,因此cglib在android中是不能使用的。不过,网上已经有人根据dexmaker框架(dex代码生成工具)来仿照cglib库动态生成.dex文件,实现了类似于cglib的AOP的功能,不过还有bug尚待修复,对高版本的Android支持不太友好。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-2-24 21:20
被LivedForward编辑
,原因: