核心:破解安卓NDK端native方法動(dòng)態(tài)JNI反射的so文件簽名校驗(yàn)
分析之前,關(guān)于Android的簽名機(jī)制就略過(guò)啦凯肋,先簡(jiǎn)單惡補(bǔ)一下Android簽名校驗(yàn)的方式,方便小白理解秕重。
在講簽名校驗(yàn)的方式前策治,需要先明確dex文件校驗(yàn)和簽名校驗(yàn):
1、將apk以壓縮包的形式打開(kāi)刪除原簽名后创夜,再簽名杭跪,安裝能夠正常打開(kāi),但是用IDE工具反編譯(classes.dex)后再二次打包挥下,卻出現(xiàn)非正常情況的揍魂,如:閃退/彈出非正版提示框∨镂粒可以確定是dex文件校驗(yàn)现斋。
2、將apk以壓縮包的形式打開(kāi)刪除原簽名再簽名偎蘸,安裝之后打開(kāi)異常的庄蹋,則基本可以斷定是簽名檢驗(yàn)。如果在斷網(wǎng)的情況下同樣是會(huì)出現(xiàn)異常迷雪,則是本地的簽名檢驗(yàn)限书。如果首先出現(xiàn)的是提示網(wǎng)絡(luò)沒(méi)有連接,則是服務(wù)器端的簽名校驗(yàn)章咧。
對(duì)于Android編程我們知道分為SDK編程和NDK編程倦西,當(dāng)然Android簽名校驗(yàn)也都是通過(guò)SDK或NDK來(lái)實(shí)現(xiàn)的。SDK編程也就是我們通常所說(shuō)的java端的即編譯出來(lái)的classes.dex靜態(tài)校驗(yàn)赁严,NDK編程也就是C / C++端的即編譯出來(lái)的*.so動(dòng)態(tài)加載的校驗(yàn)扰柠。
總之粉铐,
Java層一般通過(guò)getPackageManager().getPackageInfo.signatures來(lái)獲取簽名信息。
NDK層一般調(diào)用Native方法/DLL/Lua腳本等通過(guò)獲取Java的context/Activity對(duì)象卤档,動(dòng)態(tài)JNI反射調(diào)用getPackageInfo等來(lái)獲取簽名蝙泼。
好了,話不多說(shuō)劝枣,切入正題汤踏。
群里聊天,小伙伴找我去除某款圖像處理軟件的廣告舔腾,介于此軟件已一年未更新溪胶,且互聯(lián)網(wǎng)上出現(xiàn)的修改版均無(wú)法使用。琢唾。载荔。。那么采桃。懒熙。開(kāi)搞。普办。工扎。。
apk重簽名衔蹲,閃退肢娘,斷定有簽名校驗(yàn)。
直接拖入AndroidKiller大法舆驶,一段等待之后反編譯完畢橱健。
因?yàn)闆](méi)有錯(cuò)誤提示,那么對(duì)整個(gè)項(xiàng)目搜索
signatures
或
[Landroid/content/pm/Signature
或
Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature
或
Ljava/security/Signature;->verify([B)Z
等一系列可能調(diào)用或者判斷簽名的方法
我們基本找到四處可能為簽名對(duì)比函數(shù)的驗(yàn)證沙廉,我們讓其強(qiáng)制返回true拘荡。
滿心歡喜的回編譯,安裝撬陵。珊皿。。巨税。蟋定。
結(jié)果。草添。依舊閃退驶兜。。。內(nèi)心無(wú)數(shù)匹你懂得馬奔馳而過(guò)抄淑。犀盟。。蝇狼。
看到\lib目錄和\assets\lib目錄下的.so文件,我倒是有些懷疑懸疑在.so動(dòng)態(tài)文件中倡怎。
繼續(xù)對(duì)整個(gè)項(xiàng)目搜索
loadLibrary
或
Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
等一系列讀取.so文件的方法
我們得到了三個(gè)結(jié)果迅耘,前兩個(gè)是圖像處理的lib,第三個(gè)嘛监署。颤专。。別急澳品Α栖秕!先等等。晓避。簇捍。
以armeabi-v7a架構(gòu)為例,我們把所有l(wèi)ib都弄到一起俏拱,用EditPlus或者UltraEdit呀notepad++呀之類的編輯器來(lái)全局搜索signature
看看我們得到了什么~
我的天哪暑塑,有戲啊锅必!
說(shuō)時(shí)遲那時(shí)快事格,我的IDA已經(jīng)饑渴難耐。
New-Open-Ok一氣呵成搞隐!
打開(kāi)文本查找:
搜索signature
勾選上Find all occurences
搜索完畢驹愚,沒(méi)什么說(shuō)的,妥妥的在5個(gè)Function中找到
雙擊第一個(gè)Function跳過(guò)去
右鍵選擇Graph view
切換圖形視圖
通過(guò)視圖劣纲,我們找到了一個(gè)關(guān)鍵跳轉(zhuǎn)(可以通過(guò)Ctrl+鼠標(biāo)滑輪來(lái)調(diào)整視圖縮放)
右鍵選擇Text view
切換回文本視圖
其對(duì)應(yīng)的就是文本視圖界面中的
F5看一下C語(yǔ)言代碼(這樣做的前提是逢捺,你的IDA Pro必須支持F5功能)
通過(guò)分析C代碼我們得知這里將獲取到的簽名信息進(jìn)行判斷,
由此我們得知BEQ指令就是問(wèn)是不是不相等味廊,不相等那么為真的意思蒸甜。而查閱之后印證了我們的判斷:
BEQ指令是“相等(或?yàn)?)跳轉(zhuǎn)指令”,
BNE指令是“不相等(或不為0)跳轉(zhuǎn)指令”余佛,
B指令是“無(wú)條件跳轉(zhuǎn)指令”柠新,
CBZ 指令是“比較,為零則跳轉(zhuǎn)”辉巡,
CBNZ指令是“比較恨憎,為非零則跳轉(zhuǎn)”。
通過(guò)工具,我們發(fā)現(xiàn):
BNE跳轉(zhuǎn)指令對(duì)應(yīng)的HEX機(jī)器碼是D1憔恳,
BEQ跳轉(zhuǎn)指令對(duì)應(yīng)的HEX機(jī)器碼是D0瓤荔,
CBZ跳轉(zhuǎn)指令對(duì)應(yīng)的HEX機(jī)器碼是B1,
CBNZ跳轉(zhuǎn)指令對(duì)應(yīng)的HEX機(jī)器碼是B9钥组。
回過(guò)頭來(lái)输硝,簡(jiǎn)單的看一下指令流程,BEQ下面是exit方法程梦,則說(shuō)明不能跳轉(zhuǎn)指令為簽名驗(yàn)證失敗点把,反向邏輯一下,把BEQ指令改為相反的BNE指令即可屿附。
修改方式一:我們可以在HEX界面右鍵Edit
將D0改為D1郎逃,再右鍵Apply changes
來(lái)保存修改,需要注意的是挺份,在IDA中的修改僅僅是為了驗(yàn)證我們修改的正確與否褒翰,源文件并不會(huì)改變,我們可以定位修改位置后再利用010Editor匀泊、UltraEdit等編輯器來(lái)對(duì)源文件進(jìn)行修改优训。
驗(yàn)證發(fā)現(xiàn)BEQ已經(jīng)修改為BNE
修改方式二:當(dāng)然,強(qiáng)大的IDA怎么可能沒(méi)有修改后保存的功能呢各聘。我們可以使用Edit->Patch Program菜單來(lái)方便的進(jìn)行修改保存型宙。
(需要注意的是,Patch Program菜單是GUI版本的IDA的一項(xiàng)隱藏功能伦吠,用戶需要編輯idagui.cfg配置文件才能激活該菜單妆兑, 編輯IDA配置文件cfg目錄下的idagui.cfg,修改DISPLAY_PATCH_SUBMENU=YES毛仪,重啟IDA即可)
首先我們?cè)贗DA View 中顯示十六進(jìn)制機(jī)器碼, Options -> General -> Disassembly -> Number of opcode bytes = 8
然后Edit->Patch Program->Change byte
將D0改為D1搁嗓,OK
然后Edit->Patch Program->Apple patches to input file
OK即可
同理,我們找到其他方法中的跳轉(zhuǎn)點(diǎn)來(lái)進(jìn)行反向邏輯箱靴,保存so文件腺逛,覆蓋原文件,回編譯衡怀,安裝棍矛。完美運(yùn)行~
具體去廣告過(guò)程不是本次重點(diǎn)所以就不再過(guò)多陳述,另外說(shuō)一點(diǎn)sdk23以上的權(quán)限請(qǐng)求問(wèn)題抛杨,當(dāng)過(guò)完簽名校驗(yàn)并去除廣告后够委,當(dāng)要讀取圖庫(kù)照片來(lái)進(jìn)行處理時(shí),原本應(yīng)該進(jìn)行文件存儲(chǔ)的權(quán)限請(qǐng)求怖现,但是此時(shí)卻FC了茁帽,當(dāng)我手動(dòng)給予權(quán)限后才正常玉罐。想想就苦惱,讓人安裝后邊還得手動(dòng)給權(quán)限潘拨。吊输。。铁追。
不行季蚂,我們得解決了它。我們知道如果APP運(yùn)行在Android 6.0或以上版本的手機(jī)琅束,并且target sdk>=23癣蟋,那么在使用一些相對(duì)敏感的權(quán)限時(shí),需要征求用戶的許可狰闪。比如讀寫(xiě)sdcard,攝像濒生,聯(lián)系人信息等埋泵。 這是Android 6.0,在原有的AndroidManifest.xml聲明權(quán)限的基礎(chǔ)上罪治,新增了運(yùn)行時(shí)權(quán)限動(dòng)態(tài)檢測(cè)丽声。不過(guò)為了兼容性,Android為targetSdkVersion小于23的應(yīng)用默認(rèn)授予了所申請(qǐng)的所有權(quán)限觉义,所以如果你以前的APP設(shè)置的targetSdkVersion低于23雁社,也能正常使用。等于或者大于23晒骇,則必須 request permission,否則會(huì)崩潰閃退霉撵。
當(dāng)我們用apktool反編譯后破壞了complierSdkversion的值,我們可以在apktool.yml中的sdkInfo中添加complierSdkversion: '23'
洪囤,或者干脆我們索性將targetSdkVersion
設(shè)置為22
徒坡,默認(rèn)給它權(quán)限就好了。(complierSdkversion的值和targetSdkVersion的值一定要統(tǒng)一瘤缩,不然會(huì)出錯(cuò))
修改apktool.yml文件完美解決~
步驟回顧:
1喇完、反編譯apk
2、利用關(guān)鍵詞查找簽名調(diào)用
3剥啤、IDA靜態(tài)調(diào)試分析
4锦溪、了解arm指令詳情作用
5、修改邏輯跳轉(zhuǎn)繞過(guò)簽名校驗(yàn)
總結(jié):
本文主要介紹破解安卓NDK端native方法動(dòng)態(tài)JNI反射so文件簽名校驗(yàn)的方法府怯。