某殼分析+修復(二)

Editor發表於2018-05-14

宣告

僅限技術討論,不得用於非法途徑,後果自負。

分析中有什麼錯誤歡迎大家指出


Java層分析

快分析完才想起打算用art模式分析的,那就分析下一個殼用art模式分析把

這個是dalvik模式,nexus5 4.4.4

邏輯比較簡單,主要是載入libSecShell.so,和替換原APP的Application,Helper.h的native方法是對華為手機一些設定,手裡沒有華為手機具體native沒有分析

某殼分析+修復(二)

java層有一個DexInstall類,Native層會通過jni方法呼叫install(ClassLoader loader, String dex_path, String dexDir)方法

一直往下分析,此方法主要作用就是把Native層解密的dex通過反射呼叫makeDexElements方法把生成的Element陣列加入到dexElements陣列中

某殼分析+修復(二)

某殼分析+修復(二)

某殼分析+修復(二)


具體過程可以參考android原始碼

https://www.androidos.net.cn/android/4.4.4_r1/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java

https://www.androidos.net.cn/android/4.4.4_r1/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java


Native方法分析

通過檢視.init_array和.finit_array段沒有做具體內容,解密方法應該放在了JNI_OnLoad中,一看就是經過llvm混淆過,正常程式碼怎麼會有這種邏輯

某殼分析+修復(二)

f5看一眼,能正常反編譯,大體掃一眼邏輯還是可以接受的沒那麼變態,發現字串都被加密了,部分方法也被加密了

只能動態分析了,具體就不帖程式碼了,最後我會把分析的so檔案分享給大家

某殼分析+修復(二)

JNI_OnLoad 4.4.4 dalvik流程,這裡的反除錯並不影響我們分析這個,反除錯具體程式碼我沒有分析,感興趣的可以分析一遍


某殼分析+修復(二)

Jar解密方法,有興趣的可以還原下,那樣直接把apk的jar解密直接解壓就是原apk的dex檔案


unsigned int __fastcall sub_25C90(unsigned int result, _BYTE *a2, int jarBuff)

{

int v3; // r1

int v4; // r3

unsigned int v5; // r3

int v6; // r6

int v7; // r5

char v8; // r2

int v9; // r4

int v10; // r3

int v11; // r7

_BYTE *v12; // r6

int v13; // r4

_BYTE *v14; // r1

int v15; // [sp+0h] [bp-138h]

unsigned int v16; // [sp+4h] [bp-134h]

_BYTE *v17; // [sp+8h] [bp-130h]

int v18; // [sp+10h] [bp-128h]

char v19[256]; // [sp+1Ch] [bp-11Ch]

v17 = a2;

v16 = result;

v15 = jarBuff;

v3 = 0;

if ( result <= 0x1FFFF )                      // result=0

{

v3 = 0x20000 - result;

if ( (signed int)(0x20000 - result) > jarBuff )

v3 = jarBuff;

v15 = jarBuff - v3;

if ( v3 > 0 )

{

v18 = dword_53C70;

v4 = 0;

do

{

v19[v4] = v4;

++v4;

}

while ( v4 != 256 );

v5 = 0;

v6 = 0;

v7 = 0;

do

{

v6 = (*(unsigned __int8 *)(v18 + v5) + (unsigned __int8)v19[v7] + v6) & 0xFF;

v8 = v19[v7];

v5 = (v5 + 1) & -((v5 + 1 <= 0xF) + ((v5 + 1) >> 31));

v19[v7] = v19[v6];

v19[v6] = v8;

++v7;

}

while ( v7 != 256 );

v9 = 0;

result = 0;

v10 = 0;

while ( v9 != v16 )

{

v10 = (v10 + 1) & 0xFF;

v11 = (unsigned __int8)v19[v10];

++v9;

result = (v11 + result) & 0xFF;

v19[v10] = v19[result];

v19[result] = v11;

}

v12 = v17;

do

{

v10 = (v10 + 1) & 0xFF;

v13 = (unsigned __int8)v19[v10];

result = (result + v13) & 0xFF;

v19[v10] = v19[result];

v19[result] = v13;

*v12++ ^= v19[(v13 + (unsigned __int8)v19[v10]) & 0xFF];

}

while ( v12 != &v17[v3] );

}

}

if ( v15 > 0 )

{

v14 = &v17[v3];

result = (unsigned int)v14;

do

*v14++ ^= 0xACu;

while ( (signed int)&v14[-result] < v15 );

}

return result;

}


脫殼dump

殼只是把原dex加密放到了secData0.jar中,所以直接拿到dex,修復AndroidManifest的application重打包完美執行

dump方法比較多,列舉幾個方法

1.通過還原加密演算法,解密secData0.jar,直接解壓解密jar就是原dex(不推薦這種方法,雖然方便,但演算法更新太快)

2.殼儲存在.cache的classes.dex是加密的,主要通過hook實現,開啟時解密,關閉時候加密。

殼hook了open和mmap方法,這裡下斷得到的dex是解密的dex即原dex(呼叫open,mmap方法可能不只是開啟dex,通過檔案大小可以篩選出來)

3.在解密jar函式下斷點,執行完得到解密jar,dump出解密jar,解壓出dex

4.殼hook了dvmRawDexFileOpen,在這裡下斷點,得到的dex是解密的dex即原dex(比較推薦這種)


提醒

1.idb用的ida7.0儲存的

2.給switch下斷點注意,一級下的switch,如果沒執行到一級的switch直接下斷點可能會失敗(不知道是ida問題還是?)


總結

別被JNI_OnLoad的流程給唬住,靜下心來分析還是挺簡單的。

感覺這種記憶體載入dex安全性還是挺低的,只要分析出關鍵程式碼dump出原dex那就是分分鐘的事,連修復都不用。


本文由看雪論壇 Roselia  原創

轉載請註明來自看雪社群


相關文章