apk 脫殼


  在理解android的類加載后,我們可以愉快對apk來脫殼了。脫殼重要的是斷點:

  斷點:在哪個位置脫殼,這里着重指的是在哪個方法

  先介紹斷點,我們只要知道加殼是用哪個方法來加載dex的,hook這個方法就可以追蹤到dex了。這個方法就是我們要的斷點!

  dvmDexFileOpenPartial:——int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)

    apk為dex文件,android在執行前會先將dex轉化為odex文件,由函數dvmContinueOptimization(/dalvik/vm/analysis/DexPrepare.cpp)執行。在dvmContinueOptimization中先調用mmap(這也是一個斷點)將原Dex文件整體映射到內存;然后調用dvmDexFileOpenPartial去嘗試生成DexFile(既然會生成DexFile,當然會調用dexFileParse函數)。以上步驟在dex轉odex時才會執行,若加固的apk本來就是odex,則此斷點失效。

  dexFileParse:——DexFile* dexFileParse(const u1* data, size_t length, int flags)

    odex會生成dex的內存描述DexFile(dalvik淺析三:類加載),此函數的前2個參數與dvmDexFileOpenPartial相同(自行查看源碼)。沒什么好說的了,記住在生成DexFile時調用。看雪上已經將提取dex代碼集成到libdvm中了:【原創】讓開下,讓我脫下殼

   上面提及的是在dex加載過程(優化,解析)中,我們可以下斷的函數(當然其他還有很多,不一一舉例)。但這個有缺點是需要動態調試時才能dump出dex,這需要我們過加固apk的反調試,有點繁瑣。新方法是修改libdvm代碼去自動脫殼,參考上面看雪中的做法,下面還會詳細解析。以下是dump dex的ida script command:

static main(void)
{
  auto fp, begin, end, dexbyte;
  fp = fopen("C:\\dump.dex", "wb");
  begin = r0;
  end = r0 + r1;
  for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
      fputc(Byte(dexbyte), fp);
}

 

  下面來看看dex運行過程中可以下斷點函數(native):——/dalvik/vm/native/dalvik_system_DexFile.cpp基於源碼4.4

const DalvikNativeMethod dvm_dalvik_system_DexFile[] = {
520    { "openDexFileNative",  "(Ljava/lang/String;Ljava/lang/String;I)I",
521        Dalvik_dalvik_system_DexFile_openDexFileNative },
522    { "openDexFile",        "([B)I",
523        Dalvik_dalvik_system_DexFile_openDexFile_bytearray },
524    { "closeDexFile",       "(I)V",
525        Dalvik_dalvik_system_DexFile_closeDexFile },
526    { "defineClassNative",  "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;",
527        Dalvik_dalvik_system_DexFile_defineClassNative },
528    { "getClassNameList",   "(I)[Ljava/lang/String;",
529        Dalvik_dalvik_system_DexFile_getClassNameList },
530    { "isDexOptNeeded",     "(Ljava/lang/String;)Z",
531        Dalvik_dalvik_system_DexFile_isDexOptNeeded },
532    { NULL, NULL, NULL },
533};

 

  上面的幾個函數在加載dex或運行dex會執行,Dalvik_dalvik_system_DexFile_openDexFile_bytearray對於加殼的來說很熟悉吧(看我加殼中提到的文章)。這幾個函數已經不能像先前一樣直接到dex的addr和len來dump了。但你可以從中得到DexFile,然后在組合出dex文件。在這里你需要了解以下結構體:

  DexFile、DvmDex、DexOrJar;

/*
521     * The set of DEX files loaded by custom class loaders.
522     */
523    HashTable*  userDexFiles;      //dvmHashTableRemove(gDvm.userDexFiles, hash, pDexOrJar)

 

  知道userDexFiles的作用,它管理着用戶加載的DexFile。

  ok,有了上面的知識我們可以寫代碼來脫殼,你可以用xposed來函數,也可以修改源碼直接dump。

  

  修改源碼脫殼:

  用上面看雪上的代碼來解釋,它修改了dexFileParse源碼,在其中直接添加脫殼代碼(具體的脫殼代碼執行請看源碼)。代碼寫好了,如何編譯呢(編譯libdvm.so: makefile,mm)。當然事情到這里還沒有結束,若修改了內存的dex結構體,那我們dump出來東西也無法執行。這時候需要我先進行修復,看參考資料3、4。dannerWorking這方面還沒去研究待續

 

 參考資料:

  1 安卓動態調試七種武器之孔雀翎 – Ida Pro

  2 【原創】讓開下,讓我脫下殼

    3  從Android運行時出發,打造我們的脫殼神器

     4  Android應用程序通用自動脫殼方法研究

      


免責聲明!

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



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