ximalaya(三) playUriList值解密--webpack
本文主要介绍解密音频播放url参数。
本文仅代表个人理解,如有其他建议可在评论区沟通。
声明
仅仅记录一下自己的学习方法,不作为其他参考、更不作为商业用途。如有侵犯请联系本人删除
目标地址:aHR0cHM6Ly93d3cueGltYWxheWEuY29tL3NvdW5kLzM3NTA4NDM2OQ==

前面两张分析了xm-sign的生成逻辑,
ximalaya 新xm-sign逆向思路-CSDN博客
ximalaya 新xm-sign逆向思路(二)-CSDN博客
下面主要讲解如何逆向解密url播放地址。
该文章是按照博主从0到1的思路,其中也包含了博主踩过的坑,供各位老板借鉴。
错误示范:
一、播放地址定位。
点击下一个之后,可以看到浏览器发起了如下请求,
其中就有一个媒体请求,打开发现是本章的mp3声音,下面需要分析这个媒体请求。


二、媒体请求分析
请求携带了sign值,大胆猜测这个sign值,是我们需要逆向的,可以赋值url生成request请求去严正下,如果sign的值改变了,请求会返回404报错。只有sign正确时,才会加载mp3声音。

三、sign值是从哪里生成的。
这里我们点开启动器,发现无法跟栈。那需要尝试关键字搜索。

将可疑位置全部打上断点后,切换下一章节,发现并没有断住,思路就此打断,放弃逆向


但是博主不信邪,困难像弹簧,你强它就弱,你若他就强!

正确示范:
一、分析媒体播放地址。
除了媒体请求外,这两个请求是不是有点可疑?其实逆向本身就有一定的偶然性,三分经验七分猜。

1.interval请求
发现没啥用

2.另一个请求
这可不得了,里面这么多信息,部分人可能直接放弃了,但是俗话说得好,你看到的信息越多,你看到的信息就越多!咱们逐级点开分析一下

看看,这是什么?playUrlList! 翻译成中文就是:



翻译成中文就是:播放列表url
至此逆向结束,大功告成!我们查看下playUrlList,答案近在咫尺。


这是什么东西!怎么全是密文

接下来有两个选择:
放弃 继续肝
二、放弃 继续肝
但是到这里已经感觉无从下手了,因为这个请求只有一个逆向值xm-sign,前面已经讲过,在和里面全是固定的,返回的数据中包含了加密的url地址。
https://pinoss.com/pdan123/i/pdan1/2021/10y/16/20211016a18.gif
遇到加密我们需要考虑下,服务器肯定会解密并且返回一个正确的url地址,供浏览器调用从而播放音频。结合前面两张分析xm-sign的步骤,前面最喜欢用的就是异步调用获取返回结果,这里百分之99.9999999也是使用了异步,进行url解密,解密后发起请求获取音频进行播放。
我们只需要先这样,再这样,再那样,然后这样,就解密成功啦!逆向结束。
1.跟栈分析,直接跟最后一个栈
加上断点后点下一首,然而并没有发现什么有用的信息,这时候肯定大多数人就放弃了,博主也放弃了,后来过了2、3天有人联系博主继续讲解,看着他们对知识的渴望,才又重新捡起来分析。


2、继续往下跟栈,发现还是些无用信息
这时候就需要我们反省下,是不是哪个步骤做错了?

重新分析了下,发现这个断点请求的url,并不是我们所需要的
我们需要跟栈的url是https://www.ximalaya.com/mobile-playpage/track/v3/baseInfo开头的,所以之前我们什么有用的信息也获取不到。

3.增加xhr断点,跟栈分析
增加xhr断点后重新请求下一首,断住后查看url,发现这才是我们需要分析的url。
继续往后看堆栈即可,看下哪个环节有体现有用的信息

一直跟到e这个栈,发现代码就比较可疑了,逆向的时候,对于不熟悉的代码要抱着可疑的态度去阅读。下面主要分析e这个堆栈
三、e堆栈分析
可疑处打上断点,重新请求,进行分析B(Qt({....})),控制台输入后发现是异步的,加一个then,再跟个箭头函数,然后放开断点,查看下异步执行结果。

