diff --git a/_config.melody.yml b/_config.melody.yml index 949934c..62d2193 100644 --- a/_config.melody.yml +++ b/_config.melody.yml @@ -127,9 +127,9 @@ cdn: fontawesome: https://cdn.jsdelivr.net/npm/font-awesome@latest/css/font-awesome.min.css # fontawesomeV5: https://use.fontawesome.com/releases/v5.3.1/css/all.css js: - anime: https://cdn.jsdelivr.net/npm/animejs@latest/lib/anime.min.js - jquery: https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js - fancybox: https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js + anime: https://cdnjs.loli.net/ajax/libs/animejs/3.2.1/anime.min.js + jquery: https://cdnjs.loli.net/ajax/libs/jquery/3.6.0/jquery.min.js + fancybox: https://cdnjs.loli.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js velocity: https://cdn.jsdelivr.net/npm/velocity-animate@latest/velocity.min.js velocity-ui: https://cdn.jsdelivr.net/npm/velocity-ui-pack@latest/velocity.ui.min.js @@ -211,9 +211,9 @@ addThis: # Comments System # --------------- disqus: - enable: false - #shortname: - #count: + enable: true + shortname: nazukis-blog + count: true # laibili: # enable: false @@ -269,7 +269,7 @@ disqus: # Footer Settings # --------------- -since: 2017 +since: 2015 footer_custom_text: 萌ICP备20229233号 diff --git a/_config.yml b/_config.yml index 1713a1f..f253f51 100644 --- a/_config.yml +++ b/_config.yml @@ -13,8 +13,8 @@ timezone: '' # URL ## Set your site url heare. For example, if you use GitHub Page, set url as 'https://username.github.io/project' -url: http://example.com -permalink: :year/:month/:day/:title/ +url: https://nazuki.moe +permalink: :title/ permalink_defaults: pretty_urls: trailing_index: true # Set to false to remove trailing 'index.html' from permalinks @@ -103,3 +103,18 @@ theme: melody ## Docs: https://hexo.io/docs/one-command-deployment deploy: type: '' + + +feed: + enable: true + type: atom + path: atom.xml + limit: 20 + hub: + content: + content_limit: 140 + content_limit_delim: ' ' + order_by: -date + icon: icon.png + autodiscovery: true + template: \ No newline at end of file diff --git a/package.json b/package.json index 7e54ec0..8f6f501 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "dependencies": { "hexo": "^6.2.0", "hexo-generator-archive": "^1.0.0", - "hexo-generator-category": "^1.0.0", + "hexo-generator-category": "^2.0.0", + "hexo-generator-feed": "^3.0.0", "hexo-generator-index": "^2.0.0", "hexo-generator-tag": "^1.0.0", "hexo-renderer-ejs": "^2.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e4c442..a0b7f82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,7 @@ specifiers: hexo: ^6.2.0 hexo-generator-archive: ^1.0.0 hexo-generator-category: ^1.0.0 + hexo-generator-feed: ^3.0.0 hexo-generator-index: ^2.0.0 hexo-generator-tag: ^1.0.0 hexo-renderer-ejs: ^2.0.0 @@ -18,6 +19,7 @@ dependencies: hexo: 6.2.0 hexo-generator-archive: 1.0.0 hexo-generator-category: 1.0.0 + hexo-generator-feed: 3.0.0 hexo-generator-index: 2.0.0 hexo-generator-tag: 1.0.0 hexo-renderer-ejs: 2.0.0 @@ -716,6 +718,16 @@ packages: hexo-pagination: 1.0.0 dev: false + /hexo-generator-feed/3.0.0: + resolution: {integrity: sha512-Jo35VSRSNeMitS2JmjCq3OHAXXYU4+JIODujHtubdG/NRj2++b3Tgyz9pwTmROx6Yxr2php/hC8og5AGZHh8UQ==} + engines: {node: '>=10.13.0'} + dependencies: + hexo-util: 2.7.0 + nunjucks: 3.2.3 + transitivePeerDependencies: + - chokidar + dev: false + /hexo-generator-index/2.0.0: resolution: {integrity: sha512-q/29Vj9BZs0dwBcF+s9IT8ymS4aYZsDwBEYDnh96C8tsX+KPY5v6TzCdttz58BchifaJpP/l9mi6u9rZuYqA0g==} engines: {node: '>=10.13.0'} diff --git a/source/_posts/netease-eapi-music-recognize-reverse-1.md b/source/_posts/netease-eapi-music-recognize-reverse-1.md index f8a023a..c9bcb6d 100644 --- a/source/_posts/netease-eapi-music-recognize-reverse-1.md +++ b/source/_posts/netease-eapi-music-recognize-reverse-1.md @@ -1,103 +1,139 @@ --- -title: netease-eapi-music-recognize-reverse-1 -date: 2022-06-27 13:46:44 +title: 网易云音乐听歌识曲 API 逆向 (一) +date: 2022-05-05 tags: --- 首先是抓了一下协议, 网易云音乐的接口本身是有加密的, 但是没关系, 已经有 [NetEaseCloudMusic](https://github.com/Binaryify/NeteaseCloudMusicApi) 这样的项目逆向出了基本的通讯协议, 可以直接使用. + ![surge_mitm.png](https://s2.loli.net/2022/05/05/3BGhneWfKdCQzFm.png) + + + 网易云音乐识曲会向 `https://music.163.com/eapi/music/audio/match?_nmclfl=1` 这个接口发送请求 + 解密后的请求体大概长这样 ```json -{ - "rawdata":"eJx11H9M1HUYB\/C7+2p5\/PhHTUQGwW......", - "from":"recognize-song", - "verifyId":1, - "deviceId":"??????", - "os":"iOS", - "header":{ - - }, - "algorithmCode":"shazam_v2", - "times":1, - "sessionId":"??????", - "duration":3.4, - "e_r":true, - "sceneParams":"{\"action\":0,\"code\":2}" -} +{ + "rawdata":"eJx11H9M1HUYB/C7+2p5/PhHTUQGwW......", + "from":"recognize-song", + "verifyId":1, + "deviceId":"??????", + "os":"iOS", + "header":{ + + }, + "algorithmCode":"shazam_v2", + "times":1, + "sessionId":"??????", + "duration":3.4, + "e_r":true, + "sceneParams":"{"action":0,"code":2}" +} ``` - ![response_decrypted.png](https://s2.loli.net/2022/05/05/23zLWdGwqIacXoy.png) -猜测其中 `rawdata` 就是录音的 Base64 编码, 尝试解码扔进 ffprobe, 但是失败了 + +猜测其中 `rawdata` 就是录音的 Base64 编码, 尝试解码扔进 ffprobe, 但是失败了 有可能 `rawdata` 是根据音频频谱生成了摘要, `algorithmCode` 字段也提示了 `shazam_v2` 这个值 + 接下来开始逆向 APP + 下载了一份比较旧但还能用的 网易云音乐 APK -[old_version_apk.png](https://s2.loli.net/2022/05/05/uliO4SfnUpyIN1L.png) + +![old_version_apk.png](https://s2.loli.net/2022/05/05/uliO4SfnUpyIN1L.png) + 扔进 Jadx, 发现有比较奇特的混淆方法, 任意地方的字符串都会调用一个函数来进行解密 -[Obfuscation.jpg](https://s2.loli.net/2022/05/05/wrAiL2uzyHUsPD7.jpg) + +![Obfuscation.jpg](https://s2.loli.net/2022/05/05/wrAiL2uzyHUsPD7.jpg) + 定位到解密函数 -[decryptor.png](https://s2.loli.net/2022/05/05/d43Aw5fTby2h9ju.png) + +![decryptor.png](https://s2.loli.net/2022/05/05/d43Aw5fTby2h9ju.png) + 这里的解密看起来并不困难, `C0003a()` 这个类显然是 Base64 解码用的 -过我们要写出一个反向的操作(用来方便逆向查找字符串) +不过我们要写出一个反向的操作(用来方便逆向查找字符串) ```java -import java.util.Base64; - -class Main { - public static String key = "Encrypt"; - - public static void main(String[] args) { - if (args[0].equals("decrypt")) { - System.out.println(decrypt(args[1]));; - }else{ - System.out.println(encrypt(args[1])); - } - } - - public static String decrypt(String s) { - byte[] decode = Base64.getDecoder().decode(s); - String str2; - int length = decode.length; - int length2 = key.length(); - int i = 0; - int i2 = 0; - while (true) { - int i3 = i2; - if (i >= length) { - break; - } - int i4 = i3; - if (i3 >= length2) { - i4 = 0; - } - decode[i] = (byte) (decode[i] ^ key.charAt(i4)); - i++; - i2 = i4 + 1; - } - str2 = new String(decode); - return str2; - } - - public static String encrypt(String str_enc) { - byte[] s = str_enc.getBytes(); - int length = str_enc.length(); - int length2 = key.length(); - int i = 0; - int i2 = 0; - while (true) { - int i3 = i2; - if (i >= length) { - break; - } - int i4 = i3; - if (i3 >= length2) { - i4 = 0; - } - s[i] = (byte) (s[i] ^ key.charAt(i4)); - i++; - i2 = i4 + 1; - } - return Base64.getEncoder().encodeToString(s); - } -} +import java.util.Base64; + +class Main { + public static String key = "Encrypt"; + + public static void main(String[] args) { + if (args[0].equals("decrypt")) { + System.out.println(decrypt(args[1]));; + }else{ + System.out.println(encrypt(args[1])); + } + } + + public static String decrypt(String s) { + byte[] decode = Base64.getDecoder().decode(s); + String str2; + int length = decode.length; + int length2 = key.length(); + int i = 0; + int i2 = 0; + while (true) { + int i3 = i2; + if (i >= length) { + break; + } + int i4 = i3; + if (i3 >= length2) { + i4 = 0; + } + decode[i] = (byte) (decode[i] ^ key.charAt(i4)); + i++; + i2 = i4 + 1; + } + str2 = new String(decode); + return str2; + } + + public static String encrypt(String str_enc) { + byte[] s = str_enc.getBytes(); + int length = str_enc.length(); + int length2 = key.length(); + int i = 0; + int i2 = 0; + while (true) { + int i3 = i2; + if (i >= length) { + break; + } + int i4 = i3; + if (i3 >= length2) { + i4 = 0; + } + s[i] = (byte) (s[i] ^ key.charAt(i4)); + i++; + i2 = i4 + 1; + } + return Base64.getEncoder().encodeToString(s); + } +} ``` +根据 `rawdata` 这个关键词在 Jadx 里查找 + +![script.png](https://s2.loli.net/2022/05/05/HftdwSoXDxGZ4rK.png) + +确实能找到这个字符串 + +![jadx-search.png](https://s2.loli.net/2022/05/05/21eOoprbA8XMcwf.png) + +继续跟踪函数调用栈, 最终跟踪到了 `MusicDetector` 类 + +![classMusicDetector.png](https://s2.loli.net/2022/05/05/O2LAXsbWQKMmqfD.png) + +看起来是 `getFP()` 这个 Native 函数返回了一个三维数组, 最终封装成了 `rawdata` + +![native-getFP.png](https://s2.loli.net/2022/05/05/GaiMZqrzTgAUwCn.png) + +![binary-reverse.jpg](https://s2.loli.net/2022/05/05/X27B6ZKoY38PAtd.jpg) + +暂时跟踪不下去了, 看见汇编就头大( + +敬请期待第二章(咕咕咕 + +![image.png](https://s2.loli.net/2022/05/05/btmIr6v8R9L2onp.png) \ No newline at end of file diff --git a/source/_posts/netease-eapi-music-recognize-reverse-2.md b/source/_posts/netease-eapi-music-recognize-reverse-2.md index e089087..264eb0d 100644 --- a/source/_posts/netease-eapi-music-recognize-reverse-2.md +++ b/source/_posts/netease-eapi-music-recognize-reverse-2.md @@ -1,5 +1,48 @@ --- -title: netease-eapi-music-recognize-reverse-2 +title: 网易云音乐听歌识曲 API 逆向 (二) date: 2022-05-12 00:33:26 tags: --- + + +前两天看到网易云音乐发布了一个网页上做音乐识别的 [Chrome 插件](https://juejin.cn/post/7094083239702659109) + +![netease-chrome-recognize](https://s2.loli.net/2022/05/12/sdvE3LHGx19owOY.png) + + + +于是立即下载了一份来研究 + +![source](https://s2.loli.net/2022/05/12/XwcgmIPYsuLpCBf.png) + +Chrome 插件的请求方式和结构和客户端几乎一模一样 + +![request-struct](https://s2.loli.net/2022/05/12/feCIWNdhlBVJXML.jpg) + +根据函数栈追踪, 可以分析出比较核心的逻辑都在 `sandbox.bundle.js` 内 + +看起来是用了 WebAssemble 来解析网页录音, 在点击开始录音后会开始录制当前 TAB 的音频 + +当录音完成后就会将音频传到 WASM 暴露的函数 `l().ExtractQueryFP(...)` 中 + +![parse-buffer](https://s2.loli.net/2022/05/12/Ljm8hg5Kztv9VHW.jpg) + +WASM 层处理完成后就会将返回的 ArrayBuffer 封装成一个 Base64 串, 最后会将这个 Base64 串提交给 API + +![request-code](https://s2.loli.net/2022/05/12/TEWq917khpOKZPd.jpg) + +* * * + +虽然还是不太清楚 WASM 层内部是如何处理传入的音频数据, 但是已经可以将它的代码抽出来作为一个类库了 + +基于插件代码制作了一份 DEMO, 可以参考 [NeteaseCloudMusic-Audio-Recognize](https://github.com/akinazuki/NeteaseCloudMusic-Audio-Recognize) + +`rec.json` 内是封装成 JSON 的录音 ArrayBuffer + +运行后会在 Chrome Console 打印出音频指纹的 Base64 串 + +[本页面已更新](/netease-eapi-music-recognize-reverse-3/) + +![console](https://s2.loli.net/2022/05/12/ZuSIAYHMtlxgpsk.png) + +![postman-test](https://s2.loli.net/2022/05/12/UmwNMRthrfbzQiJ.jpg) \ No newline at end of file diff --git a/source/_posts/netease-eapi-music-recognize-reverse-3.md b/source/_posts/netease-eapi-music-recognize-reverse-3.md index 91a82c8..0e1e7fe 100644 --- a/source/_posts/netease-eapi-music-recognize-reverse-3.md +++ b/source/_posts/netease-eapi-music-recognize-reverse-3.md @@ -1,5 +1,24 @@ --- -title: netease-eapi-music-recognize-reverse-3 +title: 网易云音乐听歌识曲 API 逆向 (三) date: 2022-06-27 20:46:28 tags: --- + +闲来无事填一下坑 + +根据 [这个 issue 的讨论](https://github.com/akinazuki/NeteaseCloudMusic-Audio-Recognize/issues/1) + +现在已经将 [NeteaseCloudMusic-Audio-Recognize](https://github.com/akinazuki/NeteaseCloudMusic-Audio-Recognize) 这个项目移植到了 Node.js上 + + + +![recognize-and-send-request.png](https://s2.loli.net/2022/06/27/VB1NUkxeAsqn3RD.png) + +顺便吐槽一下 NPM 上的 `web-audio-api` 项目 +NPM 版的 `web-audio-api` 已经 7 年没更新了, 直接 `npm install web-audio-api` 安装的包完全不能用 +连 `AudioContext.decodeAudioData()` 方法都没有, 一开始还以为是自己的调用方式有问题 +但是它的示例代码里也是这样写的 +结果一翻 GitHub 上的代码, 发现 GitHub 上安装的版本和 NPM 上的版本完全不一样 +GitHub 上的版本是一直在更新的, 估计有在 Node.js 里解析 `AudioBuffer` 的不少人都会踩这个坑 + +~~本项目由 Copilot 强力驱动~~ \ No newline at end of file diff --git a/source/about/index.md b/source/about/index.md new file mode 100644 index 0000000..36dac0b --- /dev/null +++ b/source/about/index.md @@ -0,0 +1,24 @@ +--- +title: 关于 +date: 2022-08-16 +tags: +--- + +Bug Producer / ~~猫娘~~ +{% raw %} +
+

