Android微信数据库解密
本篇主要讲下解密EnMicroMsg.db 。
1:数据库密码
微信的数据库密码规则 是 imei +uin ,获取bytes[], 生成md5,截取前 7位。
不过目前imei微信写死的"1234567890ABCDEF";
uin 一般会在微信的 shared_prefs 中的 auth_info_key_prefs.xml 或者
system_config_prefs.xml 。
2:相关代码
以下代码 以微信8.0.31 为例.
首先对应的是 数据库下的openDatabase方法。
public static SQLiteDatabase openDatabase(String str, byte[] bArr, SQLiteCipherSpec sQLiteCipherSpec, CursorFactory cursorFactory, int i14, DatabaseErrorHandler databaseErrorHandler, int i15) {
SQLiteDatabase sQLiteDatabase = new SQLiteDatabase(str, i14, cursorFactory, databaseErrorHandler);
sQLiteDatabase.open(bArr, sQLiteCipherSpec, i15);
return sQLiteDatabase;
}
接着是o83.e类下,可以看到有下面这块代码.
if (str3.endsWith("EnMicroMsg.db")) {
eVar.f216755a = SQLiteDatabase.openDatabase(str3, bytes, sQLiteCipherSpec, null, i15, eVar, 8);
} else {
eVar.f216755a = SQLiteDatabase.openDatabase(str3, bytes, sQLiteCipherSpec, null, i15, eVar);
}
根据方法,找到调用的地方.
linkedHashSet.add("1234567890ABCDEF");
it = linkedHashSet.iterator();
z17 = false;
while (true) {
if (!it.hasNext()) {
break;
}
//此处写死的1234567890ABCDEF.
String str5 = (String) it.next();
//此处就是获取到的数据库密码 ,h.f获取md5值.
String substring = h.f((str5 + j14).getBytes()).substring(0, 7);
this.f216727b = substring;
try {
//传入数据库密码substring
e r14 = e.r(str2, substring, 0, true);
this.f216726a = r14;
a(r14);
if (!t.d(true).equals(str5)) {
Log.i("MicroMsg.DBInit", "IMEI changed detected: " + str5);
n.a().b(258, str5);
tb2.e.INSTANCE.idkeyStat(181L, 5L, 1L, false);
break;
}
break;
} catch (SQLiteException e17) {
if (e17 instanceof SQLiteDatabaseCorruptException) {
z17 = true;
} else {
z17 = false;
break;
}
}
}
h.f()如下:
public static final String f(byte[] bArr) {
char[] cArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(bArr);
byte[] digest = messageDigest.digest();
char[] cArr2 = new char[digest.length * 2];
int i14 = 0;
for (byte b14 : digest) {
int i15 = i14 + 1;
cArr2[i14] = cArr[(b14 >>> 4) & 15];
i14 = i15 + 1;
cArr2[i15] = cArr[b14 & 15];
}
return new String(cArr2);
} catch (Exception unused) {
return null;
}
}
j14 是通过参数传递过来 . o83.f 类的 n()
public boolean n(String str, String str2, String str3, long j14, String str4, HashMap<Integer, b> hashMap, boolean z14) {
int lastIndexOf;
if (str.lastIndexOf("/") != -1) {
this.f216782a += "." + str.substring(lastIndexOf + 1);
}
k(str2);
if (this.f216785d.f(str, str2, str3, j14, hashMap, z14)) {
o83.a aVar = this.f216785d;
if (aVar.f216726a != null) {
aVar.e();
this.f216788g = "";
this.f216783b = this.f216785d.f216726a;
return true;
}
}
this.f216785d.e();
this.f216788g = "";
this.f216783b = null;
this.f216785d = null;
Log.i(this.f216782a, "initDB failed. %s", "");
return false;
}
继续 查找j14的来源 可以找到c10.x.b().g(). 而这个方法返回值就是uin.