通常對于加殼的程式,第一步的操作通常是脫殼,而現在脫殼一般都選擇利用<code>frida</code>來進行<code>hook</code>進行脫殼,不談其他脫殼方式,利用<code>frida</code>脫殼原理大緻分為兩種:
1、找到DexFile對象(art虛拟機下是DexFile對象,dalvik虛拟機下是DexFile結構體),擷取到DEX檔案的起始位址和大小,然後<code>dump</code>下來。常見能夠找到<code>DexFile對象</code>的函數有<code>LoadMethod</code>、<code>ResolveMethod</code>函數等,能直接擷取到<code>DEX起始位址和大小</code>的常見函數有<code>openMemory</code>、<code>dexparse</code>、<code>dexFileParse</code>、<code>dvmDexFileOpenPartial</code>等函數。<code>frida_unpack</code>便是其中的代表作。
2、利用frida的搜尋記憶體,通過比對<code>DEX</code>檔案的特征,例如<code>DEX</code>檔案的<code>檔案頭</code>中的<code>magic</code>---<code>dex.035</code>這個特征。<code>frida-Dexdump</code>便是這種脫殼方法的代表作。
然而不管是上述哪一種原理,在我這個有點<code>強迫症</code>的看來,都有一點小缺陷,這兩種方法從原理上決定了經過某個函數的<code>DEX</code>(或者存在于記憶體中的<code>DEX</code>)都會被<code>dump</code>下來,是以出現了<code>dump</code>下來很多個<code>DEX檔案</code>,但是隻有其中一個或者幾個是我們的<code>目标DEX</code>,為了尋找到<code>目标DEX</code>,隻有全部反編譯出後來能知道,這就比較浪費時間和精力了,對此,本人對脫殼腳本做了一些改進,通過對<code>dump</code>下來的<code>DEX</code>進行解析,進而識别出那個是我們的<code>目标DEX</code>!!!
PS:通過類名識别是本人發現識别率最準确、實作代價最小的方法,是以本篇重點主要在這,後面的其他識别方法在某些特殊情況下更好用!!!
<code>DEX</code>檔案的格式可以大緻分為<code>檔案頭</code>、<code>索引區</code>、<code>資料區</code>,<code>檔案頭</code>這個區域無法找到一個<code>DEX</code>檔案的一個<code>唯一特征</code>(ps:<code>sha-1</code>和<code>校驗碼</code>這兩個能作為一個<code>DEX檔案</code>唯一特征的前提是我們已經知道這個<code>dex</code>檔案所有位元組了,是以放在這裡并不成立),<code>索引區</code>包括了很多資料的索引,其中便包括<code>字元串</code>的索引,通過這我們可以解析出整個<code>DEX</code>檔案使用到的字元串。而我們已知的<code>DEX</code>檔案的一些資訊便包括<code>包名</code>。
通過解析一個<code>DEX</code>檔案,我們可以發現在<code>DEX</code>中一個類被表示出如下形式--<code>L包名/類名;</code>,例如<code>Lcom/example/test/ManActivity;</code>這種形式,例如下面為使用腳本解析<code>DEX</code>的字元串,擷取到的類名的截圖:

包名是唯一的,是以我們隻需要構造<code>/com/example/test</code>這種形式的特征,便可以很輕易的鎖定到<code>目标DEX</code>,但是,在<code>殼程式</code>中,也可能含有這種類型的字元串,我們的特征便不再是唯一的,這個時候,我們便需要一個新的唯一特征。
在一個APP中,我們通常所寫的類不止一個,而是很多個,那麼便含有很多個上述所說的<code>特征</code>;而寫過加殼程式都應該知道,我們在加殼程式中,最多也就拉起那麼一個或幾個類。那麼,通過這種數量上的差異同樣也可以作為唯一特征,以下是<code>脫殼改進腳本腳本</code>運作截圖:
1、其他字元串,通過将app安裝運作手動觀察到的,但是這種方式有點碰運氣,隻有直接寫入到<code>java</code>源碼中的才能作為特征,寫入到<code>strings.xml</code>便不得行。如下截圖(ps:為直接寫入到java中的,可以在字元串池中解析出來的),解析字元串池:
2、布局xml檔案名、控件名(ps:這種可行性太低,在這裡籌字數的,基本不能作為特征)
3、布局、控件資源ID,這些16進制搜尋整個DEX檔案也可以作為特征,但是有很其他DEX檔案裝車的可能。
4、方法原型,例如一個方法傳回值是Double,參數也是Double,那個這個方法原型便是<code>FF</code>,而這個方法原型一定存在于字元串池中,但是也不是很靠譜這個特征,原因如下截圖所示(而且還需要知道一個方法才行):
5、對DEX做更深入解析,解析出更多特征,而不僅僅止于解析出字元串池,感興趣的研究一下,但第一個依靠類名便夠用了。
github位址:https://github.com/windy-purple/dumpshell