申请ID:qwert3166
个人邮箱:23227225@qq.com
原创技术文章:
某大厂阅读app内容解密分析
工具准备
1、frida 15.1.4
2、jadx1.3.0
3、idea(编译最终代码)
4、写字板或其他16进制查看工具(由于常用mac,家里的win环境不齐全,随便用个写字板了,哈哈)
5、一台root手机
开始先吐槽以下win11下python安装frida的坑,我本来wsl2上装有frida,奈何wsl2上的adb连不上设备,使用相同版本(win和wsl2都装了版本号完全相同的)也不不行;然后只能在win11的python中安装frida,安装后还是报错,最后查看frida官网的issue里,有个用户说他的3.10python也和我一样的错误,最后只能卸载3.10,装了3.9,环境才总算正常。
下面开始整体。
首先既然是要解密文件,那我先想到的点是文件读取,遂hook在file上
function printTrace(){
var Exception = Java.use("java.lang.Exception");
var ins = Exception.$new("Exception");
var straces = ins.getStackTrace();
if (straces != undefined && straces != null) {
var strace = straces.toString();
var a = strace.replaceAll(",","\r\n");
console.log("========stacktrace start============")
console.log("straces:"+a);
console.log("========stacktrace end============")
}
}
Java.perform(function () {
var file = Java.use("java.io.File")
file.$init.overload("java.io.File","java.lang.String").implementation = function(v1,v2){
if(v1.getAbsolutePath().indexOf("prefix")>0){
console.log("file-init:"+v1.getAbsolutePath() + "/" + v2);
printTrace();
}
return this.$init(v1,v2);
}
});
然后找到了以下调用栈;
1
打开jadx,逆向看了一下对应的类,看了一圈,混淆得太厉害,看不到什么看起来有用的代码;
但是看到了很多输出日志的地方,hook一下日志输入类,先看看在哪下hook点好
日志1
跟进去,调的是info,继续往里
日志2
然后printLog,可以看到,不管info、error、还是debug、最终都是走的printLog,那就hook这个试下
日志3
日志4
代码如下,包名我就隐藏了,以免惹麻烦
var logwrap = Java.use("com.xxx.xxx.base.util.LogWrapper");
logwrap.printLog.implementation = function(v1,v2,v3){
console.log("log:"+ v1 +":"+v2+":"+v3);
return this.printLog(v1,v2,v3);
}
看看有没有什么合适的代码;然后找到了下面的文字
2
顺着 章节已被加密 这段文字 找到了下面代码
3
这块红色区域很可能是写文件的地方,继续往下,发现是把itemContent对象转换成了另一个对应
其中重要的点,itemContent.content赋值给了f55484h,这个f55484h真正的字段名也是content;
另一个是itemContent.keyVersion;content既然是加密的内容,那就看看content在哪些地方读取了,搜了一下发现下面这个点,明显就是解密的地方;
5
进入m44616a看看
6
好家伙,把content先base64解码,前16位作为参数,str2估计是密钥,16位以后则是真正的内容;往下
7
额,原来是aes加密,前16位作为向量,str果然是密钥,这下好办了,下一步看下密钥从哪取的;
8
密钥是由a.m35841c() (进去看了下对应的是user_id)和f55483g(对应章节内容的key_version);继续往下
9
可以看到,获取服务端生成的设备id+用户id+keyversion,从函数中取,如果没有,则从服务器取
10
11
12
13
搞半天,密钥存在mmkv下 prefix_public_crypt_key_kv_userid下了;打开re文件浏览器看看是个什么东西
14
拿来试用一下上面的解密算法,看能不能拿到正常的内容;
我们找来加密内容如下:
15
然后找到对应keyversion对应的密钥6BEE392E0946866E0AE3286053E1F194;得到以下结果
16
果然可以解密,至此就暂时告一段落了,有时间再继续。 |