android免root hook框架legend
一、前言
Android中hook框架已經非常多了,最優秀的當屬Xposed和Substrate了,這兩個框架我在之前的文章都詳細介紹過了,不了解的同學,可以轉戰這里:http://www.wjdiankong.cn;但是這兩個框架用于破解逆向是非常有用的,可惜他們最大的局限性就是需要root權限,這個幾乎現階段可能阻礙了很多產品的商業化,畢竟國內人的安全意識越來越高了。所以這里就需要借助一個免root的hook框架了。而對于免root的框架最大的好處就在于無需root權限,但是弊端就是只能hook自身,對于系統其它app無能無力,就有人好奇了,只能hook自己有個卵用,的確是沒什么用,但是也并非一點用都沒有。
二、免root的hook功能用途
關于Android中的Hook機制,我在之前已經說得非常詳細了,大致就兩個方式:
第一個方式:root權限,直接hook系統,可以干掉所有app。
第二種方式:免root權限,但是只能hook自身。
對于免root權限只能hook自身,并非一點用都沒有,比如我之前介紹到的自動破解簽名校驗工具kstools,就是借助這個原理實現,不了解原理的同學可以看這里:Android中自動破解簽名校驗工具kstools,我們在破解逆向app的時候,需要反編譯,二次打包,那么這時候其實我們想針對于這個app做點手腳,就可以借助這個技術,比如現在想改一個app,使得他獲取系統的imei值是隨機的,有這種需求的,有的游戲有的功能會用設備的imei值做唯一處理,隨機imei值的話就可以跳過這個功能了。那么這時候我們可以反編譯這游戲,在游戲入口處加上hook代碼,即hook游戲自身的imei值即可,這就是需求,只需要hook這一款游戲即可。這樣無需在用xposed來編寫外掛了。游戲二次打包即可使用了。
三、以往hook框架原理分析
那么其實免root進行hook功能在之前我已經介紹過了一款阿里的開源框架Dexposed了,不過這個框架已經廢棄了,取而代之的是AndFix,原理很簡單在native層把Java層的方法強制改成native類型,然后在將方法的native標志指向自定義的native函數即可。這樣原來的方法就會走到自定義的native函數中,這個框架是非常優秀的AOP框架,可惜兼容性問題不能繼續維護了。取而代之的是AndFix,關于它的原理就更簡單了,他沒有了AOP功能,直接將原始方法和自定義的新方法信息進行對換,這樣原來方法執行的邏輯就是新的方法了。這個框架主要用于熱修復,所以沒必要需要AOP功能了。而今天介紹的這款框架原理也是類似,只不過覺得比較好的是,他把大部分的功能都放到了Java層,這樣的兼容性就非常好了,而且自身的兼容也很優秀。
四、Legend框架原理分析
下面就來介紹一下他的原理,代碼量不是很多,框架下載地址可以去github上:https://github.com/asLody/legend,下載下來直接運行就ok了,我們繼續來分析它的代碼吧:
進入這個方法查看:
到這里我們會發現,他是編譯傳入進來的class類,然后編譯他所有用到了Hook注解的方法,獲取其需要hook的方法信息,具體樣式為:類名::方法名@參數1#參數2#...
然后解析完了注解獲取方法簽名信息之后,開始調用hookMethod進行hook操作:
這里看到,每個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++中干了:
這里看到,其實不是寫入內存,而是對內存數據的一個替換,直接利用指針方便快捷。
五、案例用法
那么到這里,其實我們就大致分析完了這個框架的功能,關于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層做的,這樣很大程度上能夠做到兼容,因為這樣,我也想嘗試利用這個框架來操作項目,畢竟也算是一種嘗試。
注意:
1、框架可以選擇不使用注解的方式進行hook,直接使用api方式,具體用法參見github上說明。
2、hook的時機最好要早,一般在程序的入口處即可。
總結
以上是生活随笔為你收集整理的android免root hook框架legend的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌曾承诺不会在称气候变化为骗局的内容上
- 下一篇: ASP金额转人民币大写的函数