現在android開發人員社區裏,除了app開發外,還有很是多周邊的工具類產品,比方安全、性能等,app產品php
已經出現了巨無霸,但是工具類的產品。眼下尚未出現規模比較大的公司,大部分還處於創業階段,這可能java
是創業者的下一個機會。工具類的產品相對app開發有比較高的技術門檻,從事這方面開發的技術人員需要掌python
握的基本功例如如下:android
一、熟悉android app的編譯過程,瞭解jvm的bytecode與dalvik bytecode的差異;shell
二、熟悉android framework,讀過部分代碼。比方系統啓動過程,zygote進程相關邏輯,熟練使用ndk,json
掌握inline hook的基本原理;安全
三、熟練使用腳本語言,比方python,腳本語言在一些分析工具的開發中仍是有很是大優點的,而且一些著名的數據結構
開源工具也是用python寫的,比方androguard。app
四、熟悉apk文件的結構,熟悉dex文件的結構,比方dex文件頭的結構;jvm
五、熟悉smali語法,熟練使用apktool等工具。能解析smali文件,並讀入內存本身定義數據結構中;
有了上述功底,可以作的事情有很是多,比方可以經過smali注入的方式插入本身定義代碼來監控app的行爲數據。
包含性能數據以及部分邏輯數據,可以經過inline hook的方式在執行時監控應用的行爲,筆者作了一個工具可以
本身主動往apk中插入smali代碼。詳細的過程例如如下:
一、經過androguard解析apk文件,並得到dex文件;
二、經過baksmali將dex文件反編譯爲smali文件;
三、開始解析smali文件。將smali文件映射爲內存數據結構;
四、分析smali文件,找出需要替換的方法keyword。並經過改寫smali文件的方法注入代碼;
固然這裏面有很是多細節問題需要解決,比方插入代碼後會對原有的smali代碼邏輯產生影響。如寄存器數量
添加,寄存器的的使用,跳轉邏輯的影響。這些都需要你本身分析需要插入或者替換的代碼上下文邏輯,使插入邏輯正確。
我如下以json爲例,來具體描寫敘述怎樣替換smali代碼:
json對象初始化的smali代碼:
new-instance v3, Lorg/json/JSONObject; invoke-direct {v3, p0}, Lorg/json/JSONObject;-><init>(Ljava/lang/String;)V
第一行代碼用來生成一個JSONObject對象,並放到v3寄存器中。第二行代碼
調用v3中JSONObject對象的init方法。參數爲存在p0寄存器(第一個參數)中的String對象調用json對象
格式化字符串jsonObject.toString。相應的smali代碼例如如下:
invoke-virtual {v3}, Lorg/json/JSONObject;->toString()Ljava/lang/String; move-result-object v8
第一行代碼調用v3中存放的json對象的toString方法,第二行代碼將該返回值存放到v8寄存器中。
如下定義一個靜態的方法,覆蓋jsonobject相應的方法:
public static String toString(JSONObject jsonObject) { String jsonString = jsonObject.toString(); Log.i("json toString:" + jsonString); return jsonString; }ok,剩下的就是將smali代碼裏的邏輯改成調用上面的靜態方法。替換後的內容例如如下:
invoke-static {v3}, Lcom/test/JsonReplace;->toString(Lorg/json/JSONObject;)Ljava/lang/String; move-result-object v7
init方法作相同的處理。這樣就可以截獲json對象的內容,從而可以監控使用json來上傳數據的app內容,
假設在上面的方法開始和結束的地方獲取系統時間。還可以用來獲取json toString方法耗費的時間。
json方法僅僅是衆多可以捕獲的方法之中的一個,依照相似的邏輯還可以捕獲不少其它您感興趣的方法。
爲了測試一下smali本身主動注入的成果,筆者下載了一個360安全衛士,進行了本身主動注入,此處需要注意的是,
改動完smali後需要又一次打包簽名。而360安全衛士在啓動時作了簽名校驗。假設發現簽名不一致會彈出一個
對話框讓你去下載應用並退出,只是這也可以經過改動smali代碼的方式來解決,可以找到簽名校驗的地方將
返回值改成1就能夠。由於這部分的內容涉及app的安全策略,且和本文的主題沒有多大關係,因此筆者就不寫
出來了,有興趣的可以私下交流。
注入smali後可以抓取到360安全衛士上傳的所有json字符串內容。我摘取了當中的部份內容:
json init:{"ads":[{"des":"1mob","ris":0,"name":"1mob","fbs":[{"t":1,"s":1,"c":"ff#*#1a#/BR;#1a#/PIA;#1a#/Main;#1a#/PManager;#1a#Ljava/lang/reflect/Method;.getParameterTypes:()[Ljava/lang/Class;#1a#Ljava/lang/Class;.getDeclaredMethods:()[Ljava/lang/reflect/Method;","n":"ad.push.1mob","st":2},{"t":1,"s":0,"c":"ff#*#1a#/BR;#1a#/US;#1a#/Main;#1a#/UNManager;#1a#Ljava/lang/reflect/Method;.getParameterTypes:()[Ljava/lang/Class;#1a#Ljava/lang/Class;.getDeclaredMethods:()[Ljava/lang/reflect/Method;#1a#setGapTime","n":"ad.spot.1mob","st":8}]},{"des":"360dianjing","ris":0,"name":"360dianjing","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#http://mob.tf.360.cn/#1a1#360dianjing#1a1#ibstates.php","n":"ad.banner.360dianjing.a","st":1},{"t":1,"s":0,"c":"ff#*#1a1#http://ads.lianmeng.360.cn/#1a1#360dianjing#1a1#ibstates.php","n":"ad.banner.360dianjing.b","st":1}]},{"des":"3gyu","ris":0,"name":"3gyu","fbs":[]},{"des":"7xpush","ris":0,"name":"7xpush","fbs":[{"t":1,"s":1,"c":"ff#*#1a1#http://www.qixiazi.com/ads.xml#1a1#com.kding.ads.service.DownService#1a1#/kding/ads#1a1#notification","n":"ad.push.7xpush","st":2}]},{"des":"91zan","ris":0,"name":"91zan","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#com.skpresent.shell.ShellServiceKit#1a1#zpresent.jar#1a1#zpresent.dex","n":"ad.banner.91zan.a","st":1},{"t":1,"s":0,"c":"ff#*#1a1#com.skpop.shell.ShellServiceKit#1a1#zpop.jar#1a1#zpop.dex","n":"ad.banner.91zan.b","st":1},{"t":1,"s":0,"c":"ff#*#1a1#com.skfloat.shell.ShellServiceKit#1a1#zfloat.jar#1a1#zfloat.dex","n":"ad.banner.91zan.c","st":1},{"t":1,"s":1,"c":"ff#*#1a1#com.skpush.shell.ShellServiceKit#1a1#zan_dev_appconfig_push#1a1#zpush.dex","n":"ad.push.91zan","st":2}]},{"des":"98mid","ris":0,"name":"98mid","fbs":[{"t":1,"s":1,"c":"ff#*#1a1#img=D:/images#1a1#myAppMarket98mid#1a1#times.bat#1a1#http://www.98mid.com/","n":"ad.push.98mid","st":2}]},{"des":"A立方廣告","ris":33,"name":"a3ad","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#Lcom/allyes/a3/sdk/widget/AdView;","n":"ad.banner.a3ad","st":1}]},{"des":"adchina","ris":33,"name":"adchina","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#Lcom/adchina/android/ads/AdManager;","n":"ad.banner.adchina.b","st":1},{"t":1,"s":0,"c":"ff#*#1a1#Lcom/adchina/android/ads/views/AdView;","n":"ad.banner.adchina.c","st":1}]},{"des":"adcocoa","ris":0,"name":"adcocoa","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#adcocoa_icon_default.png#1a1#adcocoa_id#1a1#adcocoa/cache","n":"ad.spot.adcocoa","st":8}]},{"des":"ader","ris":0,"name":"ader","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#AdBigWebView#1a1#com.rrgame.sdk#1a1#banner","n":"ad.banner.ader","st":1}]},{"des":"adfonic","ris":0,"name":"adfonic","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#http://adfonic.net/ad/","n":"ad.banner.adfonic","st":1}]},{"des":"adlantis","ris":0,"name":"adlantis","fbs":[{"t":1,"s":0,"c":"ff#*#1a#Ljp/adlantis/android/","n":"ad.banner.adlantis.a","st":1},{"t":1,"s":0,"c":"ff#*#1a1#sp.ad.adlantis.jp","n":"ad.banner.adlantis.b","st":1}]},{"des":"adlayout","ris":32,"name":"adlayout","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#Lnet/adlayout/ad/AdLayout;","n":"ad.gather.adlayout","st":11}]},{"des":"admarket","ris":0,"name":"admarket","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#showmyappdialog#1a1#huituixiazai","n":"ad.banner.admarket","st":1}]},{"des":"admob","ris":0,"name":"admob","fbs":[{"t":1,"s":0,"c":"ff#*#1a1#http://a.admob.com/f0?#1a1#AdMobSDK",
/catchjson( 7454): json toString:{"pkg":"org.orangenose.games","ti":{"v":0,"m":2},"si":{"v":22907852054,"m":511}} I/catchjson( 7454): json toString:{"pkg":"cn.ishuidi.shuidi","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"net.ot24.et.sqt","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"cc.freecall.ipcall","ti":{"v":0,"m":2},"si":{"v":22906542357,"m":511}} I/catchjson( 7454): json toString:{"pkg":"cn.btcall.ipcall","ti":{"v":0,"m":2},"si":{"v":22906542613,"m":511}} I/catchjson( 7454): json toString:{"pkg":"cn.pyt365.ipcall","ti":{"v":0,"m":2},"si":{"v":22906541333,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.lanshan.weimi","ti":{"v":0,"m":2},"si":{"v":22907853334,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.liulishuo.engzo","ti":{"v":0,"m":2},"si":{"v":22907591190,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.wandoujia.phoenix2.usbproxy","ti":{"v":0,"m":2},"si":{"v":22906541333,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.dnurse","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.sec.android.app.myfiles","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.qihoo360.smartkey","ti":{"v":10,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.qihoo.wifi","ti":{"v":10,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.qihoo.antivirus","ti":{"v":10,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.android.fileexplorer","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.meizu.filemanager","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}} I/catchjson( 7454): json toString:{"pkg":"com.android.browser","ti":{"v":0,"m":2},"si":{"v":22906475797,"m":511}}
I/catchjson( 7454): json toString:{"s":"11146d3626e64dab800a6a0ae57e4ec0","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"12332c1955435e036a5a94df4e188bd7","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"15db4f6a2b422f536cd3ce8230120e35","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"1d4dcf3a79293e05fa9744444263d048","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"328f0b456d41a3f19464241ab327b6c5","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"3bd87d5c8d98f7d711eff0d82d8fe7b9","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"517badabd9c40f1fca00d0b74d514a31","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"58f2fe7e4a67c1ba29c2a5c58c66739b","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"5b252a142a450b34bd3253acb51882bd","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"6d1fc48aeafe7286cfc9b05d815fd9f9","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"72fa45c1f82c02200c2bb769f641759e","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"829e5b4f1e9725ee6a3900009521d6df","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"8609665349f3431def232651c7785b86","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"8823a09ee4baaf6c63d767e56e5a295d","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"ca45263bc938da16ef1b069c95e61ba2","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"d488edaf562233024a034073f7d2bd93","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"dc6dbd6e49682a57a8b82889043b93a8","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"fec53268a38f029357056d46098c9384","a":1119509,"t":10} I/catchjson( 7454): json toString:{"s":"bb5cf8250d16d684a7b1e28b12780636","a":1119509,"t":10}
至於字符串裏內容的用處,由於筆者沒有分析其代碼邏輯,且和個人寫做主題無關,因此不作解釋,這裏僅此
技術角度來分析經過本身主動注入smali代碼的方式來得到應用行爲的可能性,並且檢測一下筆者開發的本身主動化注入
工具,無他意。
這裏是經過smali注入的技術來獲取應用的數據,還可以經過inline hook的方式,動態抓取應用的行爲數據,
這個筆者也作了個工具。興許寫文章具體介紹。