用Python和Smali模擬器搞定一個加混淆、防篡改的APK逆向

ChiConnery 8年前發布 | 26K 次閱讀 Python 加密解密 Android Python開發

這個周末我和好友聊天時,他向我求助修改一個他正在編寫Python腳本。他試圖通過解混淆一個APK,來理解該APK的混淆基址和防篡改保護機制。同我以往的APK逆向過程(dex2jar->jd-gui->done)相比,這是一個很有挑戰性同時充滿趣味的工作。同時,這個逆向過程我編寫了一個我認為比較酷比較獨特的工具。

怪異的字符串

同其他有過APK反編譯工作經驗的逆向工作者一樣,我已經很習慣程序中的類和名字被ProGuard混淆(或者被DexGuard混淆字符串等),這對我來說不是什么困難。但是當我使用apktool打開這個應用的時候還是大吃一驚:

大部分的類和方法名都是很怪異的字符串,這幾乎沒法讓我使用一個單獨的工具或者編輯器來查看這些文件。所以目前最首要的步驟就是修復(坦誠的說應該是從頭開始寫)Matteo寫的python腳本,這個腳本試圖重新命名所有的混淆入口,腳本本身工作流程比較簡單:

遍歷所有名稱為不能打印字符的smali文件

使用ClassXXX替代混淆的類名字(XXX是一個自增的數字)

重命名文件

查找所有引用這些類的地方并使用新的名稱替代(正則匹配)

在.field文件夾(類變量,方法等)中重復這個操作

這個過程結束之后,最終獲得了一個可以瀏覽的文件夾和可讀的smali文件:

但是這離完成還有很遠的距離。

反篡改

在我繼續進行之前,我先需要指出兩點,以便你能夠理解我這么做背后的理由:

1. 這個應用使用了很奇怪的反篡改(很大可能是反調試之類的措施)保護,因此,使用注入代碼的方式將smali代碼重新打包成APK是不可行的,同樣調試也是不行的

2. 這樣的保護措施不僅阻止了代碼注入/修改,同時也會在檢測到這種篡改后卸載軟件

所以代碼注入(XPosed也不行)、調試都無法使用,基本我通常的標準逆向方式都無法使用。

加密字符串

作為一個懶惰(或者說是聰明)的逆向者,我不想先去理解其中的邏輯,相反,我試圖發現那些能夠給我一些提示的、有意義的字符串,幫助我發現這個app在做些什么,但是我再次被震驚到了。

所有的字符串都進過了傳統的加密算法加密,基本上所有引用字符串的地方都被如下的方式進行了替換:

Stringdecrypted = Class623 :: method5 (new int []{-12, 44,-35,…}, 52);  

函數的參數僅僅是一個整形數組和其他的一些數字作為第二個參數(或許是某種形式的密鑰?)

通常我遇到這種情況的做法是:

1. 反編譯APK到Java(使用dex2jar+jd-gui或者僅僅是jadx)

2. 獲取到解密的java代碼,并將其粘貼到一個獨立的java控制臺

3. 對加密的東西執行解密例程從而獲得明文結果

然而。。。任何工具都無法正確的將Class623::method5 的smali代碼轉換成

java代碼,這些工具獲得的輸出都是無意義的東西,不起作用。但是目前我并不是很擅長閱讀smali代碼(這個解密程序本身也十分復雜,至少對我來說很復雜)…但是我不能就這么放棄。

所有的都讓Smali模擬器來搞定吧

我當然可以利用Class623::method5的smali代碼,創建一個新的安卓APP,然后使用apktool反編譯,在這個方法的輸出中注入代碼,插入一個調用該函數代碼的調用到app中,重新構建這個app并且運行它。但是:

1. 同樣,我是一個懶惰的人

2. 這個實現方式并不優雅

3. 我頭腦里閃現出一個很酷的想法,我必須嘗試一下!

長話短說,我要做的是:“寫一個smali解析器和模擬器,然后加載這個函數例程,最終它將輸出所有我需要的明文!”。

于是我開始閱讀Dalvik操作碼說明,整合了一些代碼,經過幾個小時,我完成了這個簡單的pyhon 腳本用于測試:

from smali . emulator import Emulator

emu = Emulator ()

# The smali file to emulate.

filename ='decryptor.smali'  

# Arguments for the method.

args ={  

'p0':(-62,-99,-106,-125,-123,-105,-98,-37,-105,-97,-103,-41,-118,-97,-113,-103,-109,-104,-115,111,98,103,35,52),

'p1':19

}

ret = emu . run ( filename , args )

print emu . stats

print"RESULT:\n"

print"'%s'"% ret 

而且,運行結果如下:

成功了!

我對所有的加密字符串執行該腳本,模擬器也能正確的解析和執行解密例程的smali代碼,并解密所有我從反編譯程序中抽取的每一個條目。從現在開始,所有的工作就是使用明文替換所有的加密條目,從而這個逆向過程易如反掌。

via: http://www.freebuf.com/articles/web/103980.html

 本文由用戶 ChiConnery 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!