近期对拷贝漫画(copymanga)进行数据分析,发现网页端获取漫画章节使用 JavaScript API 异步请求数据,相关请求代码经过混淆、返回数据经过加密。因此进行逆向分析。
示例网址:https://copymanga.site/comic/nizaonanlema
抓包
首先,查看网页源代码发现漫画简介等元数据在 HTML 代码中,而如上图所示的章节列表则没有。抓包分析,发现漫画章节应该是这个 URL 返回的:
https://copymanga.site/comicdetail/nizaonanlema/chapters
直接访问,很明显 results 是数据,经过加密。
抓包发现另一处 js 请求:
https://hi77-overseas.mangafuna.xyz/static/websitefree/js20190704/comic_detail_pass20210918.js
返回的内容是一大堆混淆过的 js 代码:
该代码整体是一个 eval 函数,具备直接可执行性。在浏览器控制台执行效果如下:
执行后,界面出现章节详细列表,可确定这段代码就是需要解密的代码。
反混淆 JS
将代码粘贴入 jsnice 在线工具:http://jsnice.org/
- jsnice 是一个反混淆利器之一,可以将混淆后的代码进行更加有好的展示,从而提升代码的可读性;
- jsnice 在元素关系的建立上大部分来自于 AST 语法树,同时采用了概率图模型进行 推理 和 联想,通过样本学习推测出未混淆 JS 脚本的 概率图;
得到的代码结构如下(关键部分已写注释):
|
|
找到如上函数,传入的参数中包括 iv、mode、padding 等键名,推测是使用了 AES 加密处理数据。
但代码中很多关键词都使用_0x2f1f
函数间接调用表示,这其实是一种针对名称的混淆。我们需要把这个混淆还原。
上面将_0x4a5d
数组进行了二次处理,之后写回原变量。而原变量使用 var 声明,泄露在了全局命名空间里。因此可以直接在浏览器控制台获取到经过二次处理后的_0x4a5d
数组:
|
|
编写 Node.js 代码如下:
|
|
得到关键词反混淆后的代码,这样就可以分析 AES 加密的逻辑了。
AES 加密分析
将关键代码分析如下:
|
|
dio 这个变量在 js 文件中搜索不到,推测可能是全局命名空间的变量,在浏览器控制台输入,果不其然,是一个固定 key:
使用加解密测试工具CyberChef
,验证猜想是否正确:
可以成功解密。
代码实现
下面是 Go 语言的实现:
|
|
其中类型定义如下:
|
|
Go 的 AES 加密实现比较偏向底层,不像 js 那样传几个参数进去就完了。注意 AES 加密是先做 Padding 再加密,AES 解密是先解密完再 Unpadding。在配置好 padding 的前提下,解密结果的长度和加密内容的长度是相同的。