首先,拿到一款app,二话不说,抓包。
这个就是它的文章详情的包。可以看到部分解码正常,部分乱码。这是它自定义的协议格式。乱码部分为文章内容。
看一下它的响应格式
使用了字节流传输。
接下来使用jadx打开它的app,分析一下。
这里采用逆向分析。
一般根据这些阅读类的app,喜欢在本地写一些缓存文件,用来提升用户体验。我们去文件目录下找找看下有没有这些我们比较敏感的文件。
看我们发现了啥。打开看看
这不就是文章的内容了吗? 说明在这之前,它已经完成了内容的解密。 可以发现这些文件都是以.deb结尾。那我们到jadx里搜一下
只有一处,非常完美。
这里我们使用frida专门hook此方法,打堆栈,查看调用情况。
可以看到它确实调用了该方法,返回了我们期待的文件路径。 根据调用栈,我们看下它的上层函数
其中a2就是我们的文件路径,然后传到了m19274a中,最后又返回了a2。 我们进入到这个函数看它进行了啥操作。
可以基本猜想这里是写入文件的操作。 重点再观察一下EasyEncrypt.mbb37b这个函数。
继续使用frida hook这个函数。
这里因为它的返回值是字节, 没办法直观看到结果。我们这里转一下字符串。方便观察。
可以看到这个函数确实最终转成了字符串。
我输入的字节是不是我们从响应里得到的呢? 这里需要摘取部分片段搜索一下。
从抓包软件中随便复制一行
把16进制转成java字节码
然后去搜索刚才frida hook的参数里,去搜下这传数字。确定下传入参数。
可以发现传入参数确实有这串字节码
但是却转换失败了。 我们看下最后成功的字节码
实际通过m6637b这个函数转换成功的字节码是这一串。 通过观察整个调用情况,发现总共经过了两次m6637b这个函数的转换。 第一次参数是我们请求接口中获取的字节码,第二次才是可以通过此函数转成字符串的字节码。所以现在的问题是,怎么由第一步结果的字节码,转成第二次参数的字节码。
我们看下b的调用栈,看有没有更多信息。
这是m6637b第一次调用的调用栈。进去看一下。
可以看到它这个首先对我们响应的字节流用m6637b这个函数进行了一次处理,之后又用gzip完成了一次解压缩。 那我们把第一次的值进行解压缩,看一下解压缩完毕的值是不是第二次调用m6637b函数的参数 。
转换代码
最后结果
拿到这串结果,去hook到的数据里搜一下。
结果发现刚好是这组字节码转成的字符串。 也就是说只经过了一次m6637b函数处理和gzip解压缩就可以完成解密。那和之前分析的不符。之前分析的明明是调用了两次m6637b函数才完成的解密。后来通过hook EasyEncrypt中的另一个函数才知道原因。
解压缩完毕调用 mbb35a这个函数,之后再调用继续调用mbb37b函数,也能还原数据。 现在解压缩之后就可以的话,那后面两步是可以省略的。