<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/8084

            注:框架有風險,使用要謹慎.

            Cydia Substrate是一個代碼修改平臺.它可以修改任何主進程的代碼,不管是用Java還是C/C++(native代碼)編寫的.而Xposed只支持HOOK app_process中的java函數,因此Cydia Substrate是一款強大而實用的HOOK工具.

            官網地址:http://www.cydiasubstrate.com/

            官方教程:http://www.cydiasubstrate.com/id/38be592b-bda7-4dd2-b049-cec44ef7a73b

            SDK下載地址:http://asdk.cydiasubstrate.com/zips/cydia_substrate-r2.zip

            0x00Hook Java 層


            之前講解過 xposed 的用法為啥還要整這個了,下面簡單對比兩款框架.想了解之前 xposed 篇的可以看這里:http://drops.wooyun.org/tips/7488

            劣勢:

            優勢:

            使用方法


            1.安裝框架app:http://www.cydiasubstrate.com/download/com.saurik.substrate.apk

            2.創建一個空的Android工程.由于創建的工程將以插件的形式被加載,所以不需要activity.將SDK中的substrate-api.jar復制到project/libs文件夾中.

            3.配置Manifest文件

            <manifest xmlns:android="http://schemas.android.com/apk/res/android">
                <application>
                    <meta-data android:name="com.saurik.substrate.main"
                        android:value=".Main"/>
                </application>
                <uses-permission android:name="cydia.permission.SUBSTRATE"/>
            </manifest>
            

            4.創建一個類,類名為Main.類中包含一個static方法initialize,當插件被加載的時候,該方法中的代碼就會運行,完成一些必要的初始化工作.

            #!java
            import com.saurik.substrate.MS;
            public class Main {
                static void initialize() { 
                    // ... code to run when extension is loaded
                }
            }
            

            5.hook imei example

            #!java
            import com.saurik.substrate.MS;
            public class Main {
                static void initialize() {
                    MS.hookClassLoad("android.telephony.TelephonyManager",
                            new MS.ClassLoadHook() {
                                @SuppressWarnings("unchecked")
                                public void classLoaded(Class<?> arg0) {
                                    Method hookimei;
                                    try {
                                        hookimei = arg0.getMethod("getDeviceId", null);
                                    } catch (NoSuchMethodException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                        hookimei = null;
                                    }
                                    if (hookimei != null) {
                                        final MS.MethodPointer old1 = new MS.MethodPointer();
                                        MS.hookMethod(arg0, hookimei, new MS.MethodHook() {
                                            @Override
                                            public Object invoked(Object arg0,
                                                    Object... arg1) throws Throwable {
                                                // TODO Auto-generated method stub
                                                System.out.println("hook imei----------->");
                                                String imei = (String) old1.invoke(arg0,
                                                        arg1);
                                                System.out.println("imei-------->" + imei);
                                                imei = "999996015409998";
                                                return imei;
                                            }
                                        }, old1);
                                    }
                                }
                            });
                }
            }
            

            6.在 cydia app 界面中點擊 Link Substrate Files 之后重啟手機

            7.使用getimei的小程序驗證imei是否被改變

            #!java
            public class MainActivity extends ActionBarActivity {
                private static final String tag = "MainActivity";
                TextView mText ;
                @Override
                protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_main);
                    mText = (TextView) findViewById(R.id.text);
                    TelephonyManager mtelehonyMgr = (TelephonyManager) getSystemService(this.TELEPHONY_SERVICE);
                    Build bd = new Build(); 
                    String imei = mtelehonyMgr.getDeviceId(); 
                    String imsi = mtelehonyMgr.getSubscriberId();
                    //getSimSerialNumber()   獲取 SIM 序列號  getLine1Number 獲取手機號
                    String androidId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 
                    String id = UUID.randomUUID().toString();
                    String model = bd.MODEL;
                    StringBuilder sb = new StringBuilder();
                    sb.append("imei = "+ imei);
                    sb.append("\nimsi = " + imsi);
                    sb.append("\nandroid_id = " + androidId);
                    sb.append("\nuuid = " + id);
                    sb.append("\nmodel = " + model);
                    if(imei!=null)
                        mText.setText(sb.toString());
                    else
                        mText.setText("fail");
                }
            

            8.關鍵api介紹

            MS.hookClassLoad:該方法實現在指定的類被加載的時候發出通知(改變其實現方式?).因為一個類可以在任何時候被加載,所以Substrate提供了一個方法用來檢測用戶感興趣的類何時被加載.

            這個api需要實現一個簡單的接口MS.ClassLoadHook,該接口只有一個方法classLoaded,當類被加載的時候該方法會被執行.加載的類以參數形式傳入此方法.

            void hookClassLoad(String name, MS.ClassLoadHook hook);
            
            參數 描述
            name 包名+類名,使用java的.符號(被hook的完整類名)
            hook MS.ClassLoadHook的一個實例,當這個類被加載的時候,它的classLoaded方法會被執行.
            #!java
            MS.hookClassLoad("java.net.HttpURLConnection",
                new MS.ClassLoadHook() {
                    public void classLoaded(Class<?> _class) {
                        /* do something with _class argument */
                    }
                }
            );
            

            MS.hookMethod:該API允許開發者提供一個回調函數替換原來的方法,這個回調函數是一個實現了MS.MethodHook接口的對象,是一個典型的匿名內部類.它包含一個invoked函數.

            #!java
            void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old);
            
            參數 描述
            _class 加載的目標類,為classLoaded傳下來的類參數
            member 通過反射得到的需要hook的方法(或構造函數). 注意:不能HOOK字段 (在編譯的時候會進行檢測).
            hook MS.MethodHook的一個實例,其包含的invoked方法會被調用,用以代替member中的代碼

            0x01Hook Native 層


            這塊的功能 xposed 就不能實現啦.

            整個流程大致如下:

            使用方法


            **第零步:添加 ndk 支持,將 cydia 的庫和頭文件加入工程

            有關 ndk 開發的基礎可以參考此文: NDK入門篇

            注意要是 xxx.cy.cpp,不要忘記.cy

            其實應該是動態鏈接庫名稱中的 cy 必須有,所有在 Android.md 中module 處的 .cy 必須帶上咯

            LOCAL_MODULE    := DumpDex2.cy
            

            第一步:修改配置文件

            <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                android:installLocation="internalOnly"
            >
                <application android:hasCode="false">
                </application>
            
                <uses-permission android:name="cydia.permission.SUBSTRATE"/>
            </manifest>
            

            設置 android:hasCode 屬性 false,設置android:installLocation屬性internalOnly"

            第二步:指定要 hook 的 lib 庫

            #include <substrate.h>
            
            MSConfig(MSFilterExecutable, "/system/bin/app_process")  //MSConfig(MSFilterLibrary, "liblog.so")
            
            // this is a macro that uses __attribute__((__constructor__))
            MSInitialize {
                // ... code to run when extension is loaded
            }
            

            設置要 hook 的可執行文件或者動態庫

            第三步: 等待 class

            static void OnResources(JNIEnv *jni, jclass resources, void *data) {
                // ... code to modify the class when loaded
            }
            
            MSInitialize {
                MSJavaHookClassLoad(NULL, "android/content/res/Resources", &OnResources);
            }
            

            第四步:修改實現

            static jint (*_Resources$getColor)(JNIEnv *jni, jobject _this, ...);
            
            static jint $Resources$getColor(JNIEnv *jni, jobject _this, jint rid) {
                jint color = _Resources$getColor(jni, _this, rid);
                return color & ~0x0000ff00 | 0x00ff0000;
            }
            
            static void OnResources(JNIEnv *jni, jclass resources, void *data) {
                jmethodID method = jni->GetMethodID(resources, "getColor", "(I)I");
                if (method != NULL)
                    MSJavaHookMethod(jni, resources, method,
                        &$Resources$getColor, &_Resources$getColor);
            }
            

            下面是步驟是在官網教程基礎上對小白同學的一些補充吧.

            ? file libprocess.so                                                                  
            libprocess.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
            

            第五步

            復制libsubstrate-dvm.so(注意 arm 和 x86平臺的選擇)和substrate.h到 jni 目錄下.創建SuperMathHook.cy.cpp文件

            第六步

            配置Android.mk文件

            LOCAL_PATH := $(call my-dir)
            
            include $(CLEAR_VARS)
            LOCAL_MODULE:= substrate-dvm
            LOCAL_SRC_FILES := libsubstrate-dvm.so
            include $(PREBUILT_SHARED_LIBRARY)
            
            include $(CLEAR_VARS)
            LOCAL_MODULE    := SuperMathHook.cy
            LOCAL_SRC_FILES := SuperMathHook.cy.cpp
            LOCAL_LDLIBS := -llog
            LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm //-L指定庫文件的目錄,-l指定庫文件名,-I指定頭文件的目錄.
            include $(BUILD_SHARED_LIBRARY)
            

            加入 c 的 lib

            LOCAL_PATH := $(call my-dir)
            
            include $(CLEAR_VARS)
            LOCAL_MODULE:= substrate-dvm
            LOCAL_SRC_FILES := libsubstrate-dvm.so
            include $(PREBUILT_SHARED_LIBRARY)
            
            
            include $(CLEAR_VARS)
            LOCAL_MODULE:= substrate
            LOCAL_SRC_FILES := libsubstrate.so
            include $(PREBUILT_SHARED_LIBRARY)
            
            include $(CLEAR_VARS)
            
            LOCAL_MODULE    := CydiaN.cy
            LOCAL_SRC_FILES := CydiaN.cy.cpp
            LOCAL_LDLIBS := -llog
            LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm -lsubstrate
            
            include $(BUILD_SHARED_LIBRARY)
            

            strings 查看下里面的函數.

            /data/data/com.jerome.jni/lib # strings libprocess.so                                                               <
            /system/bin/linker
            __cxa_finalize
            __cxa_atexit
            Jstring2CStr
            malloc
            memcpy
            __aeabi_unwind_cpp_pr0
            Java_com_jerome_jni_JNIProcess_getInfoMD5
            ....
            

            脫殼機模塊發開


            網上流傳的 IDA dump 脫殼流程大致如下:

            現在目標就是通過 Cydia 的模塊來自動化完成這個功能.這里咱選擇對dvmDexFileOpenPartial函數進行 hook.至于為什么要選擇這里了?這就需要分析下 android dex優化過程


            Android會對每一個安裝的應用的dex文件進行優化,生成一個odex文件.相比于dex文件,odex文件多了一個optheader,依賴庫信息(dex文件所需要的本地函數庫)和輔助信息(類索引信息等).

            dex的優化過程是一個獨立的功能模塊來實現的,位于http://androidxref.com/4.4.3_r1.1/xref/dalvik/dexopt/OptMain.cpp#57 其中extractAndProcessZip()函數完成優化操作.

            http://androidxref.com/4.1.1/xref/dalvik/dexopt/OptMain.cpp

            OptMain中的main函數就是加載dex的最原始入口

            #!c
            int main(int argc, char* const argv[])
            {
                set_process_name("dexopt");
            
                setvbuf(stdout, NULL, _IONBF, 0);
            
                if (argc > 1) {
                    if (strcmp(argv[1], "--zip") == 0)
                        return fromZip(argc, argv);
                    else if (strcmp(argv[1], "--dex") == 0)
                        return fromDex(argc, argv);
                    else if (strcmp(argv[1], "--preopt") == 0)
                        return preopt(argc, argv);
                }
                ...
                return 1;
            }
            

            可以看到,這里會分別對3中類型的文件做不同處理,我們關心的是dex文件,所以接下來看看fromDex函數:

            #!c
            static int fromDex(int argc, char* const argv[])
            {
            ...
            if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode, flags) != 0) {
                ALOGE("VM init failed");
                goto bail;
            }
            
            vmStarted = true;
            
            /* do the optimization */
            if (!dvmContinueOptimization(fd, offset, length, debugFileName,
                    modWhen, crc, (flags & DEXOPT_IS_BOOTSTRAP) != 0))
            {
                ALOGE("Optimization failed");
                goto bail;
            }
            ...
            }
            

            這個函數先初始化了一個虛擬機,然后調用dvmContinueOptimization函數 /dalvik/vm/analysis/DexPrepare.cpp,進入這個函數:

            #!c
            bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
                const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
            {
                ...
                /*
                     * Rewrite the file.  Byte reordering, structure realigning,
                     * class verification, and bytecode optimization are all performed
                     * here.
                     *
                     * In theory the file could change size and bits could shift around.
                     * In practice this would be annoying to deal with, so the file
                     * layout is designed so that it can always be rewritten in place.
                     *
                     * This creates the class lookup table as part of doing the processing.
                     */
                    success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
                                doVerify, doOpt, &pClassLookup, NULL);
            
                    if (success) {
                        DvmDex* pDvmDex = NULL;
                        u1* dexAddr = ((u1*) mapAddr) + dexOffset;
            
                        if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) {
                            ALOGE("Unable to create DexFile");
                            success = false;
                        } else {
                ...
            }
            

            這個函數中對Dex文件做了一些優化(如字節重排序,結構對齊等),然后重新寫入Dex文件.如果優化成功的話接下來調用dvmDexFileOpenPartial,而這個函數中調用了真正的Dex文件.在具體看看這個函數/dalvik/vm/DvmDex.cpp

            #!c
            /*
             * Create a DexFile structure for a "partial" DEX.  This is one that is in
             * the process of being optimized.  The optimization header isn't finished
             * and we won't have any of the auxillary data tables, so we have to do
             * the initialization slightly differently.
             *
             * Returns nonzero on error.
             */
            int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
            {
                DvmDex* pDvmDex;
                DexFile* pDexFile;
                int parseFlags = kDexParseDefault;
                int result = -1;
            
                /* -- file is incomplete, new checksum has not yet been calculated
                if (gDvm.verifyDexChecksum)
                    parseFlags |= kDexParseVerifyChecksum;
                */
            
                pDexFile = dexFileParse((u1*)addr, len, parseFlags);
                if (pDexFile == NULL) {
                    ALOGE("DEX parse failed");
                    goto bail;
                }
                pDvmDex = allocateAuxStructures(pDexFile);
                if (pDvmDex == NULL) {
                    dexFileFree(pDexFile);
                    goto bail;
                }
            
                pDvmDex->isMappedReadOnly = false;
                *ppDvmDex = pDvmDex;
                result = 0;
            
            bail:
                return result;
            }
            

            這個函數的前兩個參數非常關鍵,第一個參數是dex文件的起始地址,第二個參數是dex文件的長度,有了這兩個參數,就可以從內存中將這個dex文件dump下來了,這也是在此函數下斷點的原因.該函數會調用dexFileParse()對dex文件進行解析

            所以在dexFileParse函數處來進行 dump 也是可行的.但是因為這個函數的原型是

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

            其返回值為一個結構體指針struct DexFile { ... },要 hook 這個函數得把結構體從 android 源碼中扣出來或者直接改鏡像.

            找到dvmDexFileOpenPartial函數在 libdvm.so 對應的名稱

            #!bash
            ? strings libdvm_arm.so|grep dvmDexFileOpenPartial
            _Z21dvmDexFileOpenPartialPKviPP6DvmDex
            
            ? strings libdvm_arm.so|grep dexFileParse
            _Z12dexFileParsePKhji
            

            有了上述理論基礎,現在可以正式開發模塊了.大致流程如下

            完整代碼

            #!c
            #include "substrate.h"
            #include <android/log.h>
            #include <unistd.h>
            #include <stdio.h>
            #include <fcntl.h>
            #include <sys/types.h>
            #include <string.h>
            
            #define BUFLEN 1024
            #define TAG "DEXDUMP"
            #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
            #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
            
            //get packagename from pid
            int getProcessName(char * buffer){
                char path_t[256]={0};
                pid_t pid=getpid();
                char str[15];
                sprintf(str, "%d", pid);
                memset(path_t, 0 , sizeof(path_t));
                strcat(path_t, "/proc/");
                strcat(path_t, str);
                strcat(path_t, "/cmdline");
                //LOG_ERROR("zhw", "path:%s", path_t);
                int fd_t = open(path_t, O_RDONLY);
                if(fd_t>0){
                    int read_count = read(fd_t, buffer, BUFLEN);
            
                    if(read_count>0){
                          int  processIndex=0;
                          for(processIndex=0;processIndex<strlen(buffer);processIndex++){
                              if(buffer[processIndex]==':'){
                                  buffer[processIndex]='_';
                              }
            
                          }
                        return 1;
                    }
                }
                return 0;
            }
            
            //指定要hook 的 lib 庫
            MSConfig(MSFilterLibrary,"/system/lib/libdvm.so")
            
            //保留原來的地址  DexFile* dexFileParse(const u1* data, size_t length, int flags)
            int (* oldDexFileParse)(const void * addr,int len,int flags);
            
            //替換的函數
            int myDexFileParse(const void * addr,int len,void ** dvmdex)
            {
                LOGD("call my dvm dex!!:%d",getpid());
            
                {
                    //write to file
                    //char buf[200];
                    // 導出dex文件
                    char dexbuffer[64]={0};
                    char dexbufferNamed[128]={0};
                    char * bufferProcess=(char*)calloc(256,sizeof(char));
                    int  processStatus= getProcessName(bufferProcess);
                    sprintf(dexbuffer, "_dump_%d", len);
                    strcat(dexbufferNamed,"/sdcard/");
                    if (processStatus==1) {
                      strcat(dexbufferNamed,bufferProcess);
                        strcat(dexbufferNamed,dexbuffer);
            
                    }else{
                        LOGD("FAULT pid not  found\n");
                    }
            
                    if(bufferProcess!=NULL)
                    {
            
                      free(bufferProcess);
                    }
            
                    strcat(dexbufferNamed,".dex");
            
                    //sprintf(buf,"/sdcard/dex.%d",len);
                    FILE * f=fopen(dexbufferNamed,"wb");
                    if(!f)
                    {
                        LOGD(dexbuffer + " : error open sdcard file to write");
                    }
                    else{
                        fwrite(addr,1,len,f);
                        fclose(f);
                    }
            
            
            
                }
                //進行原來的調用,不影響程序運行
                return oldDexFileParse(addr,len,dvmdex);
            }
            
            //Substrate entry point
            MSInitialize
            {
                LOGD("Substrate initialized.");
                MSImageRef image;
                //載入lib
                image = MSGetImageByName("/system/lib/libdvm.so");
                if (image != NULL)
                {
            
                    void * dexload=MSFindSymbol(image,"_Z21dvmDexFileOpenPartialPKviPP6DvmDex");
                    if(dexload==NULL)
                    {
                        LOGD("error find _Z21dvmDexFileOpenPartialPKviPP6DvmDex ");
            
                    }
                    else{
                        //替換函數
                        //3.MSHookFunction
                        MSHookFunction(dexload,(void*)&myDexFileParse,(void **)&oldDexFileParse);
                    }
                }
                else{
                    LOGD("ERROR FIND LIBDVM");
                }
            }
            

            效果如下:

            [email protected]:/sdcard $ l |grep dex
            app_process_classes_3220.dex
            com.ali.tg.testapp_classes_606716.dex
            com.chaozh.iReaderFree_classes_4673256.dex
            com.secken.app_xg_service_v2_classes_6327832.dex
            

            脫殼機模塊改進一

            更改 hook 點為 dexFileParse,上文已經講解了為啥也可以選擇這里.也分析了 dex 優化的過程,這里在分析下 dex 加載的過程.

            DexClassLoader廣泛被開發者用于插件的動態加載.而PathClassLoader幾乎沒怎么見過.

            因為PathClassLoader 沒有提供優化 dex 的目錄而是固定將 odex 存放到 /data/dalvik-cache 中 ,故它只能加載已經安裝到 Android 系統中的 apk 文件,也就是 /data/app 目錄下的 apk 文件.

            PathClassLoader 和 DexClassLoader 父類為 BaseDexClassLoader

            http://androidxref.com/4.4.2_r1/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java

            #!c
            45    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
                   String libraryPath, ClassLoader parent) {
            

            http://androidxref.com/4.4.2_r1/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java

            #!c
            DexPathList(this, dexPath, libraryPath, optimizedDirectory);
            
            260    private static DexFile loadDexFile(File file, File optimizedDirectory)
            

            http://androidxref.com/4.4.2_r1/xref/libcore/dalvik/src/main/java/dalvik/system/DexFile.java

            #!c
            141 static public DexFile loadDex(String sourcePathName, String outputPathName, int flags)
            

            調用 native 函數 native private static int openDexFileNative(String sourceName, String outputName, int flags)

            #!c
            294    private static int openDexFile(String sourceName, String outputName,
            295        int flags) throws IOException {
            296        return openDexFileNative(new File(sourceName).getCanonicalPath(),
            297                                 (outputName == null) ? null : new File(outputName).getCanonicalPath(),
            298                                 flags);
            299    }
            

            http://androidxref.com/4.4.2_r1/xref/dalvik/vm/native/dalvik_system_DexFile.cpp

            #!c
            151 static void Dalvik_dalvik_system_DexFile_openDexFileNative(const u4* args, JValue* pResult)
            //249 static void Dalvik_dalvik_system_DexFile_openDexFile_bytearray(const u4* args, JValue* pResult)
            

            http://androidxref.com/4.4.2_r1/xref/dalvik/vm/RawDexFile.cpp

            #!c
            109 int dvmRawDexFileOpen(const char* fileName, const char* odexOutputName, RawDexFile** ppRawDexFile, bool isBootstrap)  //工具類方法打開DEX文件/Jar文件
            

            http://androidxref.com/4.4.4_r1/xref/dalvik/vm/DvmDex.cpp

            #!c
            93 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex)  //從一個打開的DEX文件,映射到只讀共享內存并且解析內容
            //146 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)  //通過地址和長度打開部分DEX文件
            

            http://androidxref.com/4.4.4_r1/xref/dalvik/libdex/DexFile.cpp

            #!c
            289 dexFileParse(const u1* data, size_t length, int flags)  //解析dex文件
            

            方法openDexFile里通過dvmDexFileOpenFromFd函數調用dexFileParse函數,分析Dex文件里每個類名稱和類的代碼所在索引,然后dexFileParse調用函數dexParseOptData來把類名稱寫對象pDexFile->pClassLookup里面,當然也更新了索引

            #!c
            //Substrate entry point
            MSInitialize
            {
                LOGD("Cydia Init");
                MSImageRef image;
                //載入lib
                image = MSGetImageByName("/system/lib/libdvm.so");
                if (image != NULL)
                {
                    void * dexload=MSFindSymbol(image,"_Z12dexFileParsePKhji");
                    if(dexload==NULL)
                    {
                        LOGD("error find _Z12dexFileParsePKhji");
            
                    }
                    else{
                        //替換函數
                        //3.MSHookFunction
                        MSHookFunction(dexload,(void*)&myDexFileParse,(void **)&oldDexFileParse);
                    }
                }
                else{
                    LOGD("ERROR FIND LIBDVM");
                }
            }
            

            脫殼機模塊改進二

            github 地址如下,里面已經有一個編譯好但是沒有簽名的 apk 了...

            https://github.com/WooyunDota/DumpDex

            如果提取的是 encode 版的,需要 decode 一下:

            base64 -D -i com.ali.tg.testapp_606716.dex.encode.dex -o my.dex
            

            一些錯誤排除


            NDK Symbol 'NULL' could not be resolved
            

            NDK環境沒有配好,沒有找到stddef.h

            jni.h頭文件找不到
            

            也是NDK環境未配置好,或者編譯器 BUG.先強行編譯一次若問題未解決就檢查下 NDK 環境.

            如果遇到一些成員 ref 到兩種頭文件中,需要配置下 include.我在使用 mkdir 的時候 mode_t 就 ref 到 ndk 和 osx 的頭文件中導致編譯失敗.解決辦法下加入了include:

            android-ndk-r10d/platforms/android-17/arch-arm/usr/include/sys

            Android Studio 1.3已經開始支持 NDK,完全拋棄 eclipse 的時日即將到來.

            0x03參考


            http://www.cnblogs.com/goodhacker/p/4014617.html

            http://www.cnblogs.com/goodhacker/p/4014617.html

            http://www.cnblogs.com/baizx/p/4254359.html

            http://www.gitzx.com/android-cydiasubstrate/

            從源碼中跟蹤Dex的加載流程

            https://github.com/bunnyblue/DexExtractor

            Android逆向之動態調試總結

            dex文件的優化解析及裝載

            Android系統ODEX文件格式解析

            DexClassLoader4.4.2動態加載分析(磁盤加載分析)

            Android4.0內存Dex數據動態加載技術

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线