QQ音乐sign vmp逆向

定位

复制代码
return u = ie(r.data)

跟进return u = ie(r.data)

发现是个vmp

下日志断点然后分析log日志

分析

前缀

7CB69B11F03F540463B696AE679DF97A7ED34709

复制代码
通过将log给ai,ai告诉我说这是sha1

入参是啥?

复制代码
搜索 finalize
发现一个数组 SHA-1 常量 [undefined, 1732584193, 4023233417, 2562383102, 3285377520, false, true, 2147483648, 4294967295, 4294967296, 1518500249, 1859775393, 1894007588]

分析得知
{"comm":{"cv":4747474,"ct":24,"format":"json","inCharset":"utf-8","outCharset":"utf-8","notice":0,"platform":"yqq.json","needNewCode":1,"uin":2573298872,"g_tk_new_20200303":1415120135,"g_tk":1415120135},"req_1":{"module":"music.musicsearch.HotkeyService","method":"GetHotkeyForQQMusicMobile","param":{"searchid":"32782922762486672","remoteplace":"txt.yqq.top","from":"yqqweb"}},"req_2":{"module":"music.musicHall.MusicHallPlatformSvr","method":"GetFocus","param":{"ForceBig":1}},"req_3":{"module":"newalbum.NewAlbumServer","method":"get_new_album_area","param":{}},"req_4":{"module":"newalbum.NewAlbumServer","method":"get_new_album_info","param":{"area":1,"sin":0,"num":20}},"req_5":{"module":"musicToplist.ToplistInfoServer","method":"GetAll","param":{}},"req_6":{"module":"MvService.MvInfoProServer","method":"GetNewMv","param":{"style":0,"tag":0,"start":0,"size":40}},"req_7":{"module":"music.paycenterapi.LoginStateVerificationApi","method":"GetChargeAccount","param":{"appid":"mlive"}}}
得到 7CB69B11F03F540463B696AE679DF97A7ED34709

E014616分析

复制代码
h[16] = "7CB69B11F03F540463B696AE679DF97A7ED34709";
h[95] = [23, 14, 6, 36, 16, 40, 7, 19]; // 固定数组
h[139] = h[95].map(i => h[16][i]);
h[8] = h[139].join("");

h[16][23] = "E"
h[16][14] = "0"
h[16][6]  = "1"
h[16][36] = "4"
h[16][16] = "6"
h[16][40] = undefined
h[16][7]  = "1"
h[16][19] = "6"

得到 97DBD30 

中缀

复制代码
SHA1 十六进制字符串按 2 位一组转字节,然后和固定数组逐位 XOR。
十进制就是:
[124, 182, 155, 17, 240, 63, 84, 4, 99, 182, 150, 174, 103, 157, 249, 122, 126, 211, 71, 9]

日志里这个数组:
xor_key = [89, 39, 179, 150, 218, 82, 58, 252, 177, 52, 186, 123, 120, 64, 242, 133, 143, 161, 121, 179]

然后逐位异或:

124 ^ 89  = 37
182 ^ 39  = 145
155 ^ 179 = 40
17  ^ 150 = 135
240 ^ 218 = 42
...
9   ^ 179 = 186

[37, 145, 40, 135, 42, 109, 110, 248, 210, 130, 44, 213, 31, 221, 11, 255, 241, 114, 62, 186] base64
new RegExp("[\\/+]", "g") 正则将/去掉
JZEohyptbvjSgizVH90LFyPro

后缀

复制代码
SHA1 字符串
   ↓
用 [23,14,6,36,16,40,7,19] 抽字符
   ↓
得到 E014616
   ↓
用 E014616 作为种子/中间值
   ↓
生成 [16,1,32,12,19,27,8,5]
[16, 1, 32, 12, 19, 27, 8, 5] 解码
6C756DFB

拼接

复制代码
zzc + E014616 + JZEohyptbvjSgizVH90LFyPro + 6C756DFB

