逆向分析海盗听书
# 一、起因
在 52pojie论坛 看到一篇对「海盗听书」的逆向分析
刚好自己从事前端工作
刚好对逆向有着浓厚的兴趣
(对“破坏”有着一种本能冲动,和解开谜题后的自我成就感)
刚好最近在听一本付费有声小说 《诡秘之主》 (opens new window)
# 二、难点
# 2.1、无尽debugger
最简单的分析当然是从「源代码」以及「请求资源」开始分析。
当打开 Developer Tools时 会进入无尽 debugger 模式
解决方式有两种,一种是跳过所有的 debugger,自己设定的 debugger 也会跳过,效果欠佳
另一种是永久跳过此处,Never pause here 永远不要停在这里
# 2.2、分析接口
打开 Developer Tools 的 Network 页,观察到 Fetch/XHR 类别下请求了两个接口
其中一个接口分析后得出,是音频资源接口,资源路径部分(src)被简单加密了
https://www.tingxiaoshuo.cc/pc/index/getchapterurl/bookId/12502/chapterId/3899427.html
bookId后面拼接的是数据ID
chapterId后面拼接的是章节ID
{
"status": 1,
"message": "成功",
"src": "104*116*116*112*115*58*47*47*97*111*100*46*99*111*115*46*116*120*46*120*109*99*100*110*46*99*111*109*47*115*116*111*114*97*103*101*115*47*97*53*52*55*45*97*117*100*105*111*102*114*101*101*104*105*103*104*113*112*115*47*54*49*47*65*56*47*67*75*119*82*73*82*119*70*81*115*74*114*65*65*117*80*74*65*68*116*119*72*51*45*46*109*52*97",
"jsjm": 1
}
# 2.2、解密 SRC
由于 src 是被加密后的,则需要找寻解密函数
打开上面接口详情的「Initiator」切换页
看到有几个关联函数,进去康康
看到几个熟悉的单词
有audiosrc 猜测是解密后的音频资源地址
data.src 是接口的音频资源参数,jsjm接口返回资源的状态参数
data.src 被传入到 $jc.abc()
函数中,这应该就是解密函数了
在控制台中输入 $jc.abc 得到了该函数代码,点击后可进入对应的 common.js 文件中
把代码序列化以后,提取关键内容 String.fromCharCode (opens new window)
w.abc = function(u) {
// 用*号进行分割Unicode 编码,
var tArr = u.split("*");
, str = '';//将转码后的地址放这里
// for循环 将Unicode 编码转为一个字符
for (var i = 0, n = tArr.length; i < n; i++) {
str += String.fromCharCode(tArr[i]);
}
return str; //返回地址
}
# 2.3、获取该书籍所有章节,并解密所有音频
把代码复制到 Developer Tools 的 Console 窗口,会自动加载完成
点击查看代码
/**
* 获取该书籍的所有的chatperId
* 书籍地址:https://www.tingxiaoshuo.cc/book/12502.html
* 其中 12502 为书本ID
*/
function getAllChatperID() {
let list = [];
let ele = $("#playlist").find('li');
for (let i = 0; i <= ele.length; i++) {
let e = $(ele[i]).find("a");
if (e) {
let name = e.text();
let href = e.attr('href');
if (href) {
let chatper = e.attr('href').substring(12, 19);
list.push({ name, chatper });
}
}
}
return list;
}
/**
* 通过接口查询ID
* @param {*} chapterid
*/
function getId(chapterid) {
return fetch(`https://www.tingxiaoshuo.cc/pc/index/getchapterurl/bookId/12502/chapterId/${chapterid}.html`, {
"headers": {
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-language": "zh-CN,zh;q=0.9",
"sec-ch-ua": "\"Chromium\";v=\"94\", \"Google Chrome\";v=\"94\", \";Not A Brand\";v=\"99\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest"
},
"referrer": "https://www.tingxiaoshuo.cc/play/12502/3899426.html",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
}).then(d => d.json());
}
/**
* 解析出URL
* @param {*} u
* @returns
*/
function decode(u) {
var tArr = u.split("*")
, str = '';
for (var i = 0, n = tArr.length; i < n; i++) {
str += String.fromCharCode(tArr[i]);
}
return str;
}
let source = [];
/**
* 主入口
*/
function main() {
let AllList = getAllChatperID();
loop();
function loop() {
let { name, chatper } = AllList[0];
getId(chatper).then(d => {
let src = decode(d['src']);
source.push({ name, chatper, src });
AllList.shift();
if (AllList.length > 0) loop();
});
}
}
main()
变量 source 会保存该数据的名称,以及音频地址,通过这个地址即可下载
[
{
"name": "多人有声剧《诡秘之主》主题音乐《最好的时代》(官方听友群~961082420)",
"chatper": "3899426",
"src": "https://aod.cos.tx.xmcdn.com/storages/aa22-audiofreehighqps/A4/14/CMCoOSMFQsJeAA1wxgDtwHqC.m4a"
},
{
"name": "多人有声剧《诡秘之主》转运仪式主题音乐——《灰雾之上》",
"chatper": "3899427",
"src": "https://aod.cos.tx.xmcdn.com/storages/a547-audiofreehighqps/61/A8/CKwRIRwFQsJrAAuPJADtwH3-.m4a"
},
{
"name": "多人有声剧《诡秘之主》——克莱恩侄女小剧场",
"chatper": "3899428",
"src": "https://aod.cos.tx.xmcdn.com/storages/5f91-audiofreehighqps/99/48/CMCoOSYFQsJ2ABKkpgDtwIEU.m4a"
},
{
"name": "多人有声剧《诡秘之主》世界观主题音乐——《神战遗迹》",
"chatper": "3899429",
"src": "https://aod.cos.tx.xmcdn.com/storages/a0a7-audiofreehighqps/23/4E/CMCoOR4FQsKDAA21zADtwISp.m4a"
},
{
"name": "多人有声剧《诡秘之主》生活主题音乐——《甜冰茶》",
"chatper": "3899430",
"src": "\u0000"
},
....
]
# 三、APP端接口
APP端的接口抓取
获取数据所有章节
https://app.tingxiaoshuo.cc/listen/api/chapter?bookId=12502&uid=0&sort=asc&size=20
获取章节音频资源接口
https://app.tingxiaoshuo.cc/web/index/getChapterUrl?bookId=12323&chapterId=${chapterid}`
# 四、其他
现在接口有防爬操作,限制五分钟内只能访问N条
被限流了,暂时没有找到更好的解决办法
抓包听中国海盗听书网分析曲折辛酸历程 (opens new window)