微信读书本地文件加密分析
前言
仅供交流学习
加密分析
拿一台已经root了的机子找到/data/user/0/com.tencent.weread/databases/<用户ID>/books/下,这里存在已经下载到本地的书籍
下面存在几个目录,目录的名字一般都是数字,目录下有许多文件后缀为.res或.st或.ts.a的文件
.res后缀的文件以压缩文件打开提示需要密码
jadx中查找这个后缀名,可以找到getDownloadPath方法, 寻找引用观察到一个getCanonicalPath方法,继续查找引用可以发现一个来自readDataFormDisk的调用
该方法中校验了文件的魔数,这个就是读取文件的方法
继续寻找引用,发现covertChapterToHtml方法,
看到下面的unzip方法,可知这里是解压缩的地方
定位到该方法的unzipResponse调用中
看到解压密码是传入的第二个参数,也就是dataFormDisk中

byteArray从文件中读取,又进行了EncryptUtils中的处理
EncryptUtils中的方法如下:
这里提供了两个参数,用户ID和加密后的内容,而后调用了nativeDecryptHeaderKey,是native方法,到IDA中查看对应的so文件
关键逻辑如下:
以上是将vid补全到32位,接下来,根据程序内置的表映射了vid的每一位
这里实际上传入的是byte,识别为指针是ida的识别错误,对应表如下:
下面的解密调用:
注意到这里没有传入IV,观察解密函数
下面调用了openssl的AES解密函数,根据公开的函数定义,倒数第二个参数是iv
这里IDA将key的定义类型识别为了unsigned __int8 *,所以iv被反编译为key+1,实际上指向的是后16字节。而前16字节在AES_set_decrypt_key中被作为key使用
手工解密
回顾readDataFormDisk方法
第一次读取4字节魔数,然后再读取4字节作为循环次数,然后依据循环次数读取多个4字节,在这之后读取了4字节作为readByteArray的参数,这也是加密后的密码。
根据so中的解密逻辑,写出映射脚本:
随后我们输出,便得到了key和iv,前16字节为key,后16字节为iv
CyberChef中AES解密一下即可得到解压密码
(完)











