• 家用轿车投诉比例多 今年3·15,汽车维权是这样的 2018-03-26
  • 上杭县中医院举办2017年度全县基层中医药适宜技术推广培训班 2018-03-26
  • 黄金要结束“八年轮回” 打开牛市新格局 2018-03-26
  • 抗衰老药物吃多等于吸毒 2018-03-26
  • 邢善萍:努力营造民族团结一家亲浓厚氛围 2018-03-26
  • 湖北羽协主席赵芸蕾:举全协会之力组队冲羽超 2018-03-26
  • 滴滴获软银80亿美元后最新估值多少 答案是576亿美元 2018-03-26
  • 重生在末世种田的日子全本TXT小说下载 2018-03-26
  • 易车网周四早盘大跌超10%易车网周四早盘 2018-03-26
  • 喝雪梨薏米瘦肉汤 清热止咳、健脾利湿 2018-03-26
  • 张杰“我想”巡演历时两年 明年推出全新专辑 2018-03-26
  • 李水华:坚决打赢扫黑除恶专项斗争攻坚仗 2018-03-26
  • 学生花38000元培训后未获一等奖 诉培训公司获赔培训一等奖竞赛 2018-03-26
  • 绝世天君 第1182章 大结局(13) 全本小说网 2018-03-26
  • 伯莱塔AR70223自动步枪图片 2018-03-26
  • 修改安卓源码:Art模式下的通用脱壳方法

    2018-03-30 151637人围观 ,发现 5 个不明物体 终端安全

    传奇赌博大小压法技巧 dfc.bdzq64.com *本文原创作者:x565178035,本文属FreeBuf原创奖励计划,未经许可禁止转载

    前言

    在dalvik时代有很多通用的脱壳方法,而现在的安卓版本早已不使用dalvik模式,很多方法便不再适用。那么,在 art 模式下有没有一种通用的一种方法呢?在 DEF CON 25 (2017) 黑客大会中,两位大牛 Avi Bashan 和 SlavaMakkaveev 给出了一个十分精彩的方法,他们仅在Android源码中添加了十几行代码,就干掉了主流的加壳?;すぞ撸?60,百度,梆梆加固)。然而他们给出的代码只能跑在 Android 6.0 的模拟器上,总觉得还是有点不完美(如果壳中有反模拟器的反调试手段岂不是就完了?),因此本文将介绍如何将大牛的代码稍作修改,将其编译到 LineageOS 的 Android 7.1 系统中,并且利用该代码脱壳。

    0×01 基本原理

    利用加壳程序的特性,因为任何加壳程序在程序运行时都会对加密的 dex 文件进行还原,因此两位大牛根据 art 模式下的 dex 加载方式,找到了两个通用的脱壳点,在加壳程序还原原始 dex 后,将内存中的数据 dump 到文件上。

    ppt.png

    参考他们的 PPT,可以看到他们找到的脱壳点分别是DexFile的构造函数DexFile::DexFile(),以及OpenAndReadMagic()函数,之后我们就要在这两个函数中添加我们的脱壳代码。

    更加详细的解释还请看大牛的演讲和他们的项目。

    0×02 修改源代码

    两位大牛的源码托管在了GitHub, 但是他们用的系统还是 AOSP 的 Android 6.0.1 。由于我手头只有一个 Nexus 4, 不支持原生 Android 6.0 的源代码,就只能根据 patch 文件,在 Android 7.1.1 的 LineageOS 源码上做修改了。

    首先,修改art/runtime/dex_file.cc中的DexFile对象的构造函数,具体改动如下:

    *** art/runtime_bk/dex_file.cc  2018-03-19 17:23:00.587301100 +0800                             
    --- art/runtime/dex_file.cc     2018-03-25 20:37:34.655223300 +0800                             
    ***************                                                                                 
    *** 26,31 ****                                                                                  
    --- 26,32 ----                                                                                  
    
      #include <memory>                                                                             
      #include <sstream>                                                                            
    + #include <fstream>                                                                            
    
      #include "art_field-inl.h"                                                                    
      #include "art_method-inl.h"                                                                   
    ***************                                                                                 
    *** 440,445 ****                                                                                
    --- 441,464 ----                                                                                
            proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),           
            class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),        
            oat_dex_file_(oat_dex_file) {                                                           
    +                                                                                               
    +   //------------------------------------------------------------------                        
    +   // DEX file unpacking                                                                       
    +   //------------------------------------------------------------------                        
    +                                                                                               
    +   // let's limit processing file list                                                         
    +                                                                                               
    +   LOG(WARNING) << "Dex File: Filename: "<< location;                                          
    +   if (location.find("/data/data/") != std::string::npos) {                                    
    +     LOG(WARNING) << "Dex File: OAT file unpacking launched";                                  
    +     std::ofstream dst(location + "__unpacked_oat", std::ios::binary);                         
    +     dst.write(reinterpret_cast<const char*>(base), size);                                     
    +     dst.close();                                                                              
    +   } else {                                                                                    
    +     LOG(WARNING) << "Dex File: OAT file unpacking not launched";                              
    +   }                                                                                           
    +   //------------------------------------------------------------------                        
    +                                                                                               
        CHECK(begin_ != nullptr) << GetLocation();                                                  
        CHECK_GT(size_, 0U) << GetLocation();                                                       
        const uint8_t* lookup_data = (oat_dex_file != nullptr)
    

    可以看到,在加壳程序的脱壳过程运行时,会创建 DexFile 对象,它是我们的第一个脱壳点。在这里将 oat 中的 Dex 文件 dump 到应用文件夹下。

    接下来修改art/runtime/base/file_magic.cc文件,修改其中的OpenAndReadMagic方法,它是我们第二个脱壳点:

    *** art/runtime_bk/base/file_magic.cc   2018-02-07 12:08:22.606728900 +0800
    --- art/runtime/base/file_magic.cc      2018-03-25 20:39:01.813272300 +0800
    ***************
    *** 19,24 ****
    --- 19,26 ----
      #include <fcntl.h>
      #include <sys/stat.h>
      #include <sys/types.h>
    + #include <sys/mman.h>
    + #include <unistd.h>
    
      #include "base/logging.h"
      #include "dex_file.h"
    ***************
    *** 33,38 ****
    --- 35,71 ----
          *error_msg = StringPrintf("Unable to open '%s' : %s", filename, strerror(errno));
          return ScopedFd();
        }
    +
    +   //------------------------------------------------------------------
    +   // DEX file unpacking
    +   //------------------------------------------------------------------
    +
    +   struct stat st;
    +   // let's limit processing file list
    +
    +   LOG(WARNING) << "File_magic: Filename: "<<filename;
    +   if (strstr(filename, "/data/data") != NULL) {
    +     LOG(WARNING) << "File_magic: DEX file unpacking launched";
    +     char* fn_out = new char[PATH_MAX];
    +     strcpy(fn_out, filename);
    +     strcat(fn_out, "__unpacked_dex");
    +
    +     int fd_out = open(fn_out, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    +
    +     if (!fstat(fd.get(), &st)) {
    +       char* addr = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd.get(), 0);
    +       int ret=write(fd_out, addr, st.st_size);
    +       ret+=1;
    +       munmap(addr, st.st_size);
    +     }
    +
    +     close(fd_out);
    +     delete[] fn_out;
    +   } else {
    +     LOG(WARNING) << "File_magic: DEX file unpacking not launched";
    +   }
    +   //------------------------------------------------------------------
    +
        int n = TEMP_FAILURE_RETRY(read(fd.get(), magic, sizeof(*magic)));
        if (n != sizeof(*magic)) {
          *error_msg = StringPrintf("Failed to find magic in '%s'", filename);
    

    需要修改的地方仅此两处。

    0×03 编译系统

    接下来就是重新编译 Android 项目,缺乏这方面经验的读者可以参考我之前写的博文,当然英语好的同学可以直接阅读 LineageOS 的官方文档。值得注意的是,从源代码可以看到脱壳后的文件会放在/data/data的应用目录下,这一目录只有 root 和应用本身(准确的说,因为每个 android 应用都对应一个用户,这一用户对自己的应用目录有读写权限)可以访问,为了方便调试,我们需要在编译 LineageOS 时开启 root 功能,如果是其他系统的话,在刷完系统后也需要 root。

    0×04 脱壳!

    将编译好的文件刷到手机上后,进开发者模式,开 adb 调试和 root 许可

    开启 adb:

    adb.png

    开启 Root:

    root.png

    这里笔者准备了一个 apk,并用360进行加壳,值得注意的是,因为360在加壳程序默认有证书签名校验功能,如何绕过签名校验不在本文的说明范围,因此,如果读者是使用自己的 apk 放到360里面做加壳,请务必保证加壳后的程序签名使用的证书与加壳前的证书一致,或者直接关闭360的签名校验功能。这里展示加壳前的 apk 和加壳后的 apk:

    加壳前:

    before_pack.png

    加壳后:

    after_pack.png

    大神给的自动化 bash 脚本是有一点问题的,我们手动操作一下,先把 DDMS 开着:

    ddms.png

    从图中我们可以看到,我们的代码确实有运行,只不过目前还没有加壳的程序,所以不会 dump 。

    接着,安装加壳后的 apk:

    λ adb install goatdroid_sign_facaf6ed_enc_sign.apk
    Success
    

    接着,打开加壳后的 apk,这里笔者选择手动打开,也可以使用命令的方式。

    可以看到 DDMS 中的日志已经显示我们有文件被 dump 出来了。

    ddms_unpacking.png

    接下来就是用 adb 一顿操作,将 dump 的文件提取出来啦

    λ adb shell
    mako:/ $ su
    mako:/ # cd data/data
    # 这里的文件夹是原始app的包名
    mako:/data/data # find . -name *__unpacked_*
    ./org.owasp.goatdroid.fourgoats/.jiagu/classes.dex__unpacked_oat
    ./org.owasp.goatdroid.fourgoats/.jiagu/classes2.dex__unpacked_oat
    ./org.owasp.goatdroid.fourgoats/.jiagu/classes.dex__unpacked_dex
    ./org.owasp.goatdroid.fourgoats/.jiagu/classes2.dex__unpacked_dex
    mako:/data/data # cp -R /data/data/org.owasp.goatdroid.fourgoats/.jiagu/ /sdcard/jiagu
    mako:/sdcard/jiagu # ls
    classes.dex                classes2.dex
    classes.dex__unpacked_dex  classes2.dex__unpacked_dex
    classes.dex__unpacked_oat  classes2.dex__unpacked_oat
    classes.oat                libjiagu.so
    mako:/sdcard/jiagu # chmod 777 *
    mako:/sdcard/jiagu # ls -al
    total 3632
    drwxrwx--x  2 root sdcard_rw    4096 2018-03-25 02:53 .
    drwxrwx--x 12 root sdcard_rw    4096 2018-03-25 02:53 ..
    -rw-rw----  1 root sdcard_rw       4 2018-03-25 02:53 .jgck
    -rw-rw----  1 root sdcard_rw  264818 2018-03-25 02:53 classes.dex
    -rw-rw----  1 root sdcard_rw  264818 2018-03-25 02:53 classes.dex__unpacked_dex
    -rw-rw----  1 root sdcard_rw  771568 2018-03-25 02:53 classes.dex__unpacked_oat
    -rw-rw----  1 root sdcard_rw 1917356 2018-03-25 02:53 classes.oat
    -rw-rw----  1 root sdcard_rw       0 2018-03-25 02:53 classes2.dex
    -rw-rw----  1 root sdcard_rw       0 2018-03-25 02:53 classes2.dex__unpacked_dex
    -rw-rw----  1 root sdcard_rw   38856 2018-03-25 02:53 classes2.dex__unpacked_oat
    -rw-rw----  1 root sdcard_rw  437056 2018-03-25 02:53 libjiagu.so
    

    这里我们可以看到 dump 出了两种文件:classes.dex__unpacked_dex, classes.dex__unpacked_oat,(还记得我们改代码的两个脱壳点吗?),哪个有用哪个没用是由加壳程序的还原过程决定,最简单的方法是把他们都拉出来放到JEB里面看一下。

    λ adb pull /sdcard/jiagu/classes.dex__unpacked_dex
    /sdcard/jiagu/classes.dex__unpacked_dex: 1 file pulled. 6.2 MB/s (264818 bytes in 0.041s)
    
    λ adb pull /sdcard/jiagu/classes.dex__unpacked_oat
    /sdcard/jiagu/classes.dex__unpacked_oat: 1 file pulled. 9.9 MB/s (771568 bytes in 0.074s)
    

    按经验,先看体积大的那个:

    unpacked.png

    LOL,成功脱壳了。

    *本文原创作者:x565178035,本文属FreeBuf原创奖励计划,未经许可禁止转载

    发表评论

    已有 5 条评论

    取消
    Loading...
    css.php