閒來無事,學習了下安卓的逆向工程,有助於觀摩學習他人的優秀代碼,查詢瞭解後發現大致包括兩部分:
1.dex反編譯,即smali語法學習;
2.Native層,arm彙編學習。java
java環境很少說
1.apktool.jar;
2.jd-gui.jar;
3.dex2jar.zip;
這裏就不提供了,畢竟本身動手,豐衣足食,建議百度下載最新的版本,舊版本可能會有bug。程序員
假設如今有一個test.apk,若是咱們想要查看一個apk裏的java源碼,就能夠經過解壓apk文件獲得dex文件,而後使用dex2jar.zip工具包中的d2j-dex2jar.bat將dex轉爲jar文件:windows
將classes.dex拖動到d2j-dex2jar.bat上,獲得classes-dex2jar.jar,使用jd-gui.jar打開就能夠查看源碼了:app
可是jar文件只能輔助咱們查看java代碼,沒法修改。想要修改的話,仍是要反編譯出smali文件,而後對smali文件進行修改操做,使用下邊的命令反編譯apk:工具
apktool.jar d test.apk
而後會在當前目錄生成test目錄,目錄內容大致以下:學習
assets資源目錄,包含了圖片和字體等資源;
build和dist爲從新編譯生成的,新apk在dist目錄;
lib爲so文件目錄;
original保存了原簽名和反編譯前的清單文件;
res主要爲layout,strings等xml文件;
unknown不用管;
下邊是AndroidManifest.xml,清單文件,已經能夠打開查看了;
而後最重要的來了smali和smali_classes2,apk中的每一個dex文件會反編譯出一個smali文件夾,classes.dex對應smali,classes2.dex對應smali_classes2,以此類推。字體
知道了這些後,就能夠查看修改咱們想要的內容了。AndroidManifest.xml很少說,作過安卓開發均可以改,重點是smali的閱讀修改。首先打開smali文件夾內容以下:ui
因爲如今apk編譯時廣泛會進行混餚,以防他人修改二次發佈,因此目錄結構有些亂,但並沒有大礙。
隨手打開一個smali文件(sublime,已安裝smali插件):編碼
嗯,看不懂,沒事如今學還來得及,你須要瞭解下smali語法,傳送門:APK反編譯之一:基礎知識--smali文件閱讀。spa
smali修改簡單示例:
上圖爲原java代碼,下圖是反編譯出的smali代碼,此方法用來判斷外置儲存是否可讀。
如今不管外置存儲是否可讀,咱們都想讓此方法返回true,則能夠在smali代碼中的return v1
前加上一行const/4 v1, 0x1
,以下圖:
是否是很是簡單?固然,這只是最簡單的修改,一切都創建在深刻地學習和了解過smali語法的基礎上。
安卓native層,通俗來講就是對lib目錄下的so文件學習和了解,so文件是Android NDK動態連接庫,是二進制文件,做用至關於windows下的.dll文件。想要深刻了解相關知識,能夠百度關鍵字:‘安卓 native’,‘安卓 JNI’,‘安卓 ELF’,‘安卓 NDK’。
so一般是針對不一樣的cpu構建編譯而成的,以下圖:
arm64-v8a:arm最新的64cpu構架,如驍龍810,820,835等都是基於此構架的,同時兼容A32,T32指令集;
armeabi-v7a:32位cpu構架,如驍龍800,801等,兼容armv5,armv6;
armeabi:armv5,armv6構架,基本已經淘汰了;
x86:intel的32位cpu構架,即windows平臺的32位cpu構架;
x86_64:實際上是amd出的兼容64位的32位cpu構架;
arm構架都是向下兼容的,例如若是CPU是armv8,沒有對應arm64-v8a文件夾,則會執行armeabi-v7a中的so文件。
話很少說,開始研究修改so文件吧,首先使用010 editor或ida打開armeabi下的so(elf)文件(這裏使用ida),彈出界面直接點擊ok,進入以下頁面:
要了解elf文件的詳細信息能夠查看:ARM平臺下elf文件超詳細的分析與解讀,elf文件的解析這裏不作更多說明。若是你跟我同樣,別的什麼也不想看,就想知道怎麼修改so,那麼下面咱們就來看看怎麼修改arm彙編的機器碼,來達到修改so文件的目的。
1.瞭解二進制文件的大小端模式,傳送門:詳解大端模式和小端模式;
2.瞭解寄存器相關知識,瞭解arm32位和64位寄存器的區別,特別是lr,sp,pc等關鍵寄存器的做用;
3.arm指令集學習,包括32位指令(A32,T32)和64位指令(A64),這裏不上連接了,由於太多了,具體建議百度自查;
4.下載arm官網cpu構架手冊,修改時須要對應查看,連接:A-Profile Architecture,咱們主要查看a系列的構架手冊,主要下載的文件:
Arm® Architecture Reference Manual Armv8, for Armv8-A architecture profile Arm® Architecture Reference Manual Armv7-A and Armv7-R edition The A64 instruction set
第一本是關於A64指令集的手冊,其實也包含了A32和T32指令集,第二本是armv7構架,包含了ARM指令和Thumb指令,第三本介紹了A64指令。
5.熟練進行進制轉換,可使用win10自帶的計算器的程序員模式。
- 32位
如下內容創建在以上知識的基礎上,開始修改,接着咱們打開的so頁面(armeabi-v7a),滾動到彙編代碼區域,以下圖:
例如想要修改Ox00005EE8處的關鍵跳轉BEQ loc_5EFA
爲BNE loc_5EFA
,經過彙編代碼知道,此處用R0寄存器中的值和2比較大小,若是R0中的值等於2,跳轉到下邊的loc_5EFA處:
雙擊此行,而後點擊Hex View-1標籤能夠看到對應的機器碼:
因爲elf的存儲模式是小端模式(Little-endian),故實際的機器碼是D0 07
,轉換爲二進制:1101 0000 0000 0111
,能夠看出是16位的Thumb指令,打開armv7構架手冊(armv8也能夠),找到指令集部分:
如上圖,此機器碼對應紅框中的編碼方式,要修改BEQ
爲BNE
,則須要修改8-11位的條件位,當即數保持不變:
上圖能夠查出EQ
的機器碼爲0000
,NE
機器碼則是0001
,所以修改後的機器碼爲1101 0001 0000 0111
,再轉換回16進製爲D1 07
,小端存儲07 D1
,按以下步驟,右鍵點擊修改:
修改完後右鍵點擊應用修改:
而後返回IDA View-A視圖,能夠看到BEQ loc_5EFA
已經改成了BNE loc_5EFA
:
- 64位
下邊嘗試下修改64位構架下的so文件,64位的so必須用64位的ida打開:
如上圖,咱們修改紅框中的代碼,改成:
CMP W1, #1 B.LT loc_1B5C
CMP W0, #0
的機器碼爲0111 0001 0000 0000 0000 0000 0001 1111
,查看armv8a手冊:
寄存器w0
改爲w1
,只需將5-9位改成00001
。當即數#0
改成#1
,須要將10-21位改成00 0000 0000 01
,改完後機器碼變爲0111 0001 0000 0000 0000 0100 0011 1111
,轉換爲16進制後:71 00 04 3F
,小端模式3F 04 00 71
;
B.GT loc_1B10
的機器碼0101 0100 1111 1111 1111 1110 0000 1100
,編碼方式以下:
B.GT改成B.LT,即修改0-3位爲1011
。
原當即數1111 1111 1111 1110 000
,補碼轉爲原碼爲1001 0000
,即-16
。
偏移量計算方法爲:offset = SignExtend(imm19:'00', 64)
,也就是19位的當即數後邊拼接00
(左移2位),變爲1111 1111 1111 1110 000 00
,而後有符號擴展爲64位(對於負數,前邊補1,補足64位),變爲1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1100 0000
,此爲補碼,轉爲原碼1100 0000
,即-64
。正如紅框中的所述,是當即數的4倍。
此處要改成loc_1B5C
,即偏移量爲+12,則當即數爲+12/4 = +3
,5-23位的當即數變爲0000 0000 0000 0000 011
。
最終機器碼爲0101 0100 0000 0000 0000 0000 0110 1011
,轉換16進制54 00 00 6B
,小端模式6B 00 00 54
。
而後,修改應用後查看結果: