2026平航杯 手机取证题解析

yagami 发表于 1 小时前 共 6,964 字、阅读约 23 分钟

🏆 2026平航杯手机取证 Writeup


💡 报告元数据

  • 首席取证官yagami
  • 任务目录/mnt/d/文档/hermes-work/mobile-forensics/
  • 生成时间:2026-07-08
  • 生成模式:完整型取证交付 Writeup

🛠️ 工具链与环境底座

1. 算力与架构

组件分类 部署详情
自动化编排 Hermes Agent
基座大模型 Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-Q6_K_P.gguf
运行架构 本地

2. 任务信息

项目 详情
检材1 早起王手机 — Pixel 6, Android 14, Google/oriole (/mnt/z/1-手机/早起王的手机/)
检材2 倩倩手机 — nova 12 Pro, HarmonyOS 6.0.0.380 (/mnt/z/1-手机/倩倩的手机/)
检材3 倩倩手机逆向包 — RAR压缩包 (/mnt/z/1-手机/倩倩手机逆向包.rar)
题目数量 17题 (Q1-Q17)
完成状态 17/17 ✅ 全部完成并验证

📊 考题最终答案汇总看板

题号 核心考点 权威标准答案 状态 等级 核心证据链检索摘要
Q1 Android手机型号识别 Pixel 6 🟢 已验证 L1 PhoneInfo JSON直接提取Model字段
Q2 高德地图POI搜索记录取证 西湖 🟢 已验证 L2 PoiDetailUserBehavior.xml + pre_set_word_local_storage.xml双证据交叉
Q3 微信FTS5加密数据库解密与加好友时间 2026-03-3015:13:08 🟢 已验证 L2 MMKV提取FTS密码→SQLCipher解密→FTS5MetaMessage系统消息时间戳
Q4 微信朋友圈protobuf解码 麻薯小蛋糕 🟢 已验证 L1 SnsMicroMsg.db未加密,protobuf解码朋友圈内容
Q5 HarmonyOS备份元数据分析 6.0.0.380 🟢 已验证 L1 .info.json中BackupFileVersionInfo.versionName直接读取
Q6 SQLite WAL文件原始数据提取 wxid_uh5tfx2zi8yh22 🟢 已验证 L1 fts_contact.db-wal原始WAL帧数据中搜索"舔狗"联系人记录
Q7 HarmonyOS备忘录AES-GCM解密 冰糖 🟢 已验证 L2 备忘录cloud_notes原文 + 截图交叉验证
Q8 加密截图解密与视觉分析 zero sievert 🟢 已验证 L1 .tb文件xorEncrypt解密后截图视觉分析
Q9 HarmonyOS搜狐新闻数据库统计 33 🟢 已验证 L1 gen_natural_store.db主库sync_data表精确COUNT查询
Q10 HarmonyOS逆向包module.json分析 com.koishi.fpt 🟢 已验证 L1 module.json中bundleName字段直接提取
Q11 ABC字节码字符串提取 6 🟢 已验证 L1 ABC字节码strings提取"密码长度至少为6位"
Q12 ABC字节码加密后缀识别 .tb 🟢 已验证 L1 ABC字节码strings提取.tb后缀
Q13 ABC字节码文件类型分类统计 5 🟢 已验证 L1 ABC字节码中提取图片类型列表:jpg/jpeg/png/gif/webp共5种
Q14 SO模块NAPI方法数IDA反汇编验证 2 🟢 已验证 L2 IDA反汇编napi_define_properties count=2 + SO rodata交叉验证
Q15 SO rot13函数ROT+16发现与密码恢复 217cb94a01679e39 🟢 已验证 L2 IDA确认rot13=ROT+16 → vault_prefs ROT-16逆运算恢复原始密码
Q16 xorEncrypt自定义算法解密JSON 1472580369123 🟢 已验证 L1 xorEncrypt公式 output[i]=data[i]^(key[i%k]+(i%k)) 解密notes JSON
Q17 PNG文件末尾隐写数据提取 flag 🟢 已验证 L1 PNG IEND chunk后27字节隐藏flag数据

⚔️ 深度取证与解题全链路复盘

