zoukankan      html  css  js  c++  java
  • 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应用程序通用自动脱壳方法研究

          

  • 相关阅读:
    vc 网络编程(socket)
    《精通Windows API-函数、接口、编程实例》——第4章文件系统
    WindowsAPI使用详解——GetVersion|GetVersionEx 获取操作系统版本和名称
    Windows编程 鼠标
    Windows 编程 键盘
    Windows编程 Windows程序的生与死(下)
    二叉查找树——A1043.Is it a Binary Search Tree(25)
    Springboot + ElasticSearch 构建博客检索系统
    树的遍历——A1053.Path of Equal Weight(30) 只可DFS不可BFS
    树的遍历——A1004.Counting Leaves(30) 给出一棵树,问每一层有多少叶子节点(可DFS也可BFS)
  • 原文地址:https://www.cnblogs.com/vendanner/p/4865272.html
Copyright © 2011-2022 走看看