怎么样,牛不牛,牛的给我喊声666,顺便评论收藏+关注支持下老弟。
成功获取到了这个目标的响应值。
接下来分析then之后的函数。
t.trackInfo就是响应结果中的trackInfo

playUrlList

继续往下加断点分析,发现src就是最后服务器解密后的播放地址。复制粘贴验证一下


四、参数解密分析
1.还原解密部分js代码

2.补getPlayUrl
执行后报错,提示 getPlayUrl is not defined,扣JS代码即可。补上getPlayUrl函数,接着执行

3.补decryptFn函数

去掉try catch之后,继续执行强行抛出异常。
4.补getSoundCryptLink
这里需要着重讲一下,博主之前硬扣的getSoundCryptLink 函数,最后补全之后执行发现返回一串乱码。这里感兴趣的同学可以自己尝试扣一下,博主觉得麻烦没再继续往下扣了就。
1.点进去getSoundCryptLink 函数。

将这段包含getSoundCryptLink函数的父级节点一并阅读下,很像webpack结构,是使用【】数组方式调用的。所以博主从webpack入手。在该断函数结尾打上断点,找到加载器。

加上断点后,刷新页面,跟进去r函数,r函数就是加载器
2.定义1个全局变量loader
loader用于接收加载器。
然后将这个页面替换文本,调整其中的代码。CTRL+S保存后重新刷新页面。


