久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Apk脫殼圣戰(zhàn)之---脫掉“360加固”的殼

 quasiceo 2016-06-28

2016-06-28 09:51

目錄(?)[+]

一、前言

現(xiàn)在主流的加固平臺(tái)有:梆梆加固,,愛加密,,360加固,騰訊加固,,在之前的一篇文章中介紹了:如何脫掉“愛加密”的殼,,現(xiàn)在這里要脫掉另外一個(gè)平臺(tái)的殼:360加固,因?yàn)橛辛酥暗拿摎そ?jīng)驗(yàn),,很多基礎(chǔ)知識(shí)和準(zhǔn)備工作這里就不詳細(xì)介紹了,,為了能夠脫掉他家的殼,用一個(gè)案例來去360平臺(tái)進(jìn)行加固,,然后進(jìn)行脫殼,。下面就來開始脫殼:


二、分析360加固的原理

首先拿到加固之后的apk,,這里為了方便查看內(nèi)部信息,,先不用dex2jar+jd-gui工具進(jìn)行分析了,直接使用我們之前分析了源碼的一個(gè)工具:Jadx,,直接查看:


其實(shí)現(xiàn)在的加固的常規(guī)套路都差不多,,這里看到和之前分析的愛加密加固的形式幾乎一樣,這里的殼Application是StubApplication在attachBaseContext中做一些初始化操作,一般是將assets目錄中的so文件拷貝到程序的沙盒目錄下:/data/data/xxx/files/..,;然后再用System.load進(jìn)行加載,通過查看可以得知源程序apk已經(jīng)被加密了,,就是存放在這里的so中,,之前的文章也是分析了,一般源程序加密之后就存放在那幾個(gè)目錄下,,一般是:dex文件尾部,,libs目錄,assets目錄,。


下面再來看一下他的AndroidManifest.xml文件:


找到了他的入口Activity了,,但是這里沒有Android:debuggable="true",所以程序是不能被調(diào)試的,,所以我們需要添加這個(gè)屬性,,然后在進(jìn)行回編譯進(jìn)行調(diào)試,這時(shí)候就需要使用到apktool工具了:


好了,,這里看到,,360加固為了防止apktool反編譯功能,添加了一個(gè)qihoo屬性,,這個(gè)屬性apktool不認(rèn)識(shí)就報(bào)錯(cuò)了,,但是我們之前的一篇文章已經(jīng)介紹了:Apktool工具錯(cuò)誤修復(fù),我們有了apktool源碼,,可以直接進(jìn)行修復(fù)的,,然后進(jìn)行反編譯:


反編譯成功了,查看他的AndroidManifest.xml文件內(nèi)容:


的確,,是有一個(gè)屬性qihoo,,這個(gè)就是Android系統(tǒng)在解析apk文件的時(shí)候,發(fā)現(xiàn)不存在的屬性直接略過,,但是apktool工具卻不會(huì),,360加固就是利用這個(gè)漏洞來增加反編譯難度的,但是我們之前的一篇文章中介紹了如何修復(fù),,這里修復(fù)很簡單了,。所以說只要有了apktool源碼,什么都好做了,。

然后我們在添加android:debuggable屬性:


然后回編譯:



這時(shí)候看到,,在回編譯的時(shí)候也是報(bào)錯(cuò)了,說找不到這個(gè)屬性,,為了方便這里直接把a(bǔ)ndroid:qihoo給干掉,,因?yàn)槠鋵?shí)他沒有任何作用的,就是為了干擾反編譯工作的,所以直接去掉即可,,然后在回編譯:


好了,,回編譯成功,然后在進(jìn)行簽名打包即可,。這里就不在介紹了,。


那么從上面我們可以看到,其實(shí)360加固為了防止反編譯,,就利用了Android系統(tǒng)本身在解析apk的時(shí)候,,遇到不認(rèn)識(shí)的屬性直接略過,而apktool工具卻不會(huì)的漏洞來給AndroidManifest.xml中添加一個(gè)混淆反編譯的屬性:qihoo,,幸好我們有源碼,,可以修復(fù)這個(gè)問題,在進(jìn)行反編譯即可,,這里也希望apktool官網(wǎng)能夠及時(shí)修復(fù)這個(gè)漏洞,。為了回編譯成功,我們可以直接把這個(gè)屬性刪除,。不然回編譯也是會(huì)報(bào)錯(cuò)的,。這個(gè)屬性只是360為了混淆反編譯工作,所以刪除對(duì)程序邏輯沒有任何影響的,。