🧩 Q1 早起王的手机-1:手机型号

  • 题目:分析早起王的手机,手机型号为?【答案格式:Xiaomi13】

  • 标准答案Pixel 6

  • 状态等级:🟢 已验证 / L1

  • 解题主线:早起王手机检材根目录下有 PhoneInfo-1775206177238 JSON文件,直接读取Model字段即可。

  • 💡 关键证据

    • PhoneInfo-1775206177238 JSON内容:"Model":"Pixel 6", "Device":"oriole", "Brand":"google"
  • 🛠️ 核心命令

cat /mnt/z/1-手机/早起王的手机/PhoneInfo-1775206177238
# Model: Pixel 6, Device: oriole, Brand: google
  • 验证闭环:从原始检材独立复现,JSON字段直接提取,无歧义。

🧩 Q2 早起王的手机-2:高德地图最可能去的景点

  • 题目:分析早起王的手机,早起王最近想旅行,结合高德地图搜索记录,他最可能去的景点是哪个?【答案格式:黄山】

  • 标准答案西湖

  • 状态等级:🟢 已验证 / L2

  • 解题主线:从root.tar中提取高德地图(com.autonavi.minimap)数据,查看shared_prefs中的POI访问行为和预设搜索词。

  • 💡 关键证据

    • 证据源1:PoiDetailUserBehavior.xml 中最后访问的POI为 "name":"杭州西湖风景名胜区"
    • 证据源2:pre_set_word_local_storage.xml 中预设搜索词 "杭州西湖":1
  • 🛠️ 核心命令

mkdir -p /tmp/zqw-phone && cd /tmp/zqw-phone
tar xf /mnt/z/1-手机/早起王的手机/root.tar --strip-components=3 data/data/com.autonavi.minimap/

cat shared_prefs/PoiDetailUserBehavior.xml
# "name":"杭州西湖风景名胜区"

cat shared_prefs/pre_set_word_local_storage.xml
# "杭州西湖":1
  • 验证闭环:双证据交叉验证 — POI访问记录 + 预设搜索词均指向"杭州西湖",答案简化为"西湖"。

🧩 Q3 早起王的手机-3:加上倩倩微信的时间

  • 题目:分析早起王的手机,早起王在什么时间加上倩倩微信的?【答案格式:2025-08-1807:09:19】

  • 标准答案2026-03-3015:13:08

  • 状态等级:🟢 已验证 / L2

  • 解题主线

    • 阶段1 — FTS密码提取:在微信MMKV配置文件中搜索FTS数据库加密密码
    • 阶段2 — SQLCipher解密:用提取的密码解密FTS5IndexMicroMsg_encrypt.db
    • 阶段3 — 好友验证消息定位:在FTS5MetaMessage中查找最早的系统消息(好友验证通过)
  • 💡 关键证据

    • FTS密码来源mmkv_private/ConfigStorage2 中明文存储 USERINFO_FTS_MASTER_DB_ENCRYPT_PWD_STRING → 20623a1
    • SQLCipher参数:page_size=4096, kdf_iter=64000, hmac_reserve=48, digest=sha1
    • 好友验证消息:FTS5MetaMessage.docid=38: aux_index=wxid_zuaa9igqlro22, talker=wxid_zuaa9igqlro22, timestamp=1774854788001
    • 消息内容:FTS5IndexMessage_content docid=38: "我通过了你的朋友验证请求,现在我们可以开始聊天了"
    • 时间戳转换:1774854788001 → 2026-03-30 15:13:08 (UTC+8)
  • 🛠️ 核心命令

# 阶段1: MMKV提取FTS密码
grep -a "USERINFO_FTS_MASTER_DB_ENCRYPT_PWD_STRING" /tmp/zqw-wechat/data/data/com.tencent.mm/MicroMsg/bdf648ed55f29d2f2b30888e605a2a86/mmkv_private/ConfigStorage2
# → USERINFO_FTS_MASTER_DB_ENCRYPT_PWD_STRING ... 20623a1

# 阶段2: SQLCipher解密FTS数据库
DB="/tmp/zqw-wechat/data/data/com.tencent.mm/MicroMsg/bdf648ed55f29d2f2b30888e605a2a86/FTS5IndexMicroMsg_encrypt.db"
sqlcipher "$DB" <<'EOF'
PRAGMA key = '20623a1';
PRAGMA cipher_page_size = 4096;
PRAGMA kdf_iter = 64000;
PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
.output /tmp/zqw-wechat/FTS5Index_plain.db.sql
.dump
EOF
# → 82张表,解密成功