3.定位getSoundCryptLink函数所在模块的索引位置。
控制台执行以下代码,f(t.replace是该模块中所包含的内容,需要保证全局唯一,可以使用全局搜索确认下


所以该函数所在的模块索引是206,将加载器代码都复制到本地,并且将数组[]改成{}格式。执行代码查看报错
补window环境后执行。查看报错

执行后提示getSoundCryptLink 找不到。现在我们知道getSoundCryptLink 函数所在模块是索引206的位置。直接将该代码复制下来,补到模块中。
4.补模块206
控制台输入loader.m[206],点击结果定位目标位置后,复制该段代码。然后我们还需要定义一个变量接收206模块中的t.getSoundCryptLink函数

直接用window.getSoundCryptLink接收即可。

执行后报错如下:直接补全,window.getSoundCryptLink,然后再次执行。

发现这次报错还是没变化,还是找不到getSoundCryptLink函数。
原因是因为我们只补了加载器和模块,还没有调用模块,所以拿不到206模块中的getSoundCryptLink函数。只需要在代码中调用206模块即可

5.调用206模块
添加上代码
loader(206),然后执行代码,发现报错变了,提示缺少535模块。
后面的按提示补模块即可,一共有7个模块。
其中补索引5模块的时候会有报错如下:
直接在开发者工具源代码中查看 award_17d4b是啥,然后补到window环境下面就行。

5.补全后执行代码,得到mp3播放地址

总结:
喜马拉雅使用了大量的异步请求,将异步执行的结果用于发起新的请求。
本文主要就是异步调用目标链接,拿到响应值后,对响应值的trackInfo--playUrlList中的数据进行解密,从而得到一个新的播放地址。如果想下载音频文件的话,使用python的request库下载即可。不再做详细描述。
webpack源码不放了,太多了。只放扣的JS函数源码,相信你也可以自己做出来。欢迎评论区讨论补充。
loader(206)//加载器调用206模块
function decryptFn(e) {// try {return (0,window.getSoundCryptLink)({deviceType: "www2",link: e})// } catch (e) {// return console.error(e, "new sound Link occur error"),// ""// }}
function getPlayUrl(t) {var e, r = this, n = 1;return this.mediaType && t.some((function (t) {return t.type.indexOf(r.mediaType) >= 0 && (e = t.url,!0)})),e || (e = t[0].url),t && t.length && (n = t[0].qualityLevel),{qualityLevel: n,encodeText: e}
}
function getsrc(trackInfo) {var n = trackInfo, a = n.playUrlList, s = n.type;var u = getPlayUrl(a), l = u.encodeText, c = u.qualityLevel;// src = decryptFn(l) 需要处理换行符src = decryptFn(l).replace(/\n/g, '');console.log(src)
}
trackInfo ={"trackId": 375093753,"title": "第二十九章 重要的日子","categoryId": 3,"categoryName": "有声书","intro": "","headSkip": 0,"tailSkip": 0,"paidType": 0,"processState": 2,"createdAt": 1610718355000,"coverSmall": "http://imagev2.xmcdn.com/storages/66a0-audiofreehighqps/B2/6B/CMCoOR4D11VfAABKVAB8EFBN.jpg!op_type=3&columns=100&rows=100","coverMiddle": "http://imagev2.xmcdn.com/storages/66a0-audiofreehighqps/B2/6B/CMCoOR4D11VfAABKVAB8EFBN.jpg!op_type=3&columns=180&rows=180","coverLarge": "http://imagev2.xmcdn.com/storages/66a0-audiofreehighqps/B2/6B/CMCoOR4D11VfAABKVAB8EFBN.jpg!op_type=3&columns=1000&rows=1000","videoCover": "","uid": 162260752,"nickname": "原点儿","isLike": false,"isPublic": true,"likes": 17,"comments": 19,"shares": 1,"userSource": 1,"status": 1,"duration": 499,"sampleDuration": 0,"isPaid": false,"isFree": false,"isAuthorized": true,"isVideo": false,"isDraft": false,"isRichAudio": false,"isAntiLeech": false,"vipFirstStatus": 0,"ximiFirstStatus": 0,"playUrlList": [{"huaweiSound": false,"type": "M4A_64","fileSize": 4047211,"sampleSize": 0,"url": "Fils1uhGGP6hvq1Ejr-FabguUfIhWc-DnarBSIq6soVXJDVMJMeIq1lBF12KDMmjzEiz7OPIy0dlrEK07r5b1W911_ks5xu2N5XcernanGrRm1Edhn5-8fqIqvYJX_DFY85xjgR_3bYrubrNb78N8jf6bqBLjj_tAGxhgqQHZDXgBVX1zWbXgQP3F80jEzh3GuUUrumOWUour4h2At8g0PMF3dHJLShb2IHimXuavcqg5BQdQo5McFV2rzGR5xdLtZmWyCQZjdn-6_A2tgsEpqXPX4WUFqS0AAkupa4E300","qualityLevel": 1,"uploadId": 10539947180,"width": 0,"height": 0,"version": 1},{"huaweiSound": false,"type": "MP3_64","fileSize": 4004964,"sampleSize": 0,"url": "xqMQcqR0FtShvq1EjkStN9zWpd5ZfxvRnarBSIoi7TgeYzMsW9PKwllBF12KNsYdmCtVLjfRvQdlrEK07qTeiJUiLQQZOc-aK5Buerk14FSjfKWq9eyaEvqIqg8JFwpPOiI_dVtRspl-uYlKIwyeTuAJdvQq9ZxBLmzAgqTzOHZp4rPharNjzQP3F80j8WSJB6sxMSNDONkur4h2Ah6w_WPilRsrWh912IHimXtWnrEgzzH0fkPFflV2rzGRa87jnvA_Qlvrxkr-6_A2tnU3TvhBhGtqRBRWAAkupa4FUR8","qualityLevel": 1,"uploadId": 10539947180,"width": 0,"height": 0,"version": 1},{"huaweiSound": false,"type": "M4A_24","fileSize": 1547815,"sampleSize": 0,"url": "BczWdNSHOMWhvq1Ejr9lxRFDl20bWN_7narBSIpcYvNwXLctmSjxE1lBF12KDAEbxXSduV0unmllrEK07r7cfNUf2c9Fmvp9GYDcernaJfoFz5fcPAHSivqIqkdGum4gJ563QTwwv30Z7LGaZjbAfcKBm2TxwK2OGGFJgqQHI26ok1mz_SVLNgP3F80jE4i_muZhoDZVFlsur4h2At-r3L-TdO51lslK2IHimXuaXkTxfGHc7VX_GVV2rzGR5_436MZzFJlJ_HX-6_A2tgubtDtaw4KNzpgKAAkupa4Eo5c","qualityLevel": 0,"uploadId": 10539947180,"width": 0,"height": 0,"version": 1},{"huaweiSound": false,"type": "MP3_32","fileSize": 2006075,"sampleSize": 0,"url": "sdIP9VSDhzmhvq1EjkSJeU6z7PP7KchVnarBSIryktJrsWDrc8VhB1lBF12KNkAL_8jIsWNLw6VlrEK07qQIRr5Xop8ji_zcKx_cerk10uVk_uyAZiezMfqIqjBZsSlra8b45p9C3YDrt8p9c_GMU3eB9Ym5fVkw1TL4gqTzJ4oDgIfWf0RYaAP3F80j8ZCp0lH1jBkLP_our4h2Ah48IrqAAI6O6dsf2IHimXtWeDTKn_VrewuRpVV2rzGRa-lfy7uiQ3MM-uD-6_A2tnUivbcLQ8g_pajDAAkupa4FGYc","qualityLevel": 0,"uploadId": 10539947180,"width": 0,"height": 0,"version": 1},{"huaweiSound": false,"type": "AAC_24","fileSize": 1999517,"sampleSize": 0,"url": "biq_EoexXXWhvq1Ejr9poc-QIN8ukCKBnarBSIq6eUgJudAZr3dyvVlBF12KDGN8jh45atADTkZlrEK07r5IcsOkU6ts-_jJniOKerna8-6-k-CyAaNjWfqIqupUQOjB-QIk-YI56UvrgcohoVaj1qRc31LdY7LH6hz4gqQHQjxaz0ozNR-agwP3F80jEzo_av8ekOVXiWIur4h2At_FXsjPO0OUeArU2IHimXua_9Y_4h7woldO01V2rzGR5xMB7mr9jq_GIcX-6_A2tgu4kcc6aZrpYItEAAkupa4EVDw","qualityLevel": 0,"uploadId": 10539947180,"width": 0,"height": 0,"version": 1}],"childAlbumInWhiteList": false,"recommendSkip": {"recommendHeadSkip": 15000,"recommendHeadSkipCount": 2905,"recommendHeadTail": 10000,"recommendHeadTailCount": 1312},"isEnjoying": false,"offlineVisibleType": 0,"hasShqAuthorized": false,"isXimiUhqTrack": false,"isXimiUhqAuthorized": false,"playtimes": 18930
}
getsrc(trackInfo)
相关文章:
ximalaya(三) playUriList值解密--webpack
本文主要介绍解密音频播放url参数。 本文仅代表个人理解,如有其他建议可在评论区沟通。 声明 仅仅记录一下自己的学习方法,不作为其他参考、更不作为商业用途。如有侵犯请联系本人删除 目标地址:aHR0cHM6Ly93d3cueGltYWxheWEuY29tL3NvdW5k…...
ASP.NET Core JWT
目录 Session的缺点 JWT(Json Web Token) 优点: 登录流程 JWT的基本使用 生成JWT 解码JWT 用JwtSecurityTokenHandler对JWT解码 注意 Session的缺点 对于分布式集群环境,Session数据保存在服务器内存中就不合适了&#…...
原生redis实现分布式锁
用 原生 Redis(Jedis、Lettuce) 实现分布式锁,可以参考 Redisson 的原理,但需要自己处理锁的自动续期、故障恢复等细节。核心思路是使用 Redis 的 SET NX EX 或 SET PX NX 命令来实现互斥锁,并利用 Lua 脚本 保障原子性…...
光伏-报告显示,假期内,硅料端签单顺序发货相对稳定。若3月份下游存提产,则不排除硅料价格有上调预期。
据TrendForce集邦咨询报告显示,假期内,硅料端按照前期签单顺序发货,相对稳定。若3月份下游存提产,则不排除硅料价格有上调预期。 002306中科云网 旅游 | 公司为提供复合菜系特色餐饮的连锁企业,形成了以粤菜ÿ…...
【信息系统项目管理师-案例真题】2017上半年案例分析答案和详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一【问题1】8 分【问题2】4 分【问题3】8 分【问题4】5 分试题二【问题1】10 分【问题2】8 分【问题3】6 分【问题4】5 分试题三【问题1】5 分【问题2】7 分【问题3】6 分【问题4】3 分试题一 阅读下列说明…...
滴水逆向_程序实现弹窗修改OEP
作业: 几个很重要的注意事项。 1 我们模拟的是内核如何将一个文件硬盘中拉伸到内存中,但是我们做的仅仅是 模拟拉伸过程。也就是说其中的属性字段是无差别的拷贝的。 但是加载exe的时候 ,imagebase 是随机分配的。 我们打开内存中的exe&…...
快速上手——.net封装使用DeekSeek-V3 模型
📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,用爱发电,去丈量人心,是否能达到人机合一?开工大吉 新的一年就这么水灵灵的开始了,在这里,祝各位读者新春快乐,万事如意! 新年伊…...
ReactNative进阶(五十九):存量 react-native 项目适配 HarmonyOS NEXT
文章目录 一、前言二、ohos_react_native2.1 Fabric2.2 TurboModule2.2.1 ArkTSTurboModule2.2.2 cxxTurboModule: 三、拓展阅读 一、前言 2024年10月22日19:00,华为在深圳举办“原生鸿蒙之夜暨华为全场景新品发布会”,主题为“星河璀璨&…...
1-2 面向对象编程方法
1.0 面向对象编程思维 在面向对象风格中,结构体被看做数据(data),而操作数据的函数称作方法(method)。目前函数 和数据是分离的,函数并不直接操作数据,我们需要拿到函数返回的结果&a…...
k8s中部署nginx的pod
在当今数字化的浪潮中,容器编排技术成为了构建和管理应用程序的核心力量。Kubernetes(简称 k8s)作为容器编排领域的佼佼者,凭借其强大的自动化部署、扩展和管理能力,深受开发者和运维人员的青睐。而 Nginx 作为一款高性…...
CSS 组合选择符详解与实战示例
在 Web 开发过程中,CSS 用于定义页面元素的样式,而选择器则帮助我们精确定位需要添加样式的元素。今天我们主要来讲解 CSS 中的组合选择符,它们能够根据 DOM 结构中元素之间的关系来选中目标元素,从而写出结构清晰、易于维护的 CS…...
html为<td>添加标注文本
样式说明: /*为td添加相对定位点*/ .td_text {position: relative; }/*为p添加绝对坐标(相对于父元素中的定位点)*/ .td_text p {position: absolute;top: 80%;font-size: 8px; }参考资料:...
apachePoi中XSSFClientAnchor图片坐标简述;填充多张图片
概述 业务中经常会遇到在单元格内填充图片的需求,而且要求指定图片在单元格内的位置。 一般都是用的apache的poi,设置图片坐标。 HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)dx1 dy1 起始单元…...
无界构建微前端?NO!NO!NO!多系统融合思路!
文章目录 微前端理解1、微前端概念2、微前端特性3、微前端方案a、iframeb、qiankun --> 使用比较复杂 --> 自己写对vite的插件c、micro-app --> 京东开发 --> 对vite支持更拉跨d、EMP 方案--> 必须使用 webpack5 --> 很多人感觉不是微前端 --> 去中心化方…...
数据留痕的方法
在项目中,数据变更时,经常需要记录上次的数据,以便查看对比,专业术语叫做数据留痕。数据变更留痕(即记录数据的变更历史)是一个常见的需求,例如在审计、追踪数据变化或满足合规性要求的场景中。…...
Glustefs 服务端配置流程
Glustefs 服务端配置流程 (一)环境搭建 名称ip硬件设备文件虚拟机 gluster1192.168.101.12G新磁盘/dev/sdb虚拟机 gluster2192.168.101.22G新磁盘/dev/sdb虚拟机 gluster3192.168.101.32G新磁盘/dev/sdb (二)磁盘格式化&#x…...
为飞牛OS基于FRP的内网穿透开启HTTPS加密
前言 玩NAS的朋友应该有比较多只是在家庭局域网使用,比如日常看看电影、备份手机照片什么的,这属于家庭局域网的使用场景。 当然了,如果你经常出差,或者过年回家不想把NAS也背回去,或者是想上班摸鱼,或者是…...
《基于Python与DashScope的智能语音合成工具开发》
《基于Python与DashScope的智能语音合成工具开发》 在当今数字化时代,语音合成技术已经广泛应用于各种场景,如智能语音助手、有声读物、导航系统等。本文将介绍如何使用Python和DashScope平台开发一个简单而功能强大的文字转语音工具。通过这个工具&…...
快速上手Vim的使用
Vim Linux编辑器-vim使用命令行模式下所有选项都可以带数字底行模式可视块模式(ctrlV进入) Linux编辑器-vim使用 Vim有多种模式的编辑器。能帮助我们很快的进行代码的编辑,甚至完成很多其他事情。 默认情况下我们打开vim在命令模式下&#x…...
vue学习第四天 v-on事件绑定
v-on绑定事件如下,点击按钮会弹出alert v-on:事件具体名称“事件调用的函数名” 事件调用的函数写在methods里面 在methods属性的函数里,可以用this获取data的数据,this代表的就是整个vue实例 用this.age就可以拿到age࿰…...
2.8寒假作业
web:[HNCTF 2022 Week1]2048 之前也做过类似的题目,之前的解法是直接get传参score20000,可以尝试 打开环境看源代码,直接改源代码显然是不行的,那么用一下上面的办法也不行,估计是要改其他方向的ÿ…...
PyTorch torch.sign函数介绍
torch.sign 是 PyTorch 库中用于计算输入张量每个元素符号的函数。下面从功能概述、函数原型、参数解释、返回值、使用示例以及与相关函数对比等方面详细介绍 torch.sign。 功能概述 torch.sign 函数会返回一个与输入张量形状相同的新张量,其中每个元素的值表示输…...
Formality:时序变换(五)(寄存器复制)
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一、引言 时序变换在Design Compiler的首次综合和增量综合中都可能发生,它们包括:时钟门控(Clock Gating)、寄存器合并(Register Merging)、…...
音频知识基础
音频知识基础 声音属性声音度量人耳特性通道数音频数字化传输接口 声音属性 响度 响度是人耳对声音强弱的主观感受; 主要和声波的振幅相关,同时也和频率有一定关系; 音调 音调是人耳对声音高低的主观感受; 主要与频率相关&#…...
科技赋能数字内容体验的核心技术探索
内容概要 在数字化时代,科技的迅猛发展为我们的生活和工作带来了深刻的变革。数字内容体验已经成为人们获取信息和娱乐的重要途径,而这背后的技术支持则扮演着至关重要的角色。尤其是在人工智能、虚拟现实和区块链等新兴技术的推动下,数字内…...
DeepSeek-R1 本地大模型搭建对接API
DeepSeek-R1 在这里将学到很多知识 欢迎使用使用DeepSeek-R1本地大模型DeepSeek 的模型基础说明DeepSeek的本地 API 说明DeepSeek 本地模型搭建1、执行命令安装及测试 DeepSeek-R1 API接口调用当然,我们为了让用户更加便捷,我们把API 接口全部放到上面截…...
利用NestJS构建高效的RESTful API接口
1. 引言 项目背景与目标 随着互联网应用的快速发展,RESTful API已成为前后端分离架构中的重要组成部分。本文将介绍如何使用NestJS构建一个高效且可维护的RESTful API接口。目标是通过NestJS的模块化和依赖注入特性,实现一个易于扩展和维护的API系统。 RESTful API的重要性…...
redis高级数据结构布隆过滤器
文章目录 背景什么是布隆过滤器Redis 中的布隆过滤器布隆过滤器使用注意事项实现原理空间占用估计 背景 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻…...
《Wiki.js知识库部署实践 + CNB Git数据同步方案解析》
一、wiki.js 知识库简介 基本概述 定义 :Wiki.js 是一个开源、现代、轻量且功能强大的 Wiki 应用程序,基于 Node.js 构建,旨在帮助个人和团队轻松创建、管理和共享知识。开源性质 :它遵循 AGPLv3 许可证,任何人都可以…...
CSS Overflow 属性详解:控制内容溢出的利器
在前端开发中,处理内容溢出是一个常见的需求。CSS 提供了 overflow 属性,帮助我们控制当内容超出元素框时的显示方式。本文将详细介绍 overflow 属性的各种取值及其应用场景。 1. 什么是 overflow 属性? overflow 属性用于控制当元素的内容…...
