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 定义参考:https://cs.android.com/android/platform/superproject/+/android15-qpr2-release:external/musl/arch/mips64/bits/errno.h;l=13?q=EACCES
解决方案:把 dump 路径改为:/sdcard/Android/data/<packageName>/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/<packageName>/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 实现自动化脱壳
即使 app 没有存储卡读写权限也能正常 dump 了。
跳过 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/dex2oatdstrstr(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;}...
}
完整源码
开源地址:https://github.com/CYRUS-STUDIO/FART
相关文章:
-
FART 自动化脱壳框架简介与脱壳点的选择
-
FART 主动调用组件设计和源码分析
-
移植 FART 到 Android 10 实现自动化脱壳
相关文章:

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_pat…...

基于Flask实现豆瓣Top250电影可视化
项目截图 概述 该项目旨在对豆瓣Top 250电影进行全面的数据分析,使用了Python爬虫、Flask框架进行开发,并采用了Echarts进行数据可视化以及WordCloud进行词云分析。应用展示了多个功能,如电影列表、评分分布、词频统计和团队信息。 主要功能…...

More SQL(Focus Subqueries、Join)
目录 Subqueries Subqueries That Return One Tuple Subqueries and Self Connection The IN Operator The Exists Operator The Operator ANY The Operator ALL Union, Intersection, and Difference(交并差) Bag Semantics Controlling Dupl…...
项目部署react经历
简单的说: 1. 编译打包并压缩为压缩包 2. 将压缩包上传到服务器(这里以宝塔面板为例:www/wwwroot/目录下) 3. 将文件解压生成比如:www/wwwroot/ttms/build/* 多文件 4. php 项目建站,选择静态ÿ…...

从图像处理到深度学习:直播美颜SDK的人脸美型算法详解
在直播的镜头前,每一位主播都希望自己“光彩照人”。但在高清摄像头无死角的审视下,哪怕是天生丽质,也难免需要一点技术加持。于是,美颜SDK应运而生,成为直播平台提升用户粘性和视觉体验的重要工具。 尤其是在“人脸美…...
智能教育个性化学习路径规划系统实战指南
引言 在数字化教育革命中,如何利用AI技术实现"因材施教"的千年教育理想?本文将通过构建一个完整的智能教育系统,演示如何基于Python生态(Django机器学习)实现从数据采集到个性化推荐的全流程。系统将通过分…...
spark- ResultStage 和 ShuffleMapStage介绍
目录 1. ShuffleMapStage(中间阶段)1.1 作用1.2 核心特性1.3 示例2. ResultStage(最终结果阶段)2.1 作用2.2 核心特性2.3 示例3. 对比总结4. 执行流程示例5. 常见问题Q1:为什么需要区分两种 Stage?**Q2:如何手动观察 Stage 划分?Q3:ShuffleMapStage 的数据一定会落盘吗…...

zTasker一款Windows自动化软件,提升效率:大小仅有10MB,免费无广告
一、zTasker是什么? zTasker是一款发布于2023年9月的免费无广告工具,专为Windows用户打造。它以仅8MB的轻量体积、极低资源占用(内存消耗不足10MB)和秒级启动速度脱颖而出,堪称“任务计划程序的终极强化版”。无论是定…...
人工智能100问☞第34问:什么是语音识别与合成?
目录 一、通俗解释 二、专业解析 三、权威参考 在人工智能的世界里,“看、听、说、写”早已不是人类的专属技能。语音识别,让机器有了耳朵;语音合成,让机器长了嘴巴;合在一起,机器就开始“说人话、听人言”了。 一、通俗解释 1、语音识别:让机器听懂人说话 你有没…...

最大流-Ford-Fulkerson增广路径算法py/cpp/Java三语言实现
最大流-Ford-Fulkerson增广路径算法py/cpp/Java三语言实现 一、网络流问题与相关概念1.1 网络流问题定义1.2 关键概念 二、Ford-Fulkerson算法原理2.1 核心思想2.2 算法步骤 三、Ford-Fulkerson算法的代码实现3.1 Python实现3.2 C实现3.3 Java实现 四、Ford-Fulkerson算法的时间…...
怎么从一台电脑拷贝已安装的所有python第三方库到另一台
要将Python库从一台电脑拷贝到另一台,可以采用以下方法: 方法一:使用pip命令导出和安装依赖 如果目标电脑在线,且python与pip命令可以正常使用 在源电脑上,打开命令行,执行以下命令导出所有依赖库到requ…...

【测试】Bug和用例
软件测试贯穿于软件的整个⽣命周期 软件测试的⽣命周期是指测试流程,这个流程是按照⼀定顺序执⾏的⼀系列特定的步骤,去保证产品质量符合需求。在软件测试⽣命周期流程中,每个活动都按照计划的系统的执⾏。每个阶段有不同的⽬标和交付产物 Bu…...
缓存穿透、缓存击穿、缓存雪崩目前记录(纯日记)
今天学了学这三个知识,这命名真是有点东西。 1.先说在命名方面与其余两个内容能明显区分开的缓存雪崩,简单来讲: 缓存雪崩就是缓存宕机了,也甭管咋宕机了,反正就是某一时刻,缓存用不了了。 那咋办&#…...

鸿蒙OS的5.0.1.120版本体验怎么样?
点击上方关注 “终端研发部” 设为“星标”,和你一起掌握更多数据库知识 越来越是好用了,之前是凑合能用,现在是大多能用。 我朋友的mate30PRO和PuraX一起用,新系统确实满足我90%以上的需求 一个系统适配一款机型,是要…...

使用ssh-audit扫描ssh过期加密算法配置
使用ssh-audit扫描ssh过期加密算法配置 安装检查ssh的加密算法配置修改ssh的加密算法配置 安装 # pip3安装ssh-audit pip3 instal ssh-audit检查ssh的加密算法配置 # 检查ssh的配置 ssh-audit 192.168.50.149修改ssh的加密算法配置 # 查看ssh加密配置文件是否存在 ls /etc/c…...
前端工程化 Source Map(源码映射)详解
我们来深入讲解前端 Source Map(源码映射),围绕以下结构展开: 一、为什么要用 Source Map?(Why) 背景问题: 在前端构建中,源代码通常会被压缩(minify&#…...
2025.05.28-华为暑期实习第二题-200分
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. A先生的旅游路径规划 问题描述 A先生正在为即将到来的假期规划一次城市旅游。这座城市有 n n n...

Java+Playwright自动化-2-环境准备与搭建-基于Maven
1.简介 上一章中已经讲如何通过引入jar包来搭建JavaPlaywright自动化测试环境,这一种是比较老的方法,说白了就是过时的老古董,但是我们必须了解和知道,其实maven搭建无非也就是下载引入相关的jar包,只不过相比之下是简…...

由sigmod权重曲线存在锯齿的探索
深度学习的知识点,一般按照执行流程,有 网络层类型,归一化,激活函数,学习率,损失函数,优化器。如果是研究生上课学的应该系统一点,自学的话知识点一开始有点乱。 一、激活函数Sigmod…...

二、OpenCV图像处理-图像处理
目录 1、连通性 2、形态学操作 2.1腐蚀和膨胀 2.2开闭运算 2.3礼帽和黑帽 2.4总结 3、图像平滑 3.1图像噪声 3.2均值滤波 3.3高斯滤波 3.4中值滤波 3.5总结 4、直方图 4.1直方图的原理与显示 4.2掩膜的应用 4.3直方图均衡化 4.4自适应均衡化 4.5总结 5、边缘…...

UPS的工作原理和UPS系统中旁路的作用
UPS(不间断电源)根据工作原理和适用场景的不同,主要分为以下三种类型,每种类型的特点和适用场景如下: 1. 后备式UPS(Offline/Standby UPS) 工作原理: 正常供电时,负载直接…...

麒麟系统 Linux(aarch64处理器)系统java项目接入海康SDK问题
1. 麒麟系统部署海康摄像头时的 JNA 链接错误, 海康提供的jna sdk版本太低,需升级版本4.5及以上,把集成的Structure 替换成以下类 public class SDK_Structure extends Structure {protected List<String> getFieldOrder() {List<St…...
深入理解数组索引:原理、应用与优化
在编程中,数组是一种最基本且广泛使用的数据结构。而数组索引则是访问数组元素的关键机制。本文将深入探讨数组索引的原理、应用以及优化方法,帮助读者更好地理解和使用数组索引。 一、数组索引的基本原理 数组是一种线性数据结构,它将一组…...
【洛谷P9303题解】AC- [CCC 2023 J5] CCC Word Hunt
在CCC单词搜索游戏中,单词隐藏在一个字母网格中。目标是确定给定单词在网格中隐藏的次数。单词可以以直线或直角的方式排列。以下是详细的解题思路及代码实现: 传送门: https://www.luogu.com.cn/problem/P9303 解题思路 输入读取与初始化&…...

Python图片格式批量转换器教程
📚 前言 编程基础第一期《11-30》-- 在图像处理工作中,我们经常需要将大量图片从一种格式转换为另一种格式。本教程将介绍如何使用Python的Pillow库开发一个简单但功能强大的图片格式批量转换器,帮助你高效处理图片格式转换任务。 目录 &…...

从公开到私密:重新思考 Web3 的数据安全
去中心化存储是 Web3 的基石之一,使用户和应用能够在无需依赖中心化服务商的情况下存储数据。但自由也带来了一个重大挑战:数据安全。在一个无许可的世界中,如何确保用户文档、游戏资产或 AI 数据集等敏感内容是私密的、可控访问的࿰…...

计算机网络常见体系结构、分层必要性、分层设计思想以及专用术语介绍
计算机网络体系结构 从本此开始,我们就要开始介绍有关计算机网络体系结构的知识了。内容包括: 常见的计算机网络体系结构 计算机网络体系结构分层的必要性 计算机网络体系结构的设计思想 举例说明及专用术语 计算机网络体系结构是计算机网络课程中…...

接口自动化测试用例的编写方法
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 phpunit 接口自动化测试系列 Post接口自动化测试用例 Post方式的接口是上传接口,需要对接口头部进行封装,所以没有办法在浏览器下直接调…...
解决Docker存储空间不足问题
虚拟机磁盘扩展实战:解决Docker存储空间不足问题 问题背景 在虚拟机中运行的Linux系统上,Docker服务因根分区空间不足而无法正常运行。初始状态如下: [rootlocalhost ~]# df -h / 文件系统 容量 已用 可用 已用% 挂载点…...

基于SpringBoot的商家销售管理网站的设计与实现
湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 基于SpringBoot的商家销售管理网站的设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕…...