三,、打開系統(tǒng)的調(diào)試總開關(guān)

這里就要開始介紹本文的第一個(gè)重點(diǎn)了:如何在不需要反編譯的情況下,添加android:debuggable屬性,,就可以進(jìn)行調(diào)試,。

這個(gè)現(xiàn)在已經(jīng)有很多工具可以做了,先來說說具體的原理吧:

其實(shí)Android中有一些常用的配置信息都是存放在一個(gè)文件中,,比如設(shè)備的系統(tǒng),,版本號(hào),cpu型號(hào)等信息,,而這個(gè)文件位置在:

/system/build.prop


我們查看文件的內(nèi)容,,可以看到很多設(shè)備的信息,而且這些ro開頭的表示這些屬性值是只讀的,,不能進(jìn)行修改的,。

同時(shí)Android中提供了兩個(gè)命令來操作這些信息:getprop和setprop命令:


查看系統(tǒng)的sdk版本號(hào)


設(shè)置系統(tǒng)的sdk版本號(hào)為22,可是這里并沒有修改成功,,原因就是因?yàn)閞o開頭的屬性是不允許后期修改的,,改也是可以修改的,需要重新編譯系統(tǒng)鏡像文件boot.img,,但是這里并不是本人介紹的重點(diǎn)了,。


既然Android中的一些系統(tǒng)屬性值存放在一個(gè)文件中的,,而且這些值是只讀的,當(dāng)然不僅可以通過getprop命令讀取,,有一個(gè)api也是可以直接讀取的,,就是:System.getProperty("ro.build.version.sdk");其實(shí)這個(gè)方法是native層實(shí)現(xiàn)的,具體就不分析了,。

那么這個(gè)文件是存儲(chǔ)這些屬性值的,,那么是誰來進(jìn)行解析加載到內(nèi)存中,能夠給每個(gè)app都能訪問到呢,?


這個(gè)工作就是init.rc進(jìn)程操作的,我們應(yīng)該了解了系統(tǒng)啟動(dòng)的時(shí)候第一步就是解析init.rc文件,,這個(gè)文件是在系統(tǒng)的根目錄下,,這里會(huì)做很多初始化操作,這里不詳細(xì)分析了,,后面再分析Android中系統(tǒng)啟動(dòng)流程的時(shí)候在詳細(xì)分析,。這里同時(shí)會(huì)做屬性文件的解析工作,所以,,Android 屬性系統(tǒng)通過系統(tǒng)服務(wù)提供系統(tǒng)配置和狀態(tài)的管理,。為了讓運(yùn)行中的所有進(jìn)程共享系統(tǒng)運(yùn)行時(shí)所需要的各種設(shè)置值,系統(tǒng)會(huì)開辟一個(gè)屬性存儲(chǔ)區(qū)域,,并提供訪問該內(nèi)存區(qū)域的 API,。所有進(jìn)程都可以訪問屬性值,但是只有 init 進(jìn)程可以修改屬性值,,其他進(jìn)程若想修改屬性值,需要向 init 進(jìn)程發(fā)出請(qǐng)求,,最終由 init 進(jìn)程負(fù)責(zé)修改屬性值。


那么上面說到的是system/build.prop文件,。里面主要是系統(tǒng)的配置信息,其實(shí)還有一個(gè)重要文件在根目錄下面:default.prop:


這里有一個(gè)重要屬性:ro.debuggable,,對(duì)這里就是關(guān)系到系統(tǒng)中每個(gè)應(yīng)用是否能夠被調(diào)試的關(guān)鍵,。其實(shí)在Android系統(tǒng)中一個(gè)應(yīng)用能否被調(diào)試是這么判斷的:

當(dāng)Dalvik虛擬機(jī)從android應(yīng)用框架中啟動(dòng)時(shí),系統(tǒng)屬性ro.debuggable為1,,如果該值被置1,系統(tǒng)中所有的程序都是可以調(diào)試的,。如果系統(tǒng)中的 ro.debuggable 為0,則會(huì)判斷程序的AndroidManifest.xml中application標(biāo)簽中的 android:debuggable元素是否為true,,如果為true則開啟調(diào)試支持,。


