做微信本地数据恢复的时候最让人头疼的就是那个 EnMicroMsg.db它是微信在本地存储聊天记录、联系人、消息索引的核心数据库文件。很多人以为把它从手机里拷出来就能直接打开结果拿 SQLite 工具一开就一句 file is not a database 甩在脸上。这套加密机制不是微信随意加的而是基于 SQLCipher 对 SQLite 的完整加密改造底层用的是 AES默认走 CBC 模式数据库每一页都有 HMAC 校验。这篇内容就是把 EnMicroMsg.db 的加密原理和恢复流程拆开讲清楚从 AES 的初始向量怎么来、32 字节密钥怎么算到最终怎么把数据库还原成可读的明文文件适合做数据恢复、取证分析、安全研究的读者也适合那些账号还在、但误删或换机后想找回本地聊天记录的普通用户。需要先说明一个边界本文涉及的解密和恢复方案只适用于你自己设备上的数据或者你拥有明确授权的数据。技术本身是中立的但使用场景必须合法合规。下面正式开始。1. 先搞明白 EnMicroMsg.db 到底锁住了什么1.1 一个数据库文件背后是整个微信本地消息体系微信不像很多 App 那样把聊天记录全部放服务器而是采用本地存储 云端同步混合模式。你每次收发消息、图片、语音、文件除了服务端有一份客户端也会实时写入本地数据库这个数据库就是 EnMicroMsg.db。名字里的 EnMicroMsg 拆开看是 Encrypted Micro Message翻译过来就是加密的微消息从命名就能看出它从诞生起就没打算让你明文读取。数据库文件路径在 Android 上固定为/data/data/com.tencent.mm/MicroMsg/32位MD5文件夹/EnMicroMsg.dbiOS 因为有沙盒机制路径稍复杂但本质一样。这个 32位MD5文件夹 也不是随机生成的它是 MD5(IMEI UIN) 的哈希值用于区分不同的微信账号实例。一个手机上登录过多个微信号就会出现多个这样的文件夹每个账号一套数据库。数据库内部包含几十张表核心的有message聊天消息、rcontact联系人、chatting会话列表、img_flag图片索引、voice语音消息索引等。message表是数据量最大的每条消息的content字段里存的是 XML 结构包含了文本内容、引用消息、提醒等信息。图片和语音文件本身不直接存在数据库里数据库只存路径和缩略图索引原始文件在同一个目录下的attachment、image2、voice2等文件夹里。所以恢复微信本地数据的本质是两件事第一把 EnMicroMsg.db 解密成明文 SQLite第二根据解密后的索引字段把散落在各个目录下的语音、图片、视频文件重新关联起来。网上很多所谓的微信聊天记录恢复工具核心都是先做第一步再做第二步。1.2 为什么微信要上加密而不是直接用明文 SQLite如果你用过早期版本的微信或者逆向过其他 App会发现很多应用当年的本地数据库就是裸的 SQLite拿一个 DB Browser 就能直接打开聊天记录、账号信息一目了然。微信后来改得这么严原因倒不复杂。第一是隐私合规压力用户的聊天记录属于高度敏感数据明文存在手机里一旦手机被 root、被备份、被拿去维修数据就等于拱手送人。第二是商业和安全考量防止第三方工具随意读写数据库导致消息错乱、索引崩溃最终影响微信自身的稳定性。第三是技术架构上的选择SQLCipher 是一个成熟的 SQLite 加密扩展加密粒度细、性能损耗可控微信不需要从头造轮子直接把 SQLCipher 编译进客户端就能用。理解了这个背景你才能明白为什么恢复工作不是绕过加密而是还原密钥。加密方案设计的初衷不是让你永远读不出来是让没有密钥的人读不出来。你作为设备的主人IMEI 和 UIN 都在自己手里理论上密钥是可计算的所以恢复是可行的。这也正是本文核心思路的来源。2. AES 加密在这个场景里的实际工作方式2.1 对称加密与 AES-CBC 的基本逻辑EnMicroMsg.db 用的加密算法是 AES全称 Advanced Encryption Standard这是一种对称加密算法。对称的意思是加密和解密用同一把密钥你拿这把密钥把数据库加密同样拿这把密钥才能解开。AES 本身支持 128/192/256 位三种密钥长度SQLCipher 默认用的是 AES-256也就是 32 字节的密钥。AES 加密有很多工作模式ECB、CBC、CTR、GCM 等。SQLCipher 选择的是 CBC 模式全称 Cipher Block Chaining中文叫密码分组链接。CBC 的核心特点是每一个明文分组在加密之前要先和前一个密文分组做异或运算第一个分组没有前一个密文就用一个叫 IVInitial Vector初始向量的随机值来充当。IV 的作用是让同样的明文在不同加密过程中产生不同的密文。比如数据库第一页的内容是固定的结构头如果不用 IV所有微信数据库的第一页密文都会完全一样攻击者一看就知道是同一个软件产生的这会给分析和破解提供巨大便利。加了随机 IV 之后即使两个数据库内容一模一样密文也完全不同。在 EnMicroMsg.db 的加密场景里SQLCipher 会为每个数据库文件生成一个随机盐Salt和随机 IV存储在文件头部。打开数据库时SQLCipher 会先用密钥和盐做密钥派生再开始逐页解密。这就是为什么你不能直接把一个 32 字节的密钥喂进去就完事必须让 SQLCipher 自己走完头部的解析流程。2.2 密钥是怎么来的IMEI UIN 的哈希链网上关于 EnMicroMsg.db 密钥的说法很多最常见的说法是密钥等于 MD5(IMEI UIN)这个说法对老版本基本准确但不完全准确因为 MD5 输出是 32 字节的十六进制字符串也就是 32 个 ASCII 字符而 SQLCipher 需要的是二进制密钥。实际的过程分两步。第一步把 IMEI 和 UIN 拼接成字符串比如 IMEI 是860000000000000UIN 是123456789拼接结果是860000000000000123456789。第二步对这个字符串做 MD5 哈希得到 32 字节的十六进制文本这一步在整个微信历史版本里几乎没变过。但在旧版微信的 SQLCipher 参数里密钥长度用的是 7 字节有效位。你没看错就是取 MD5 结果的前 7 个字节。SQLCipher 打开数据库时你传进入的口令是那 32 个十六进制字符但最终派生的密钥只取前 14 个十六进制字符对应的 7 个原始字节。所以新手在用 SQLCipher 命令行解密的时候明明 MD5 算对了却一直提示密码错误就是因为把完整 32 字节塞进去了而微信当年实际用的是 PRAGMA key xxxxxxxxxxxxxx 这种只支持短密钥的旧格式。到了微信 7.0 之后的版本加密参数升级了密钥处理方式也变了。新版本不再直接依赖 IMEI而是在某些设备上改用 Android ID 或者其他设备唯一标识拼接 UIN再走同样的 MD5 流程。这一步对做恢复的人来说是最大的坑因为 IMEI 在 Android 10 以后普通应用拿不到了微信内部可能早就换用了备选方案。所以当你用老方法算出来的密钥打不开较新版本的数据库时不要急着怀疑自己算错了先确认微信版本对应的密钥生成规则。2.3 SQLCipher 的页级加密与 HMAC 校验SQLCipher 不是一个独立的数据库它是 SQLite 的一个编译分支保留了 SQLite 的全部 API只是在文件存储层做了加密。它把整个数据库文件切成固定大小的页默认 4096 字节每一页独立加密每一页末尾附带 16 字节的 HMAC 校验值用于检测数据是否被篡改。页级加密带来的影响是如果你只解密了文件的前半部分后半部分依然是密文SQLite 工具打开时就会报错。所以解密操作必须是整体性的SQLCipher 在打开数据库后会通过读取每一页来验证密钥是否正确。密钥对了第一页的 HMAC 校验通过数据库就能正常读取密钥错了第一页就解不开直接提示file is not a database或者HMAC verification failed。这也解释了为什么暴力破解 EnMicroMsg.db几乎不可行。AES-256 的密钥空间是 2 的 256 次方即便是 7 字节有效位的旧版密钥也有 2 的 56 次方种可能靠普通电脑暴力枚举在不掌握任何前缀信息的前提下算到宇宙毁灭也跑不完。正确思路永远是从设备上拿到 IMEI/Android ID 和 UIN自己算密钥而不是硬碰硬。3. 恢复前的准备工作工具、文件与关键参数3.1 需要准备哪些工具解密 EnMicroMsg.db 不需要特别冷门的工具但需要把链条上的每一环都备齐。列一个我实测过的工具清单AdbAndroid Debug Bridge用于从手机里导出数据库文件。Windows、macOS、Linux 都有对应版本建议直接装官方 platform-tools。SQLCipher 命令行工具官方提供的sqlcipher二进制支持 Windows 和 LinuxmacOS 可以用 Homebrew 安装。这是解密的核心工具。DB Browser for SQLiteSQLCipher 版图形化工具SQLCipher 官方有定制版支持直接输入密钥打开加密数据库适合不习惯命令行的用户。Python 3 hashlib 模块用于计算 MD5 密钥不需要额外安装第三方库。手机文件管理器用于确认数据库文件路径和拷贝辅助文件。如果手机没有 root需要先用系统的备份机制导出数据。关于 root 的问题多说一句。传统方案里获取 EnMicroMsg.db 需要 root 权限因为数据库在/data/data/com.tencent.mm/目录下普通应用无法直接访问。但如果你的手机支持 Android 的adb backup备份功能可以在不 root 的情况下把应用数据备份出来再从中解包提取数据库文件。新款手机很多阉割了adb backup那就要靠自己手机品牌官方的整机备份方案把备份文件恢复到电脑上再提取或者通过应用内自带的聊天记录迁移功能中转。3.2 从设备导出 EnMicroMsg.db 的正确姿势导出数据库文件看起来简单但这里有一个非常关键的操作细节不能用文件管理器直接去拷贝正在被微信占用的数据库。SQLite 在写入时是页级别的如果你在微信运行状态下强行拷贝拿到的文件可能是损坏的中间状态解密时会遇到页校验失败甚至打开后部分消息缺失。我自己的操作流程是这样的先打开微信进入我 设置 聊天 聊天记录备份与迁移如果数据量不大可以直接用迁移功能把数据备份到另一台设备再从另一台设备提取如果只是做数据库文件层面的导出进入下一步。在系统设置里强行停止微信应用。这一步会中断微信的后台写入保证数据库文件处于静态一致状态。确认手机已开启 USB 调试用数据线连接电脑执行adb shell进入手机环境。有 root 的设备直接执行adb pull /data/data/com.tencent.mm/MicroMsg/文件夹/EnMicroMsg.db D:/backup/没有 root 的设备建议先用厂家备份方案导出整个应用数据包再用工具解包。同时把同目录下的system_config_prefs.xml也导出来这个文件里存有 UIN 信息是计算密钥的关键输入。这里还要强调一个容易忽略的点UIN 不是你微信里的微信号也不是手机号而是微信服务器为每个用户分配的一个内部数字 ID。旧版本里它直接写在system_config_prefs.xml的int nameuin value123456789 /标签中新版本可能需要从auth_info_key_prefs.xml或ConfigIni其他文件里找。找到 UIN 之后别忘了它前面可能带一个负号比如-123456789算密钥时负号也要算进拼接字符串里少一个符号密钥就完全不对。3.3 提取 IMEI 和 UIN 的注意事项IMEI 是设备唯一标识获取方式分两种情况。老设备可以在拨号盘输入*#06#直接查看或者在系统设置里找关于手机 状态信息 IMEI。新设备特别是 Android 10 以上的设备系统设置里可能不再显示完整 IMEI这时候可以用adb shell配合getprop ro.ril.oem.imei等属性获取或者查看手机的包装盒、保修卡。UIN 的获取稍微绕一些。最常用的方式是从微信的数据目录里翻配置文件。在已 root 的设备上用文件管理器进入/data/data/com.tencent.mm/shared_prefs/打开system_config_prefs.xml里面大概率有一个int nameuin value.../字段。在未 root 的设备上可以通过之前导出的备份包解析出来。如果文件的 UIN 值是 0那说明这个账号可能用的是新的登录机制需要到auth_info_key_prefs.xml里查找。有个容易被忽视的细节部分微信版本里 UIN 字段的 value 前会有一个-号比如-1023456789。计算密钥时切记把负号一并拼接进字符串。我第一次实操时就是漏掉了负号导致 MD5 结果不对多花了差不多一小时排查。后来养成了拿到 UIN 先检查符号的习惯再没出过问题。4. 从零复现EnMicroMsg.db 的完整解密实操4.1 用 Python 计算数据库密钥拿到 IMEI 和 UIN 之后第一步是计算 32 字节的 MD5 值。这里我用 Python 脚本执行代码非常短但每一步都值得细看。import hashlib # 替换为你自己的 IMEI 和 UIN imei 860000000000000 uin -1023456789 # 微信旧版密钥计算MD5(IMEI UIN) raw imei uin md5_result hashlib.md5(raw.encode(utf-8)).hexdigest() print(MD5 result:, md5_result) # 旧版微信的SQLCipher默认只取前7个字节即前14个十六进制字符 legacy_key md5_result[:14] print(Legacy key:, legacy_key)执行后你会得到一个 32 位十六进制字符串例如3f2c3a1b9d8e7f6a...。如果你处理的是 2018 年之前安装的旧版微信数据库直接把legacy_key作为密钥去解。如果是新版微信先尝试完整 32 位字符串如果完整字符串打不开再尝试旧版截断逻辑因为新版微信对密钥的截断策略在不同版本里不完全一致。需要提醒的是这个 Python 脚本要确保字符串拼接时没有多余的空格和换行。从 XML 文件里复制 UIN 时编辑器可能带上隐藏的空白字符最好的办法是在脚本里把imei和uin都打印出来肉眼确认一下拼接结果是不是你期望的样子。4.2 使用 SQLCipher 命令行解密数据库拿到密钥之后解密才是重头戏。SQLCipher 命令行工具的行为是先以加密方式打开数据库文件然后执行导出指令生成一个新的明文 SQLite 数据库。我用的是官方编译的sqlcipher操作命令如下。# 打开加密数据库并指定密钥 sqlcipher EnMicroMsg.db进入 sqlcipher 交互界面后依次执行下面的命令-- 设置密钥旧版微信用截断后的14位hex字符串 PRAGMA key 3f2c3a1b9d8e7f6a; -- 如果上面的key无效尝试新版完整32位密钥 -- PRAGMA key 3f2c3a1b9d8e7f6a...完整32位...; -- 先测试是否能正常读取 SELECT count(*) FROM sqlite_master; -- 如果上述查询正常返回说明密钥正确开始导出明文数据库 ATTACH DATABASE plaintext.db AS plaintext KEY ; SELECT sqlcipher_export(plaintext); DETACH DATABASE plaintext;sqlcipher_export是 SQLCipher 提供的专用函数用来把当前加密数据库完整导出到另一个数据库。ATTACH DATABASE plaintext.db AS plaintext KEY 这行的意思是创建一个新的、没有加密的 SQLite 数据库文件作为挂载点。执行完导出函数后plaintext.db就是一个完全不加密的普通 SQLite 文件。这里有一个细节值得多说ATTACH DATABASE里的KEY 不是可选项。如果你不指定空密钥导出的新库默认会继承当前会话的加密参数导出来的还是加密状态那就白做了。很多人卡在这一步就是因为漏了KEY 。4.3 验证解密结果并处理常见报错导出完成后用普通的 SQLite 工具打开plaintext.db。我习惯先用命令行验证一下sqlite3 plaintext.db .tables如果能看到一堆表名比如message、rcontact、chatting说明解密成功。如果提示file is not a database那基本可以确定是密钥的问题需要回头检查 MD5 计算过程中 IMEI 和 UIN 是否正确。如果密钥正确但某些表打开时报database disk image is malformed这种情况通常是源数据库文件本身有页损坏可能是导出时微信还在写数据或者存储介质有坏块。解决办法是回到第一步重新在微信完全退出的状态下导出一次文件然后重跑解密流程。解密之后数据库文件的大小通常会比加密时大一些这是因为加密数据库每一页都带有 HMAC 校验值去掉这些校验后净数据量会略增这属于正常现象不用紧张。4.4 图形化方案DB Browser for SQLite 的一键打开如果你不想敲命令行SQLCipher 官方提供了 DB Browser for SQLiteSQLCipher 版这个工具可以直接打开加密数据库。打开方式是启动软件后选择打开数据库选中 EnMicroMsg.db然后在弹出的密码输入框里填入密钥再选择加密类型为SQLCipher。需要特别留心的是图形界面会要求你选择 SQLCipher 的加密版本比如SQLCipher 3、SQLCipher 4或者自定义参数。老版本微信数据库对应的是 SQLCipher 3 的legacy模式新版本对应 SQLCipher 4。如果选错版本即使密码正确打开也会失败或乱码。这块没有一个万能选项我的经验是优先尝试SQLCipher 3的默认配置不行再换SQLCipher 4再不行就回到命令行手动指定参数。命令行在这个问题上更灵活因为你可以精确控制 KDF 迭代次数、HMAC 算法、页大小等参数。5. 解密之后怎么恢复出可读的聊天记录5.1 把 message 表变成人话核心 SQL 查询解密成功后一大堆表摆在面前很多人反而不知道下一步怎么办。其实恢复聊天记录的核心就是message表我用一个查询把关键字段取出来基本能覆盖绝大部分需求。SELECT m.createTime / 1000 AS timestamp, CASE m.isSend WHEN 1 THEN 我 ELSE r.nickname END AS sender, m.type AS msg_type, m.content AS content FROM message m LEFT JOIN rcontact r ON m.talker r.username WHERE m.talker wxid_xxxx ORDER BY m.createTime ASC;解释一下关键字段createTime消息创建时间单位是毫秒除以 1000 就是标准 Unix 时间戳后续可以用datetime(timestamp, unixepoch, localtime)转成本地时间。isSend标识消息方向1 表示自己发送0 表示对方发送。talker会话对象的用户名相当于聊天对象的 ID对应rcontact表的username字段。type消息类型1 是文本3 是图片34 是语音49 是文件或链接不同的类型对应content字段里不同的 XML 结构。5.2 图片、语音、视频的关联恢复文本消息恢复很简单真正麻烦的是图片和语音。微信存储媒体文件的命名规则是乱序的哈希文件名数据库里只存路径和摘要信息。图片消息的content字段里通常是一个 XML里面包含cdnthumburl、md5等属性实际文件散落在MicroMsg/attachment或MicroMsg/image2目录下。要恢复某条图片消息一个可行的路径是先解析 XML 拿到md5值然后到image2目录里按哈希路径查找。微信的图片存储路径本身也是按 MD5 做的二级目录比如image2/xx/yy/md5.dat这种结构匹配到文件名之后再把.dat后缀改为.jpg或.png就能查看了。不过新版微信对图片文件也做了加密处理文件头不是标准的 JPEG 魔数需要先做一个简单的异或解密算法是文件每个字节和0xFF异或。这一步如果不熟悉可以先用小文件做测试确认输出是FF D8 FF开头再批量处理。语音文件相对简单voice2目录下的.amr或.silk文件通常没有二次加密直接改后缀名或者用支持 SILK 解码的工具就能播放。视频文件在video目录下很多时候是明文 MP4直接拷贝出来就能看。5.3 导出成 HTML 或 CSV 的批量脚本思路如果聊天记录量很大手动一条条翻message表不现实。一个实用的思路是写一个 Python 脚本连接解密后的plaintext.db把每个会话的文本消息导出为 CSV再把图片和语音按时间线关联起来最终生成一个简单的 HTML 时间线页面。核心代码如下import sqlite3 import csv conn sqlite3.connect(plaintext.db) cursor conn.cursor() cursor.execute( SELECT m.createTime, m.isSend, r.nickname, m.content FROM message m LEFT JOIN rcontact r ON m.talker r.username WHERE m.type 1 ORDER BY m.createTime ASC ) with open(chat_export.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([时间, 发送人, 内容]) for row in cursor.fetchall(): ts row[0] / 1000 sender 我 if row[1] 1 else row[2] writer.writerow([ts, sender, row[3]]) conn.close()导出的 CSV 用 Excel 或 WPS 打开时编码要用utf-8-sig不然中文会乱码。这个细节我踩过坑第一次导出后用 Excel 直接打开看到满屏乱码还以为数据解错了后来才发现是编码问题。6. 十次实操里最容易翻车的几个坑6.1 密钥计算出来是错的但你不知道密钥错误是出现频率最高的问题而且它有个迷惑性你算出的 MD5 结果看起来完全正常32 位十六进制毫无异常但 SQLCipher 就是打不开数据库。这个时候不要反复重算同一个式子而是去检查三个变量源。第一IMEI 是否真的对应这台设备有些手机是双卡双待有两个 IMEI微信保存的可能是主卡那个如果你用的是副卡的 IMEI自然算不对。第二UIN 是否带了负号负号有没有被拼接进去。第三微信版本是否高于 7.0如果是密钥规则可能已经不是简单的 MD5(IMEIUIN)而是换成了 Android ID 或其他标识这时候需要通过解密system_config_prefs.xml里的密钥存储字段来获取真实口令。6.2 数据库文件本身是损坏的怎么解都是白搭有些情况下数据库文件尺寸正常密钥也算对了但解密时 SQLCipher 报HMAC verification failed这通常意味着数据库文件在导出时就损坏了。最常见的触发场景是微信还在运行你就用 root 文件管理器直接拷贝了 EnMicroMsg.db。微信会在后台持续写入 WAL 日志和数据库页你拷贝到的可能是某一瞬间的不一致快照。解决方法是先强制停止微信再导出文件。如果已经导出了损坏文件也不要彻底放弃可以试试 SQLCipher 的PRAGMA cipher_migrate;命令这条命令能修复一部分页校验问题但成功率不是百分之百。6.3 SQLCipher 版本参数不匹配SQLCipher 本身经过多次迭代不同版本的 KDF 迭代次数、HMAC 算法都不同。旧的 SQLCipher 3 默认迭代 4000 次新的 SQLCipher 4 默认迭代 256000 次。如果你拿着 SQLCipher 4 的工具去打开一个 SQLCipher 3 加密的数据库即使密钥完全正确也会因为参数不匹配而失败。命令行下可以手动指定兼容参数比如PRAGMA kdf_iter 4000; PRAGMA cipher_hmac_algorithm HMAC_SHA1; PRAGMA cipher_kdf_algorithm PBKDF2_HMAC_SHA1;不过对大多数用户来说更省心的办法是优先用 DB Browser for SQLite 的图形化版本选择或者直接下载对应版本的 SQLCipher 工具而不是手动去调这些底层参数。6.4 手机未 root 时怎么拿到数据库未 root 的设备导数据库确实麻烦但也不是没有路。我实测可行的一条路线是使用手机厂商自带的整机备份功能把应用数据备份到电脑再用Android Backup Extractor一类工具解包备份文件。不同厂商的备份格式差异很大有的厂商备份出来直接就是.ab格式用abe工具解包即可有的厂商是私有格式需要借助第三方工具或者先恢复到另一台手机再提取。这条路线比 root 麻烦很多但正规、稳定、不需要破坏设备保修。如果只是恢复聊天记录更推荐直接用微信自带的聊天记录迁移功能在同网络环境下迁移到另一台手机或电脑无损且不需要处理加密问题。6.5 解密后的数据库里时间和内容对不上部分微信版本的createTime字段单位不是毫秒而是秒或者在某些特殊会话里存的是本地时间而非服务器时间。如果导出的消息时间整体偏移了 8 小时那基本是时区问题需要在 SQL 里加datetime(createTime/1000, unixepoch, localtime)处理。如果时间完全乱序检查一下是否混入了群聊和公众号的会话因为这些会话的talker不是普通微信号排序时会被ORDER BY createTime正常处理但展示时容易让人误以为数据错乱。7. 合规使用与后续扩展建议7.1 数据合规的边界要主动划清最后聊几句重要的。微信本地数据解密这件事技术上做得到但合规边界必须讲清楚。你可以解密自己手机里、自己账号名下的 EnMicroMsg.db可以拿它做个人数据备份、做取证分析、做安全研究但绝对不能拿它去读取别人的手机数据不能把它用于任何形式的隐私窃取或商业牟利。几乎所有涉及他人数据的场景在未经授权的情况下都是违法的哪怕对方是你的家人或朋友也需要获得明确的同意。在公开发布相关内容时我也建议只讨论技术原理和正向应用不要详细教别人如何绕过系统限制去提取他人数据更不要提供所谓微信聊天记录恢复服务的商业模式。这类灰色地带一旦踩进去轻则封号重则有法律风险。7.2 解密后的数据还能做什么扩展解密之后的宝藏远不止聊天记录导出。你可以把数据库里的message表和rcontact表关联起来做个人年度聊天报告统计你和每个联系人一年的互动频次、深夜聊天最活跃的时段、表情包使用量排名。也可以把图片和语音按时间线归档生成一个本地化的聊天备份站点不依赖微信服务器永久保留在自己手里。我自己的一个延伸项目是把解密后的数据库接入 Elasticsearch用 Kibana 做可视化分析能非常直观地看到自己和某个人的聊天热度随时间的变化曲线。这个玩法对个人数据的价值挖掘很有帮助但注意不要涉及敏感信息的公开所有统计结果只留在本地。微信的本地数据解密看似是一个偏门的逆向工程话题但它背后涉及的 AES 加密、SQLCipher 机制、数据恢复方法论都是通用性很强的技术能力。学会这一套流程你再去接触其他 App 的本地加密数据库思路基本是相通的。就我个人经验来说花一个下午把整个流程完整走一遍比看十篇原理文章都管用。
