android逆向奇技淫巧七:apk加殼(一代)和脫殼分析


        自己寫了個簡單的helloword.apk,用x固(二代)的版本加殼后,在模擬器能正常運行,今天來試試手動dump脫殼;用jadx打開加殼后的apk,發現結構我沒加殼的比變化較大。該從哪入手分析了?整個apk中,AndroidMainfest是大而全的配置文件,標明了apk的四大組件、包明、入口點等所有配置信息,這里是不能混淆的,逆向必須從這里開始。從該文件查到:入口改成了TxAppEntry,是個application!

        

  進入該Application中,代碼如下所示:

       

  attachBaseContext比onCreate先執行,所以這里的入口函數應該是attachBaseContext;attachBaseContext從log打印的字符串就能看出這是殼解密的開始;前面幾行代碼從字面看是奔潰日志采集和報告,最重要的是調用a(this)函數,所以先在進入a()函數繼續分析:從log看是開始安裝啥(應該是解密、脫殼了),調用了d()和load()函數;d()函數是拼接so庫路徑、然后調用System.load加載so庫的代碼邏輯很清晰了;接着就是load函數了;這個是native函數,既然放so層,肯定“見不得人“,可以試試從這里開始突破!那么這個load在那個so了? 從文件來看,只有3個so,shella或shellx最像,可以從這里下手;從名字看,x感覺是x86版本的,a感覺是arm版本的,所以從shella開始下手逆向分析;先用IDA打開:打開過程中IDA不停地報錯,打開后右邊函數列表沒有JNI_OnLoad,也沒有java開頭的函數;只是在string這里找到了JNI_OnLoad字符串,直觀感覺是動態注冊,但JNI_OnLoad函數又找不到.........

      

     導入和導出函數這里也是空的:

     

     很明顯這個so被處理過了,那么該從哪下手了?IDA解析失敗,這里我們換010editor試試,用ELFTemplate試試:符號表都是0!

      

  section table大部分也是0:

   

   既然section大部分信息都是空的,干脆不讓IDA按照section解析了,這里把section在文件的偏移、table entry size、table entry count、string table index都置0,如下:

  

        奇跡發生了:導入導出表能看到部分函數了;左側的函數列表也能看到部分函數了;JNI_OnLoad也能找到了:

       

       不過這里的代碼明顯不正常:所以這里又需要注意一點:在JNI_OnLoad(或dex)執行之前肯定會解密的(好像又是一句真確的廢話......)!

        

       既然靜態分析沒啥結果,分析不出啥,也找不到脫殼的突破點,只能動態調試了;該apk自身+系統有幾十個so,自己so的jni_onload方法又被加密了,該在哪下斷點開始調試了?因為so是由androud的linker加載的,那就在linker這里下斷點唄,這里只要抓住一點就行:肯定會先解密jni_onload!先找到linker下個斷點:

        

       然后單步調試,發現這里有大量的EOR異或指令,稍微優點經驗的同學都能看出來這是在解密(windows下PG保護的代碼也是異或加密的,執行的時候才用異或解密);而且這個方法被反復調用,說明代碼在使用前才開始解密:

  

   繼續執行,同時看DDMS,發現日志已經打印了end install、attach end等關鍵字眼。還記得文章剛開始截圖的解釋么:那上面有源代碼的分析,其中就有Log.d打印日志(有點像電影中“反派死於話多”的經典場景,想不通為啥x固的研發同學要打印這么多日志);已經執行到attch end,說明dex已經被完全解密並且加載到內存,下一步就是從內存dump dex了!

      

      還有關鍵的dex的偏移和大小:這里是10進制,687124=0xA7C14,記住這個數,后面還有用(這里先打個伏筆)!

      

      這里遇到了反調試的函數,直接換成00干掉(試了很多次,每次到這里就崩掉):

  

      然后在jni_onload下斷點,目的是找到動態注冊的load函數:下斷后單步調試,這里就是registerNative函數了:從參數可以看出來,動態注冊了5個方法,R2就是映射數組的地址了:

  

       繼續執行:這里面就是dex的解密函數了(里面有大量的異或運算,很明顯是解密用的)!

      

       看到dex.035了吧?這就是dex文件頭,內存這里的數據大概率是解密后的dex文件:大小是0A7C14=687124byte;和上面看到的DDMS打印出來的日志是不是一樣的呀?

     

     導出來,保存成dex文件,然后用jadx打開如下:MainActivity被復原:

      

 

      總結:原始APK被加密的方式有很多種,但是無論怎么加密,在執行時肯定會解密!所以必須要動態調試,從linker下手,一步一步調試,指導找到解密后的so或dex;

  • 怎么識別解密函數了?有大量異或的代碼很可疑!比如在init_array中,有大量如下代碼:都是通過循環,逐字符異或,這個字符串普通人是看不懂含義的,這里明顯在解密!
  •        怎么在內存找dex或so了?看文件頭,dex是dex.035,so是elf!

     基於此案例,總結一下加殼的一些要點:

       

 

 

        小tips:

     (1)我調試用的還是模擬器,不過不是常見的雷電、夜神等x86架構的,而是android stuido自帶的arm模擬器,雖然速度慢很多,但是相比x86模擬器少了很多莫名其妙的bug!

     (2)我用的低版本模擬器,android自身的防護功能少,更利於逆向和調試

        

 

 

參考:

1、https://blog.csdn.net/long117long/article/details/66477562    Android系統中的Application和四大組件一些方法的啟動順序

2、https://blog.csdn.net/tabactivity/article/details/106994496  Android SO 加殼(加密)與脫殼思路

3、https://blog.csdn.net/feibabeibei_beibei/article/details/75734795  樂固加殼的原理分析

           

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM