沉瓶:在网上看到一些人微信头像做成一张图片,看着不错,既好玩又能吸引用户,这个能不能做。
饭咸:获取微信的信息方法很多,以前网页版微信能用的时候,可以直接网页请求获取,网上很多开源代码。
沉瓶:我看了,很多代码都不更新了,是不是不能用了。
饭咸:是的,微信关闭了服务器,这些请求自然不能做了。不过有些人直接通过对PC版本的微信进行HOOK,实现很多有意义的功能,你可以找找。
沉瓶:找到了一个,不过没有提供可以运行的程序,还有别的方法木有了。
饭咸:微信本身就是手机系统的,对手机进行分析就可以了,而且分析微信的文章也很多,微信程序没有加壳,分析难度也不大,可以试试。
沉瓶:那你试试,我研究下怎么拼接图片去。
饭咸:好的,盘它。
关于获取微信聊天记录的方案网络上有很多资料,本博文就是根据下面的文章学习而来的:
结合上面两篇博文,我执行了下面的方案。
根据资料,我们找到一份基于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,该函数的参数分别为:
我使用的微信版本为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仓库,请自取。
将数据库文件导出到本地,思路也很多,我的方案是,将android手机作为ftp服务器(Servers Ultimate Pro),在本机(PC)使用FileZilla软件连接手机的ftp服务器,直接将文件下载到本地。
ps:
实用开源项目SQLiteStudio,在github上下载最新的软件即可,该软件跨平台(Mac、Windows已经测试通过)、支持多种加密方式(这里选择SQLCipher选项),使用方法如下图所示:
选择数据库软件的过程经历了很多次尝试,尝试过程请参考另一篇文章:【程序员日记】2020-02-19__踩坑微信加密后的Android数据库,
这里不详细介绍了,参考下面资料即可
本文章仅供用于技术研究用途,请勿利用文章内容操作用于违反法律的事情。
欢迎各位关注公众号和QQ群进行技术交流,关注有福利喔。
微信公众号:
qq群:IT技术控/953949723