摘要:下面我們正式開(kāi)始嘗試小米推送,首先,找出其業(yè)務(wù)邏輯中的一個(gè)節(jié)點(diǎn)。因?yàn)樾∶淄扑褪巧虡I(yè)產(chǎn)品,這里不便于探索太多內(nèi)容,但是通過(guò)這個(gè)插件可以比較方便的進(jìn)行類似的研究。
前言
有時(shí)候我們?cè)贘ava開(kāi)發(fā)過(guò)程中可能有這樣的需求:需要研究或者修改工程依賴的Jar包中的一些邏輯,查看代碼運(yùn)行中Jar包代碼內(nèi)部的取值情況(比如了解SDK與其服務(wù)器通信的請(qǐng)求報(bào)文加密前的情況)。
這個(gè)需求類似于Hook。
但是往往這些依賴的Jar包中的代碼已經(jīng)被混淆過(guò),刪去了本地變量表和代碼行號(hào)等debug信息,所以無(wú)法直接斷點(diǎn)調(diào)試,其內(nèi)部邏輯和運(yùn)行情況也幾乎無(wú)法觸及,研究更難以下手。這時(shí)候,一般的辦法有二:1.將Jar反解為Java源碼,以module方式引入,便可自由修改調(diào)試;2.修改字節(jié)碼或者打包后的smali代碼,實(shí)現(xiàn)想要的邏輯后再重新打包。這兩種方法中,前者往往十分繁雜,尤其在混淆后邏輯變得極其復(fù)雜,幾乎不可能完成;后者也很麻煩,工序較多,修改成本也比較高。
插件:HiBeaverGradle編譯插件hibeaver結(jié)合Java AOP編程中對(duì)于大名鼎鼎的ASM.jar的應(yīng)用,和Android gradle 插件提供的最新的Transform API,在Apk編譯環(huán)節(jié)中、class打包成dex之前,插入了中間環(huán)節(jié),依據(jù)開(kāi)發(fā)者的配置調(diào)用ASM API對(duì)項(xiàng)目所依賴的jar進(jìn)行相應(yīng)的修改,從而可以比較高效地實(shí)現(xiàn)上面的Hook需求。
源碼地址:https://github.com/BryanSharp/hibeaver
(現(xiàn)在hiBeaver已經(jīng)發(fā)布了1.2.7版本,支持輕量級(jí)AOP框架設(shè)計(jì)。)
唯一需要注意的是,運(yùn)用好這個(gè)插件需要有一定的Java匯編指令基礎(chǔ),并了解基本的ASM3的使用方法:后者還是很簡(jiǎn)單的,而前者,關(guān)于Java匯編指令基礎(chǔ)這塊,對(duì)于事先不了解的同學(xué),接觸起來(lái)有一定難度,但是學(xué)一學(xué)這個(gè)其實(shí)非常有益處,對(duì)于理解Java的運(yùn)行有很大的幫助。
閑話少說(shuō),先看看如何快速實(shí)踐一把!關(guān)鍵看療效!
關(guān)于匯編指令的資料可以參閱本人的文章:大話+圖說(shuō):Java匯編指令——只為讓你懂
實(shí)戰(zhàn)演練我們就先來(lái)嘗試用這個(gè)Hook掉小米推送的SDK。
首先,在需要的工程的根項(xiàng)目gradle配置中加入以下內(nèi)容:
如圖所示,該插件上傳到了jcenter中,只需引入classpath:
classpath "com.bryansharp:HiBeaver:1.2.7"
這里需要注意的是,目前該插件僅支持Android gradle編譯插件2.0及以上的版本。
然后,在你的App項(xiàng)目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 = [:] }
然后,重新編譯一下項(xiàng)目,會(huì)先去jitpack下載這個(gè)插件,開(kāi)始編譯后可以看到Android Studio的右下角的Gradle Console中,多輸出了以下內(nèi)容:
如果你看到了和我一樣的內(nèi)容,那說(shuō)明初步配置成功。
可以看到,使用插件后會(huì)輸出一段友好的幫助內(nèi)容,還是中英文的,告訴我們可以直接拷貝作為初始配置,這個(gè)幫助輸出也是可以關(guān)閉的。
下面我們正式開(kāi)始嘗試Hook小米推送SDK,首先,找出其業(yè)務(wù)邏輯中的一個(gè)節(jié)點(diǎn)。
首先,引入小米推送,這個(gè)過(guò)程不贅述了,blablabla,引入成功!
眾所周知,使用小米推送需要先在代碼中調(diào)用如下:
MiPushClient.registerPush(this, APP_ID, APP_KEY);
這個(gè)代碼應(yīng)該會(huì)調(diào)起本地長(zhǎng)連接的建立、注冊(cè)服務(wù)器等流程。假如我們出于學(xué)習(xí)的目的,想研究其中的流程,試舉一例,先從查看其反編譯的代碼開(kāi)始,找一個(gè)切入的節(jié)點(diǎn),如下:
首先進(jìn)入查看MiPushClient.registerPush這個(gè)方法:
在initialize的方法中,找到一段邏輯如下:
進(jìn)入a方法,來(lái)到了這個(gè)類:com.xiaomi.mipush.sdk.u中,發(fā)現(xiàn):
下面如果我們想看看運(yùn)行時(shí)前兩個(gè)方法傳入?yún)?shù)的值,就可以開(kāi)始Hook了。該如何做呢?這個(gè)方法體內(nèi)打Log輸出所有的值嗎?那樣太麻煩了。我們可以這樣做:
首先在我們項(xiàng)目的源碼里新建一個(gè)靜態(tài)方法,包含兩個(gè)參數(shù),如下圖:
其后,我們只要在a方法中加入一段代碼,調(diào)用我們的靜態(tài)方法,并傳入我們想查看的兩個(gè)參數(shù)即可。
這就有賴于我們的hibeaver插件了,具體如何做呢?
我們可以先看看之前的幫助內(nèi)容:
里面有提到一個(gè)the most important par,最重要的部分。沒(méi)錯(cuò),這個(gè)插件的核心就在于配置這個(gè)類型為Map
首先我們配置如下:
然后重新編譯,發(fā)現(xiàn)輸出log如下:
這樣就輸出這個(gè)u類的所有方法信息,用于后面進(jìn)行配置。
再來(lái)看看剛剛的方法a:
是一個(gè)泛型方法,眾所周知泛型只存在于編碼階段,編譯后是沒(méi)有泛型的,其實(shí)傳入的參數(shù)的實(shí)際類型為org.apache.thrift.a,最終找到其方法描述應(yīng)該為:
(Lorg/apache/thrift/a;Lcom/xiaomi/xmpush/thrift/a;ZLcom/xiaomi/xmpush/thrift/r;)V
進(jìn)一步配置:
然后重新編譯,console輸出新增revist部分,如下:
最后,我們?cè)黾尤缦麓a,在其中植入我們的代碼,調(diào)用剛剛的靜態(tài)方法,并把對(duì)應(yīng)值傳遞過(guò)來(lái):
終極配置:
以上代碼就不做詳細(xì)解釋了,相信有基礎(chǔ)的都能明白,然后編譯查看輸出:
下面我們debug一下,看看是否可以成功在registerPush的運(yùn)行流程中調(diào)用到我們的方法:
上面可以看到,無(wú)論是debug還是log輸出都可以抓到想要的參數(shù)了。
因?yàn)樾∶淄扑褪巧虡I(yè)產(chǎn)品,這里不便于探索太多內(nèi)容,但是通過(guò)hibeaver這個(gè)插件可以比較方便的進(jìn)行類似的研究。
hibeaver所體現(xiàn)的技術(shù),并沒(méi)有特別大的價(jià)值,僅僅作為工具來(lái)講比較方便易用,有助于學(xué)習(xí)研究Jar中的邏輯,和學(xué)習(xí)應(yīng)用Java匯編碼。除此之外,還有幾個(gè)應(yīng)用場(chǎng)景:1.修改引用SDK中的一些bug或者提高其效率;2.獲得必要的SDK的一些關(guān)鍵調(diào)用時(shí)機(jī),通過(guò)hook建立回調(diào);3.欺騙SDK、關(guān)閉或減少SDK中不受控制的網(wǎng)絡(luò)傳輸。不一而足,還是很有趣、很有想象空間的。
目前存在的問(wèn)題,如下,這個(gè)除了偶爾同步報(bào)錯(cuò)之外沒(méi)有影響,編譯正常:
還有,如果僅僅修改了gradle文件,不會(huì)觸發(fā)更新,需要在代碼上也進(jìn)行任意修改方生效。
關(guān)于項(xiàng)目hibeaver完全開(kāi)源,大家可以自行查看其中代碼,有大量的中文注釋,對(duì)于學(xué)習(xí)gradle插件開(kāi)發(fā)大有裨益。
github開(kāi)源項(xiàng)目地址:https://github.com/BryanSharp/hibeaver
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66722.html
摘要:理解本文需要一定的字節(jié)碼指令基礎(chǔ),可以閱讀筆者的另一篇文章大話圖說(shuō)字節(jié)碼指令只為讓你懂利用字節(jié)碼插樁技術(shù)可以很方便地幫助我們實(shí)現(xiàn)很多手術(shù)刀式的代碼設(shè)計(jì),如無(wú)埋點(diǎn)統(tǒng)計(jì)上報(bào)輕量級(jí)等。 理解本文需要一定的Java字節(jié)碼指令基礎(chǔ),可以閱讀筆者的另一篇文章:大話+圖說(shuō):Java字節(jié)碼指令——只為讓你懂 利用Android字節(jié)碼插樁技術(shù)可以很方便地幫助我們實(shí)現(xiàn)很多手術(shù)刀式的代碼設(shè)計(jì),如無(wú)埋點(diǎn)統(tǒng)計(jì)...
摘要:注入機(jī)制作為工作的基礎(chǔ),也為無(wú)侵入捕獲應(yīng)用數(shù)據(jù)提供可能。代碼注入機(jī)制結(jié)合和技術(shù),在應(yīng)用字節(jié)碼加載到之前進(jìn)行字節(jié)碼改寫(xiě)。當(dāng)然,修改字節(jié)碼文件流的動(dòng)作是在中進(jìn)行的。 UAVStack的中間件增強(qiáng)框架專題(MOF)】為大家詳細(xì)講述UAV中的MOF Agent是如何借助javaagent(premain)和javaassist技術(shù)在對(duì)應(yīng)用無(wú)侵入的前提下完成數(shù)據(jù)捕獲的。歡迎繼續(xù)關(guān)注UAVStac...
閱讀 1226·2023-04-26 02:20
閱讀 3349·2021-11-22 14:45
閱讀 4166·2021-11-17 09:33
閱讀 1020·2021-09-06 15:00
閱讀 1492·2021-09-03 10:30
閱讀 3900·2021-07-26 22:01
閱讀 1004·2019-08-30 15:54
閱讀 544·2019-08-30 15:43