# 阶段3: 查询好友验证消息
grep "^INSERT INTO \"FTS5MetaMessage\" VALUES(38," /tmp/zqw-wechat/FTS5Index_plain.db.sql
# → aux_index=wxid_zuaa9igqlro22, timestamp=1774854788001

grep "^INSERT INTO \"FTS5IndexMessage_content\" VALUES(38," /tmp/zqw-wechat/FTS5Index_plain.db.sql
# → content = "我通过了你的朋友验证请求,现在我们可以开始聊天了"

# 时间戳转换
python3 -c "from datetime import datetime,timezone,timedelta; ts=1774854788001; print(datetime.fromtimestamp(ts/1000,tz=timezone.utc).astimezone(timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))"
# → 2026-03-30 15:13:08
  • 验证闭环:FTS5MetaMessage中docid=38是该wxid最早的37条消息之一,内容为系统自动生成的好友验证通过消息。联系人索引建档时间(2026-04-01 15:23:33)晚于首次消息时间,确认为FTS异步索引延迟。

  • ⚠️ 修正复盘:最初误用联系人索引建档时间 2026-04-01 15:23:33 作为答案,后经交叉验证发现FTS5MetaMessage中最早消息时间为 2026-03-30 15:13:08,且内容为好友验证通过系统消息,修正为正确答案。


🧩 Q4 早起王的手机-4:倩倩2026年3月30号吃了什么

  • 题目:分析早起王的手机,倩倩在2026年3月30号吃了什么?【答案格式:西湖醋鱼】

  • 标准答案麻薯小蛋糕

  • 状态等级:🟢 已验证 / L1

  • 解题主线:早起王手机中微信SnsMicroMsg.db未加密,直接查询倩倩(wxid_zuaa9igqlro22)的朋友圈数据,protobuf解码后找到2026-03-30发布的内容。

  • 💡 关键证据

    • SnsMicroMsg.db (protobuf解码): createTime=1774857137 → 2026-03-30 15:52:17
    • 朋友圈内容:"今天吃了麻薯小蛋糕 开心开心开心!"
  • 🛠️ 核心命令

DB="/tmp/zqw-wechat/data/data/com.tencent.mm/MicroMsg/bdf648ed55f29d2f2b30888e605a2a86/SnsMicroMsg.db"
sqlite3 "$DB" "SELECT snsId, userName, createTime, content FROM SnsInfo WHERE userName='wxid_zuaa9igqlro22' ORDER BY createTime DESC;"

python3 -c "from datetime import datetime; print(datetime.fromtimestamp(1774857137))"
# 2026-03-30 15:52:17 — "今天吃了麻薯小蛋糕 开心开心开心!"
  • 验证闭环:从原始检材独立复现,SnsMicroMsg.db未加密直接查询,protobuf解码后内容明确。

🧩 Q5 倩倩的手机-1:系统版本

  • 题目:分析倩倩的手机,倩倩手机的系统版本是多少?【答案格式:5.2.3.123】

  • 标准答案6.0.0.380

  • 状态等级:🟢 已验证 / L1

  • 解题主线:直接读取HarmonyOS备份元数据文件 .info.json,从中提取 BackupFileVersionInfo.versionName

  • 💡 关键证据

    • .info.json: BackupFileVersionInfo.versionName = "6.0.0.380"
    • versionCode = “60000380” 也对应 6.0.0.380
  • 🛠️ 核心命令

python3 -c "import json; info=json.load(open('/mnt/z/1-手机/倩倩的手机/备份/.info.json')); print(info['BackupFileVersionInfo']['versionName'])"
# → 6.0.0.380
  • 验证闭环:从原始检材直接读取,无歧义。

  • ⚠️ 修正复盘:原答案 5.0.0.123 是推断值(无直接证据),实际应从 .info.json 直接读取为 6.0.0.380。


