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

作者:小谢取证 发布:2026-09-05 00:17 收录:2026-09-07 11:03 1 次阅读 约 3959 字
摘要:3 小时无人值守,APK 从丢进目录到报告自动落盘全流程拆解:去重账本怎么防重跑、定时任务凌晨自己开工、批量解析翻车现场的三层根因。非必要别升级底层引擎——原因和避坑脚本都在文里。
推荐理由:本文涵盖「APK批量解析」、「自动出报告」、「定时任务」等多个主题,重点关注 APK批量解析。

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 批量解析自动出报告》, 查看原文。 版权归原作者及原发布平台所有,本站仅作收录与展示,未对正文内容作实质性修改; 若涉及侵权请联系本站处理。