Android FART脫殼機流程分析
阿新 • • 發佈:2020-12-11
> 本文首發於安全客
>
> 連結:https://www.anquanke.com/post/id/219094
## 0x1 前言
在Android平臺上,程式設計師編寫的Java程式碼最終將被編譯成位元組碼在Android虛擬機器上執行。自從Android進入大眾的視野後,apktool,jadx等反編譯工具也層出不窮,功能也越來越強大,由Java編譯成的位元組碼在這些反編譯工具面前變得不堪一擊,這相當於一個人裸奔在茫茫人海,身體的各個部位被眾人一覽無餘。一種事物的出現,也會有與之對立的事物出現。有反編譯工具的出現,當然也會有反反編譯工具的出現,這種技術一般我們加固技術。APP經過加固,就相當於給那個裸奔的人穿了衣服,“衣服”在一定程度上保護了APP,使APP沒那麼容易被反編譯。當然,有加固技術的出現,也會有反加固技術的出現,即本文要分析的脫殼技術。
Android經過多個版本的更迭,它無論在外觀還是內在都有許多改變,早期的Android使用的是dalvik虛擬機器,Android4.4開始加入ART虛擬機器,但不預設啟用。從Android5.0開始,ART取代dalvik,成為預設虛擬機器。由於dalvik和ART執行機制的不同,在它們內部脫殼原理也不太相同,本文分析的是ART下的脫殼方案:FART。它的整體思路是通過**主動呼叫**的方式來實現脫殼,專案地址:https://github.com/hanbinglengyue/FART 。FART的程式碼是通過修改少量Android原始碼檔案而成的,經過修改的Android原始碼編譯成系統映象,刷入手機,這樣的手機啟動後,就成為一臺可以用於脫殼的脫殼機。
## 0x2 流程分析
FART的入口在`frameworks\base\core\java\android\app\ActivityThread.java`的performLaunchActivity函式中,即APP的Activity啟動的時候執行fartthread
```java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Log.e("ActivityThread","go into performLaunchActivity");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
......
//開啟fart執行緒
fartthread();
......
}
```
fartthread函式開啟一個執行緒,休眠一分鐘後呼叫fart函式
```java
public static void fartthread() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Log.e("ActivityThread", "start sleep,wait for fartthread start......");
Thread.sleep(1 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("ActivityThread", "sleep over and start fartthread");
fart();
Log.e("ActivityThread", "fart run over");
}
}).start();
}
```
fart函式中,獲取Classloader,反射獲取一些類。反射呼叫`dalvik.system.DexPathList`的dexElements欄位得到`dalvik.system.DexPathList$Element`類物件陣列,Element類儲存著dex的路徑等資訊。接下來通過遍歷`dexElements`,得到每一個Element物件中的DexFile物件,再獲取DexFile物件中的mCookie欄位值,呼叫DexFile類中的`String[] getClassNameList(Object cookie)`函式並傳入獲取到mCookie,以得到dex檔案中所有的類名。隨後,遍歷dex中的所有類名,傳入`loadClassAndInvoke`函式。
```java
public static void fart() {
ClassLoader appClassloader = getClassloader();
List