🧩 Q6 倩倩的手机-2:"舔狗"的微信内部ID

  • 题目:分析倩倩的手机,"舔狗"的微信内部ID是多少?【答案格式:wxid_ab12】

  • 标准答案wxid_uh5tfx2zi8yh22

  • 状态等级:🟢 已验证 / L1

  • 解题主线:HarmonyOS备份中微信模块的 fts_contact.db 主文件为69KB全零占位符,实际数据在WAL文件(3.8MB)中。直接在WAL原始二进制数据中搜索"舔狗"字符串,找到完整联系人记录。

  • 💡 关键证据

    • fts_contact.db-wal offset 424271 处原始数据:舔狗\0越过山丘\0...\0wxid_uh5tfx2zi8yh22
    • 联系人信息:昵称=“舔狗”, 签名=“越过山丘”, wxid=wxid_uh5tfx2zi8yh22
  • 🛠️ 核心命令

# 在WAL文件中搜索"舔狗"
grep -a -o -P ".{0,50}舔狗.{0,100}" fts_contact.db-wal
# → 舔狗\0越过山丘\0...\0wxid_uh5tfx2zi8yh22
  • 验证闭环:WAL原始数据中昵称、签名、wxid完整对应,无歧义。

🧩 Q7 倩倩的手机-3:推荐游戏的好友名字

  • 题目:分析倩倩的手机,倩倩曾给一位好友推荐游戏,这个好友叫什么名字?【答案格式:杨梅】

  • 标准答案冰糖

  • 状态等级:🟢 已验证 / L2

  • 解题主线

    • 阶段1 — HarmonyOS备忘录解密:用 per_backup_key 派生模块key,AES-GCM解密备忘录数据
    • 阶段2 — 备忘录原文提取:从 notepad.db cloud_notes 表中找到游戏推荐相关记录
    • 阶段3 — 截图交叉验证:解密加密截图确认聊天对象
  • 💡 关键证据

    • 证据源1 — 备忘录原文:HarmonyOS备忘录模块 com.huawei.hmos.notepad,解密后 cloud_notes.data JSON内容:
      "找一下截图在哪\n很久以前我给好友**冰糖**推荐过一款游戏,但我这笨脑子却想不起来了。所幸我当时有截过图,但是被放到什么位置来着?"
    • HTML实体解码:&#25214;&#19968;&#19979;&#25130;&#22270;&#22312;&#21738; → “找一下截图在哪”
    • 证据源2 — 解密截图:Snipaste_2026-04-03_10-56-53.jpg 顶部显示"冰糖君酱"(微信备注名),聊天内容中"冰糖若喜欢…“断句为"冰糖 若(如果) 喜欢…”
  • 🛠️ 核心命令

# HarmonyOS备忘录解密流程
# 1. per_backup_key = "59fpxqgiqe+c7sqtXHCkmA==" (ASCII字节)
# 2. PBKDF2(per_backup_key, module.encryptionSalt, count=10000) → module_key
# 3. AES-GCM(module_key, module.encryptionIv, encrypted_blob) → plaintext
# 4. 解压 part.0.tar → notepad.db
# 5. cloud_notes.data JSON: "很久以前我给好友冰糖推荐过一款游戏"
  • 验证闭环:备忘录原文是倩倩自己的记录,明确写的是"好友冰糖"。截图顶部"冰糖君酱"是微信中的备注名/显示名。题目问"这个好友叫什么名字",以备忘录原文为准。

  • ⚠️ 修正复盘:一度误将截图顶部"冰糖君酱"(微信备注名)作为答案,后经HarmonyOS备忘录原文交叉验证确认为"冰糖"。


🧩 Q8 倩倩的手机-4:推荐的游戏名

  • 题目:分析倩倩的手机结合逆向包,推荐的游戏叫什么?【答案格式:far echo】

  • 标准答案zero sievert

  • 状态等级:🟢 已验证 / L1

  • 解题主线:解密加密截图 Snipaste_2026-04-03_10-56-53.jpg.tb,视觉分析聊天内容找到游戏名。

  • 💡 关键证据

    • 解密截图中的聊天内容:"话说回来我刚打了半天另一款平面射击的类塔科夫游戏呢,叫 zero sievert"
    • 推荐消息:"冰糖若喜欢原版塔科夫的话,这个游戏大概也会对你的口味,可以了解下(就是画风和机制完全不一样)"
  • 验证闭环:截图视觉分析直接提取游戏名 “zero sievert”。


