FART 自动化脱壳框架一些 bug 修复记录

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

open() 判断不严谨

https://github.com/CYRUS-STUDIO/FART/blob/master/fart10/art/runtime/art_method.cc

比如:

复制代码
int dexfilefp = open(dex_path.c_str(), O_RDONLY);
if (dexfilefp > 0) {
    close(dexfilefp);
}

这个判断条件其实是不严谨的,导致 if 中 的 close(dexfilefp); 一直没有执行。

open() 的返回值语义是:

  • 成功时:返回一个非负整数(即 >= 0),它是打开的文件描述符。

  • 失败时:返回 -1

正确的判断方式应该是:

复制代码
if (fp >= 0) {
    // 成功打开
} else {
    // 打开失败,打印错误信息
    LOG(ERROR) << "open dex file failed";
}

mkdir failed errno: 13

FART 中通过 mkdir 函数在 sdcard 上创建 dump 文件存放目录,但是这样必须 app 拥有存储卡读写权限。不然 mkdir 会执行失败。

下面时一个 frida 脚本,调用系统 的 mkdir 函数创建目录

复制代码
function mkdir(path) {
    const libc = Module.findExportByName(null, "mkdir");
    if (!libc) {
        console.error("[-] Cannot find mkdir symbol.");
        return;
    }

    const mkdirNative = new NativeFunction(libc, 'int', ['pointer', 'int']);

    const pathStr = Memory.allocUtf8String(path);
    const mode = 0o777; // 权限

    const result = mkdirNative(pathStr, mode);
    if (result === 0) {
        console.log("[+] mkdir success:", path);
    } else {
        const errnoLocation = Module.findExportByName(null, "__errno");
        if (errnoLocation) {
            const errnoPtr = new NativeFunction(errnoLocation, 'pointer', []);
            const errnoValue = Memory.readU32(errnoPtr());
            console.error("[-] mkdir failed errno:", errnoValue);
        } else {
            console.error("[-] mkdir failed");
        }
    }
}

调用 mkdir 创建目录 /sdcard/fart/com.cyrus.example

复制代码
mkdir("/sdcard/fart/com.cyrus.example");

结果如下:

复制代码
[Remote::com.cyrus.example]-> mkdir("/sdcard/fart/com.cyrus.example");
[-] mkdir failed errno: 13

