某狗网歌曲接口逆向之加密算法刨析

逆向网址

aHR0cHM6Ly93d3cua3Vnb3UuY29t


逆向链接

aHR0cHM6Ly93d3cua3Vnb3UuY29tL21peHNvbmcvN2dxcGVzNjguaHRtbA==


 逆向接口

aHR0cHM6Ly93d3dhcGkua3Vnb3UuY29tL3BsYXkvc29uZ2luZm8=

 逆向过程 

请求方式:GET

逆向参数

        signature:1898d8f157837fadc9751fdacf1398f9

过程分析

根据XHR断点方式可快速进入发包内容

再次跟栈找到位置打条件断点

可以看到此处加密参数【signature】 已经生成,继续跟栈.....

发现如下位置关键词  signature 打上断点开始调试

添加条件断点:

l.encode_album_audio_id == '7gqpes68'

l

 s

那么就可以发现加密函数【d】 

 signature ===  d(s.join(""))

加密调试

调试加密字符串长度可知:32, 猜测 md5

d( '1' )

 

由此就可知 signature 加密方式为 MD5

参数分析

那么由上面分析可知,我们需要构建数据 【s】,那么需要知道来源,将方法全部拿出来进行分析

function c() {var t, n = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "", o = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, i = !1, c = !1, a = "json", l = r({}, n), u = s.isInClient();"function" == typeof o ? t = o : (t = o.callback,i = o.useH5 || !1,a = o.postType || "json",c = o.isCDN || !1),e && ("[object Object]" != Object.prototype.toString.call(e) ? u = !1 : "urlencoded" == a && (u = !1));var f = function() {var n = (new Date).getTime(), i = [], s = [], u = "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt", f = {srcappid: "2919",clientver: "20000",clienttime: n,mid: n,uuid: n,dfid: "-"};c && (delete f.clienttime,delete f.mid,delete f.uuid,delete f.dfid),l = r({}, f, {}, l);for (var g in l)i.push(g);if (i.sort(),i.forEach(function(t) {s.push(t + "=" + l[t])}),e)if ("[object Object]" == Object.prototype.toString.call(e))if ("json" == a)s.push(JSON.stringify(e));else {var b = [];for (var g in e)b.push(g + "=" + e[g]);s.push(b.join("&"))}elses.push(e);s.unshift(u),s.push(u),l.signature = d(s.join("")),o.log && (console.log("H5签名前参数", s),console.log("H5签名后返回", l)),e ? t && t(l, "[object Object]" == Object.prototype.toString.call(e) && "json" == a ? JSON.stringify(e) : e) : t && t(l)};if (u && !i) {var g = !1;s.mobileCall(764, {get: l,post: e}, function(n) {return !g && (g = !0,n && n.status ? (delete n.status,o.log && (console.log("客户端签名前参数", {get: l,post: e}),console.log("客户端签名后返回", r({}, l, {}, n))),l = r({}, l, {}, n),e ? t && t(l, "[object Object]" == Object.prototype.toString.call(e) && "json" == a ? JSON.stringify(e) : e) : t && t(l),!1) : (u = !1,void f()))})} elseu = !1,f()
}

加密参数

["NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt","appid=1014","clienttime=1712727965638","clientver=20000","dfid=3exIvy0NDCiI1x9u9X0MmaUX","encode_album_audio_id=7gqpes68","mid=df8eb959431e3f2696fc23d514fd9bf4","platid=4","srcappid=2919","token=","userid=0","uuid=df8eb959431e3f2696fc23d514fd9bf4","NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
]

请求参数

{'srcappid': '2919','clientver': '20000','clienttime': '1712720179947','mid': 'df8eb959431e3f2696fc23d514fd9bf4','uuid': 'df8eb959431e3f2696fc23d514fd9bf4','dfid': '3exIvy0NDCiI1x9u9X0MmaUX','appid': '1014','platid': '4','encode_album_audio_id': '7gqpes68','token': '','userid': '0',
}

 类比加密参数与请求参数下,结合加密函数

l = r({}, n), u = s.isInClient();
var n = (new Date).getTime()
s = [],
u = "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
f = {srcappid: "2919",clientver: "20000",clienttime: n,mid: n,uuid: n,dfid: "-"
};
l = r({}, f, {}, l);
for (var g in l)i.push(g);
if (i.sort(),
i.forEach(function(t) {s.push(t + "=" + l[t])
}),
e)