🧩 Q9 倩倩的手机-5:阅读搜狐新闻条数

  • 题目:分析倩倩的手机,倩倩一共阅读过多少条搜狐新闻?【答案格式:11】

  • 标准答案33

  • 状态等级:🟢 已验证 / L1

  • 解题主线:从HarmonyOS备份中解密 com.sohu.harmonynews 模块,在 gen_natural_store.db 主库的 sync_data 表中统计 article 开头的记录数。

  • 💡 关键证据

    • gen_natural_store.db sync_data表: SELECT COUNT(*) FROM sync_data WHERE key LIKE 'article%'33条
    • 总记录35条(33条article + CHANNEL_LIST_DATA + NEWS_LIST_DATA)
  • 🛠️ 核心命令

sqlite3 "$DB" "SELECT COUNT(*) FROM sync_data WHERE key LIKE 'article%';"
# → 33
  • 验证闭环:主库精确查询,排除非article记录。

  • ⚠️ 修正复盘:原答案39来自WAL文件提取(可能包含已删除或重复记录),经主库精确查询修正为33条。


🧩 Q10 倩倩的手机-6:数据加密app包名

  • 题目:分析倩倩手机逆向包,数据加密app的包名是什么?【答案格式:com.komeiji.satori】

  • 标准答案com.koishi.fpt

  • 状态等级:🟢 已验证 / L1

  • 解题主线:解压逆向包RAR,读取 module.json 中的 bundleName 字段。

  • 💡 关键证据

    • module.json: "bundleName": "com.koishi.fpt"
  • 🛠️ 核心命令

mkdir -p /tmp/qianqian-reverse && cd /tmp/qianqian-reverse
unrar x /mnt/z/1-手机/倩倩手机逆向包.rar

cd /tmp/qianqian-reverse/app_extract/hap_extract
cat module.json | python3 -m json.tool | grep bundleName
# "bundleName": "com.koishi.fpt"
  • 验证闭环:module.json直接提取,无歧义。

🧩 Q11 倩倩的手机-7:初始化密码最少位数

  • 题目:接上题,初始化app时需要至少几位数的密码?【答案格式:10】

  • 标准答案6

  • 状态等级:🟢 已验证 / L1

  • 解题主线:从ABC字节码中提取字符串,找到密码长度校验提示。

  • 💡 关键证据

    • ABC字节码strings: "密码长度至少为6位", "请输入新密码(至少6位)"
  • 🛠️ 核心命令

strings ets/modules.abc > /tmp/abc_strings.txt
grep "至少为6位" /tmp/abc_strings.txt
# "密码长度至少为6位"
  • 验证闭环:两处字符串均确认最少6位。

🧩 Q12 倩倩的手机-8:加密文件后缀

  • 题目:接上题,加密后的文件名的后缀是什么?【答案格式:.enc】

  • 标准答案.tb

  • 状态等级:🟢 已验证 / L1

  • 解题主线:从ABC字节码中提取 .tb 后缀字符串,vault目录中实际加密文件也使用 .tb 后缀。

  • 💡 关键证据

    • ABC字节码strings: .tb suffix found
    • vault目录文件:139346145_p0.png.tb, Snipaste_2026-04-03_10-56-53.jpg.tb, *.json.tb
  • 🛠️ 核心命令

grep "\.tb" /tmp/abc_strings.txt
# .tb
  • 验证闭环:ABC字节码 + vault目录实际文件双重确认。

🧩 Q13 倩倩的手机-9:自动识别图片后缀种类数

  • 题目:接上题,app会自动识别几种后缀的文件为图片类型?【答案格式:8】

  • 标准答案5

  • 状态等级:🟢 已验证 / L1

  • 解题主线:从ABC字节码中提取文件类型列表,区分图片和视频类型。

  • 💡 关键证据

    • ABC字节码中文件类型列表:
      • 图片类型(5种): jpg, jpeg, png, gif, webp
      • 视频类型(4种): mp4, mov, avi, mkv
    • 题目问的是"图片类型",答案为5
  • 🛠️ 核心命令

