java 修改字节码_Java字节码修改神器HiBeaver:黑掉你的SDK

前言

有时候我们在Java开发过程中可能有这样的需求:需要研究或者修改工程依赖的Jar包中的一些逻辑,查看代码运行中Jar包代码内部的取值情况(比如了解SDK与其服务器通信的请求报文加密前的情况)。

这个需求类似于Hook。

但是往往这些依赖的Jar包中的代码已经被混淆过,删去了本地变量表和代码行号等debug信息,所以无法直接断点调试,其内部逻辑和运行情况也几乎无法触及,研究更难以下手。这时候,一般的办法有二:1.将Jar反解为Java源码,以module方式引入,便可自由修改调试;2.修改字节码或者打包后的smali代码,实现想要的逻辑后再重新打包。这两种方法中,前者往往十分繁杂,尤其在混淆后逻辑变得极其复杂,几乎不可能完成;后者也很麻烦,工序较多,修改成本也比较高。

插件:HiBeaver

Gradle编译插件hibeaver结合Java AOP编程中对于大名鼎鼎的ASM.jar的应用,和Android gradle 插件提供的最新的Transform API,在Apk编译环节中、class打包成dex之前,插入了中间环节,依据开发者的配置调用ASM API对项目所依赖的jar进行相应的修改,从而可以比较高效地实现上面的Hook需求。

源码地址:https://github.com/BryanSharp/hibeaver

(现在hiBeaver已经发布了1.2.7版本,支持轻量级AOP框架设计。)

唯一需要注意的是,运用好这个插件需要有一定的Java汇编指令基础,并了解基本的ASM3的使用方法:后者还是很简单的,而前者,关于Java汇编指令基础这块,对于事先不了解的同学,接触起来有一定难度,但是学一学这个其实非常有益处,对于理解Java的运行有很大的帮助。

闲话少说,先看看如何快速实践一把!关键看疗效!

实战演练

我们就先来尝试用这个Hook掉小米推送的SDK。

首先,在需要的工程的根项目gradle配置中加入以下内容:

6232f26ca02c8eb7eb2e29a25c3f1220.png

如图所示,该插件上传到了jcenter中,只需引入classpath:

classpath 'com.bryansharp:HiBeaver:1.2.7'

这里需要注意的是,目前该插件仅支持Android gradle编译插件2.0及以上的版本。

然后,在你的App项目gradle配置底部或任意位置加入如下代码:

apply plugin: 'hiBeaver'

hiBeaver {

//turn this on to make it print help content, default value is true

showHelp = true

//this flag will decide whether the log of the modifying process be printed or not, default value is false

keepQuiet = false

//this is a kit feature of the plugin, set it true to see the time consume of this build

watchTimeConsume = false

//this is the most important part

modifyMatchMaps = [:]

}

然后,重新编译一下项目,会先去jitpack下载这个插件,开始编译后可以看到Android Studio的右下角的Gradle Console中,多输出了以下内容:

1796b1f930009f9895bc923c795b902f.png

如果你看到了和我一样的内容,那说明初步配置成功。

可以看到,使用插件后会输出一段友好的帮助内容,还是中英文的,告诉我们可以直接拷贝作为初始配置,这个帮助输出也是可以关闭的。

下面我们正式开始尝试Hook小米推送SDK,首先,找出其业务逻辑中的一个节点。

首先,引入小米推送,这个过程不赘述了,blablabla,引入成功!

众所周知,使用小米推送需要先在代码中调用如下:

MiPushClient.registerPush(this, APP_ID, APP_KEY);

这个代码应该会调起本地长连接的建立、注册服务器等流程。假如我们出于学习的目的,想研究其中的流程,试举一例,先从查看其反编译的代码开始,找一个切入的节点,如下:

首先进入查看MiPushClient.registerPush这个方法:

2491de45992ede234ad3e733925ebd55.png

13bcb05b3e201fed9b2451446c36bc3e.png

在initialize的方法中,找到一段逻辑如下:

db44da2b6edcb35f5ea1b4e074810b26.png

进入a方法,来到了这个类:com.xiaomi.mipush.sdk.u中,发现:

4ff109148639ca52d9ddfc8a23782618.png

下面如果我们想看看运行时前两个方法传入参数的值,就可以开始Hook了。该如何做呢?这个方法体内打Log输出所有的值吗?那样太麻烦了。我们可以这样做:

首先在我们项目的源码里新建一个静态方法,包含两个参数,如下图:

d4b93b1df12fd5b40ebd9e6ad4573b18.png

其后,我们只要在a方法中加入一段代码,调用我们的静态方法,并传入我们想查看的两个参数即可。

这就有赖于我们的hibeaver插件了,具体如何做呢?

我们可以先看看之前的帮助内容:

91f43f4a98d1839fc54b340feb8d855a.png

里面有提到一个the most important par,最重要的部分。没错,这个插件的核心就在于配置这个类型为Map>>的传入量。

首先我们配置如下:

b25525cb8bcd9e17fcb038fed5a6123e.png

然后重新编译,发现输出log如下:

704419de9a4b3027ad4e7be5f12ea3da.png

这样就输出这个u类的所有方法信息,用于后面进行配置。

再来看看刚刚的方法a:

50b094609f7229bcda012aca5deed0e0.png

是一个泛型方法,众所周知泛型只存在于编码阶段,编译后是没有泛型的,其实传入的参数的实际类型为org.apache.thrift.a,最终找到其方法描述应该为:

(Lorg/apache/thrift/a;Lcom/xiaomi/xmpush/thrift/a;ZLcom/xiaomi/xmpush/thrift/r;)V

进一步配置:

b46459bd1ee34fce4d4f03d9a393c547.png

然后重新编译,console输出新增revist部分,如下:

a994687e96f201ae1d9bba1a39331c06.png

最后,我们增加如下代码,在其中植入我们的代码,调用刚刚的静态方法,并把对应值传递过来:

终极配置:

2d63404fd3755d14b5759b12586736b4.png

以上代码就不做详细解释了,相信有基础的都能明白,然后编译查看输出:

dedc46a02716dd3eaad6fb48d3924087.png

下面我们debug一下,看看是否可以成功在registerPush的运行流程中调用到我们的方法:

91c856ca1ccb066831c36122b6eba720.png

cb76a0aec99d42be39fcfc1070858f50.png

上面可以看到,无论是debug还是log输出都可以抓到想要的参数了。

因为小米推送是商业产品,这里不便于探索太多内容,但是通过hibeaver这个插件可以比较方便的进行类似的研究。

总结

hibeaver所体现的技术,并没有特别大的价值,仅仅作为工具来讲比较方便易用,有助于学习研究Jar中的逻辑,和学习应用Java汇编码。除此之外,还有几个应用场景:1.修改引用SDK中的一些bug或者提高其效率;2.获得必要的SDK的一些关键调用时机,通过hook建立回调;3.欺骗SDK、关闭或减少SDK中不受控制的网络传输。不一而足,还是很有趣、很有想象空间的。

目前存在的问题,如下,这个除了偶尔同步报错之外没有影响,编译正常:

9eec1d4146df8eccb5f3c16651104caa.png

还有,如果仅仅修改了gradle文件,不会触发更新,需要在代码上也进行任意修改方生效。

关于项目

hibeaver完全开源,大家可以自行查看其中代码,有大量的中文注释,对于学习gradle插件开发大有裨益。

github开源项目地址:https://github.com/BryanSharp/hibeaver

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值