AI取证实战第06期:一个文件夹丢进去,APK批量解析自动出报告

admin 2026-09-07 04:14:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍AI取证实战第06期,聚焦apk批量解析工具v2.5版,实现一个文件夹丢入即可自动批量解析并生成报告,支持定时任务、去重账本、状态机与自定义下载。通过实战翻车案例(flutter包误判自绘)揭示三层根因:语义树字段失真、ocr兜底失效、服务端不可达,强调分层兜底与如实归因。提供三步验收法及避坑清单,并附工具发布包领取方式。 综合评分: 82 文章分类: 安全工具,移动安全,实战经验,安全开发


AI 取证实战第06期: 一个文件夹丢进去, APK 批量解析自动出报告

原创

小谢 小谢

小谢取证

2026年9月5日 00:17 福建

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

AI 取证实战 · 第 06 期(v2.5 新增批量 + 定时)

一个文件夹丢进去, APK 批量解析自动出报告: 从「采集仪效果不行」到 3 小时无人值守

批量解析 · 批量出报告 · 自定义下载 · 定时任务 · 一个 Flutter 包教会的教训

前阵子同行在微信里跟我说:「目前就是有想法做个自动解析 apk 的,这样有些 apk 分析起来就简单了,采集仪自动解析效果不怎么样」

同行:在你这个基础上可以搞不?

我:当然可以搞。有空我再出个教程:自动解析、自动归档、自动动静态分析。

这个「有空」,一拖就拖到了第 06 期。本期把工作台 v2.5 新加的批量 + 定时两条链路拆开讲:一整个文件夹的 APK 丢进去不用管,报告自己一份份出来;每天凌晨到点,把新检材自动跑掉。以及,自动解析最容易在哪儿被打脸,我用一个 Flutter 自绘包,把翻车现场和修复过程原样复盘。

🚀 本期你将看到: ① 批量解析的核心:一个目录 → 扫描去重 → 排队 → 逐包动静态 → 自动出报告 ② 去重账本:为什么同一个包不会解析两遍(路径+大小+时间戳三重指纹) ③ 批量状态机:排队/运行/完成/失败看着它走,中断不丢进度 ④ 自定义下载:批量每包一键「⬇ 报告」,单包导出共用一条链路 ⑤ 定时任务:watchDir 一挂,凌晨自动扫新检材,同批互斥不打架 ⑥ 实战翻车现场:一个 Flutter 自绘 App 被判「无法自动化」,三层根因 + v3.4 修复 ⑦ 批量解析效果怎么才算「靠谱」:语义树、OCR 兜底、如实归因的分层哲学 ⑧ 学费清单 + 三步验收法

1|批量解析:一个文件夹丢进去就行

批量解析的形态很简单:指定一个检材目录(watchDir),点「开始批量解析」,剩下的事工作台自己干。它会按这个流程走:

[扫描] 遍历目录收集 *.apk(含子目录) [去重] 每包算 路径+大小+修改时间 指纹 → 账本比对 [排队] 未解析过的进队列,逐包串行出队 [单包] 每个包完整走一遍动静态分析(同单包解析) [报告] 每包完成自动落盘 「APK报告_包名_随机串.html」 [汇总] 进度/状态/报告路径实时推给前端面板

关键设计:批量不是”重新写一套分析”,而是把单包分析原样复用,外面套一层队列。所以批量解析和单包解析的结论口径完全一致,不会出现”单跑准、批量糊”的落差。这正好回应开头那个痛点:自研批量自动解析和采集仪批量解析最大的区别,就在每一份报告用的都是同一套经过验证的引擎,而不是批量的简化版

(入口在 APK 面板右上角,一个目录 + 一个按钮)

2|去重账本:同一个包为什么不会解析两遍

定时任务和批量最容易踩的坑是重复解析:同一批检材凌晨扫一遍、中午再扫一遍,两小时就白烧了。工作台用一张本地账本(~/.dsh/fx-batch/parsed.json)记下每个包的身份:

// 每包指纹:路径 + 文件大小 + 修改时间戳 “D:\case\9月3日\com.w2obqw50bipl.apk|105465873|1788444415508” → 已解析,报告在 …\APK报告_com.w2obqw50bipl.apk_mtms1ra2.html

三个字段缺一不可:

  • 路径

    ——同名文件在不同目录是两回事,各算各的;

  • 大小 + 修改时间

    ——同一个文件名被覆盖更新(比如嫌犯端重新打包过一次),指纹就变了,会重新解析。「文件没动过」和「文件被动过」在账本上分得清清楚楚。

账本只增不改,天然可审计:哪天想查”这批检材几点解析的、报告落在哪”,直接看 JSON。这也符合取证习惯,自动化的每一步都要能回查。

3|批量状态机:看着它走,中断不丢

批量跑起来最怕黑盒:到底是卡住了还是在干活?面板上每个包都有独立状态:排队 → 解析中 → 完成 / 失败,加上总进度(完成数/总数)。

真正要命的设计决策是串行还是并行。一开始想过”4 个包一起跑”提速,后来否了:

  • 动态分析要抢同一个模拟器、同一个 adb、同一个 arc 服务,并行只会互相踩;
  • 报告路径、账本写入、日志推送全是共享状态,串行才能保证”账本和报告一一对应”。

于是批量严格单队列串行,一个包完整跑完(动+静+报告落盘)才轮到下一个。批量 3 小时无人值守这种事,宁慢勿乱。自动化的第一原则不是快,是每一份产物都可追溯。

(失败包保留原因,不会静默跳过)

4|批量自动出报告 + 自定义下载

每个包解析完,报告自动落盘到指定目录(默认 ~/.dsh/fx-reports/),文件名带包名和随机串,互不覆盖。落盘之后,面板上每个包旁边都有一个「⬇ 报告」按钮:

  • 点一下直接下载这份 HTML 报告,文件名自动取包名(com.w2obqw50bipl.html);
  • 下载链路走 RPC 端点 fx/downloadApkReport,在浏览器里用 Blob + a[download] 触发保存。不做成 file:// 直开,因为浏览器会拦本地文件,这是单包导出踩过的坑,批量直接复用同一套;
  • 报告目录也可以自定(面板输入框),批量全部写进去,归档即整理。

所以「自动归档」实际上是一句话:报告输出目录 = 你的归档目录,解析完文件已经躺好,剩下的就是下载或拷走。要按案件归档,就把报告目录指到案件文件夹,一份报告一个包名文件,取证卷宗该有的都有。

(报告文件名 = 包名,自动归档不用改文件名)

5|定时任务:新检材丢进目录,到点自己跑

批量是”点一下跑一次”,定时是”挂一个目录,到点自己扫”。定时任务表存在 ~/.dsh/fx-batch/schedules.json,每条任务记录:

// 一条定时任务 = 固定的检材目录 + 报告目录 + 是否动态 + 触发规则 { id, name, watchDir, reportDir, dynamic,   cron: “0 3 * * *” // 每天凌晨 3 点 }

三个必须交代的工程细节:

  • 到点只跑”新”的

    :触发时重新扫描目录,但账本去重保证已经解析过的包绝不再跑——凌晨扫到的都是新丢进来的检材;

  • 全局互斥

    :同一时刻只允许一个批次。定时器触发时若已有批次在跑,直接跳过本次并记日志——防止半夜两点手动批量、三点定时又抢同一个模拟器;

  • 下次运行时间可见

    :每条任务算出 nextRunAt,面板能看见”下次跑在几点”,不是黑盒。

定时+去重+互斥三件套合起来,就是一个检材到了就自动进流水线的看守目录:办案过程中同事不断往共享检材目录里丢 APK,工作台每天凌晨自动把新到的全部解析出报告。第二天早上过来,报告已经整整齐齐躺在归档目录里。

(凌晨自动跑完,早上报告已归档)