python3 -c "
with open('ets/modules.abc','rb') as f: data=f.read()
pos = data.find(b'jpg')
print(data[pos-10:pos+80].decode('utf-8',errors='replace'))
"
# jpg, jpeg, png, gif, webp (5种图片)
  • 验证闭环:ABC字节码中明确列出5种图片后缀。

🧩 Q14 倩倩的手机-10:SO模块导入方法数

  • 题目:接上题,app共从用于自定义加密的so模块导入了几个方法?【答案格式:8】

  • 标准答案2

  • 状态等级:🟢 已验证 / L2

  • 解题主线

    • 阶段1 — ABC字节码初步分析:发现9个导入符号(t1,u1,v1,w1,z1,a2,b2,c2,d2),但其中q1(random)和s1(base64)是TypeScript工具函数,非SO导入
    • 阶段2 — IDA反汇编验证加载libcrypto.so,分析NAPI模块注册流程
    • 阶段3 — 交叉确认:napi_define_properties调用时count=2,属性表仅rot13和xorEncrypt
  • 💡 关键证据

    • 证据源1 — IDA反汇编sub_5D58 调用 napi_define_properties,参数 W2=#2 (AArch64调用约定x2=第三个参数=count),明确定义了2个NAPI属性
    • 证据源2 — 属性表0xd8f0:方法1=rot13(→sub_5DE0), 方法2=xorEncrypt(→sub_603C)
    • 证据源3 — NAPI module结构体0xed48:version=1, register_func=sub_5D58, module_name=“crypto”
    • ABC字节码中的9个符号(t1,u1,v1,w1,z1,a2,b2,c2,d2)是ArkTS编译后的局部混淆名,大部分对应标准C库函数(malloc,free,memcpy等),非NAPI注册方法
  • 🛠️ 核心命令

# IDA MCP 工具调用 (非shell命令):
# 1. 查看RegisterCryptoModule反汇编
mcp_ida_disasm(addr="RegisterCryptoModule")
# → NOP; ADR X0, unk_ED48; B .napi_module_register

# 2. 查看sub_5D58反汇编 (napi_define_properties调用者)
mcp_ida_disasm(addr="sub_5D58")
# → MOV W2, #2  (count=2个属性)
# → BL .napi_define_properties

# 3. 读取属性表数据
mcp_ida_get_string(addrs=["0x23f0", "0x3312"])
# → "rot13", "xorEncrypt"

# 结论: Q14答案 = 2 (L2 IDA反汇编 + ABC交叉验证)
  • 验证闭环:IDA MCP反汇编确认NAPI只注册了2个方法,ABC字节码9个导入符号中大部分是标准C库函数。

  • ⚠️ 修正复盘:原答案9误将ABC字节码中的混淆名t1,u1,v1,w1,z1,a2,b2,c2,d2当作SO导入方法,经IDA反汇编确认实际只有2个NAPI方法(rot13, xorEncrypt)。


🧩 Q15 倩倩的手机-11:app设置的密码

  • 题目:接上题,app设置的密码是多少?【答案格式:514aalla4191a98】

  • 标准答案217cb94a01679e39

  • 状态等级:🟢 已验证 / L2

  • 解题主线

    • 阶段1 — vault_prefs分析:提取 password_hash=217sr94q01679u39
    • 阶段2 — SO rot13函数IDA反汇编:发现rot13(sub_5DE0)实际是ROT+16算法
    • 阶段3 — ROT-16逆运算恢复原始密码:对password_hash做ROT-16逆变换
  • 💡 关键证据

    • vault_prefs: password_hash=217sr94q01679u39 (ROT+16变换后的存储值)
    • IDA反汇编 sub_5DE0MOV W15,#0xAF + 除法优化 = (ch+0xAF)%26+'a' = ROT+16算法
    • 精确验证:对a-z全部26字母测试,shift均为16
      • a→q(shift=16), b→r, c→s… z→p
    • 密码变换链:用户输入 217cb94a01679e39 → ROT+16 → 217sr94q01679u39 → vault_prefs存储
    • 原始密码恢复:ROT-16(217sr94q01679u39) = 217cb94a01679e39
  • 🛠️ 核心命令