「我啊,希望自己能做一个真正的的女孩子。」

+

「能够成为真正的女孩子的话,就算要付出自己的生命也没问题的吧。」

+
+{% endraw %} + +### 公钥 +```bash +curl https://server.pub >> ~/.ssh/authorized_keys +``` + +OR + +``` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmStKmnnCJIIp2e5IQ43GuBHQrPwjLW7c6fXblGVVD5T/HO16zLYzrkKs5sqw1vd8u4UkKg6B6LyOSJOvjb+Qgit45Vgse9zfTJd+w/8lv0M0qhX+6NQidZxhyXYpS2sd/pANC5R1fRHKK57A6tpfCAnilFLClZDv8zhJPbQyOpoEsKn8obHvvlYkTHAohERPoEbeFtCpnP64ZG543OWQK1fmCyWu+gsc9UuY2kJLTU3Z9H0EdG/rQFTCgBMRNAf/mIvIF4sF6ine3h8xVe5jLHXqidFpxVX8K0KJqQQrAFKoVlH04YZyx+uCnrHSl3QHMy9FLWnAvpivJLZqgMaU5 nazuki@AkiNazuki-MBP +``` \ No newline at end of file diff --git a/source/labs/index.md b/source/labs/index.md new file mode 100644 index 0000000..0e55612 --- /dev/null +++ b/source/labs/index.md @@ -0,0 +1,8 @@ +--- +title: 实验室 +date: 2022-08-16 +tags: +--- + + +正在施工中... \ No newline at end of file diff --git a/source/links/index.md b/source/links/index.md new file mode 100644 index 0000000..f060c7c --- /dev/null +++ b/source/links/index.md @@ -0,0 +1,23 @@ +--- +title: Links +date: 2022-08-16 +tags: +--- + +[Ayaka Neko](https://neko.ayaka.moe/) +[Makito’s Notebook](https://mak1t0.cc/) +[贫困的蚊子](https://qwq.moe/) +[Nekoyue’s Blog](https://yue.moe/) +[Yukari’s Blog](https://0w0.live/) +[谦谦的博客](https://xqq.im/) +[Sukka’s Blog](https://skk.moe/) +[DIYgod](https://diygod.me/) +[小新喵~](https://xin.moe/) +[KK 的博客](https://ikk.me/) +[小竹’s blog](https://blog.justforlxz.com/) +[403 Forbidden](https://233.imjs.work/) +[Sayaka’s Blog](https://baka.studio/) +[QiroNT/blog](https://ntz.im/) +[芝士部落格](https://chee5e.space/) +[LinEvil’s Blog](https://linevil.net/) +[Canarypwn’s Blog](https://aaaab3n.moe/) \ No newline at end of file