可知:

  • 先将变量【f】压入变量 【l】
  • 将变量【l】中的key拿出进行排序
  • 构建变量【s】利用新的排序方式以 key=val 形式构建字符串
  • 将变量【u】分别加入【s】始末

逆向参数

参数分析

dfid: 3exIvy0NDCiI1x9u9X0MmaUX
mid: df8eb959431e3f2696fc23d514fd9bf4
uuid: df8eb959431e3f2696fc23d514fd9bf4

在打条件断点位置 向上跟栈....

可知由变量【bInfo】 而来,那么需要进入 【window.getBaseInfo】 内部查看

return function(t, i) {var r = {getUserInfo: 101,getVersion: 122,getMobileInfo: 124}, o = {appid: null,mid: null,uuid: null,plat: null,dfid: null,userid: null,userpic: null,userNickName: null,token: null,clientver: null};if (n.isInClient() && !n.isFXAP)n.mobileCall(r.getUserInfo, null, function(e) {1 == e.status ? (o.userid = e.kugouID,o.token = e.token,o.userpic = e.photo,o.userNickName = e.nickName,o.isVIP = e.isVIP || e.isVip) : (o.userid = null,o.token = null,o.userpic = null,o.userNickName = null),o.appid = e.appid,n.mobileCall(r.getVersion, null, function(e) {o.clientver = e.version,n.mobileCall(r.getMobileInfo, null, function(e) {o.mid = e.mid_v2 ? e.mid_v2 : e.mid,o.dfid = e.dfid ? e.dfid : "-",o.uuid = e.uuid ? e.uuid : o.mid,o.osVersion = e.osVersion ? e.osVersion : "",n.isIOS ? o.plat = 2 : o.plat = 1,i && i(o)})})});else if (n.isInClient() && n.isFXAP)n.mobileCall(625, null, function(t) {var r = JSON.parse(t.jsonStr);o.clientver = r.version,o.mid = r.mid,o.uuid = r.uuid ? r.uuid : o.mid,o.dfid = r.dfid ? r.dfid : "-",o.appid = r.appId,e.isiOS() ? o.plat = 2 : o.plat = 1,n.mobileCall(410, null, function(e) {1 == JSON.parse(e.jsonStr).status ? n.mobileCall(411, {}, function(e) {var n = JSON.parse(e.jsonStr).jsonStr ? JSON.parse(e.jsonStr).jsonStr : JSON.parse(e.jsonStr);o.userid = n.kugouId,o.token = n.token,o.pic = n.userLogo,o.nickName = n.nickName,i && i(o)}) : (o.userid = null,o.token = null,o.userpic = null,o.userNickName = null,i && i(o))})});else {o.appid = t || null,o.mid = e.getKgMid(),o.uuid = o.mid,o.plat = 4,o.dfid = e.Cookie.read("kg_dfid") || "-",o.userid = e.Cookie.read("KuGoo", "KugooID"),o.userpic = e.Cookie.read("KuGoo", "Pic"),o.userNickName = e.Cookie.read("KuGoo", "NickName"),o.token = e.Cookie.read("KuGoo", "t");var a = e.Cookie.read("KuGoo", "a_id");a && a != o.appid && o.appid && (o.userid = null,o.token = null,o.userpic = null,o.userNickName = null),o.clientver = 1e3,o.userNickName = o.userNickName ? unescape(o.userNickName) : "",i && i(o)}
}

挖掘数据

o.mid = e.getKgMid(),
o.uuid = o.mid,
o.dfid = e.Cookie.read("kg_dfid") || "-",
o.userid = e.Cookie.read("KuGoo", "KugooID"),
o.token = e.Cookie.read("KuGoo", "t");
o.clientver = 1e3,

打断点进行调试

dfid  ==  cookie中的  kg_dfid 【3exIvy0NDCiI1x9u9X0MmaUX】

mid == uuid ==  e.getKgMid()