# IDA MCP 工具调用:
mcp_ida_disasm(addr="sub_5DE0")
# 关键指令: MOV W15, #0xAF (175) -> 偏移量
# 算法: (ch + 0xAF) % 26 + 'a' = ROT+16

# Python精确验证rot13=ROT+16
python3 -c "
def ida_rot(ch):
    c = ord(ch)
    w13 = (c + 0xAF) & 0xFFFF
    w15 = (w13 * 0x4F) >> 11
    w13 = w13 - (w15 * 0x1A)
    w13 = w13 + 0x61
    return chr(w13 & 0xFF)

for ch in 'abcdefghijklmnopqrstuvwxyz':
    r = ida_rot(ch)
    shift = (ord(r) - ord(ch)) % 26
    print(f'{ch} -> {r} (shift={shift})')
"
# 全部shift=16,确认是ROT+16

# ROT-16逆运算恢复原始密码
python3 -c "
pw_hash = '217sr94q01679u39'
result = ''
for ch in pw_hash:
    if 'a' <= ch <= 'z':
        result += chr((ord(ch) - ord('a') - 16) % 26 + ord('a'))
    else:
        result += ch
print(f'password_hash: {pw_hash}')
print(f'ROT-16恢复: {result}')
"
# → 217cb94a01679e39

# 验证ROT+16正向变换
python3 -c "
original = '217cb94a01679e39'
result = ''
for ch in original:
    if 'a' <= ch <= 'z':
        result += chr((ord(ch) - ord('a') + 16) % 26 + ord('a'))
    else:
        result += ch
print(f'original: {original}')
print(f'ROT+16: {result}')
"
# → 217sr94q01679u39 (与vault_prefs一致)
  • 验证闭环:正向ROT+16(217cb94a01679e39) = 217sr94q01679u39,与vault_prefs中password_hash完全一致。用存储值作为xorEncrypt key成功解密所有3个.tb文件(JSON完美、PNG 16/16匹配、JPG FFD8正确)。

🧩 Q16 倩倩的手机-12:门锁密码

  • 题目:接上题,app中存储的门锁密码是多少?【答案格式:5141141919810】

  • 标准答案1472580369123

  • 状态等级:🟢 已验证 / L1

  • 解题主线:用xorEncrypt算法解密notes JSON文件,提取门锁密码。

  • 💡 关键证据

    • xorEncrypt加密公式:output[i] = data[i] ^ (key[i % key_len] + (i % key_len))
    • 解密key = 217sr94q01679u39 (vault_prefs存储值)
    • 解密后JSON内容:{"id":"b88c3348-9389-4fad-8cd6-3490e6bbdd26","title":"门锁密码","content":"1472580369123","updatedAt":1775196161152}
  • 🛠️ 核心命令

# xorEncrypt解密 (Python)
key = b'217sr94q01679u39'
with open('b88c3348-9389-4fad-8cd6-3490e6bbdd26.json.tb', 'rb') as f:
    ct = f.read()
pt = bytes(ct[i] ^ (key[i % len(key)] + (i % len(key))) for i in range(len(ct)))
import json
data = json.loads(pt)
print(data['content'])
# → 1472580369123
  • 验证闭环:解密后JSON结构完整,title=“门锁密码”,content=“1472580369123”。

🧩 Q17 倩倩的手机-13:加密图片隐藏flag

  • 题目:接上题,加密图片里面的隐藏的flag是多少?【答案格式:flag{123456!}】

  • 标准答案flag{happy_forensics_2026!}

  • 状态等级:🟢 已验证 / L1

  • 解题主线:用xorEncrypt解密PNG文件后,检查PNG结构发现IEND chunk后有27字节额外数据。

  • 💡 关键证据

    • 解密后的PNG文件 (3200x2000, 5.7MB) 包含709个chunk
    • 最后一个正常chunk是 IEND (0字节数据)
    • IEND之后有27字节额外数据:flag{happy_forensics_2026!}
    • 标准PNG阅读器忽略IEND后的数据,属于文件末尾隐写
  • 🛠️ 核心命令

# xorEncrypt解密PNG
key = b'217sr94q01679u39'
with open('139346145_p0.png.tb', 'rb') as f:
    ct = f.read()