好了到這里,,我們可以總結(jié)一下了:

Android系統(tǒng)中有一個(gè)可以調(diào)試所有設(shè)備中的應(yīng)用的開關(guān),在根目錄中的default.prop文件中的ro.debuggable屬性值,,如果把這個(gè)值設(shè)置成1的話,,那么設(shè)備中所有應(yīng)用都可以被調(diào)試,即使在AndroidManifest.xml中沒有android:debuggable=true,,還是可以調(diào)試的,。而這些系統(tǒng)屬性的文件system/build.prop和default.prop,都是init進(jìn)程來進(jìn)行解析的,,系統(tǒng)啟動(dòng)的時(shí)候就會(huì)去解析init.rc文件,,這個(gè)文件中有配置關(guān)于系統(tǒng)屬性的解析工作信息。然后會(huì)把這些系統(tǒng)屬性信息解析到內(nèi)存中,,提供給所有app進(jìn)行訪問,,這塊信息也是內(nèi)存共享的。但是這些ro開頭的屬性信息只能init進(jìn)程進(jìn)行修改,。下面來分析一下修改這個(gè)屬性值的三種方式:


第一種:直接修改default.prop文件中的值,,然后重啟設(shè)備

那么現(xiàn)在如果按照上面的目的:就是不需要反編譯apk,添加android:debuggable屬性的話,,直接修改default.prop文件,把ro.debuggable屬性改成1即可,,但是通過上面的分析,,修改完成之后肯定需要重啟設(shè)備的,因?yàn)樾枰宨nit進(jìn)程重新解析屬性文件,,把屬性信息加載內(nèi)存中方可起作用的,。但是并沒有那么順利,在實(shí)踐的過程中,,修改了這個(gè)屬性,,結(jié)果出現(xiàn)的結(jié)果就是設(shè)備死機(jī)了,其實(shí)想想也是正常的,,如果屬性能夠通過這些文件來修改的話,,那就感覺系統(tǒng)會(huì)出現(xiàn)各種問題了,,感覺系統(tǒng)是不會(huì)讓修改這些文件的內(nèi)容的。


第二種:改寫系統(tǒng)文件,,重新編譯系統(tǒng)鏡像文件,,然后刷入到設(shè)備中

那么上面修改default.prop文件,結(jié)果導(dǎo)致死機(jī),,最終也是沒有修改成功,,我們還有什么辦法呢?其實(shí)上面已經(jīng)提到過一次了,,就是這些屬性文件其實(shí)是在系統(tǒng)鏡像文件boot.img在系統(tǒng)啟動(dòng)的時(shí)候,,釋放到具體目錄中的,也就是說如果我們能夠直接修改boot.img中的這個(gè)屬性即可,,那么這個(gè)操作是可以進(jìn)行的,但是困難那是不一般的順利,,至少我沒成功過,,修改系統(tǒng)文件,,然后重新編譯鏡像文件,,最后在刷到設(shè)備中,。這個(gè)過程我嘗試過是失敗了,,不過理論上是可以的,。而且這種方式如果成功了,,那么這個(gè)設(shè)備就是永遠(yuǎn)可以進(jìn)行各種應(yīng)用的調(diào)試了,。


第三種:注入init進(jìn)程,修改內(nèi)存中的屬性值

那么上面直接重新編譯boot.img,,然后在刷到設(shè)備中的工作是失敗的,,那么還有其他方法嗎,?肯定是有的,,我們其實(shí)在上面分析了,,init進(jìn)程會(huì)解析這個(gè)屬性文件,,然后把這些屬性信息解析到內(nèi)存中,,給所有app進(jìn)行訪問使用,,所以在init進(jìn)程的內(nèi)存塊中是存在這些屬性值的,,那么這時(shí)候就好辦了,,有一個(gè)技術(shù)可以做到了,就是進(jìn)程注入技術(shù),,我們可以使用ptrace注入到init進(jìn)程,,然后修改內(nèi)存中的這些屬性值,,只要init進(jìn)程不重啟的話,,那么這些屬性值就會(huì)起效。好了,,這個(gè)方法可以嘗試,,但是這個(gè)方法有一個(gè)弊端,,就是如果init進(jìn)程掛了重啟的話,,那么設(shè)置就沒有任何效果了,必須重新操作了,,所以有效期不是很長,,但是一般情況下只要保證設(shè)備不重啟的話,init進(jìn)程會(huì)一直存在的,,而且如果發(fā)生了init進(jìn)程掛掉的情況,那么設(shè)備肯定會(huì)重啟的,。到時(shí)候在重新操作一下即可,。