getKgMid: function() {var n = e.Cookie.read("kg_mid");if (navigator.cookieEnabled) {if (e.IsEmpty(n)) {var t = e.Guid();n = e.Md5(t);try {e.Cookie.write("kg_mid", e.Md5(t), 864e6, "/", "kugou.com")} catch (e) {}}} else {var i = navigator.userAgent, r = function() {var e = navigator.plugins, n = "";if (e.length > 0) {for (var t = [], i = 0, r = e.length; i < r; i++) {var o = e[i].name;t.push(o)}n = t.toString()}return n}(), o = screen.width + "x" + screen.height, a = screen.colorDepth ? screen.colorDepth : "", l = screen.pixelDepth ? screen.pixelDepth : "", s = function() {var n = ["canvas"];try {var t = document.createElement("canvas");if (t.getContext && t.getContext("2d")) {t.width = 200,t.height = 200,t.style.display = "inline";var i = t.getContext("2d");i.rect(0, 0, 10, 10),i.rect(2, 2, 6, 6),n.push("canvas winding:" + (!1 === i.isPointInPath(5, 5, "evenodd") ? "yes" : "no")),i.textBaseline = "alphabetic",i.fillStyle = "#f60",i.fillRect(125, 1, 62, 20),i.fillStyle = "#069",i.font = "14px 'Arial'",i.fillText("hello kugou", 2, 15),i.fillStyle = "rgba(102, 204, 0, 0.2)",i.font = "18pt Arial",i.fillText("hello kugou", 4, 45),i.globalCompositeOperation = "multiply",i.fillStyle = "rgb(255,0,255)",i.beginPath(),i.arc(50, 50, 50, 0, 2 * Math.PI, !0),i.closePath(),i.fill(),i.fillStyle = "rgb(0,255,255)",i.beginPath(),i.arc(100, 50, 50, 0, 2 * Math.PI, !0),i.closePath(),i.fill(),i.fillStyle = "rgb(255,255,0)",i.beginPath(),i.arc(75, 100, 50, 0, 2 * Math.PI, !0),i.closePath(),i.fill(),i.fillStyle = "rgb(255,0,255)",i.arc(75, 75, 75, 0, 2 * Math.PI, !0),i.arc(75, 75, 25, 0, 2 * Math.PI, !0),i.fill("evenodd"),t.toDataURL && n.push("canvas fp:" + t.toDataURL())}} catch (e) {}return e.Md5(n.toString())}();n = e.Md5(i + r + o + a + l + s)}return n
},

代码分析

// 首先取cookie  kg_mid
var n = e.Cookie.read("kg_mid");// 判定 navigator中的  cookieEnabled 值
if (navigator.cookieEnabled) {// 开启}else{//关闭}
开启条件情况
//判定 n 是否为空
// 如果是空 则重新生成写入到 cookie中if (e.IsEmpty(n)) {var t = e.Guid();n = e.Md5(t);try {e.Cookie.write("kg_mid", e.Md5(t), 864e6, "/", "kugou.com")} catch (e) {}
}///  e.Guid()
Guid: function() {function e() {return (65536 * (1 + Math.random()) | 0).toString(16).substring(1)}return e() + e() + "-" + e() + "-" + e() + "-" + e() + "-" + e() + e() + e()
},
关闭条件情况
n = e.Md5(i + r + o + a + l + s)var i = navigator.userAgent
var r = navigator.plugins >>> 循环取 name 进行拼接成字符串
var o = screen.width + "x" + screen.height
var a = a = screen.colorDepth ? screen.colorDepth : ""
var l = screen.pixelDepth ? screen.pixelDepth : ""
var s = e.Md5(n.toString())n
var n = ["canvas"];
n.push("canvas fp:" + t.toDataURL())//这里的 t 为DOM画布 ->  document.createElement("canvas");

Python代码

构建参数

### 构建参数
###  encode_album_audio_id 歌曲短链  可由歌曲详情页链接后缀拿到
params = {'srcappid': '2919','clientver': '20000','clienttime': str( round(time.time()*1000) ),'mid': cookie['kg_mid'],'uuid': cookie['kg_mid'],'dfid': cookie['kg_dfid'],'appid': '1014','platid': '4','encode_album_audio_id': 'a9ton4f5','token': '','userid': '0',
}

提取KEY并排序

### 提取 params中的key
arrKeys = []
for key in params:arrKeys.append( key )//排序 -升序
arrKeys.sort()

构建加密字符串

### 构建加密字符串u = 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
strRegParams = u
for key in arrKeys:strRegParams += f"{key}={params[key]}"strEnc = strRegParams + u