执行 toLowerCase

复制代码
zzce014616jzeohyptbvjsgizvh90lfypro6c756dfb

很简单 附代码

复制代码
import hashlib
import base64
import json
from typing import List


IDX_1 = [23, 14, 6, 36, 16, 40, 7, 19]
IDX_2 = [16, 1, 32, 12, 19, 27, 8, 5]

XOR_KEY = [
    89, 39, 179, 150, 218,
    82, 58, 252, 177, 52,
    186, 123, 120, 64, 242,
    133, 143, 161, 121, 179
]


def pick_chars(s: str, idx: List[int]) -> str:
    return "".join(s[i] if 0 <= i < len(s) else "" for i in idx)


def get_sign(json_str: str) -> str:
    sha1_hex = hashlib.sha1(json_str.encode("utf-8")).hexdigest().upper()

    part1 = pick_chars(sha1_hex, IDX_1)

    sha_bytes = bytes.fromhex(sha1_hex)

    xor_bytes = bytes(
        b ^ k
        for b, k in zip(sha_bytes, XOR_KEY)
    )

    mid = base64.b64encode(xor_bytes).decode()
    mid = mid.replace("/", "").replace("+", "").replace("=", "")

    part2 = pick_chars(sha1_hex, IDX_2)

    return "zzc" + part1 + mid + part2


data = {"comm":{"cv":4747474,"ct":24,"format":"json","inCharset":"utf-8","outCharset":"utf-8","notice":0,"platform":"yqq.json","needNewCode":1,"uin":2573298872,"g_tk_new_20200303":1415120135,"g_tk":1415120135},"req_1":{"module":"music.musicsearch.HotkeyService","method":"GetHotkeyForQQMusicMobile","param":{"searchid":"32782922762486672","remoteplace":"txt.yqq.top","from":"yqqweb"}},"req_2":{"module":"music.musicHall.MusicHallPlatformSvr","method":"GetFocus","param":{"ForceBig":1}},"req_3":{"module":"newalbum.NewAlbumServer","method":"get_new_album_area","param":{}},"req_4":{"module":"newalbum.NewAlbumServer","method":"get_new_album_info","param":{"area":1,"sin":0,"num":20}},"req_5":{"module":"musicToplist.ToplistInfoServer","method":"GetAll","param":{}},"req_6":{"module":"MvService.MvInfoProServer","method":"GetNewMv","param":{"style":0,"tag":0,"start":0,"size":40}},"req_7":{"module":"music.paycenterapi.LoginStateVerificationApi","method":"GetChargeAccount","param":{"appid":"mlive"}}}

json_str = json.dumps(data, separators=(",", ":"), ensure_ascii=False)

print(json_str)
print(get_sign(json_str).lower())

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请联系作者立即删除!

相关推荐
冷小鱼1 小时前
多线程编程深度解析:Java与Python框架实战指南
java·开发语言·python·多线程
Allen_LVyingbo1 小时前
面向医疗群体智能的协同诊疗与群体决策支持系统(上)
数据结构·数据库·人工智能·git·python·动态规划
lcreek1 小时前
端口扫描技术实战指南
网络安全·端口扫描
_Evan_Yao2 小时前
零基础学编程,第一门语言选Python还是C?
c语言·开发语言·python
步步为营DotNet2 小时前
深入探究.NET 11 中.NET Aspire 在云原生应用持续集成与交付安全加固
python
Soari2 小时前
深度办公革命:拆解 Claude for Microsoft 365,打造金融级智能办公生态
python·microsoft·金融·flask
.唉3 小时前
06. FastAPI框架从入门到实战
python·fastapi·web
27669582923 小时前
某白山小程序限制PC端调试
python·小程序·apache·小程序逆向·某白山·限制pc调试
XerCis3 小时前
ngrok实现内网穿透(以Python FastAPI为例)
开发语言·python·fastapi·ngrok