一、前言
從這篇開始咋們開始一個全新的靜態(tài)方式逆向工具icodetools的實現(xiàn)過程惠奸,這個也是我自己第一次寫的個人覺得比較有用的小工具,特別是在靜態(tài)方式逆向apk找關(guān)鍵點的時候宇整,后續(xù)會分為三篇來詳細介紹這個工具實現(xiàn):
第一篇:開鑿篇晌坤,簡單介紹實現(xiàn)原理以及簡單的初次方案實現(xiàn)簡單的apk注入代碼功能
第二篇:填坑篇,這一篇是在前一篇的基礎上對工具的優(yōu)化丈牢,可以應對市面上大部分的apk代碼注入功能實現(xiàn)
第三篇:生產(chǎn)篇祭钉,這一篇是在前兩篇的基礎上利用這個工具來實際操刀如何進行快速定位應用的關(guān)鍵方法功能
還記得那一年咋們 靜態(tài)方式破解應用,為了更好的追蹤代碼位置己沛,手動反編譯成smali文件慌核,然后添加smali日志代碼,在回編譯申尼,查看日志信息來定位關(guān)鍵點垮卓。那種操作現(xiàn)在回想是苦不堪言,操作非常復雜师幕。那么就嘗試想想如果有一個工具可以在自動為每個方法注入日志代碼粟按,這樣就可以很快速的定位到我們想要的方法,所以本文就來介紹一下這個工具的實現(xiàn)原理霹粥,我將其命名為icodetools灭将。
二、實現(xiàn)方案
首先咋們來看一下具體實現(xiàn)原理吧后控,這個工具最終的形態(tài)應該是這樣的庙曙,就是輸入一個apk,然后在為apk中每個類的每個方法添加一段打印此方法的堆棧信息日志浩淘,然后在重新簽名打包成新的apk捌朴。所以這個過程中我們最關(guān)鍵的地方就是如何把日志代碼插入到已經(jīng)編譯好的apk中吴攒。我們可能想到的有兩個方案:
第一個方案:首先利用apktool進行反編譯成smali文件,然后解析smali文件找到每個方法的位置男旗,添加指定smali日志代碼舶斧。那么這里有一個很大的問題,就是如何分析smali文件察皇,如何定位到每個方法茴厉?這個過程工作量就比較大了,所以這個方案就廢棄了什荣。
第二個方案:利用dex2jar獲取到apk中的dex轉(zhuǎn)化之后的jar文件矾缓,然后在解析jar文件獲取到每個class文件,解析class文件進行方法的信息獲取稻爬。這里會發(fā)現(xiàn)這個方案很靠譜嗜闻,因為我們解析class文件比解析smali文件方便多了。而且在這個過程中會發(fā)現(xiàn)有一個更大的驚喜桅锄,就是dex2jar這個工具是開源的琉雳,其實內(nèi)部實現(xiàn)原理就是解析dex文件格式,然后借助asm工具將其變成class文件的友瘤,這里又出現(xiàn)了一個非常重要的工具asm翠肘,這個工具下面會詳細介紹。
說明:
1》這里非常感謝dex2jar的作者Claud大神的開源精神辫秧,這個工具的地址:https://github.com/pxb1988/dex2jar束倍,是純java代碼,所以大家一定要先解讀這個工具源碼盟戏,內(nèi)部實現(xiàn)原理自己研讀绪妹,本文不會詳細介紹的。
2》這里有的同學會想到柿究,能不能直接解析dex文件格式邮旷,然后在找到每個類的每個方法添加日志信息,雖然我們在前面有詳細介紹dex文件格式:Dex文件格式詳解蝇摸,但是如果想在每個類每個方法中添加日志代碼這個工作量感覺比操作smali還要復雜廊移,所以直接將其轉(zhuǎn)化成class文件進行操作就非常方便了,因為我們有asm工具探入。
三狡孔、方案實現(xiàn)
上面已經(jīng)探討了方案了,在上面提到了很多次一個非常重要的工具就是asm蜂嗽,那么這個工具到底是干嘛的呢苗膝?這個工具非常有用,他的表現(xiàn)之處在JavaWeb開發(fā)中的Spring框架就有用到植旧,可以動態(tài)的解析class文件辱揭,然后可以操作這個類离唐,比如添加類成員,方法等等操作问窃。所以下面不多解釋了亥鬓,直接用一個簡單的案例來看看他的強大之處,我們實現(xiàn)給一個類添加一個成員字段域庇,方法嵌戈,給每個方法調(diào)用前添加一行代碼。
第一听皿、asm庫基本使用
這里借助ClassReader來讀取一個類熟呛,使用ClassVisitor來進行類信息操作,ClassWriter將操作完之后的類寫入文件中
第二尉姨、添加類成員字段
上面看到了一個主要的類ClassVistor庵朝,他主要就是用來操作一個類:
這里看到的是繼承了ClassAdapter,然后在構(gòu)造方法中可以添加類成員信息包括字段又厉,方法等九府,這里我們添加一個字段mJW,類型是String的覆致≈堆看看如何添加的:
借助ClassVisitor的visitField方法就可以進行字段的添加了。然后我們運行程序之后篷朵,使用JD-GUI工具查看保存本地的class文件信息:
看到了吧勾怒,這里成功的定義了一個字段mJW婆排。
第三声旺、為類的所有方法前添加代碼
這里我們需要借助另外一個類了MethodVisitor了,他是用來操作方法信息的:
在ClassAdapter的visitMethod回調(diào)方法中可以獲取方法信息段只,然后進行操作:
在visitCode回調(diào)方法中利用MethodVisitor開始添加代碼:
這里看到可以利用visitFieldInsn方法方法System類的靜態(tài)變量out腮猖,然后在使用visitLdcInsn從常量池中獲取值,最后在利用visitMethodInsn方法來調(diào)用PrintStream類的成員方法println來打印信息赞枕,運行程序之后繼續(xù)借助JD-GUI來查看class文件:
看到了澈缺,類中所有的方法前面都被加了一行打印代碼。
注意:有的同學發(fā)現(xiàn)了炕婶,上面那個添加代碼怎么得到呢姐赡?難道真的要記住那么多api去添加嗎?其實不用那么復雜柠掂,Eclipse有一個插件Bytecode项滑,可以把Java代碼自動生成類似于上面的代碼,咋們之后手動拷貝一下就好了涯贞!工具后面會說枪狂。
第四危喉、為類添加成員方法
下面在來看最后一個操作吧,就是給類中添加一個成員方法州疾,有了上面的操作之后我們應該知道辜限,如果要操作類就要借助ClassVisitor類,要是操作方法就需要借助MethodVisitor類严蓖,那么這里為類添加成員方法薄嫡,借助ClassVistor類來進行操作了,但是在操作之前咋們得先搞好一個工具Bytecode谈飒,這個是Eclipse插件岂座,安裝很簡單:
安裝完成之后,可以打開視圖欄:
然后選擇Java中的bytecode視圖就可以了:
下面咋們首先在一個類中編寫好我們想要添加的方法代碼杭措,然后點擊Bytecode視圖卡片就可以看到對應的asm代碼:
看到了吧费什,這樣操作是不是如此簡單,我們可以把這段asm代碼直接拷貝到AsmUtils中:
然后在ClassVisitor的構(gòu)造方法中直接調(diào)用這個方法就可以了:
再次運行程序之后手素,使用JD-GUI查看類信息:
成功的添加了printStackTrace方法了鸳址。就是如此簡單。借助Eclipse的強大工具Bytecode就可以了泉懦,以后都不要在自己去調(diào)用asm庫的api去手動編寫了稿黍。這個工具太好了得記住它!
四崩哩、工具案例實踐
上面就介紹完了如何操作一個類和方法巡球,給類添加字段,方法邓嘹,在每個方法之前添加一行代碼酣栈。下面就得進入本文的主題了,如何給apk應用中每個類中的每個方法添加一行打印日志信息汹押。在開始的時候我們有了方法矿筝,就是借助工具dex2jar源碼,他內(nèi)部也是解析dex格式棚贾,然后利用asm將其信息變成一個class文件的窖维,那么我們只要在這個過程中得到ClassVisitor和MethodVisitor這兩個對象,就可以盡情的干很多事了妙痹。所以第一步你一定要先看懂dex2jar的源碼铸史。這里我不會對源碼進行詳細分析了,用過dex2jar工具的都知道怯伊,找入口很簡單琳轿,直接看他的一個d2j-dex2jar.bat腳本信息:
Dex2jarCmd就是工具的入口類:
然后分析代碼,會發(fā)現(xiàn)處理的核心類是Dex2jar類:
這里會看到可以拿到ClassVisitor類對象的,那么我就可以添加打印堆棧信息的方法了:
這里需要注意的是打印消息用了Android的Log.d方法利赋。然后在每個方法調(diào)用之前在調(diào)用這個打印方法:
這里過濾依然過濾了構(gòu)造方法和靜態(tài)代碼塊方法水评。
其實我們就需要這么做就可以了,下面咋們就用一個簡單的Apk來做一下實驗媚送,咋們把apk中的classes.dex文件解壓出來中燥,為了簡單直接跑這個dex2jar工具,可以在Dex2jarCmd開始處構(gòu)造一個簡單的命令:
輸入的dex文件為指定目錄的塘偎,輸出的jar文件也是指定目錄的:
然后咋們就可以運行程序了疗涉。運行結(jié)束之后我們得到了一個classes.jar文件,可以使用JD-GUI進行查看:
到這里我們就成功的吟秩,把apk中的classes.dex中的每個類每個方法添加了我們自己的打印消息的代碼了咱扣,已經(jīng)成功一大半了,下面為了驗證效果涵防,咋們還得把classes.jar轉(zhuǎn)成dex闹伪,在弄到apk中運行看效果。這個過程就簡單了壮池,利用系統(tǒng)的dx命令偏瓤,把classes.jar在變成classes.dex文件:
然后在把這個classes.dex文件塞到apk中,不過這時候得重新簽名了椰憋,可以借助jarsigner工具:
jarsigner -verbose -keystore cyy_game.keystore -storepass cyy1888 -signedjar signed.apk unsigned.apk cyy_game.keystore -digestalg SHA1 -sigalg MD5withRSA
然后咋們就可以安裝apk厅克,然后開始運行效果:
看到效果了吧,表示成功的不要不要的橙依。有點小興奮证舟,通過棧信息加上我們出發(fā)一個事件之后就可以定位這個事件的方法了。對于我們在使用hook的時候?qū)ふ襤ook點非常重要窗骑。
五女责、技術(shù)總結(jié)
到這里我們本文的知識點就算結(jié)束了,但是整個工具開發(fā)并沒有結(jié)束慧域,下面就來總結(jié)一下本文涉及到的知識點:
1鲤竹、學會了利用asm庫來操作類浪读,實現(xiàn)添加字段昔榴,方法等操作。
2碘橘、了解到了Eclipse的一個強大插件Bytecode互订,可以快速得到java代碼對應的asm代碼
3、了解了dex2jar的實現(xiàn)原理痘拆,內(nèi)部也是借助于asm來進行操作的
其實本文的這個自動注入代碼工具絕大部分是借助了dex2jar這個工具的仰禽,我們只是在適當?shù)牡胤教砑恿宋覀兿胍男畔⒋a。在操作類的時候只要有ClassVisitor對象就可以操作類,MethodVisitor對象就可以操作方法了吐葵。而在dex2jar中正好有這兩個對象规揪,所以我們實際要操作的內(nèi)容并不復雜。當我們使用通過修改之后的dex2jar得到了classes.jar之后温峭,在用dx工具將其還原成classes.dex文件猛铅,在放到apk中進行重簽名驗證。
六凤藏、遺留的問題
如果到這里有的同學覺得這個是挺簡單的奸忽,那其實就錯了,因為開始的時候我已經(jīng)說了后面還有一個填坑篇文章揖庄,在那篇文章會詳細說明在實際操作其他企業(yè)app會遇到哪些問題栗菜,我們需要繼續(xù)優(yōu)化這個工具,同時對這個工具最好能夠做到一鍵化工作蹄梢,所以我們需要解決這幾個問題:
1疙筹、上面看到我們是為每個類添加了一個打印棧信息的方法,那么就有一個很大的問題禁炒,如果一個dex文件過大腌歉,包含的類很多,那么就是增加了很多方法齐苛,對于dx進行轉(zhuǎn)化的時候會發(fā)現(xiàn)方法數(shù)超了翘盖。
2、在實際的apk操作過程中會發(fā)現(xiàn)在每個方法中插入日志之后凹蜂,當你啟動app的時候那日志幾乎會被霸屏的馍驯,而且一個龐大的app內(nèi)部調(diào)用的方法非常多,導致應用會出現(xiàn)無響應狀態(tài)玛痊,所以咋們得弄個開關(guān)以及想在哪些方法中添加汰瘫。
3、上面在看到在整個過程中擂煞,先把dex轉(zhuǎn)成jar混弥,然后再把jar轉(zhuǎn)成dex,在放到apk中对省,在簽名蝗拿,整個過程我們都是手動操作的,顯得非常的費勁蒿涎,所以我們還得優(yōu)化這個工作哀托,做到真正意義上的一鍵化,輸入一個apk劳秋,輸入就是已經(jīng)添加日志信息的apk就可以了仓手。
所以后面一個填坑篇文章會有很多工作要做的胖齐,當坑都填完了,咋們就得實際生產(chǎn)拿一些app進行實戰(zhàn)操刀了嗽冒。最后在來看一下我總結(jié)的一張原理圖吧(可以點擊查看高清大圖):
嚴重說明:
===》本文介紹的是基礎篇呀伙,可以看到我們是大致走通了整個流程,但是這個和最終的工具實現(xiàn)差的很多添坊,后續(xù)還有很多問題需要解決区匠,所以重點其實在下一篇中,那里會去解決在實際使用過程中遇到的各個問題帅腌。以及最重要的就是如何把所有的步驟連貫起來驰弄,一鍵化開發(fā)完善。一定要記得看下一篇內(nèi)容速客,那里才是主戰(zhàn)場戚篙!
===》一定要自己去github上下載dex2jar的源碼,自己先調(diào)試走通程序溺职,不然一切都是枉然岔擂,因為這個工具是純Java編寫的,代碼不是很多浪耘,所以難度不大乱灵。
七、總結(jié)
對于這個自動插入代碼的工具我個人覺得有需求采取這么干的七冲,因為以前遭受過那種手動注入代碼的痛苦痛倚,但是從本文的工具可以看到,對于一些加固app是無能無力的澜躺。而工具的理念來源是美團的一個熱修復框架Robust的蝉稳。關(guān)于源碼的話等后面都介紹完了,我把我寫的部分公開掘鄙,但是你還是得先去看看dex2jar的源碼耘戚。又開始了寫這種文章,每次寫完感覺自己身體被掏空了一樣操漠,多多點贊收津。打賞就在好不過了。
更多內(nèi)容:點擊這里
關(guān)注微信公眾號浊伙,最新技術(shù)干貨實時推送
掃一掃加小編微信添加時注明:“編碼美麗”否則不予通過撞秋!