好了上面分析了三種方式去設(shè)置系統(tǒng)中的調(diào)試屬性總開關(guān),那么最后一種方式是最靠譜的,。

而且思路也很簡單,,但是我們不會(huì)重新去寫這個(gè)代碼邏輯的,因?yàn)橐呀?jīng)有大神做了這件事,,具體工具后面會(huì)給出下載地址:

這個(gè)工具用法很簡單,,首先把可執(zhí)行文件mprop拷貝到設(shè)備中的目錄下,然后運(yùn)行命令:

./mprop ro.debuggable 1


這個(gè)工具可以修改內(nèi)存中所有的屬性值,,包括機(jī)型信息,。

這里修改完成之后,,使用getprop命令在查看值,發(fā)現(xiàn)修改成功了,,但是需要注意的是,我們修改的是內(nèi)存的值,,而不是文件中的值,。所以default.prop文件中的內(nèi)容是沒有發(fā)生變化的,。


這時(shí)候,,我們可以使用Eclipse的DDMS來查看可以調(diào)試的應(yīng)用列表:


當(dāng)然也可以使用adb jdwp命令來查看可以調(diào)試的進(jìn)程id:


但是可惜的是,發(fā)現(xiàn)還是沒有展示設(shè)備中所有的應(yīng)用,,其實(shí)這里是有一個(gè)細(xì)節(jié)問題了,,因?yàn)槲覀冸m然修改了內(nèi)存值,,但是有一個(gè)進(jìn)程我們需要重啟一下,哪個(gè)進(jìn)程呢,?那就是adbd這個(gè)進(jìn)程,,這個(gè)進(jìn)程是adb的守護(hù)進(jìn)程,,就是設(shè)備連接信息傳輸后臺(tái)進(jìn)程,,所以想看到可以調(diào)試的進(jìn)程信息的話,,那么需要重啟這個(gè)進(jìn)程,,這樣連接信息才會(huì)更新,。

重啟這個(gè)進(jìn)程很簡單:直接使用stop;start命令即可


其實(shí)這是兩個(gè)命令,,用分號(hào)隔開,,首先是干掉進(jìn)程,,然后在重啟,。

運(yùn)行完命令之后,再去看DDMS窗口信息:


這時(shí)候所有的應(yīng)用進(jìn)程都是可以調(diào)試的了,,這時(shí)候我們在使用dumpsys package命令查看一個(gè)應(yīng)用的包信息:


這里可以看到,這個(gè)應(yīng)用的flags標(biāo)志中并沒有debuggable屬性值,,但是這個(gè)應(yīng)用是可以調(diào)試的,。所以看到ro.debuggable這個(gè)是總開關(guān),,只要他為1,開啟的話,,即使沒有android:debuggable也是可以的了,。


好了到這里,我們來總結(jié)一下:

1,、我們的目的是怎么在不需要反編譯apk包,,添加android:debuggable屬性,就可以進(jìn)行apk的調(diào)試?

2,、我們通過分析系統(tǒng)屬性文件和系統(tǒng)啟動(dòng)流程以及解析系統(tǒng)屬性文件的流程,,知道了設(shè)備中關(guān)于調(diào)試有一個(gè)總開關(guān)屬性值:ro.debuggable,默認(rèn)是0,,不開啟的。那么這時(shí)候我們就可以猜想有這幾種方式可以去修改,。

3、分析了三種方式去修改這個(gè)屬性值:

第一種方式:直接修改default.prop文件中的這個(gè)字段值,,但是可惜的是修改失敗,,在修改的過程中出現(xiàn)死機(jī),,重啟設(shè)備之后,,屬性值還是0。

第二種方式:修改系統(tǒng)源碼的編譯腳本,,直接修改屬性值,然后重新編譯鏡像文件boot.img,,然后刷入到設(shè)備中,,但是在實(shí)踐的過程中并沒有成功,,所以放棄了,,而且這種方式有一個(gè)好處就是一旦修改了,,只要不在重新刷系統(tǒng),,那么這個(gè)字段將永遠(yuǎn)有效。

