当我们拿到微信的朋友圈数据库的时候,我们能够直接打开,这个数据库并没有像EnMicroMsg数据库一样采用了加密方式。但是当我们想要获取其内容的时候,发现content和attrBuf加密了,这是个Blob型的字段,虽然我们可以直接用String(contentBlob) 的方式拿到字符串,但是显示的内容夹杂了许多乱码。如下图所示:
发送一个纯文本朋友圈,且内容为:hello
可以看到图上白圈内就是hello的字段,且还有我的微信号
为了找到解密方法,我查了一些资料,这里分享一个很好的文章,然后此文章也是因此而派生出来的~
https://www.jianshu.com/p/0704e0d58531
root手机一部
打开上面的那个链接,翻到最后面,作者有列出两种方式来解析数据,而本文的主题就是使用DexClassLoader来解析数据,所以接下来以此来进行探究吧~
我们先来看看DexClassLoader的构造方法,把需要实例化该类的参数了解一下。
public DexClassLoader(String dexPath, String optioptimizedmizedDirectory, String librarySearchPath, ClassLoader parent)
dexPath: 需要载入的apk文件的位置,在本文中需要指向微信apk的位置。
optioptimizedmizedDirectory: 这个目录是apk的解压路径。
librarySearchPath: 目标类可能使用的c或者c++的库文件的存放路径。
parent: 就是一个ClassLoader对象了。
接下来我们就一步一步操作吧。
val dexClassLoader = DexClassLoader(
wxApkFile.absolutePath,
context.getDir("dex1", 0).absolutePath,
null,
context.classLoader
)
val timeLineObjects = dexClassLoader.loadClass("com.tencent.mm.protocal.protobuf.TimeLineObject")
val parseMeths = timeLineObjects.getMethod("parseFrom", ByteArray::class.java)
//contentBlob是从数据库中直接获取!
val parsedObj = parseMeths.invoke(timeLineObjects.newInstance(), contentBlob)
import com.tencent.mm.bt.a
当我们打开这个类,一下子就恍然大悟了!
该类中包含一个parseFrom(bye[])方法,我推测:所有继承该类的派生类都相当于是一个能够加密的储存数据的bean类
那么我们就直接创建一个递归方法来遍历该类,找到能够展示数据的字段吧
fun findAllDisplayData(obj: Any, map: HashMap<String, String>) {
val fields = obj.javaClass.fields
if (fields.isEmpty()) {
return
}
fields.forEach {
//使用下方Log,可以获取所有字段的类型
//Log.e("===>SnsType", "===>${it.type.name}")
when (it.type.name) {
//获取String类型的字段
"java.lang.String" -> {
val valueObj = it.get(obj)
if (valueObj != null) {
map["${obj.hashCode()}" + it.name] = valueObj as String
}
}
"long",
"float",
"boolean",
"java.lang.Boolean",
"int" -> {
val valueObj = it.get(obj)
if (valueObj != null) {
map["${obj.hashCode()}" + it.name] = valueObj.toString()
}
}
"java.util.LinkedList" -> {
Log.e("===>SnsDeFind", "卧槽!这是个LinkedList")
val valueObj = it.get(obj)
if (valueObj != null) {
val list = valueObj as LinkedList<*>
list.forEach { item ->
findAllStringAndInt(item, map)
}
}
}
else -> {
val valueObj = it.get(obj)
if (valueObj != null) {
findAllStringAndInt(valueObj, map)
}
}
}
}
}
当我们打印map中的数据的时候,还真就获取到了一些有用的数据~
以上就是SnsMicroMsg数据库中SnsInfo表中content字段的解析。
但是当我们想再次以同样的方式解析attrBuf的时候,却出错了。 于是我很快的翻阅微信源码,查找关键字段:attrBuf
如上图红框的内容,看到了很熟悉的方法,但是却是不同的类来调用,根据上面的推测,这个类极有可能是继承自com.tencent.mm.bt.a,所以赶紧找到该类:
果然是继承 com.tencent.mm.bt.a!!,那么要解析attrBuf字段的话,就使用dexClassloader来加载这个cbf的类,使用该类调用parseFrom(byte[])方法就能够拿到attrBuf中的数据了!