完整代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time   : 2024/4/10 16:11
# @Author : Carey
# @File : music.py
# @Descriptionimport requests
import time
import hashlibheaders = {'accept': '*/*','accept-language': 'en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7','origin': '{origin}','referer': '{referer}','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
}cookie = {"kg_mid": "df8eb959431e3f2696fc23d514fd9bf4","kg_dfid": "3exIvy0NDCiI1x9u9X0MmaUX",
}### 构建参数
###  encode_album_audio_id 歌曲短链  可由歌曲详情页链接后缀拿到
params = {'srcappid': '2919','clientver': '20000','clienttime': str( round(time.time()*1000) ),'mid': cookie['kg_mid'],'uuid': cookie['kg_mid'],'dfid': cookie['kg_dfid'],'appid': '1014','platid': '4','encode_album_audio_id': 'a9ton4f5','token': '','userid': '0',
}arrKeys = []
for key in params:arrKeys.append( key )arrKeys.sort()u = 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
strRegParams = u
for key in arrKeys:strRegParams += f"{key}={params[key]}"strEnc = strRegParams + u
signature = hashlib.md5( strEnc.encode(encoding='UTF-8')).hexdigest()
params[ 'signature' ] = signatureresponse = requests.get('{api}', params=params, headers=headers)
print( response )
print( response.json() )

调试测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/303980.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【洛谷】P9236 [蓝桥杯 2023 省 A] 异或和之和

题目链接 P9236 [蓝桥杯 2023 省 A] 异或和之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 1. 暴力求解 直接枚举出所有子数组&#xff0c;求每个子数组的异或和&#xff0c;再对所有的异或和求和 枚举所有子数组的时间复杂度为O&#xff08;N^2&#xff09;&…

(学习日记)2024.04.10:UCOSIII第三十八节:事件实验

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

6.1Python之字典的初识

【1】字典的创建与价值 字典&#xff08;Dictionary&#xff09;是一种在Python中用于存储和组织数据的数据结构。元素由键和对应的值组成。其中&#xff0c;键&#xff08;Key&#xff09;必须是唯一的&#xff0c;而值&#xff08;Value&#xff09;则可以是任意类型的数据。…

性能测试干2年,还不会这个技术点?!

nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具&#xff0c;记录的信息比较全面&#xff0c;结合nmon_analyzer工具产生数据文件与图形化结果。 nmon可监控的数据类型 内存使用情况、磁盘适配器、文件系统中的可用空间、CPU使用率等等数据信息 特点 ①占用…

urwid,一个好用的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个好用的 Python 库 - urwid。 Github地址&#xff1a;https://github.com/urwid/urwid Urwid 是一个功能强大的 Python 库&#xff0c;用于创建基于文本的用户界面&#xf…

稀碎从零算法笔记Day45-LeetCode:电话号码的字母组合

题型&#xff1a;映射、回溯算法、递归 链接&#xff1a;17. 电话号码的字母组合 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出…

vue vue3 手写 动态加载组件

效果展示 一、需求背景&#xff1a; # vue3 项目涉及很多图表加载、表格加载 #考虑手写一个动态加载组件 二、实现思路 通过一个加载状态变量&#xff0c;通过v-if判断&#xff0c;加载状态的变量等于哪一个&#xff0c;动态加载组件内部就显示的哪一块组件。 三、实现效果…

雄安建博会:中矿雄安新区的总部开工建设

中矿落位雄安&#xff1a;助力国家战略与新区发展 雄安新区&#xff0c;作为中国未来发展的重要战略支点&#xff0c;正迎来一系列央企总部的疏解与建设。最近&#xff0c;中国矿产资源集团有限公司&#xff08;简称“中矿”&#xff09;在雄安新区的总部项目正式开工建设&…

防止U盘拷贝复制的软件和方法

防止U盘拷贝复制的软件和方法 防止U盘拷贝的软件旨在限制未经授权的用户从U盘中复制、移动、打印或以其他方式传播存储在其上的文件。 以下是一些具体的防U盘拷贝软件及其特点&#xff1a; 1、安企神软件 提供专业的U盘加密保护&#xff0c;可将普通U盘制作成防拷贝U盘&…

单链表专题