第三種方式:注入到init進(jìn)程,,修改內(nèi)存中的這些系統(tǒng)屬性值,這種方式實(shí)現(xiàn)是最簡單的,,但是有一個(gè)問題,就是一旦設(shè)備重啟,init進(jìn)程重新解析default.prop文件的話,,那么ro.debuggable值將又重新被清空,,需要再次注入修改。

4,、最后采用了第三種方式,,不過網(wǎng)上已經(jīng)有人寫了這樣的工具,,用法也很簡單:./mprop ro.debuggable 1,;但是修改完成之后,,一定要記得重新啟動(dòng)adbd進(jìn)程,這樣才能夠獲取到可以調(diào)試應(yīng)用信息,。

5、使用工具修改完成之后,,在Eclipse中的DDMS窗口發(fā)現(xiàn),,設(shè)備中的所有應(yīng)用都處于可以調(diào)試狀態(tài)了。也就是說我們的操作成功了,。


那么上面的這個(gè)過程成功之后的意義還是很大的:標(biāo)志著我們以后如果是單純的想讓一個(gè)apk能夠被調(diào)試,,去反編譯在添加屬性值的話,其實(shí)這種方式很高效的,??梢宰屓我庖粋€(gè)apk出于被調(diào)試狀態(tài)。


四,、開始脫殼

講完了上面的一個(gè)重點(diǎn)之后,,下面我們就開始來講解本文的另外一個(gè)重點(diǎn),開始脫殼了,。

第一步:開啟android_server



第二步:端口轉(zhuǎn)發(fā)



第三步:啟動(dòng)應(yīng)用

adb shell am start -D -n com.CMapp/com.e4a.runtime.android.mainActivity



第四步:開啟IDA,,附加進(jìn)程



第五步:設(shè)置Debugger Option選項(xiàng)



第六步:運(yùn)行jdb調(diào)試等待

jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=10265


注意:這里需要注意了,因?yàn)槲覀兏牧讼到y(tǒng)的ro.debuggable屬性,,設(shè)備中所有的應(yīng)用都處于可調(diào)式狀態(tài),,基本端口8700已經(jīng)被占用了,那么這時(shí)候需要使用被調(diào)試程序的獨(dú)有端口了,,可以在DDMS窗口進(jìn)行查看,。


第七步:關(guān)鍵函數(shù)下斷點(diǎn)


首先找到mmap函數(shù)的內(nèi)存地址,這里可以直接使用G鍵,,通過函數(shù)名來跳轉(zhuǎn):


注意:這里和之前的脫愛加密的殼方法可能不一樣了,,還記得之前脫愛加密的殼的時(shí)候,給fopen和fgets函數(shù)下斷點(diǎn),,因?yàn)槿绻蟹凑{(diào)試的話,,肯定是讀取/proc/pid/status文件中的TracerPid字段值的,然后修改TracerPid值為0即可,,但是這個(gè)方法對(duì)360加固的不好使了,,因?yàn)?60加固的反調(diào)試是通過mmap函數(shù)來讀取/proc/pid/status,所以這里需要給mmap函數(shù)下斷點(diǎn)了,,而且后面還會(huì)看到給dvmDexFileOpenPartial這個(gè)函數(shù)下斷點(diǎn)也不好使了,,原因是360加固自己在底層實(shí)現(xiàn)了解析dex的函數(shù)來替代了這個(gè)dvmDexFileOpenPartial函數(shù),。但是不管是他自己實(shí)現(xiàn)dex解析加載,最終都是需要把dex文件加載到內(nèi)存中,,還是得用mmap函數(shù)來進(jìn)行操作,。所以在脫360加固的殼的時(shí)候mmap函數(shù)是重點(diǎn),。


好了給mmap函數(shù)下了斷點(diǎn),,下面就F9運(yùn)行程序吧:


進(jìn)入到了mmap的斷點(diǎn)處,這里因?yàn)閙map函數(shù)代碼比較長,,為了節(jié)省時(shí)間,,我們可以在mmap函數(shù)的結(jié)束處下一個(gè)斷點(diǎn),然后直接F9運(yùn)行到函數(shù)的結(jié)尾處,,因?yàn)橄到y(tǒng)中有很多個(gè)so需要加載到內(nèi)存中,,所以mmap函數(shù)會(huì)執(zhí)行多次,但是其實(shí)我們最關(guān)心的是加載我們自己的so文件,,即libjiagu.so文件,,因?yàn)檫@個(gè)才是我們的native層代碼,所以等出現(xiàn)如下界面:


這時(shí)候,,說明這個(gè)so文件被加載到內(nèi)存中了,,也就是程序的native層代碼開始執(zhí)行了,注意不能在F9了,,而是使用F8單步調(diào)試:


F8單步運(yùn)行到這里的時(shí)候,,遇到一個(gè)問題,就是F8了很多次,,始終在這個(gè)地方執(zhí)行,,后來分析了arm指令之后,發(fā)現(xiàn)原來這里是一個(gè)循環(huán),,初始值是0,,存儲(chǔ)在R11中,然后逐步加1,,和R3中存儲(chǔ)的閾值作比較,,通過查看寄存器的值,發(fā)現(xiàn)R3寄存器中是A7,,所以這里得去修改寄存器R11的值了,,不然我們得單步A7次,這里直接把R11值修改為A6:


修改寄存器也是很容易的,,直接右擊寄存器:


點(diǎn)擊Modify value:


點(diǎn)擊OK,,之后再來看看R11的寄存器的值:


修改成功了,這時(shí)候在單步F8,,兩次之后就執(zhí)行完了循環(huán)了,,從這里也可以看到,,這個(gè)地方也算是為了防止被調(diào)試,加大調(diào)試成本的一種方式,。繼續(xù)往下走:


到這里,,執(zhí)行完BL之后就退出調(diào)試界面了,嘗試多次都一樣,,所以猜想反調(diào)試肯定在這里,,可以F7跟進(jìn)去看看:


到BLX這里,每次之前完也是退出調(diào)試界面,,所以這里還得F7單步進(jìn)入看看:


這里看到了一行重要的arm指令:CMP比較指令,,而且是和0比較,很可能這里就是比較TracerPid的值是否為0,,如果不為0就退出,,可以查看R0寄存器的內(nèi)容:


然后在查看被調(diào)試進(jìn)程的TracerPid的值:


果然R0存儲(chǔ)的是TracerPid的值,為了驗(yàn)證正確性,,這里繼續(xù):


果然,,運(yùn)行到了自殺的地方,一直單步運(yùn)行:


退出程序了,。


那么上面就知道了反調(diào)試的地方,,就好辦了,直接修改寄存器R0的值為0即可:


然后繼續(xù)單步F8運(yùn)行,,后面還有一個(gè)CMP和0進(jìn)行比較的地方,,我們一樣進(jìn)行置零操作,再次單步F8,,當(dāng)運(yùn)行到此處的時(shí)候:


看到memcpy函數(shù)的時(shí)候,,這時(shí)候可以直接運(yùn)行F9,又會(huì)執(zhí)行到mmap那里,,然后依次F9,,還是運(yùn)行到了上面的那個(gè)循環(huán),這樣依次類推,,在這個(gè)過程中我運(yùn)行了7次循環(huán),,改了R0值改了9次,所以這個(gè)地方會(huì)執(zhí)行多次是正常的,,但是這里在我多次調(diào)試之后總了一個(gè)好的方法,,就是看到多次執(zhí)行的路線都差不多:

mmap函數(shù)=》循環(huán)=》(MOV R0,R8)BL=》(MOV LR,,R4)BLX=》CMP R0,,#0=》mmap....

這個(gè)過程中,其實(shí)為了簡便我們可以

1》在mmap函數(shù)的開始處,,結(jié)束處下一個(gè)斷點(diǎn),,這兩個(gè)斷點(diǎn)是為了后面加載內(nèi)存的dex文件做準(zhǔn)備

2》在循環(huán)處下一個(gè)斷點(diǎn),,這個(gè)斷點(diǎn)是為了修改循環(huán)值,節(jié)省時(shí)間

3》在BL處下個(gè)斷點(diǎn),,是為了進(jìn)入BLX

4》在BLX處下個(gè)斷點(diǎn),,是為了進(jìn)入比較TracerPid處

5》在CMP下斷點(diǎn),是為了修改TracerPid的值