-\] mkdir failed errno: 13 表示 Permission denied(权限被拒绝)。 **常见的 errno 错误码:** | errno 值 | 含义 | |--------------|---------------| | EEXIST | 目录已经存在 | | EACCES | 权限不足 | | ENOENT | 上级目录不存在 | | ENAMETOOLONG | 路径太长 | | ENOSPC | 没有磁盘空间或 inode | errno 定义参考: 解决方案:把 dump 路径改为:/sdcard/Android/data/\/fart 该目录无需动态申请存储权限,也不受 MANAGE_EXTERNAL_STORAGE 限制。 art_method.cc 中增加以下方法,创建目录并并打印日志 //add 创建目录 bool ensure_dir_exists(const std::string& path) { int res = mkdir(path.c_str(), 0777); if (res == 0 || errno == EEXIST) { return true; } else { LOG(ERROR) << "mkdir failed: " << path << ", errno=" << errno << ", " << errno; return false; } } 修改 dumpDexFileByExecute 和 dumpArtMethod 方法中 dump 文件存放路径 // 创建目录:/sdcard/Android/data//fart std::string base_dir = "/sdcard/Android/data/"; std::string app_dir = base_dir + szProcName; std::string fart_dir = app_dir + "/fart"; ensure_dir_exists(app_dir); ensure_dir_exists(fart_dir); // 保存 dex 文件 std::string dex_path = fart_dir + "/" + std::to_string(size_int) + "_dex_file.dex"; // 保存 class 列表 std::string class_list_path = fart_dir + "/" + std::to_string(size_int) + "_class_list.txt"; dumpArtMethod 方法中 CodeItem 的保存路径也要修改 // 保存 CodeItem std::string ins_path = fart_dir + "/" + std::to_string(size_int) + "_ins_" + std::to_string(tid) + ".bin"; 修改完成后重新编译刷机。参考:[移植 FART 到 Android 10 实现自动化脱壳](https://cyrus-studio.github.io/blog/posts/%E7%A7%BB%E6%A4%8D-fart-%E5%88%B0-android-10-%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%B1%E5%A3%B3/) 即使 app 没有存储卡读写权限也能正常 dump 了。 ![word/media/image1.png](https://i-blog.csdnimg.cn/img_convert/113f557eed207a94db4fd843b06a7503.png) ## 跳过 Android 编译构建阶段的 dump 调用 在 Android 编译构建阶段的 dex2oatd 工具执行时 调用了 art_method.cc 中的方法,导致出现下面的日志 dex2oatd E 05-27 19:26:24 7330 7330 art_method.cc:151] mkdir failed: /sdcard/Android/data/out/soong/host/linux-x86/bin/dex2oatd, errno=2, 2 dex2oatd E 05-27 19:26:24 7330 7330 art_method.cc:151] mkdir failed: /sdcard/Android/data/out/soong/host/linux-x86/bin/dex2oatd/fart, errno=2, 2 dex2oatd E 05-27 19:26:24 7330 7330 art_method.cc:234] [dumpDexFileByExecute] /sdcard/Android/data/out/soong/host/linux-x86/bin/dex2oatd/fart/4376620_dex_file_execute.dex open failed, fp=-1 dex2oatd E 05-27 19:26:24 7330 7330 art_method.cc:151] mkdir failed: /sdcard/Android/data/out/soong/host/linux-x86/bin/dex2oatd, errno=2, 2 dex2oatd E 05-27 19:26:24 7330 7330 art_method.cc:151] mkdir failed: /sdcard/Android/data/out/soong/host/linux-x86/bin/dex2oatd/fart, errno=2, 2 在 dump 前加上判断是否运行在 Android 环境 //add 跳过 Android 编译构建阶段的 dex2oatd 工具执行时的调用 bool isValidAndroidApp(const char* procName) { // 排除 host 工具,例如 dex2oat、dex2oatd、aapt2 等 return procName != nullptr && strstr(procName, "/") == nullptr && // 不应该包含路径 strstr(procName, "dex2oat") == nullptr && // 排除 dex2oat/dex2oatd strstr(procName, "soong") == nullptr; // 排除构建系统相关路径 } //add extern "C" void dumpDexFileByExecute(ArtMethod* artmethod) REQUIRES_SHARED(Locks::mutator_lock_) { ... if (szProcName[0] == '\0') { LOG(WARNING) << "[dumpDexFileByExecute] 获取进程名失败:" << artmethod->PrettyMethod(); return; } if (!isValidAndroidApp(szProcName)) { LOG(WARNING) << "[dumpDexFileByExecute] 当前进程 " << szProcName << " 非法,跳过 dex dump"; return; } ... } //add extern "C" void dumpArtMethod(ArtMethod* artmethod) REQUIRES_SHARED(Locks::mutator_lock_) { ... if (szProcName[0] == '\0') { LOG(WARNING) << "[dumpArtMethod] 获取进程名失败:" << artmethod->PrettyMethod(); return; } if (!isValidAndroidApp(szProcName)) { LOG(WARNING) << "[dumpArtMethod] 当前进程 " << szProcName << " 非法,跳过 dex dump"; return; } ... } ## 完整源码 开源地址: 相关文章: * [FART 自动化脱壳框架简介与脱壳点的选择](https://cyrus-studio.github.io/blog/posts/fart-%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%B1%E5%A3%B3%E6%A1%86%E6%9E%B6%E7%AE%80%E4%BB%8B%E4%B8%8E%E8%84%B1%E5%A3%B3%E7%82%B9%E7%9A%84%E9%80%89%E6%8B%A9/) * [FART 主动调用组件设计和源码分析](https://cyrus-studio.github.io/blog/posts/fart-%E4%B8%BB%E5%8A%A8%E8%B0%83%E7%94%A8%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E5%92%8C%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/) * [移植 FART 到 Android 10 实现自动化脱壳](https://cyrus-studio.github.io/blog/posts/%E7%A7%BB%E6%A4%8D-fart-%E5%88%B0-android-10-%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%B1%E5%A3%B3/)

相关推荐
小蜜蜂嗡嗡40 分钟前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi001 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil2 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你3 小时前
Android View的绘制原理详解
android
移动开发者1号5 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号6 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best10 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk11 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭15 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0016 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体