6|实战翻车现场:一个 Flutter 包,差点让”自动解析”翻车

开头同行说”采集仪自动解析效果不怎么样”。这话我信,因为9 月 3 日批量解析真就翻过一次车。检材目录里有个 com.w2obqw50bipl.apk,批量列表里它那行显示的是:

跳过:自绘界面(Flutter等)无法自动化

这是自动解析最难受的失败方式:不是报错,是”跳过”,它连挣扎都没挣扎就放弃了。我决定把这个包揪出来查清楚,结果查出三层根因,每一层都值得讲:

根因一:Flutter 的语义不在 text,在 content-desc

这个 App 确实是 Flutter 自绘(libflutter.so + libapp.so + flutter_assets)。但查语义树发现它其实有语义内容,只是全放在 contentDescription 里,text 是空的。而引擎当时只统计 text 字段 → 判定”语义节点少于 5 个” → 误判自绘。uiautomator dump 的证据清清楚楚:text="" 但 content-desc="请检查您的网络是否通畅…ERROR_CODE:V_1"

根因二:OCR 兜底存在,但从没生效过

引擎里其实早就写了”语义树拿不到 → 截屏 OCR → 按坐标识别表单注册”的兜底代码,但日志里的一行 兜底识别失败:Unexpected end of JSON input 出卖了它。查到最后,问题出在截图用的 adb shell cat 把二进制损坏了:PNG 魔数从 89504e470d0a1a0a 被改成 89504e470d0d0a1a(CRLF/0x1A 转换),图片识别直接失败、OCR 返回空,兜底永远落空,最后降级”自绘”。兜底通道从没生效过,却一直显示”自绘”这个看似合理的结果,这就是自动化里最坑的静默失效。

根因三:App 压根没到注册页,它卡在网络错误页

把 OCR 修好后,截图识别出 App 的真实状态:「请检查您的网络是否通畅或切换网络重试 / 点击屏幕重新连接 / ERROR_CODE:V_1」。这个包的服务端已经不可达(配置资源 404),它连登录页都没到。所谓”无法自动化”,不是界面结构问题,而是服务端已经死了。这在取证上反而是一条更关键的结论:这个 App 的后台已停止服务,比”自绘界面”有价值得多。

修复后同一份报告从「自绘界面无法自动化」变成:

网络错误页:App 服务端不可达(network_blocked)

(同一个包、同一套引擎,结论从”跳过”变成”服务端不可达”)

7|批量自动解析怎么才算”靠谱”:分层兜底 + 如实归因

一个 Flutter 包教会的最大一课:自动解析的”效果不怎么样”,九成是兜底链断了,而不是自动化本身不行。靠谱的批量解析必须分三层递进,任何一层都不许静默放弃:

| 层次 | 干什么 | 拿不到就怎样 | | — | — | — | | ① 语义树 | uiautomator / arc 拿控件,text + content-desc 双通道 | 不放弃,进下一层 | | ② OCR 兜底 | 截屏 + 本地 RapidOCR 认文字坐标,识别到表单就按坐标填注册 | 识别到网络错误页 → 归因 network_blocked | | ③ 如实归因 | 连 OCR 都认不出才判”自绘”,且把原因写进报告 | 绝不”报表成功却啥也没查到” |

同理适用于整个批量链路:失败要留下失败的原因,跳过要留下跳过的理由,归因要比结论诚实。批量列表里”跳过:自绘界面”和”跳过:需要短信验证码”和”网络错误页:App 服务端不可达”是三种完全不同的办案线索,绝不能混成一个”没搞定”。

OCR 还能顺手干一件事:把那些弹窗、协议页、验证码页的文案认出来,很多 App 的真正状态在语义树上根本看不见,但屏幕上写着。自动化的边界,就是”把看不见的东西想办法看见”。

8|学费清单:这期新增的坑

