This article is based on Android WeChat 8.0.3.
Finding the Database File#
First, find the uin, located in the file /data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml:
The WeChat chat database is named EnMicroMsg.db and is located in a specific folder under data/data/com.tencent.mm/MicroMsg/, with the file name md5_32_low(imel + uin):
The WeChat database password is generated by concatenating the IMEI number and WeChat uin, and encrypting it with md5 to obtain a 32-bit lowercase password. The first 7 characters are used as the password.
Note: In special cases where the password is incorrect and WeChat cannot obtain the IMEI number, a fixed value of 1234567890ABCDEF will be used by default.
Initially, various SQLCipher viewing tools on the Mac platform were unable to open the database. I thought the algorithm had changed, but after analysis, it was found that using SQLCipher.exe on the Windows platform could open it.
Analysis Process#
WeChat uses the wcdb database. By referring to the WCDB documentation for Android integration, you can learn about the method for opening the wcdb database:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(
"path/to/database", // DB path
passphrase.getBytes(), // WCDB password, parameter type is byte[]
cipher, // Encryption description object created above
null, // CursorFactory
null // DatabaseErrorHandler
// SQLiteDatabaseHook parameter is removed, specifying the parameter in cipher achieves the same purpose
);
Through analysis using jadx, there are several overloaded methods for openOrCreateDatabase, and they all internally use the SQLiteDatabase.openDatabase method.
By hooking this function using Frida and tracing the call stack, we can find the password generation rules.
Call Stack#
Tracing the call stack to find the location of password generation.
com.tencent.mm.storagebase.a.b:
this.key = C7959g.getMessageDigest((C8811q.m22244dJ(true) + j).getBytes()).substring(0, 7);
this.kiF = C67989f.m106126E(str, this.key, z);
By hooking the getMessageDigest method, we obtain:
Parameter: 1234567890ABCDEF-156*****65 (1234567890ABCDEF + uin) Here, j represents uin, which is not controversial. Let's continue analyzing C8811q.m22244dJ(true),
which returns 552**********************ac9fbb6.
public static String m22244dJ(boolean z) {
AppMethodBeat.m18334i(155720);
String str = gXe.get();
if (!Util.isNullOrNil(str)) {
AppMethodBeat.m18335o(155720);
return str;
} else if (z) {
AppMethodBeat.m18335o(155720);
return "1234567890ABCDEF";
} else {
AppMethodBeat.m18335o(155720);
return "";
}
}
gXe is a class that retrieves device information, and upon analysis, it seems quite complex. Let's stop here.
Related Files: https://pan.baidu.com/s/1WIZ_wdAFn_9tMZNxzC5i5Q Extraction code: xpnk