同時(shí)在這個(gè)過程中,,需要使用F9,,直接跳轉(zhuǎn)到下一個(gè)斷點(diǎn),高效,,只有在到達(dá)了CMP處的時(shí)候,,要用F8單步調(diào)試,,而且這個(gè)地方一定要小心,,不能按錯(cuò)了,不然又得從頭再來,,我吃了很多次虧,,也重來了很多次。只要當(dāng)看到了memcpy函數(shù)的時(shí)候,,再次F9到下一個(gè)斷點(diǎn)處,。更需要注意的是:每次到達(dá)mmap斷點(diǎn)處的時(shí)候,一定要看當(dāng)前棧信息的視圖窗口,,看看是否出現(xiàn)了classes.dex的字樣,,因?yàn)樽罱K都是使用mmap來把解密之后的dex加載到內(nèi)存中的,所以這里一定要注意,,是本次調(diào)試的核心,。

當(dāng)然這個(gè)只是個(gè)人的調(diào)試思路,每個(gè)人都有自己的思路,,只要能成功都可以,。


就這樣來回搞了幾次之后,終于看到了曙光:


當(dāng)再次來到了mmap函數(shù)處的時(shí)候,,終于看到了classes.dex字樣了,,說明這里開始解密dex然后進(jìn)行加載到內(nèi)存了,這時(shí)候不能在F9跳轉(zhuǎn)了,,而是F8單步運(yùn)行,,然后查看R0寄存器的值:


每次都是執(zhí)行完__mmap2這個(gè)函數(shù)之后,R0就有值了,,每次看到R0中有值的時(shí)候,,可以到Hex View窗口中使用G鍵開始地址跳轉(zhuǎn),查看是否為dex內(nèi)容:


如果發(fā)現(xiàn)不是,,就還是單步F8,,知道m(xù)map函數(shù)結(jié)束,,然后再次F9,到達(dá)mmap函數(shù)開始處,,時(shí)刻看緊Hex View,,棧窗口,R0寄存器這三個(gè)地方的值:


在多次嘗試之后,,終于成功了,,這里看到了熟悉的dex文件的頭信息,關(guān)于dex文件的頭部信息可以看這篇文章:Dex文件格式解析


所以這里在頭部信息的第33個(gè)字節(jié)然后連續(xù)4個(gè)字節(jié)就是dex的長度了,,那么現(xiàn)在有了dex在內(nèi)存中的其實(shí)位置,,長度大小,下面就可以使用Shirt+F2打開腳本執(zhí)行窗口,,dump出內(nèi)存中的dex數(shù)據(jù):

static main(void)
{
  auto fp, begin, end, dexbyte;
  fp = fopen("E:\\dump.dex", "wb");
  begin = 0x755A9000;
  //偏移0x20處,,取4字節(jié)為dex文件大小
  end = 0x755A9000 + 0x0004BC38;  
  for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
      fputc(Byte(dexbyte), fp);
}


保存到E:\dump.dex,然后在使用Jadx工具進(jìn)行查看:


這里可以查看到源碼了,,而且類名,,方法名,變量名都是用中文來命名的,,感覺好不習(xí)慣,,但是Java中是支持這么干的,因?yàn)镴ava采用的是Unicode編碼的,。


案例下載:http://download.csdn.net/detail/jiangwei0910410003/9561416


五,、脫殼總結(jié)

好了到這里,我們就成功了脫掉了360加固的殼了,,下面來總結(jié)一下他的殼的特點(diǎn)和調(diào)試需要注意的點(diǎn):

1,、首先360加固依然是外部套一個(gè)Application殼:StubApplication,源程序加密存放在libjiagu.so,,放在了assets目錄下,,在Application啟動(dòng)的時(shí)候,釋放到應(yīng)用的沙盒目錄files下面,,然后在使用System.load方法進(jìn)行加載,,這個(gè)和愛加密的方式是一樣的

2、關(guān)于360加固的反調(diào)試,,依然使用的是讀取/proc/[pid]/status中的TracerPid字段值,,判斷是否為0,但是這里和愛加密不一樣的是,,在讀取這個(gè)文件的時(shí)候不是用的fopen系統(tǒng)函數(shù),,而是mmap系統(tǒng)函數(shù),所以在解決反調(diào)試的時(shí)候需要給這個(gè)函數(shù)下斷點(diǎn)。

