日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > 綜合技術(shù) > Apk脫殼圣戰(zhàn)之---脫掉“360加固”的殼

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

來(lái)源:程序員人生   發(fā)布時(shí)間:2016-08-17 09:49:20 閱讀次數(shù):19789次

1、前言

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


2、分析360加固的原理

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


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


下面再來(lái)看1下他的AndroidManifest.xml文件:


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


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


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


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

然后我們?cè)谔砑觓ndroid:debuggable屬性:


然后回編譯:



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


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


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


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

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

這個(gè)現(xiàn)在已有很多工具可以做了,先來(lái)講說(shuō)具體的原理吧:

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

/system/build.prop


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

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


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


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


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

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


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


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


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

當(dāng)Dalvik虛擬機(jī)從android利用框架中啟動(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則開(kāi)啟調(diào)試支持。


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

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


第1種:直接修改default.prop文件中的值,然后重啟裝備

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


第2種:改寫(xiě)系統(tǒng)文件,重新編譯系統(tǒng)鏡像文件,然后刷入到裝備中

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


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

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


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

而且思路也很簡(jiǎn)單,但是我們不會(huì)重新去寫(xiě)這個(gè)代碼邏輯的,由于已有大神做了這件事,具體工具后面會(huì)給出下載地址:

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

./mprop ro.debuggable 1


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

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


這時(shí)候候,我們可使用Eclipse的DDMS來(lái)查看可以調(diào)試的利用列表:


固然也能夠使用adb jdwp命令來(lái)查看可以調(diào)試的進(jìn)程id:


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

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


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

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


這時(shí)候候所有的利用進(jìn)程都是可以調(diào)試的了,這時(shí)候候我們?cè)谑褂胐umpsys package命令查看1個(gè)利用的包信息:


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


好了到這里,我們來(lái)總結(jié)1下:

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

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

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

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

第2種方式:修改系統(tǒng)源碼的編譯腳本,直接修改屬性值,然后重新編譯鏡像文件boot.img,然后刷入到裝備中,但是在實(shí)踐的進(jìn)程中并沒(méi)有成功,所以放棄了,而且這類(lèi)方式有1個(gè)好處就是1旦修改了,只要不在重新刷系統(tǒng),那末這個(gè)字段將永久有效。

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

4、最后采取了第3種方式,不過(guò)網(wǎng)上已有人寫(xiě)了這樣的工具,用法也很簡(jiǎn)單:./mprop ro.debuggable 1;但是修改完成以后,1定要記得重新啟動(dòng)adbd進(jìn)程,這樣才能夠獲得到可以調(diào)試?yán)眯畔ⅰ?/span>

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


那末上面的這個(gè)進(jìn)程成功以后的意義還是很大的:標(biāo)志著我們以后如果是單純的想讓1個(gè)apk能夠被調(diào)試,去反編譯在添加屬性值的話,其實(shí)這類(lèi)方式很高效的??勺屓我?個(gè)apk出于被調(diào)試狀態(tài)。


4、開(kāi)始脫殼

講完了上面的1個(gè)重點(diǎn)以后,下面我們就開(kāi)始來(lái)說(shuō)解本文的另外1個(gè)重點(diǎn),開(kāi)始脫殼了。

第1步:開(kāi)啟android_server



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



第3步:?jiǎn)?dòng)利用

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



第4步:開(kāi)啟IDA,附加進(jìn)程



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



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

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


注意:這里需要注意了,由于我們改了系統(tǒng)的ro.debuggable屬性,裝備中所有的利用都處于可調(diào)式狀態(tài),基本端口8700已被占用了,那末這時(shí)候候需要使用被調(diào)試程序的獨(dú)有端口了,可以在DDMS窗口進(jìn)行查看。


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


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


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


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


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


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


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


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


點(diǎn)擊Modify value:


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


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


到這里,履行完BL以后就退出調(diào)試界面了,嘗試屢次都1樣,所以料想反調(diào)試肯定在這里,可以F7跟進(jìn)去看看:


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


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


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


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


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


退出程序了。


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


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


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

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

這個(gè)進(jìn)程中,其實(shí)為了簡(jiǎn)便我們可以

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

