泷羽Sec-分享网络安全 | 安全产品测评 | 网站建设 - 逆向工程
前言本文章中所有内容仅供学习交流，严禁用于商业用途和非法用途，否则由此产生的一切后果均与文章作者无关，若有侵权，请联系我立即删除！阅读本篇文章，需要一定的爬虫基础，和js逆向思维，否则无法继续首先找到一个歌单找到这个api接口api传参为这两个找到启动器发现这两个参数和刚刚api接口是一模一样的，那么大概率源码就在这里打断点，分析加密参数刷新页面，已经卡在这里了分析每个api参数X1x为后端api地址i1x为csrf_tokene1x为请求方式，该值为post我们的目标是抓取歌单评论信息，一直放行，直到这个接口分析这个参数，如下分析rid：A_PL_0_3865036，这后面的就是歌单id，threadId：A_PL_0_3865036，后面也是歌单id信息，后面的参数基本没用了，页面大小，偏移量和歌单属性那么就可以得到python代码向后端传的参数为这个def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论，-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data=data, headers=headers) print(resp.text) 但是呢没有任何响应结果，说明参数加密了 对比源参数即可看到，这些值都是乱码，显然是进行了加密的那么就要找js的加密节点，怎么找？回到这个界面把这段代码复制下来仔细分析var bVi3x = window.asrsea(JSON.stringify(i1x), bse0x(["流泪", "强"]), bse0x(Qu1x.md), bse0x(["爱心", "女孩", "惊恐", "大笑"])); 分别对应如下值这里我们就得到了每个参数的值使用变量进行替换# 服务于函数d g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) 再放行，找到加密节点鼠标移动到这里，即可看到，使用了一个方法，方法名称叫 d即可看到这样一串代码贴上源码!function() { function a(a) { var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; for (d = 0; a > d; d += 1) e = Math.random() * b.length, e = Math.floor(e), c += b.charAt(e); return c } function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") // AES加密算法中需要的偏移量 , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() } function c(a, b, c) { var d, e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d, a) } function d(d, e, f, g) { var h = {} , i = a(16); return h.encText = b(d, g), h.encText = b(h.encText, i), h.encSecKey = c(i, e, f), h } function e(a, b, d, e) { var f = {}; return f.encText = c(a + e, b, d), f } window.asrsea = d, window.ecnonasr = e }(); 仔细分析AES加密特征，打断点放行打印这些值此时即可得到参数 i ，如果你多次执行就会发现这个 i 值是变化的，调用的是a函数传了个16a 函数这就是一个随机计算结果，可以直接定死而 i 已经定死了，i = "2l8EuJuvLirixMmc" ，这里我执行了第二遍，就用我第二遍的 i 值，得到了已有的值g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) i = "2l8EuJuvLirixMmc" # 手动固定，函数中是随机的 偏移量之前已经在js代码的b函数找到了，这张图就可以很清楚的看到解密后的值就是 h.encText 的值发现这个函数是RSA加密，我们已经得到了这个值，由上图可以看到，i 值为偏移量，e为 010001，f 未知，那么就先放一放查看这个参数，断点记得放行查看值这样就能得到encSecKey的值，分析得到python逆向代码def get_encSecKey(): # 由于i是固定的，所以经过c函数输出的encSecKey也是固定的 return "288bca7fd6e42e24d4549f155b4eb6317ba323b914c9ee8aaccb786cabcd27773aea34d9413b8902f3a1a86e50863cec7e1f872092585cddd432951f210ae078e2f2c6b486c83c210820d5c09c73e2d3f225401ce1f5543f7a6f903c7bdc65b8ea27894c0299f52d801f05aaa6ec61e34082bec0135b9c74dabcabd1e1dba1ab" # 把参数进行加密，相当于 def get_params(data): # 默认收到的是字符串 first = enc_paramas(data, g) # 第一次加密，再将第二次结果与i一起加密 second = enc_paramas(first, i) # 第二次加密 return second # 返回的就是paramas # 将数据长度转化为16的倍数， 为下面加密服务 def to_16(data): # pad = 16 - len(data) % 16 data += chr(pad) * pad return data def enc_paramas(data, key): # 相当于js中的b(a, b)函数 iv = "0102030405060708" # AES加密算法中需要的偏移量 data = to_16(data) aes = AES.new(key=key.encode('utf-8'), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 创建加密器 bs = aes.encrypt(data.encode('utf-8')) # 加密,加密的长度必须是16的倍数，”123456789abcchr(4)chr(4)chr(4)chr(4)" return str(b64encode(bs), "utf-8") # 转化成字符串 此时将刚刚没有任何结果的代码进行传参即可，半成品代码如下import json from base64 import b64encode from Crypto.Cipher import AES # pip install pycryptodome import requests # 设置好已知的值 g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) i = "2l8EuJuvLirixMmc" # 手动固定，函数中是随机的 def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论，-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data={ "params": get_params(json.dumps(data)), # 通过函数的加密得到服务器需要的params参数 "encSecKey": get_encSecKey() }, headers=headers) print(resp.text) if __name__ == '__main__': get_data() 完整数据清洗后的代码import random import json from base64 import b64encode from Crypto.Cipher import AES # pip install pycryptodome import requests # 服务于函数d g = "0CoJUm6Qyw8W8jud" f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" i = "2l8EuJuvLirixMmc" # 手动固定，函数中是随机的 def get_encSecKey(): # 由于i是固定的，所以经过c函数输出的encSecKey也是固定的 return "288bca7fd6e42e24d4549f155b4eb6317ba323b914c9ee8aaccb786cabcd27773aea34d9413b8902f3a1a86e50863cec7e1f872092585cddd432951f210ae078e2f2c6b486c83c210820d5c09c73e2d3f225401ce1f5543f7a6f903c7bdc65b8ea27894c0299f52d801f05aaa6ec61e34082bec0135b9c74dabcabd1e1dba1ab" # 把参数进行加密 def get_params(data): # 默认收到的是字符串 first = enc_paramas(data, g) # 第一次加密，再将第二次结果与i一起加密 second = enc_paramas(first, i) # 第二次加密 return second # 返回的就是paramas # 将数据长度转化为16的倍数， 为下面加密服务 def to_16(data): pad = 16 - len(data) % 16 data += chr(pad) * pad return data def enc_paramas(data, key): iv = "0102030405060708" # AES加密算法中需要的偏移量 data = to_16(data) aes = AES.new(key=key.encode('utf-8'), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 创建加密器 bs = aes.encrypt(data.encode('utf-8')) # 加密,加密的长度必须是16的倍数，”123456789abcchr(4)chr(4)chr(4)chr(4)" return str(b64encode(bs), "utf-8") # 转化成字符串 def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论，-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data={ "params": get_params(json.dumps(data)), # 通过函数的加密得到服务器需要的params参数 "encSecKey": get_encSecKey() }, headers=headers) print(resp.text) dict = json.loads(resp.text) # 将得到的内容转化为字典模式 user_obj = dict['data']['hotComments'] comment_data = [] comment_sum = dict['data']['totalCount'] if not user_obj: user_obj = dict['data']['comments'] for _ in user_obj: content = _['content'] nickname = _['user']['nickname'] photo = _['user']['avatarUrl'] timeStr = _['timeStr'] like_count = _['likedCount'] addres = _['ipLocation']['location'] list = { 'nickname': nickname, 'content': content, 'photo': photo, 'timeStr': timeStr, 'addres': addres, 'like_count': like_count, 'com_count': comment_sum } comment_data.append(list) print(comment_data) if __name__ == '__main__': get_data() 得到评论结果其他api接口也是如此，还可以搞一个扫码登录的，下面是我23年8月写的项目项目推荐这是我写的一个完整的爬虫django项目，集成了网易云扫码登录，歌单信息，歌曲/歌单评论，歌单收藏，歌曲播放等等运用了aiohttp异步爬虫，requests库，IP池，线程池，redis，中间件mysql数据库，等等等等，项目仅供学习使用，严禁商业用途！！！！记得点个关注，感谢扫码登录网易云首页我的首页歌单列表源列表评论歌曲播放效果。。。。。。。总结本文章中所有内容仅供学习交流，严禁用于商业用途和非法用途，否则由此产生的一切后果均与文章作者无关，若有侵权，请联系我立即删除！，重要的事儿说三遍！！！
很多喜欢玩终端的小伙伴们不知道这种终端签名怎么制作的其实很简单，只要用到figlet库就好了，kali安装命令如下apt install figlet语法如下：figlet -f [字体名称] [你需要的艺术字] # 建议英文的艺术字，不然看不出来查看艺术字体列表showfigfonts有很多种样式其他字体比如banner、slant指定对齐方式-c、-r、-l。也可以使用-w指定宽度全屏居中，首先创建一个demo.txt里面有很多换行cat demo;figlet -f slant h0ck1r-yu -r -w 90;cat demo;效果如下往期推荐什么是域？如何搭建一个简单的域？【内网渗透】免工具，内网、域内信息收集的40种方式总结密码学中的常用加密方式？【CTF】CTF-OS，一个专门为CTF设计的操作系统【JS逆向】某大型音乐平台JS逆向分析