3,、360加固底層不是采用dvmDexFileOpenPartial這個(gè)系統(tǒng)函數(shù)來解析dex然后加載到內(nèi)存中的,,而是自己實(shí)現(xiàn)了一個(gè)函數(shù),所以給這個(gè)函數(shù)下斷點(diǎn),,然后獲取參數(shù)值來dump內(nèi)存中的dex數(shù)據(jù)是行不通的,,但是有一個(gè)思路就是不管他用哪個(gè)函數(shù)去解析dex加載到內(nèi)存,最終都得使用mmap這個(gè)系統(tǒng)函數(shù)來操作,,所以還得給這個(gè)函數(shù)下斷點(diǎn),,所以這里在調(diào)試的時(shí)候需要時(shí)刻注意的是當(dāng)斷點(diǎn)到達(dá)了mmap函數(shù)處的時(shí)候,需要觀察Stack View棧窗口中是否出現(xiàn)了classes.dex字樣,,如果出現(xiàn)了,,說明開始解密dex文件,準(zhǔn)備加載到內(nèi)存中了,,那么這時(shí)候需要觀察R0寄存器的值,,然后在Hex View中跳轉(zhuǎn)到指定內(nèi)存地址,可以觀察到是否為dex內(nèi)存數(shù)據(jù)

4,、在觀察是否為內(nèi)存數(shù)據(jù)的時(shí)候,,需要注意dex文件是有自己的文件格式的,,那么頭信息就是個(gè)根據(jù),,所以我們可以查看開頭為:dex.35 這樣的內(nèi)容來判斷此處為dex數(shù)據(jù),因?yàn)閐ex頭部信息中也有dex的文件大小,,那么這時(shí)候就可以使用腳本dump處內(nèi)存中的dex數(shù)據(jù)了,。

5、在調(diào)試的過程中,,會(huì)發(fā)現(xiàn)很多斷點(diǎn)多次執(zhí)行,,特別是有一個(gè)循環(huán),需要我們修改寄存器的值來快速結(jié)束循環(huán),,而且在關(guān)鍵處下斷點(diǎn),,也是加快調(diào)試效率的。


六,、技術(shù)概要

1,、本文開始的時(shí)候介紹了通過注入系統(tǒng)init進(jìn)程,修改內(nèi)存中的系統(tǒng)屬性值:ro.debuggable,,讓設(shè)備中所有的應(yīng)用都可以被調(diào)試,,這個(gè)功能將對(duì)后續(xù)逆向破解有重大意義,也會(huì)省去了反編譯的工作,。所以這個(gè)方式還是很具有里程碑意義的,。

2、在脫愛加密的殼的時(shí)候,,學(xué)習(xí)到了給fopen和fgets這兩個(gè)系統(tǒng)函數(shù)下斷點(diǎn)來解決反調(diào)試,,在這里我們又多了一個(gè)下斷點(diǎn)的好去處就是給mmap下斷點(diǎn),,當(dāng)發(fā)現(xiàn)給fopen函數(shù)下斷點(diǎn)不好使的時(shí)候,在嘗試給mmap下個(gè)斷點(diǎn)吧,。

3,、在脫愛加密的殼的時(shí)候,給dvmDexFileOpenPartial函數(shù)下斷點(diǎn),,來獲取dex在內(nèi)存的起始地址和大小,,從而dump處內(nèi)存中的dex數(shù)據(jù),但是360加固并沒有走這個(gè)函數(shù),,因?yàn)樵诮o這個(gè)函數(shù)下斷點(diǎn)的時(shí)候,,他壓根沒走到,所以斷定它內(nèi)部使用了其他的函數(shù)去解析dex的,,然后加載到內(nèi)存中的,,但是如果最后加載到內(nèi)存中,那肯定要用到mmap函數(shù),,所以只要給mmap函數(shù)下斷點(diǎn)即可,。


七、總結(jié)

本篇文章就介紹了如何脫掉360平臺(tái)加固的apk應(yīng)用的殼,,在結(jié)合之前的一篇脫掉愛加密家的殼的知識(shí),,看到現(xiàn)在在脫殼的時(shí)候其實(shí)就兩點(diǎn),一點(diǎn)是找到關(guān)鍵處解決反調(diào)試,,一般都是fopen,,fgets,mmap,,open等系統(tǒng)函數(shù)下斷點(diǎn),,還有一點(diǎn)就是如何找到內(nèi)存中dex的起始地址和dex的大小,這個(gè)一般現(xiàn)在就是dvmDexFileOpenPartial函數(shù)下斷點(diǎn),,還有就是給mmap函數(shù)下斷點(diǎn),。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多