pt = bytes(ct[i] ^ (key[i % len(key)] + (i % len(key))) for i in range(len(ct)))

# 检查PNG IEND后数据
png_data = bytearray(pt)
iend_pos = png_data.find(b'IEND')
if iend_pos >= 0:
    after_iend = png_data[iend_pos+8:]  # IEND + 4字节CRC
    print(after_iend[:50])
# → b'flag{happy_forensics_2026!}'
  • 验证闭环:PNG文件结构完整(709个chunk),IEND后27字节为纯文本flag。

🛑 未完成或不可提交题目审计

全量收敛:17/17题全部完成并验证,无未完成题目。

题号 状态 备注
Q1-Q17 🟢 已验证 全部从原始检材独立复现验证通过

📂 附录:自动化取证证据大索引

证据索引

编号 题号 证据描述 来源文件
FINDING-Q1-001 Q1 PhoneInfo JSON Model字段 PhoneInfo-1775206177238
FINDING-Q2-001 Q2 高德POI访问记录 PoiDetailUserBehavior.xml
FINDING-Q2-002 Q2 高德预设搜索词 pre_set_word_local_storage.xml
FINDING-Q3-001 Q3 FTS5数据库解密成功 FTS5IndexMicroMsg_encrypt.db
FINDING-Q3-002 Q3 联系人索引建档时间(非答案) FTS5MetaContact
FINDING-Q3-003 Q3 MMKV FTS密码查找方法验证 mmkv_private/ConfigStorage2
FINDING-Q3-004 Q3 好友验证消息时间戳修正 FTS5MetaMessage docid=38
FINDING-Q4-001 Q4 朋友圈protobuf解码内容 SnsMicroMsg.db
FINDING-Q5-001 Q5 系统版本直接证据 .info.json
FINDING-Q6-001 Q6 "舔狗"微信ID从WAL提取 fts_contact.db-wal
FINDING-Q7-001 Q7 截图视觉分析(冰糖君酱) Snipaste_2026-04-03_10-56-53.jpg
FINDING-Q7-002 Q7 备忘录原文确认"冰糖" notepad.db cloud_notes
FINDING-Q7Q8-001 Q7/Q8 游戏推荐截图完整分析 Snipaste_2026-04-03_10-56-53.jpg
FINDING-Q9-001 Q9 搜狐新闻主库精确统计 gen_natural_store.db sync_data
FINDING-Q10-001 Q10 app包名从module.json提取 module.json
FINDING-Q11-001 Q11 密码最少位数字符串 ABC字节码strings
FINDING-Q12-001 Q12 加密后缀.tb ABC字节码strings
FINDING-Q13-001 Q13 图片类型5种列表 ABC字节码文件类型列表
FINDING-Q14-001 Q14 SO实际导出2个NAPI方法 libcrypto.so反汇编
FINDING-Q14-IDA-001 Q14 IDA MCP验证NAPI方法数 IDA反汇编
FINDING-Q15-001 Q15 xorEncrypt算法完整破解 libcrypto.so + PNG已知明文攻击
FINDING-Q15-IDA-002 Q15 IDA确认rot13=ROT+16 IDA反汇编 sub_5DE0
FINDING-Q16-001 Q16 门锁密码从加密notes提取 b88c3348…json.tb解密JSON
FINDING-Q17-001 Q17 PNG IEND后隐藏flag 解密PNG文件末尾27字节
FINDING-HarmonyOS-Backup-Decrypt Q6-Q9 HarmonyOS备份二次解密完整流程 .info.json + PBKDF2 + AES-GCM

命令索引

编号 描述
CMD-20260707-001 Q3 FTS5IndexMicroMsg_encrypt.db 独立解密验证
CMD-20260707-Q3V1 Q3 答案验证 — 好友验证消息时间戳确认
CMD-20260707-Q5V1 Q5 独立验证 — .info.json直接读取
CMD-20260707-Q14-IDA Q14 IDA MCP 独立验证 — NAPI方法数
CMD-20260707-Q15-IDA Q15 IDA MCP rot13=ROT+16 验证
CMD-20260708-V001 全量验证批次 — 17题从原始检材独立复现

- 全链路取证闭环完成 -

退回首页 留下一言