2》在循環(huán)處下1個(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è)進(jìn)程中,需要使用F9,直接跳轉(zhuǎn)到下1個(gè)斷點(diǎn),高效,只有在到達(dá)了CMP處的時(shí)候,要用F8單步調(diào)試,而且這個(gè)地方1定要謹(jǐn)慎,不能按錯(cuò)了,不然又得從頭再來(lái),我吃了很屢次虧,也重來(lái)了很屢次。只要當(dāng)看到了memcpy函數(shù)的時(shí)候,再次F9到下1個(gè)斷點(diǎn)處。更需要注意的是:每次到達(dá)mmap斷點(diǎn)處的時(shí)候,1定要看當(dāng)前棧信息的視圖窗口,看看是不是出現(xiàn)了classes.dex的字樣,由于終究都是使用mmap來(lái)把解密以后的dex加載到內(nèi)存中的,所以這里1定要注意,是本次調(diào)試的核心。

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


就這樣來(lái)回弄了幾次以后,終究看到了曙光:


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


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


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


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


所以這里在頭部信息的第33個(gè)字節(jié)然后連續(xù)4個(gè)字節(jié)就是dex的長(zhǎng)度了,那末現(xiàn)在有了dex在內(nèi)存中的其實(shí)位置,長(zhǎng)度大小,下面就能夠使用Shirt+F2打開(kāi)腳本履行窗口,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)行查看:


這里可以查看到源碼了,而且類(lèi)名,方法名,變量名都是用中文來(lái)命名的,感覺(jué)好不習(xí)慣,但是Java中是支持這么干的,由于Java采取的是Unicode編碼的。


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


5、脫殼總結(jié)

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

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

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

3、360加固底層不是采取dvmDexFileOpenPartial這個(gè)系統(tǒng)函數(shù)來(lái)解析dex然后加載到內(nèi)存中的,而是自己實(shí)現(xiàn)了1個(gè)函數(shù),所以給這個(gè)函數(shù)下斷點(diǎn),然后獲得參數(shù)值來(lái)dump內(nèi)存中的dex數(shù)據(jù)是行不通的,但是有1個(gè)思路就是不管他用哪一個(gè)函數(shù)去解析dex加載到內(nèi)存,終究都得使用mmap這個(gè)系統(tǒng)函數(shù)來(lái)操作,所以還得給這個(gè)函數(shù)下斷點(diǎn),所以這里在調(diào)試的時(shí)候需要時(shí)刻注意的是當(dāng)斷點(diǎn)到達(dá)了mmap函數(shù)處的時(shí)候,需要視察Stack View棧窗口中是不是出現(xiàn)了classes.dex字樣,如果出現(xiàn)了,說(shuō)明開(kāi)始解密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ù),所以我們可以查看開(kāi)頭為:dex.35 這樣的內(nèi)容來(lái)判斷此處為dex數(shù)據(jù),由于dex頭部信息中也有dex的文件大小,那末這時(shí)候候就能夠使用腳本dump處內(nèi)存中的dex數(shù)據(jù)了。

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


6、技術(shù)概要

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

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

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


7、總結(jié)

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



更多內(nèi)容:點(diǎn)擊這里

關(guān)注微信公眾號(hào),最新Android技術(shù)實(shí)時(shí)推送


生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产一区二区三区在线 | 国产主播一区二区 | 亚洲国产精品第一区二区 | 欧美理论在线 | 久久国产精品精品 | 国产精品免费观看 | 午夜精品久久久久久久久久久久 | 久久精品国产一区二区三区不卡 | 九九热精品视频在线播放 | 在线看亚洲 | 日韩精品久久久久久 | 麻豆精品一区二区 | 国产中文字幕一区二区三区 | 日韩精品成人免费观看视频 | 亚洲成人av一区 | 视频一区 国产精品 | 尤物网站在线 | 欧美成人二区 | 久久久久久久久国产 | 黄色国产在线观看 | 国产高清久久 | 99精品视频在线观看视频 | 中文字幕一区二区在线播放 | 国产一级免费 | 欧美三级欧美成人高清 | 午夜精| 久久三级| 欧美一级在线视频 | 黄色精品 | 日韩 国产 欧美 精品 在线 | 成人在线一区二区 | 日本视频在线播放 | 久久精品一区二区三区不卡牛牛 | 精品一区二区三区在线观看国产 | 欧美日韩在线播放 | 国产高清无密码一区二区三区 | 91天天综合 | 国产成人在线免费观看 | 日本一级在线观看 | 亚洲精品国产精品国自产观看浪潮 | 国产激情一区二区三区在线观看 |