2026平航杯手机取证题解析

admin 2026-07-10 05:49:43 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 该文档为2026平航杯手机取证比赛的完整Writeup,涵盖17道题目的解题过程。核心要点包括:通过PhoneInfoJSON识别Pixel6手机型号;利用高德地图POI行为与预设搜索词双证据交叉验证确定西湖为最可能景点;通过MMKV提取FTS密码并解密SQLCipher数据库,定位好友验证时间2026-03-3015:13:08;从SnsMicroMsg.dbprotobuf解码获取朋友圈内容麻薯小蛋糕。文档展示了从数据提取、解密到逆向分析的全链路取证方法,工具链包括HermesAgent和Qwen3.6模型。 综合评分: 85 文章分类: 应急响应,逆向分析,数据恢复,移动安全,安全工具


  • 验证闭环:备忘录原文是倩倩自己的记录,明确写的是”好友冰糖”。截图顶部”冰糖君酱”是微信中的备注名/显示名。题目问”这个好友叫什么名字”,以备忘录原文为准。
  • ⚠️ 修正复盘:一度误将截图顶部”冰糖君酱”(微信备注名)作为答案,后经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)

  • 🛠️ 核心命令

ounter(lineounter(linesqlite3 "$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"

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(linemkdir -p /tmp/qianqian-reverse && cd /tmp/qianqian-reverseunrar x /mnt/z/1-手机/倩倩手机逆向包.rar
cd /tmp/qianqian-reverse/app_extract/hap_extractcat 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位)"

  • 🛠️ 核心命令

ounter(lineounter(lineounter(linestrings ets/modules.abc > /tmp/abc_strings.txtgrep "至少为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.tbSnipaste_2026-04-03_10-56-53.jpg.tb*.json.tb

  • 🛠️ 核心命令

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

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

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

  • 标准答案5

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

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

  • 💡 关键证据

  • 图片类型(5种): jpg, jpeg, png, gif, webp

  • 视频类型(4种): mp4, mov, avi, mkv

  • ABC字节码中文件类型列表:

  • 题目问的是”图片类型”,答案为5

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(linepython3 -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注册方法

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line# 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逆变换

  • 💡 关键证据

  • a→q(shift=16), b→r, c→s… z→p

  • vault_prefs: password_hash=217sr94q01679u39 (ROT+16变换后的存储值)

  • IDA反汇编 sub_5DE0MOV W15,#0xAF + 除法优化 = (ch+0xAF)%26+'a' = ROT+16算法

  • 精确验证:对a-z全部26字母测试,shift均为16

  • 密码变换链:用户输入 217cb94a01679e39 → ROT+16 → 217sr94q01679u39 → vault_prefs存储

  • 原始密码恢复:ROT-16(217sr94q01679u39) = 217cb94a01679e39

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line# IDA MCP 工具调用:mcp_ida_disasm(addr="sub_5DE0")# 关键指令: MOV W15, #0xAF (175) -> 偏移量# 算法: (ch + 0xAF) % 26 + 'a' = ROT+16
# Python精确验证rot13=ROT+16python3 -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:&nbsp; &nbsp; if 'a' <= ch <= 'z':&nbsp; &nbsp; &nbsp; &nbsp; result += chr((ord(ch) - ord('a') - 16) % 26 + ord('a'))&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; result += chprint(f'password_hash: {pw_hash}')print(f'ROT-16恢复: {result}')"# → 217cb94a01679e39
# 验证ROT+16正向变换python3 -c "original = '217cb94a01679e39'result = ''for ch in original:&nbsp; &nbsp; if 'a' <= ch <= 'z':&nbsp; &nbsp; &nbsp; &nbsp; result += chr((ord(ch) - ord('a') + 16) % 26 + ord('a'))&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; result += chprint(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}

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line# xorEncrypt解密 (Python)key = b'217sr94q01679u39'with open('b88c3348-9389-4fad-8cd6-3490e6bbdd26.json.tb', 'rb') as f:&nbsp; &nbsp; ct = f.read()pt = bytes(ct[i] ^ (key[i % len(key)] + (i % len(key))) for i in range(len(ct)))import jsondata = 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文件 (3200×2000, 5.7MB) 包含709个chunk

  • 最后一个正常chunk是 IEND (0字节数据)

  • IEND之后有27字节额外数据:flag{happy_forensics_2026!}

  • 标准PNG阅读器忽略IEND后的数据,属于文件末尾隐写

  • 🛠️ 核心命令

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line# xorEncrypt解密PNGkey = b'217sr94q01679u39'with open('139346145_p0.png.tb', 'rb') as f:&nbsp; &nbsp; 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:&nbsp; &nbsp; after_iend = png_data[iend_pos+8:] &nbsp;# IEND + 4字节CRC&nbsp; &nbsp; 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题从原始检材独立复现 |


- 全链路取证闭环完成 -

  • END –

免责声明:

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

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

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

本文转载自:取证与溯源 怪叔叔 怪叔叔《2026平航杯 手机取证题解析》

评论:0   参与:  0