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