| 坑 | 解法 | | — | — | | Flutter 语义在 content-desc,text 全空 → 误判自绘 | text + desc 双通道统计;arc 按 content_desc(下划线)查询 | | adb shell cat 拉 PNG 被 CRLF/0x1A 损坏,OCR 永远失败 | 改 adb pull 原生二进制通道,优先 pull、cat 仅兜底 | | App 服务端不可达卡在网络错误页 → 误报”无法自动化” | OCR 认出错误页 → 归因 network_blocked(服务端已死=取证结论) | | 定时任务与手动批量同时触发抢模拟器 | 全局互斥:同一时刻仅一个批次,定时触发时在跑则跳过并记日志 | | 重复扫描同一批检材白烧时间 | parsed.json 账本:路径+大小+修改时间 三重指纹去重 | | 批量并行解析互相踩模拟器/报告路径 | 单队列串行,宁慢勿乱,账本与报告一一对应 | | 浏览器拦 file:// 直开本地报告 | RPC 拉内容 + Blob + a[download],文件名取包名 |

💰共性规律:这批坑没有一个是”功能没做”,全是通道失真。二进制过 PTY 失真、语义树字段失真、进程状态失真、重复触发失真。做自动化,先假设每条通道都会悄悄出错,再给每条通道装一个”看出错了”的眼睛。

9|怎么知道自己做对了:三步验收

批量+定时这种”无人值守”功能,验收标准比单包更严:

  • 一次性验收

    :准备 N 个混合样本(普通包、加固包、Flutter 包、伪装包)丢进目录跑一遍,报告 N 份全出、账本 N 条全记、再跑一遍 0 份重复——去重正确;

  • 中断恢复验收

    :跑到第 3 个的时候把工作台杀了重启,继续跑——账本不丢、从第 4 个接着来,前面的报告不受影响;

  • 定时验收

    :把 cron 改成”每分钟”临时跑一次,确认到点触发、目录里新丢的包被扫到、已解析的没动,然后改回正式时间。

10|写在最后

回到开头那段对话。同行说”采集仪自动解析效果不怎么样”——我的回答是:自研批量解析的价值不在”快”,而在每一份报告都经过同一套可解释的引擎,每一行结论都能回查到证据。采集仪可能是黑盒,自己搭的工作台不是。

这期工作台从”单包解析”长到”批量 + 定时 + 自动归档”。下一步可能就是在报告里直接给出待办线索清单,或者按案件自动归档目录结构。路径还是那句话:先解决自己手里最烦的那一步,工具就会自己长。

你的检材目录里,还有多少个 APK 在等一份报告?把它们丢进去试试。

🧯 顺带一句给同行的提醒(关于工作台底层引擎升级): 写这期的时候,我顺手把工作台底层的 dsh 引擎升了个级(0.1.0 → 0.1.2),结果踩了一串坑:装包 404、启动崩溃、打开页面连环报错,前前后后 12 个。经验已写成避坑记录,并做了一个一键自愈脚本 dsh-selfheal.mjs: node dsh-selfheal.mjs –check(体检 7 项)→ node dsh-selfheal.mjs –fix(自动修复) 给你提个醒:如果工作台现在用得好好的,非必要不需要升级——升完并没有优化到哪里去,界面几乎没变化,却要付一整晚排雷的账。真到必须升级那天,记得先备份工作台,再跑一遍自愈脚本,能避开大部分坑。

📦 本期资料领取: v2.5 发布包(批量解析 · 自动出报告 · 自定义下载 · 定时任务,全包版 175.8MB / 瘦身版 63.1MB)领取:一键三连本文章且关注下方视频号并一键三连视频(点赞、关注、在看)回复 6 一并获取;第 05 期发布包回复 5,第 04 期发布包回复 4

— 小谢 · AI 取证实战 · 第 06 期 · 完 —

敬请各位大佬关注:小谢取证

 

敬请各位大佬关注:小谢取证

扫取二维码获取

更多精彩

小谢取证


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:小谢取证 小谢 小谢《AI 取证实战第06期: 一个文件夹丢进去, APK 批量解析自动出报告》

评论:0   参与:  0