2020-02-23 晴 郑州
出场人物
- 沉瓶 – 产品经理
- 饭咸 – 程序员
工作环境
- 硬件:MacBook Pro (Retina, 13-inch, Early 2015)
- 硬件相应系统:macOS Catalina,10.15.3
- 微信版本7.0.4
需求
- 微信好友头像照片墙
故事
沉瓶:在网上看到一些人微信头像做成一张图片,看着不错,既好玩又能吸引用户,这个能不能做。
饭咸:获取微信的信息方法很多,以前网页版微信能用的时候,可以直接网页请求获取,网上很多开源代码。
沉瓶:我看了,很多代码都不更新了,是不是不能用了。
饭咸:是的,微信关闭了服务器,这些请求自然不能做了。不过有些人直接通过对PC版本的微信进行HOOK,实现很多有意义的功能,你可以找找。
沉瓶:找到了一个,不过没有提供可以运行的程序,还有别的方法木有了。
饭咸:微信本身就是手机系统的,对手机进行分析就可以了,而且分析微信的文章也很多,微信程序没有加壳,分析难度也不大,可以试试。
沉瓶:那你试试,我研究下怎么拼接图片去。
饭咸:好的,盘它。
需求分析
-
- 获取微信头像
- 1.1 获得数据库文件路径和密匙
- 1.2 将数据库文件导出到本地
- 1.3 打开加密的数据库文件
-
- 将头像拼接成照片墙
实现步骤
1. 获取微信头像
关于获取微信聊天记录的方案网络上有很多资料,本博文就是根据下面的文章学习而来的:
结合上面两篇博文,我执行了下面的方案。
1.1 获得数据库文件路径和密匙
根据资料,我们找到一份基于Xposed的源码https://github.com/adamyi/AndroidWechatSQLiteDecrypt,该源码可以获得EnMicroMsg.db文件的路径和密码,但是未能正确的获取加密方式,可能是因为代码长时间不更新的原因吧(代码是两年前的)。
源码逻辑不复杂,hook了数据库打开的操作,在这个地方,腾讯执行了数据库的打开操作,该操作将路径、密码、加密方式都作为参数传了进来。具体代码如下所示:
public class XModule implements IXposedHookLoadPackage {
static private String TAG = "wxSqlPwdHook";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (loadPackageParam.packageName.equals("com.tencent.mm")) {
XposedHelpers.findAndHookMethod(
"com.tencent.wcdb.database.SQLiteDatabase", // 被HOOK对象名
loadPackageParam.classLoader, // classLoader,固定的值,不用关心
"openDatabase", // 被HOOK对象的函数名
String.class, // 参数0:数据库全路径
byte[].class, // 参数1:用户名密码(一个加密后的7位值)
loadPackageParam.classLoader.loadClass("com.tencent.wcdb.database.SQLiteCipherSpec"), // 参数2:是一个SQLiteCipherSpec对象,该对象中包含了加密方式
loadPackageParam.classLoader.loadClass("com.tencent.wcdb.database.SQLiteDatabase$CursorFactory"), // 参数3:某工厂对象
int.class, // 参数4:Flags,未知标记
loadPackageParam.classLoader.loadClass("com.tencent.wcdb.DatabaseErrorHandler"), // 参数5:错误处理的句柄
int.class, // 参数6:加密方式的某个参数PoolSize
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// 参数0:数据库全路径
Log.i(TAG, "Path: " + param.args[0]);
// 参数1:用户名密码(一个加密后的7位值)
Log.i(TAG, "Password: " + new String((byte[]) param.args[1], "UTF-8"));
Formatter formatter = new Formatter();
for (byte b : (byte[]) param.args[1]) {
formatter.format("%02x", b);
}
Log.i(TAG, "Password (hex): 0x" + formatter.toString());
// 参数2:是一个SQLiteCipherSpec对象,该对象中包含了加密方式
Log.i(TAG, "CipherSpec - Cipher: " + XposedHelpers.getObjectField(param.args[2], "cipher"));
Log.i(TAG, "CipherSpec - KdfIteration: " + XposedHelpers.getIntField(param.args[2], "kdfIteration"));
Log.i(TAG, "CipherSpec - Hmac Enabled: " + XposedHelpers.getBooleanField(param.args[2], "hmacEnabled"));
Log.i(TAG, "CipherSpec - Page Size: " + XposedHelpers.getIntField(param.args[2], "pageSize"));
// 参数4:Flags,未知标记
Log.i(TAG, "Flags: " + param.args[4]);
// 参数6:加密方式的某个参数PoolSize
Log.i(TAG, "PoolSize: " + param.args[6]);
}
});
}
}
}
代码使用的是XPosed框架,使用XposedHelpers.findAndHookMethod函数做的HOOK操作,HOOK点为com.tencent.wcdb.database.SQLiteDatabase::openDatabase,该函数的参数分别为:
- 参数0:数据库全路径
- 参数1:用户名密码(一个加密后的7位值)
- 参数2:是一个SQLiteCipherSpec对象,该对象中包含了加密方式
- 参数3:某工厂对象
- 参数4:Flags,未知标记
- 参数5:错误处理的句柄
- 参数6:加密方式的某个参数PoolSize
我使用的微信版本为7.0.4,上述代码未能正确的解析SQLiteCipherSpec对象值,为了获得该值,我对微信进行调试,发现SQLiteCipherSpec对象的成员名称变了,如下所示:
p2 = {SQLiteCipherSpec@9102}
hmacAlgorithm = 0
hmacEnabled = false
kdfAlgorithm = 0
kdfIteration = 4000
pageSize = 1024
shadow$_klass_ = {Class@8246} "class com.tencent.wcdb.database.SQLiteCipherSpec"
shadow$_monitor_ = -2105857932
我们将这些值修改即可正常的打印出来,打印调试日志如下所示(我这边使用的是VirtualApp进行试验的):
最终代码已经上传到github仓库,请自取。
1.2 将数据库文件导出到本地
将数据库文件导出到本地,思路也很多,我的方案是,将android手机作为ftp服务器(Servers Ultimate Pro),在本机(PC)使用FileZilla软件连接手机的ftp服务器,直接将文件下载到本地。
ps:
- Servers Ultimate Pro是一款集成了ssh、ftp、http等数十种协议的服务器app,可以轻松的将android手机变为服务器使用,收费软件,价格不美丽。
- 本博文使用的是VirtualApp进行XPosed测试,需要将Servers Ultimate Pro服务器程序也安装在VirtualApp中,这样以来,微信和服务器程序就处于同一用户权限了,所以PC上的FileZilla客户端就可以访问微信的数据文件了。
1.3 打开加密的数据库文件
实用开源项目SQLiteStudio,在github上下载最新的软件即可,该软件跨平台(Mac、Windows已经测试通过)、支持多种加密方式(这里选择SQLCipher选项),使用方法如下图所示:
选择数据库软件的过程经历了很多次尝试,尝试过程请参考另一篇文章:【程序员日记】2020-02-19__踩坑微信加密后的Android数据库,
2. 将头像拼接成照片墙
这里不详细介绍了,参考下面资料即可
- 使用 Python + Pillow 完成图片墙拼图
- 用python的PIL库轻松拼接一百张照片
- 提取微信/QQ聊天记录并生成词云
- https://github.com/yangxuanxc/wechat_friends
声明
本文章仅供用于技术研究用途,请勿利用文章内容操作用于违反法律的事情。
关于作者
欢迎各位关注公众号和QQ群进行技术交流,关注有福利喔。
微信公众号:
qq群:IT技术控/953949723