昨晚一个朋友问我如何将微信群消息导出。

我们知道,微信的服务器是不长期保存微信消息的。但是转移数据的时候可以将消息备份到微信的服务器,但是只保存七天而已。

因此,思考了一下,大概有以下几种方案:

  1. 备份到微信服务器,写脚本下载到本地(感觉难度很大,因为不了解微信的消息备份协议,而且估计备份的也是数据库?)
  2. 利用安卓手机的api,写类似于“抢红包插件”这样的程序,导出微信群中加载好的消息记录(难度很大,需要了解安卓程序的开发)
  3. 直接解析微信消息的数据库(可行,并且网上教程很多)

原理

将安卓手机root,导出微信数据库文件,解析数据库,并将所需的消息导出

root手机

root手机的教程在网上可谓茫茫多,思路大概如下:bootloader解锁(取决于是否有锁,因手机而异),刷recovery,最后通过recovery对手机root

这里就不赘述了,可以自己下载工具root,也可以直接用网上的小白工具root

导出数据库

这一步的教程网上也很多啊,重点在于微信的数据库位置位于/data/data/com.tencent.mm/MicroMsg/*/EnMicroMsg.db

***是一大串数字,每个账户都有一个这样的文件夹,而data文件夹需要root权限,这也就是为什么要root的原因

而将文件导出也有几种方法:

  1. 在手机上安装文件管理器(如RE管理器),将数据库文件复制到sd卡,再通过数据线传输到电脑上
  2. 手机连接数据线,用adb命令将数据库复制到sd卡或者直接pull到电脑上

这里也很简单,网上也有很多教程

解析数据库

这一步是该教程的重点,在网上查阅了一些资料,发现MaskRay的教程很不错,因此参考了他的教程

微信的数据库是使用sqlcipher加密的,所以我们要做几件事:

  1. 安装sqlcipher
  2. 获得密钥
  3. 解密数据库
  4. 写脚本,将数据库导出成我们想要的文件

安装sqlcipher

sqlcipher是开源的,因此我们可以自行编译,github上也有编译教程

1
2
3
4
git clone https://github.com/sqlcipher/sqlcipher.git
cd sqlcipher
./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="-lcrypto"
make

编译完成之后就会在源文件目录下生成sqlcipher可执行文件
注意:在编译之前可能需要安装一些必须的程序,可先执行以下命令

1
2
3
sudo apt-get install build-essential
sudo apt-get install openssl
sudo apt-get install libssl-dev

获取密钥

密钥是由手机的imei以及微信的uin拼接起来,并计算md5的值,最后截取前7位

imei:在手机拨号界面输入*#06#可以得到imei

uin:登陆web微信,在控制台中查看cookie,其中wxuin值即为uin

在bash中输入

echo -n "imei和uin的拼接值" | md5sum | cut -c -7

所得到的7位数字即为密钥,下面用abcdefg代替

解密数据库

执行了./sqlcipher EnMicroMsg.db之后,输入

1
2
3
4
5
6
PRAGMA key='abcdefg';
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;

执行完上述命令时候会在当前目录生成decrypted_database.db文件,可以直接用sqlite3命令查看

编写脚本,导出数据

经过查看,微信的消息记录保存在message表中,联系人信息保存在rcontact表中

下面为用python写的一个脚本,能够将微信群的消息输出到屏幕上

./contact.py 微信群名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/python
#-*- coding:utf-8 -*-

import sqlite3
import sys
reload(sys)
sys.setdefaultencoding('utf8')

#从rcontact表中获取联系人的nickname(对方自定义的昵称),conRemark(我方备注的昵称),username(微信标识用户的字符串)
#并且保存在字典中,键为username,值为昵称(conRemark优先)
def getContact(contact):
cursor = conn.execute("select username,conRemark,nickname from rcontact")
for row in cursor:
name=''
if row[1]:
name=row[1]
elif row[2]:
name=row[2]
contact[row[0]]=name

#从rcontact表中根据微信群名获取微信群的username
def getChatroom():
chatroom=sys.argv[1]#命令行得到的参数
cursor = conn.execute("select nickname,username from rcontact")
for row in cursor:
if row[0] == chatroom:
return row[1]

#从message表中获取属于特定微信群的消息,并且将username替换成之前获得的昵称
#并且输出到屏幕上
def getMessage():
cursor = conn.execute("select talker,content from message")
for row in cursor:
if chatroom == row[0]:
username = (row[1].split(":"))[0]
if contact.get(username):
username=contact.get(username)
message = (row[1].split(":"))[1]
print username,message,'\n'


conn = sqlite3.connect('decrypted_database.db')#打开数据库

contact = {}
getContact(contact)
chatroom = getChatroom()
getMessage()

conn.close()#关闭数据库

运行./contact.py 微信群名 > backup.text即可将微信群消息保存到文件中