解密聊天记录数据库
2017年2月12日更新:微信6.5.*可能已经更改读取方式,具体还没了解。
微信6.2.5使用sqlcipher进行AES加密,因此我们要得到密钥,根据编译的信息,可以得知微信使用 key=md5(IMEI+uin) | cut -c -7 , 即取md5的前7位做为密钥。解密微信聊天数据库就是简单的一行代码,(注意sqlcipher新版本(3.x)默认不向下兼容,需要使用,cipher_use_hmac 是兼容1.1.x,kdf_iter 是兼容2.1.x的)。
1 2 3 4 5 | sqlcipher EnMicroMsg.db 'PRAGMA key = "key"; 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;' 或者 sqlcipher EnMicroMsg.db 'PRAGMA key = "key"; PRAGMA cipher_migrate; ATTACH DATABASE "decrypted_database.db" AS decrypted_database KEY "";SELECT sqlcipher_export("decrypted_database");DETACH DATABASE decrypted_database;' |
IMEI很容易获取,uin在shared_prefs/多个文件中存在,如com.tencent.mm_preferences.xml,auth_info_key_prefs.xml, system_config_prefs.xml。理论上是在system_config_prefs.xml文件中的default_uin,注意有可能是负的,之前我没有意识到这个问题,导致一直解码不成功,直到看了这个博客。ps. 负数是因为溢出 int32(2639833126) = -1655134170 。
解密曾经登录过的帐号(多个用户的微信)
网上的解密聊天记录都是以登录帐号为基础的,直到我阴差阳错发现这个牛逼的微信聊天记录导出应用。重点不是在他能导出,而是他能导出之前登录过的帐号的聊天记录。仔细的思考一下,一旦有过登录,微信就会生成一个32位长的用户文件目录如 da60995c77c8cd8b47f69cc38e7a52cc ,一看就知道是个md5的hash。根据测试,在不同的机子上这个文件夹名是不变的,也就是说只跟微信ID(wx_user_name, uin…)有关,所以是跟微信哪个id是一一映射的? 感觉还是跟uin有关。
分析那个应用的包网络通信,发现他跟服务器通信只用了文件目录名如 da60995c77c8cd8b47f69cc38e7a52cc ,所以可以肯定能够通过目录名逆推uin。我尝试了不同的组合 wx_uin,wechat_uin... ,都不对。看来只能反编译。
反编译
直觉上来说,反编译微信的难度太大。还是反编译那个聊天记录导出应用好了。写应用的那哥们还是比较专业的,都做了加密和混淆,而且貌似是手动的,导致里面的字符串都难以识别。经过努力,还是破解了那哥们的加密方式,看得懂应用源码中的字符串就事半功倍,不到1小时就发现原来
1 | da60995c77c8cd8b47f69cc38e7a52cc = md5(mm + uin) = md5(mm-1655134170) |
TM就是前面加了”mm”。注意 uin=-1655134170 是负的。。至此,就能够逆推uin,也就是说你手机丢了,别人还是能够破解你的微信聊天记录,因为uin是int啊,找md5不要太快!所以多用户的微信当某一用户退出后能通过这种方法破解得到uin,然后破解聊天记录文件。爽歪歪。。
聊天记录整理
这方面已经很人做了,比如github上的wechat-dump,效果还是可以的,稍微有点问题,日后再改。
日后改了一些东西,最重要的是微信的头像文件不再单一保存,而是用 avatar.index
来索引,保存在一个大文件中avatar.block.0000x
。经测试,可以得知用户头像以avatar.index
中的数值为起始位置,找到avatar.block.0000x
相应连续的96×96×3×4个连续字节就算用户头像的bitmap(png.bm)。具体见代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def read_bm_block(self, pos): hex_pos = hex(pos) fname = os.path.join(self.avt_dir, 'avatar.block.0000' + hex_pos[2]) f = open(fname, 'rb') start_pos = pos - 2 ** 34 f.seek(start_pos+30) while f.read(1) != b"\x00": continue size = (96, 96, 3) img = np.zeros(size, dtype='uint8') for i in range(96): for j in range(96): r, g, b, a = map(ord, f.read(4)) img[i,j] = (r, g, b) return img |
国庆期间,别人在玩,我在写代码。这波不亏
请问一下,微信数据库应该也包含被撤销的信息吧,那么可以通过查看数据库来找到被撤回的聊天记录了?
这个不行,撤回的聊天记录不会保存到数据库里去。
请问一下楼主 EnMicroMsg.db 是要怎么拿出来呢?
是因为安卓吗? ios是不是没戏了~~
ios应该有戏,但要获得root权限。对应越狱?我没有用过ios,不是很清楚。但原理是一样的。
iOS用iTunes backup就可以了
iTunes可以拿到EnMicroMsg.db ?这有点bug啊!
以删除聊天对话的形式,删除的信息,数据库里面会保留吗?
不行啊,那已经消失了。
好的,谢谢
最新微信版本6.5.4使用android-database-sqlcipher(链接:https://github.com/sqlcipher/android-database-sqlcipher。gradle:compile ‘net.zetetic:android-database-sqlcipher:3.5.5@aar’)解密会报这个错:attempt to write a readonly database: , while compiling: select count(*) from sqlite_master;
而微信6.3.x可以正常读取数据。我是按照这个博客的代码进行读取的:http://blog.csdn.net/yuanbohx/article/details/41674949。
现在我完全没有头绪了,楼主能帮我看看是怎么回事吗
我建议先把 微信 那个EnMicroMsg.db复制到外面(可写文件目录,如sdcard),然后使用sqlcipher读取试试。不行的话再复制到电脑上试试。我觉得有可能加密方式变了。
但是有个问题是我需要每隔10秒读一次,所以拷出来不是很可行。
您觉得这个地方是不是有可以改进的地方:
mHook = new SQLiteDatabaseHook() {
public void preKey(SQLiteDatabase database) {
}
public void postKey(SQLiteDatabase database) {
database.rawExecSQL(“PRAGMA cipher_migrate;”); //最关键的一句!!!
}
};
在外面能解密吗,可能是加密方式变了。
外面能用这个脚本解密:
# 解密数据库
def decodeDb():
print(“– decodeDb”)
conn = sqlite.connect(“tmp” + “/EnMicroMsg.db”)
c = conn.cursor()
c.execute(“PRAGMA key = ‘” + password + “‘;”)
c.execute(“PRAGMA cipher_use_hmac = OFF;”)
c.execute(“PRAGMA cipher_page_size = 1024;”)
c.execute(“PRAGMA kdf_iter = 4000;”)
c.execute(“ATTACH DATABASE ‘tmp/decrypted” + “.db’ AS db KEY ”;”)
c.execute(“SELECT sqlcipher_export(‘db’);” )
c.execute(“DETACH DATABASE db;” )
c.close()
用的是Python的from pysqlcipher import dbapi2 as sqlite这个模块。
感觉没问题,https://github.com/sqlcipher/android-database-sqlcipher/issues/161
这里也有讨论,我猜测几个原因:
1. 好像跟设备也有关系。你是小米系列的5.0.x?
2. 有时候这个数据库会变成EnMicroMsg.db2,数据库确实存在吧?路径能看一下吗(/data/data/com.tencent.mm/…)这样子的?
3. 或者微信对数据库加了锁?我也不清楚什么原因
手机不是小米系列,数据库应该是存在的。估计是微信对数据库加了锁。我再研究研究。
有一个比较奇怪的问题是如果我从6.3.30升级到6.5.4则可以使用原来的方式。如果直接安装6.5.4就不能。估计就是微信换了加密方式吧。估计!
估计是微信换了加密方式,之前我看到我那个文件夹中有EnMicroMsg.db2和EnMicroMsg.db这两个文件。EnMicroMsg.db是升级前的,EnMicroMsg.db2是升级之后的。如果你解决了麻烦通知我一下,多谢!
哎,我发现只要把EnMicroMsg.db拷贝到/sdcard/目录就能正常读取了。具体原因不明。。。。暂时的解决方案是定时拷贝吧!
好,如果之后你找到了原因,也跟我说一下
我也遇到不拷贝不行的问题了,问一下有没有解决
我试过了修改数据库和目录的权限为777,java这边还是访问不到
我是把定时拷贝换成了微信收到消息再拷贝解析,这样稍微好点
请问你是怎么做到监听微信接到消息的啊。。
监听通知栏推送
@SwordYork:disqus @disqus_OqswM6AwHD:disqus 好像是存在一个journal文件,是数据备份还是什么的我查到,只要把这个文件改名或者删除就可以直接用java读取数据库了。
那个是事务回滚文件,我这里没有,我已经解决了
创建硬链接到自己的app数据库目录下,改权限606就直接可以读取了
能否告知下微信,有事情需要请教,非常感谢!