探索Android的HOOK之旅

探索AndroidHOOK之旅


因为项目需求,最近在研究Androidhook方法,总结一下研究的结果,做一个笔记。

 

因为我只研究了AndroidJava层的代码hookNative层的hook还未实际研究与应用。

 

一、Hook是什么

 

Hook的中文翻译是“钩子”,简单的说就是,钩住你的代码,对你的方法执行前后做一些操作,例如:改变方法返回值,改变传入方法的参数,替换现有的方法。

 

当然,这些改变都是不可以在原有代码上进行更改,因为改变原有方法,有时成本很大,并且很繁琐,而且hook不光是hook自己写的代码,还可以hook系统原有的代码。例如你要更改你代码所有的文字样式,在Android中也就是TextView,如果在应用已经完成,再去自定义一个TextView更改起来就很麻烦,此时你只需要hookTextView中相应的方法,就可以更改所有文字的样式了。

 

二、Hook的应用

 

Hook 的应用场景有很多,前边提到的hook其实并不常用,常用的hook应该就是热更新技术了。所谓的热更新,就是在应用不重新安装新版本,而修复和升级一些bug和功能。

因为热更新技术就是hook应用的完美展现,所以围绕热更新技术去研究hook技术,是一个不错的方向。

 

三、热更新技术

 

热更新技术阿里和腾讯都有自己的实现方案,阿里的Sophix,微信用的Tinker

这是三种热更新技术的对比图。网上有很多详细的,这里就不讲了。

 

四、我走过的路

 

因为公司需求并不是热更新,一开始我一直在寻找Android的Hook方法,准确来说是无侵入的Hook方法,就是不改变原有代码的基础上去hook。

 

最先看的到是Xposed框架,这个框架实现hook更改手机所有应用的代码,框架很好,但是需要手机进行了root权限,这就直接pass了。

 

后来又找到的Legend的框架,这个的确是实现了我的需求,它只需要很少的代码,就可以hook到你自己应用中的方法,对方法进行更改,但是很可惜,他并不可以在Android 7.0以上的系统上运行。这个作者好像是在高二时候写的(给跪),现在也不更新了,所以只好放弃了。

 

后来我采用的是YAHFA去做的,这个框架总体还是很好的,支持7.0,虽然7.0是在测试阶段,但是并没有发现什么错误。只不过他不是在本应用中添加代码,而是以插件的形式,把你的代码打包成一个debug.apk,存储到sd卡中,进行加载,从而更改代码。这更像是热更新的操作,只是如果sd卡中删除了这个debug.apk,就失效了。不过热更新用这个应该很不错,我的需求,我更喜欢在本应用中添加hook方法,而不是插件式添加。

 

五、YAHFA的应用

 

GitHub地址:https://github.com/rk700/YAHFA

 

很感谢作者提供的这个框架。

 

GitHub中,作者对框架的介绍已经很详细了,我就简单的再说一下。

 

下载demo后导入Android studio,其中有一个demoApp和demoPlugin,还有一个library,library中就是hook的逻辑,其实hook就是代码的反射调用,AOP编程的一些逻辑,不知道AOP的朋友可以百度一下。

 

demoApp安装到你的手机,把demoPlugin打包成一个debug.apk,存入你的手机内存,只要在demoApp中的lication的类中指定这个dubug的路径就好。

 

demoPlugin中编写你要hook的方法。

 


className是指定的hoook的类名

methodName是指定要hook 的方法

methodSig是指定的类型签名

(Ljava/lang/String;)Ljava/net/URI;

(Ljava/lang/String;)Ljava/net/URI;

括号中是参数的签名,括号外是返回值的签名

签名是jni中经常用法哦的,如归不是基本数据类型,就要L开头,后边跟类的全路径名用“/”分割

基本数据类型有自己的类型签名


hook方法是你重写的代码逻辑

origin方法是你的原放啊

如果返回值不是基本数据类型,就写成Object

oringin方法中写什么都可以,不影响运行


1.静态方法

 

public class Hook_url {
    public static String className = "java.net.URI";
    public static String methodName = "create";
    public static String methodSig = "(Ljava/lang/String;)Ljava/net/URI;";
    public static Object hook(String url)
    {

        Log.w("YAHFA", "in hook_url: "+url);
        Log.w("YAHFA", "网址");
        url = "http://suggest.taobao.com/sug?code=utf-8&q=袜子&callback=cb";
        return origin(url);
    }

    public static Object origin(String url)
    {
        Log.w("YAHFA", "String.startsWith() should not be here");
        return url;
    }
}

这是静态方法的hook,静态方法和静态差不多,区别就是,非静态的方法在hook和origin的参数中,多加一个Object 的参数


url是传入的参数,把url更改,在调用origin,这样就是更改了访问网址

 

2. 非静态方法

 

 

public class hookbean {
    public static String className = "lab.galaxy.yahfa.demoApp.DemoBean";
    public static String methodName = "getbean";
    public static String methodSig =
            "(Ljava/lang/String;Ljava/lang/String;)Llab/galaxy/yahfa/demoApp/Bean;";

    public static Object hook(Object obj,String a, String b) {
        Log.w("YAHFA", "in getBean: "+a+b);
        a = "ni";
        b = "咱们";
        return origin(obj,a, b);
    }

    public static Object origin(Object obj,String a, String b) {
        Log.w("YAHFA", "ClassWithStaticMethod.tac() should not be here");
        return "";
    }
}

 这是非静态方法的hook,返回值是我自定义的类,所以签名是我的全路径,返回值类型是Object


3. 返回值为非基本数据类型


可以参考2,静态和非静态都是如此


4. 参数是非基本数据类型

 

public class Hook_WebViewClient_onReceivedSslError {
    public static String className = "android.webkit.WebViewClient";
    public static String methodName = "onReceivedSslError";
    public static String methodSig =
            "(Landroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V";
    public static void hook(Object thiz, WebView webView, SslErrorHandler handler, SslError error) {
        Log.w("YAHFA", "WebViewClient.onReceivedSslError()");
        handler.proceed();
    }
}


参数是非基本数据类型,返回值是void

任何情况下都可以不写origin方法,这样只是不调用原方法了


5. Jni方法

以后补充

6. jar中的方法

如果需要hook第三方依赖,jar包的方法,需要把debug.apk中也添加依赖和jar

 

7.内部类的hook

内部类只是编译时的概念,一旦编译成功,就会出现两个不同的类,例如,类outClass中有个intClass,那么编译后就出现一个名为outClass.class和一个outClass$intClass.class的类。所以className中就要指定类路径为a.b.c.outClass$intClass。

 

六、总结

 

Hook主要就是通过反射,有很多例子,都是直接反射调用类,然后更改,只是用了框架,就不用一个个代码去反射调用更该了,省了很多的时间去做一些你更该后的代码优化等操作。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值