文章目录 目录1. 链表的概念及结构2. 实现单链表2.1 链表的打印2.2 链表的尾插2.3 链表的头插2.4 链表的尾删2.5 链表的头删2.6 查找2.7 在指定位置之前插入数据2.8 在指定位置之后插入数据2.9 删除pos节点2.10 删除pos之后的节点2.11 销毁链表 3. 链表的分类 目录 链表的概念…

蓝桥 python笔记15——矩阵运算、基础数论、GCD和LCM、质数、唯一分解定理、快速幂

目录 矩阵运算 基础数论 GCD和LCM 质数 唯一分解定理 快速幂 矩阵运算 矩阵加减法&#xff1a; 矩阵和数相乘&#xff1a; 矩阵转置&#xff1a; 矩阵乘法&#xff1a; # 矩阵乘法 def mul(A,B):N,Mlen(A),len(A[0])#行数&#xff0c;列数_M,Klen(B),len(B[0])if M!_M:re…

语音情感识别调研

语音情感识别调研 1、情绪识别综述2、语音情感识别算法3、语音特征提取4、相关项目1、用 LSTM、CNN、SVM、MLP 进行语音情感识别2、DST&#xff1a;基于Transformer的可变形语音情感识别模型3、语音情感基座模型emotion2vec4、IEEE ICME 2023论文&#xff5c;基于交互式注意力的…

【PyQt5篇】使用QtDesigner添加控件和槽

文章目录 &#x1f354;使用QtDesigner进行设计&#x1f6f8;在代码中添加信号和槽 &#x1f354;使用QtDesigner进行设计 我们首先使用QtDesigner设计界面 得到代码login.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0&q…

穿越代码之海:探寻结构体深层逻辑,展望未来应用新天地

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 结构体作为一种数据结构&#xff0c;其定义和特点决定了它在各种应用中的广泛适用性。随着科技的进步和新兴行业的不断涌现&#xf…

C++——IO流

目录 一&#xff0c;C语言的输入与输出 二&#xff0c;流是什么 三&#xff0c;C标准IO流 3.1 四个全局流对象 3.2 OJ题中的输入和输出 3.3 自定义类型重载输入和输出 四&#xff0c;C文件IO流 4.1 C文件操作步骤 4.1.1 操作文件的类 4.1.2 文件打开方式 4.1.3 文件操…

【数据下载】SODA数据更新至2022并教学下载

【数据下载】SODA数据更新至2022并教学下载 我为什么那么喜欢使用SODA数据&#xff1f; 就是三维网格化的数据&#xff0c;好用。 但是需要高分辨率还是需要找别的。 以前分享过SODA数据下载&#xff0c;但上次版本过于凌乱。因此重新借助更新再分享一次&#xff0c;不为过。…

前端mock数据——使用mockjs进行mock数据

前端mock数据——使用mockjs进行mock数据 一、安装二、mockjs的具体使用 一、安装 首选需要有nodejs环境安装mockjs&#xff1a;npm install mockjs 若出现像上图这样的错&#xff0c;则只需npm install mockjs --legacy-peer-deps即可 src下新建mock文件夹&#xff1a; mo…

Python | 超前滞后分析

Nino SST Indices (Nino 12, 3, 3.4, 4; ONI and TNI) 有几个指标用于监测热带太平洋&#xff0c;所有这些指标都是基于海表温度(SST)异常在一个给定的区域的平均值。通常&#xff0c;异常是相对于30年的周期来计算的。厄尔尼诺3.4指数(Nio 3.4 index)和海洋厄尔尼诺指数(Ocea…

【JavaWeb】Day39.MySQL概述——数据库设计-DQL(二)

数据库设计-DQL 聚合函数 聚合函数查询就是纵向查询&#xff0c;它是对一列的值进行计算&#xff0c;然后返回一个结果值。&#xff08;将一列数据作为一个整体&#xff0c;进行纵向计算&#xff09; 语法&#xff1a; select 聚合函数(字段列表) from 表名 ; 注意 : 聚合…

C++的stack和queue类(一):适配器模式、双端队列与优先级队列

目录 基本概念 stack的使用 queue的使用 适配器模式 stack.h test.cpp 双端队列-deque 仿函数 优先队列 priority_queue的使用 queue.h文件 stack.h文件 test.cpp文件 日期类的比较 商品的比较 结论 基本概念 1、stack和queue不是容器而是容器适配器&…