Android微信记录备份方案
在还没有解锁root时, 我偶尔便会闲来无事查查看微信的用户记录导出方案, 一些方案是基于Windows的聊天记录解密, 如: windows取证之导出微信&QQ聊天记录, 还有一些是基于IOS系统的Itunes来做导出. 总的来说都不是很满足需求, 基于Windows的方案一来看评论说只能解密当前的缓存数据, 除非每几天登陆一次电脑微信不然数据就不完整, 另外常用的设备也不会是windows而是安卓, 而Itunes的更不说了, 我也没有一台适合当作中转站的IPhone系列.
最后还是选择从安卓导出加密数据库, 并解密数据库的备份方案, 总体参考:
-
对应的前端工具: greycodee/wechat-backup
微信数据导出
按照教程, 我们希望下表的这些文件, 为了缩短路径长短, 假设当前的工作目录为: /data/data/com.tencent.mm/MicroMsg/[32位字母]
文件内容 | 预期路径 | 是否存在 |
---|---|---|
微信聊天图片 | image2 | 是 |
微信语音 | voice2 | 是 |
微信视频 | video | 是 |
微信头像 | avatar | 是 |
微信DB | EnMicroMsg.db | 是 |
文件索引DB | WxFileIndex.db | 是 |
收发文件 | Download | 否 |
其中, 收发文件据说是位于/sdcard/Android/data/com.tencent.mm/MicroMsg/Download
, 但是在该目录下的文件也并不全, 有关收发文件的位置后续需要再调研一下.
Root设备后, 想要导出这些微信的用户数据就很方便了: 可以走Android Studio的文件管理器直接Save, AS好像就会直接获取到Root权限然后一键取数据, 不过点了Save后会出现一个什么建立索引还是什么类似的操作, 一时半会还不结束, 我以为是AS的问题就直接退出了. 另外我也不希望以后每次导出多个文件都要通过GUI手动操作, 因而本次试验性地导出是直接使用adb操作.
adb如何导出数据呢? adb pull <src> <dst>
可以直接将手机的数据导出到本地, 不过这个指令默认好像没有root权限, 除非把/data
目录chmod -R 777
才能直接拉数据下来. 我由于稍微担心这样子做的风险就没有这样搞, 而是先su
到root用户后将这些文件cp
到/sdcard
/下的共享目录里, 然后再adb pull /sdcard/xxxx <dst>
拉取到本地. 事实上感觉有点蠢, 要占用两份内存空间, 还要花费额外的拷贝时间..
不管怎样, root后导出数据的任务任君八仙过海各显神通吧!
解密数据库
在上面这些用户数据中, 仅有两个数据库文件是加密的, 他们的密钥应该是广为流传的concat(imei, uin).md5().substr(0, 7).tolower()
, 使用该密钥对sqlite3数据库解密即可.
说起来容易做起来问题多多, 这一步我卡了非常的久, 最后差点放弃. 原因在于整个过程出现了多个坑, 连环套在一起让人不知所措, 我最后甚至开始去测试python遍历7位16进制数的时间并上网搜索如何使用命令行判断sqlite解密状态.. =_=
在整个过程中, 我其实一直担心微信的密钥生成算法发生变化, 但是一位老哥的博客给了我稍许信心: 微信数据库最新的解密方式,使用C++代码解密微信加密数据库信息! | 尼古拉斯.赵四
最近有人找我弄微信数据库解密的东西,其实这个现在网上都公开了,我在很早之前就静态分析过微信数据库加密算法,不了解的同学可以查看这里:Android中静态方式破解微信数据库加密密码,所以现在有人找我的话我都会告诉他们这个内容,微信数据库加密的密码很简单就是:MD5(IMEI+UIN).Substring(0, 7).toLower;设备的imei和微信登录账号后的唯一表示uin值拼接然后计算MD5值,取前7位在变成小写字母即可。这个我在那篇文章最后也说到了,这个加密算法不会变化的,因为维系为了兼容以前版本,如果数据库加密算法变动,那么老版本的用户升级到新版本,老版本的数据库解密就会失败,也就是用户看不到以前的消息内容了,这个用户会疯的,所以微信即使知道了这个算法被破解了,他也是没办法升级的,所以现在不会变,以后也不会变的。 很多时候其实行百里者半九十差一口气就能成功, 在反复解密失败的过程中看到了这样一句话还是很振奋人心的, 坚定了我继续在这条路上尝试的决心.. 不过现在回头想想, 微信完全可以根据版本号来决定密钥生成算法, 对于存量数据而言如果在更新版本时一次性迁移不太现实, 也可以考虑增量迁移或者一些其他的办法来处理.. 总之我个人看来如果微信想干这事还是有很多办法的, 并不像老哥说的以后也不会变的, 虽然大概率确实只要不发生什么严重的安全风险微信是不会干这种费力不讨好还有潜在风险的事情的..
下面是解密数据库的具体流程:
-
本机imei的查看方式有两种, 据说在某些场景下这两个值不一样:
-
手机打开电话界面, 拨号
*#06#
, 就会弹出一个界面展示imei号码, 震惊 -
设置中查看本机信息
-
-
[坑1] 应用未必能获取到手机的imei号, 那么上一步获取了真实的imei号也是白搭, 此时微信会使用
1234567890ABCDEF
作为imei进行字符串拼接; 我过于轻信微信了结果他获取不到我的pixel的imei号码.. 以后实际在尝试解密的时候一定要把这三个值都试一试… -
uin号是固定的, 进入adb shell后使用
cat /data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml
, 其中的_auth_uin
便是uin号 -
[坑2] 如何计算md5? 我也没想过这居然坑了我半天, 老的脚本是:
1passwd=$(echo $imei$uin | md5sum | cut -c1-7)
乍一看好像没啥问题, 直到我反复解密失败到受不了了去网上找了个在线的md5计算看看是不是我的md5sum有问题, 才意识到这尼玛echo是默认带空格的, md5计算的结果是不对的! 正确的方式需要给echo添加
-n
参数使其不要输出空格.. -
[坑3] 获取了可能的密码后, 如何解密数据库? 使用开源工具sqlcipher, 原文给的指令不适合复制, 这里又看到一个别处的教程使用了一行指令进行数据库解密, 更加方便调试与测试.
1sqlcipher EnMicroMsg.db 'PRAGMA key = "yourkey"; PRAGMA cipher_use_hmac = off; PRAGMA kdf_iter = 4000; ATTACH DATABASE "decrypted_database.db" AS decrypted_database KEY "";SELECT sqlcipher_export("decrypted_database");DETACH DATABASE decrypted_database;'
输入密码后, 到
attach database
那一步, 就一直报错file is not a database
, 这是怎么会是呢.. 一篇博客说这是因为sqlcipher的版本不匹配导致的, 事实上他说的是正确的. 我查阅了发现有篇官方(maybe?)的讨论也提到了这件事: Upgrading to SQLCipher 4 - SQLCipher / SQLCipher FAQ - Zetetic Community Discussion, 而且其中给出的针对SQLCipher 1的指令正是这些微信导出教程所使用的sqlcipher加解密配置. 太狗屎了这软件也, 好在给出了向后兼容的方案:1PRAGMA key = '<key material>'; 2PRAGMA cipher_migrate;
如果密码正确, 则会返回0表示无错误, 不然则会返回1表示失败. 此时这份数据库文件就已经调教成sqlcipher4的形状了!
-
导出明文数据库. 如果对sqlcipher或sqlite使用熟练则应当有更优雅的导出方案, 可惜我是完完全全的slqite NOOB, 所以我选择用GUI的界面sqlitebrowser, 打开上述迁移完成的数据库, 在GUI界面输出密码, 以sqlcipher4的格式进行解密, 导出!
类似地操作两次, 解密两份微信数据库文件即可.
在反复失败的彻底疯狂后, 我尝试过使用frida做override方案. 最开始完全参照的 解密安卓微信聊天信息存储 | Greycode’s Blog 进行frida操作, 但是成功运行起来后终端观察不到任何的输出, 微信确实能够被frida脚本控制重启, 但是什么输出都看不到. 我注意到这些基于frida的都是使用的微信8.0.3, 而这已经是两年前的版本了, 最新的莫非有什么改动, 就考虑自己去想办法搞懂这些frida的工作原理. 首先参考的是: Android逆向分析实例(三)-解密微信EnMicroMsg.db数据库 - 国名老公阿航 - 博客园; 亦步亦趋地完全遵循他的思路使用jadx解包的当前版本的微信, 进行函数调用链的搜索后发现当前版本的函数好像没有几乎没有发生什么变化, 那么这份python-frida理应work.. 不过没有办法, 我只是初见firda半个小时的新人, 放弃了自己改造的想法. 进一步又看了下反frida的措施以及反制措施.. frida hook不到方法 - 掘金 以及 [原创]使用frida来hook加固的Android应用的java层-Android安全-看雪-安全社区|安全招聘|kanxue.com, 要么看不懂要么照抄过去都不行.. 遂放弃.. 至少对目前的微信8.0.37而言, frida不知为何无法输出, 留待有缘人探索了.
前端展示结果
教程对应的前端工具用起来不是很方便, 貌似是硬编码了一些配置和路径, 解密数据库的过程使用docker来实现, 如果我是自己解密数据库的话需要把名字什么都对应上放到目录下.
太愚蠢了在反复失败后我应该立刻试试这份仓库的docker工具的, 可能就是别人已经实现好了, 一行指令的事情..,
使用工具尝试跑一下, 看起来确实是解密并展示成功了, 聊天记录、图片、头像、昵称什么貌似都有(语音, 视频与文件尚未测试), 不过这个前端实在不符合我的审美(尊重每一个开源的项目, 不乱发表暴论🙏), 所以这里暂时仅做一个简单的测试与展示, 后续应该会自己再捣鼓一份展示方案的.