從關停公告到 24,342 筆資料:AI 時代的逆向工程實錄
2026 年 4 月 2 日,M 平台宣布永久關停。
DNS 指向
0.0.0.0,網站變成一封告別信,看似一切都結束了。但我不信。昨天才關站,不可能那麼徹底。沒有不透風的牆。
接下來的 5 個小時裡,我和 Claude Code 從存檔站、企業官網、新站 API、關聯 CloudFront 網域四條線索層層深入,破解 HMAC-SHA1 簽名和 AES-256-CBC 加密,最終從零恢復出 24,342 筆完整影片資料。
這個過程讓我深刻體會到一件事:在 AI 時代,技術能力固然重要,但真正決定成敗的,是思維的靈活性。
這篇文章記錄的不僅是一次技術逆向,更是一次人機協作的思維實驗。
整個過程中,Claude 負責了幾乎全部的技術執行——下載、分析 JS、破解簽名、解密資料、寫入資料庫。但每一次關鍵突破,都來自人的判斷和直覺:
AI 是你手中最鋒利的刀,但往哪裡切、切多深、什麼時候該換把刀——這些決策永遠是人做的。
傳統逆向工程需要精通組合語言、密碼學、協定分析,門檻極高。但在 AI 時代,這些技術細節可以交給 AI 處理。真正稀缺的能力變成了:
所以,如果你讀完這篇文章只記住一件事,我希望是這個:
AI 時代,思維和想法的靈活性至關重要。工具會越來越強,但駕馭工具的人,需要的是敏銳的嗅覺、不服輸的韌勁、以及「再試一下」的勇氣。
好了,進入正文。
以下是整個過程中的真實對話。你會看到一個有趣的模式:AI 反覆得出「到此為止」的結論,而人反覆用直覺和追問推翻這個結論。 四次「到頭了」,四次被打臉,每一次都打開了新世界的大門。
我: 我想快速復刻一個網頁 是存檔站 web.archive.org/web/2026020… 有啥好方案,我想到的是反向代理的方式
一開始的想法很樸素:站要關了,先把頁面存下來。Claude 比對了 wget、反向代理、wayback_machine_downloader、monolith 四種方案。
我: 你推薦哪個
我: 那你試一下
Claude 自動檢查 Ruby 環境、安裝 gem、執行下載。8 分半後,196 個檔案落地。
我: 幫我起來 我看看 端口搞個冷門的
本地服務跑起來,打開一看——滿屏 404,CSS/JS/SVG 全丟了。wayback_machine_downloader 只下載了 HTML,沒拉靜態資源。
我: 沒有 css 樣式 css svg 全是 404 的
Claude 從 HTML 裡 grep 出 54 個靜態資源路徑,批量補全。又發現 CSS 裡嵌著 Wayback 的 URL 前綴(/web/20260219094859im_/https://madou.com/...),修了 33 處。又補下載了 23 張圖片。來來回回折騰了三輪。
我: 完美
到這裡,本地鏡像算是完整了。但我不滿足於靜態頁面——
我: 他這個存檔的都是靜態的吧 但是實際是有介面的吧 你看看
這是第一次追問。 存檔站只有 HTML,但原站肯定有 API。資料在哪?
Claude 分析了 JS 檔案,發現原站是 SSR 直出,客戶端幾乎沒有 API 呼叫。影片播放用 DPlayer + HLS,但 m3u8 連結帶時效 token,早就失效了。
第一條路,走到頭了。
我: 因為這個是沒有 api 的 然後我在另一個站發現的 api 介面
<div><div><div></div><span>css</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>``` <span>curl 'https://mod.run/api/app/media/detail<span>' --data-raw '</span>{"mediaId":<span>1184759</span>}'</span>你看看能不能分析一下類似的介面 有沒有 list 之類的
這就是思維靈活性的第一個體現:原站沒有 API?那換個站找。 mod.run 是 M 平台的企業官網,也許有資料介面。
Claude 下載 Nuxt.js bundle,從 minified JS 中硬扒出 6 個 API 定義。逐個測試:navi/infoV2 回傳首頁資料,config 暴露了 CDN 位址 https://cdnimg.v21c.com/。但沒有 list 介面,只能透過 media/detail 按 ID 逐個查。
我: 你試試這個裡面的 id 是否一樣呢 /Users/haose/Movies/tdl/madou/channel.json
我手上還有一張牌——官方 TG 頻道的訊息紀錄。629 則訊息,296 個編號。但一比對,TG 頻道的編號 ID、madou.com 的存檔 ID、mod.run 的 mediaId,三套體系完全不相容。
我: mod.run 的資料不全,如果暴力掃描可以嗎 head 請求不是會快嗎 而且不用全量掃描吧 目前已知的 mediaId 在他們的上下多少範圍內去掃描呢 比如每個 mediaId 的上下 1000 個
既然沒有 list,那就暴力列舉。Claude 算出 4 個 ID 集群、13,124 個待掃描 ID。
先用我自研的 hs-net 函式庫開 30 並發——秒被 403。降到 5 並發加延遲——還是被封連線。最後老老實實用 Python urllib 單線程、每個請求間隔 0.5 秒,像螞蟻搬家一樣逐個驗證。
結果出來了:49 筆有效影片。 百萬級 ID 範圍裡只有 49 筆。mod.run 就是個企業展示站,放了幾十條精選片段而已。
我: 保存的檔案裡面 圖片的網域寫進去 cdnimg.v21c.com
我: 網域影片的網域是 mod.run/api/app/med…
資料雖少,但每一筆都得存完整。逐步補全欄位。
我: 你看看 madou.com/assets/inde… 我發現是有 madou.com 的 api 的 madou.com/api/stat/la… 觸發頁面是 madou.com/mobile/vide…
我:
<div><div><div></div><span>css</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>``` <span>curl 'https://madou.com/api/stat/landPageConfig/getByType<span>'</span></span> <span> --data-raw '{"appId":<span>888</span>,<span>"pageNum"</span>:<span>1</span>,<span>"pageSize"</span>:<span>10</span>,<span>"type"</span>:<span>2</span>}'</span>
這是人機協作的經典場景:AI 負責分析程式碼,人負責在瀏覽器裡觀察行為。 我在 Chrome DevTools 裡抓到了新站的 API 請求,連 appId=888 這個關鍵參數都直接給了。
回傳 68 筆影片。Claude 從 Wayback Machine 取得 JS chunk,確認整個新站只導出這一個 API 呼叫。
我: 你對比一下 兩個加起來去重後是多少個
mod.run 48 + madou.com 68 = 116 個編號,零重疊。兩個站的內容庫完全互補——mod.run 偏老片,madou.com 偏新片。但 TG 頻道有 212 個編號,API 只覆蓋了 38.7%。
還有 61.3% 的資料不知道在哪。
我: 你在翻翻新站的 js 看看是否有其他的介面
Claude 下載了所有 Vite chunk,確認只有一個 API。
Claude 的結論:「madou.com 新站就這一個資料介面,68 筆就是全部了。」
我: 真的沒辦法了嗎 我不信,沒有不透風的牆,昨天才關站不可能那麼徹底,肯定還是我們沒有找到的線索
這句話是整篇文章的轉折點。 也是我想傳達的核心理念的最好註腳——AI 給出的「結論」,往往只是當前視角下的最優解。換一個視角,整個局面可能完全不同。
AI 說到頭了。但我的直覺告訴我:一個營運了多年的平台,昨天才關站,不可能只留下 116 筆資料。資料一定還在某個地方,只是我們沒找到入口。
Claude 被這句話「激活」了,開始重新檢視所有線索:回到 mod.run 的 config 介面,提取出一串關聯網域——mdapp12.com、mdbba02.com、ge.dfg3t534.cc、admin.qsxon.com,以及多個 CloudFront 網域。
我: 你順著 madou.com/pc/video 往下找 不要找 madou.com/ 的
Claude 發現 madou.com DNS 已指向 0.0.0.0——站確實關了。但靈機一動,試了 --resolve madou.com:443:104.21.0.0 繞過 DNS,直接連到 Cloudflare 邊緣節點——居然還在回應!
更刺激的發現:掃描後端路由,30+ 個 API 介面全部存在,只是回傳 {"msg":"no token"}。這是一個完整的 Go CMS 系統——media、actor、category、tag、banner,應有盡有。資料就在裡面,只是鎖著。
我: 有註冊嗎
沒有。註冊介面也在 token middleware 後面。
我: 你試一下登入呢
我: 試一下 試一下
Claude 偵測到 admin/login 欄位是 account + password,還發現介面會告訴你「該帳號不存在」(使用者列舉漏洞)。但 admin、test、demo、madou 全部不存在。管理員用的是自訂帳號名。
這條路,又卡住了。
我: 應該會有公開的介面的啊
又一次追問。 這次 Claude 換了個方向——回到最初下載的 196 個存檔 HTML 頁面,grep 出所有外部網域。
在一堆廣告連結和 CDN 位址中間,藏著 7 個 CloudFront 網域。其中一個 de1j8jm5ajr3l.cloudfront.net——回傳了一個活著的站點。
標題叫 "B 站點"。
這不是 M 平台,但下載它的 JS bundle(487KB)後發現——160+ 個 API 介面,跟 mod.run 同一套後端系統! 而且包含了完整的簽名密鑰和加密設定:
<div><div><div></div><span>javascript</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span><span>const</span> <span>Vn</span> = {</span>
<span> <span>http_request_key</span>: <span>"jR6dO6fT1yD9zY7u"</span>, <span>// 就這樣明文寫在前端 JS 裡</span></span>
<span> <span>http_response_key</span>: <span>"vEukA&w15z4VAD3kAY#fkL#rBnU!WDhN"</span>,</span>
<span> <span>guest_skey</span>: <span>"wM5wK1jP3lK7pS2t"</span>,</span>
<span>};</span>
**一個存檔頁面裡的廣告網域,最終指向了 24,000 多筆資料。** 這就是為什麼說「存檔 HTML 是線索金礦」。
接下來是純技術活:破解 HMAC-SHA1 簽名讓請求通過驗證,破解 AES-256-CBC 把加密的回應解開。簽名演算法從 JS 裡直接抄,解密演算法最大的坑是 **JS 的 `Array.splice()` 會修改原陣列**——密鑰派生過程中 6 次 splice,必須精確追蹤每一步的陣列狀態。
遊客登入被禁了(「帳戶禁止登入」),但 Claude 逐個測試介面權限,發現 **`media/home` 不需要登入就能存取**:
<div><div><div></div><span>python</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>api_call(<span>"/api/app/media/home"</span>, {<span>"id"</span>: <span>1</span>}) <span># → 2707 筆!</span></span>
<span>api_call(<span>"/api/app/media/home"</span>, {<span>"id"</span>: <span>2</span>}) <span># → 12327 筆!! 原創影視!</span></span>
從 116 筆到 24,726 筆。翻了 213 倍。
我: 可以都要嗎 我全部要 保存的時候不混在一起就行,如果不好存的話 我本地有 redis 你可以存 不存 0 1 庫就行
我: docker 裡面的
6 個分類全量拉取,Redis db=2 存原始 JSON。
我: 這會你看看 M 平台的影片一共有多少個 或者你存資料庫也行 docker 裡面有個 tidb 127.0.0.1 4000 你新建個庫
TiDB 建庫建表,24,342 筆入庫。其中 M 平台編號 194 筆。
我: 還是寶貝厲害
指標 數值
人類傳送的訊息 ~30 條
關鍵轉折性指令 5 條
Claude 讀取的檔案 200+ 個
Claude 執行的命令 300+ 條
Claude 下載的 JS bundle 8 個
被限流/封鎖次數 3 次
說「到頭了」被打臉次數 4 次
1 "我在另一個站發現的 api 介面" + curl — 原站沒資料?換個入口打開 mod.run 資料源
2 appId=888 的 curl 命令 — 瀏覽器抓包,人機配合直接拿到新站 API
3 "我不信,沒有不透風的牆" — 拒絕接受「到頭了」——資料量翻 213 倍
4 "應該會有公開的介面的啊" — 不死心,繼續推找到 CloudFront 金礦
5 "我全部要...本地有 redis...docker 裡的 tidb" — 明確需求 + 提供基礎設施快速入庫
注意第 3 條:這不是一條技術指令,而是一種信念。 它沒有告訴 AI 該做什麼,但它改變了 AI 的搜尋方向。這就是人在 AI 協作中最核心的價值——判斷和決策。
指標 數值
對話總時長 約 4-5 小時
資料來源 5 個(Wayback Machine、mod.run、madou.com、CloudFront、TG 頻道)
破解的加密演算法 2 個(HMAC-SHA1 簽名、AES-256-CBC 回應加密)
發現的 API 介面 160+ 個
最終取得的影片資料 24,342 筆
提取的 M 平台編號 179 個
儲存 Redis + TiDB
<div><div><div></div><span>arduino</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>存檔站 HTML 頁面 : <span>196</span> 筆</span>
<span>mod.run API : <span>49</span> 筆 ← AI:<span>"這就是全部了"</span></span>
<span>madou.com 新站 API : <span>68</span> 筆 ← AI:<span>"確實只有這一個介面"</span></span>
<span>三源合計去重 : <span>116</span> 個編號 ← AI:<span>"公開能拿的到頭了"</span></span>
<span> ↓</span>
<span> <span>"我不信,沒有不透風的牆"</span></span>
<span> ↓</span>
<span>CloudFront 網域發現 :<span>24</span>,<span>342</span> 筆 ← !!!</span>
**每一次說「到頭了」,都被打臉。** 但說到底,不是 AI 錯了——在當時的信息下,它的判斷是合理的。是人的「不合理的堅持」打開了新的可能性。
---
### 第一階段:存檔站鏡像——先把屍體保存下來
站要關了,第一反應是保存。就像火災現場,先搶救能搶救的。
#### 方案選擇
方案 優點 缺點
wget mirror 簡單粗暴 Wayback URL 重寫混亂
反向代理 動態,不用下載 依賴 archive.org
wayback_machine_downloader 專為 Wayback 設計,自動還原 URL 需要 Ruby
一條命令搞定:
<div><div><div></div><span>bash</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>wayback_machine_downloader http://madou.com/ --from 20260209 --to 20260210 -d ./site</span>
下載的 196 個 HTML 頁面只是骨架。補全經歷了三輪:
wombat 運行時,Python 腳本批量清理/web/20260219094859im_/https://madou.com/static/... 正則替換為 /static/...本地可完整瀏覽的靜態站點。但沒有 API 資料——原站是 SSR 直出,客戶端幾乎沒有資料介面。影片 m3u8 連結帶時效 token,早已失效。
收穫:196 個 HTML 頁面。 當時覺得只是存個檔,沒想到後來正是這些 HTML 裡嵌入的一個廣告網域,最終指向了 24,000 多筆資料。
mod.run 是 M 平台的企業官網(Nuxt.js),下載其前端 bundle,從 minified JS 中提取到 API 路由定義:
<div><div><div></div><span>javascript</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span><span>var</span> lr = {</span>
<span> <span>SITEINFO</span>: <span>"/api/app/navi/infoV2"</span>,</span>
<span> <span>CONFIG</span>: <span>"/api/app/config"</span>,</span>
<span> <span>VIDEO_DETAIL</span>: <span>"/api/app/media/detail"</span>,</span>
<span> <span>// ... 一共 6 個</span></span>
<span>};</span>
關鍵發現:
- **圖片 CDN:** `https://cdnimg.v21c.com/`
- **影片串流:** `https://mod.run/api/app/media/m3u8/{path}`
- **沒有 list 介面** —— 只能按 ID 逐個查
#### 暴力列舉 ID
從 Nuxt SSR 的 `__NUXT__` 資料中提取已知 ID,發現分佈在 3 個集群(242640~242648, 666865~667142, 1184741~1184779)。
30 並發掃描→秒被 403。5 並發→還是封。最後單線程 0.5s 間隔逐個跑。
**結果:49 筆。** 百萬級 ID 範圍裡只有 49 筆。mod.run 就是個門面。
#### 三套 ID 體系的碰撞
來源 ID 體系 範例
TG 頻道編號(檔名) `MD-0332.mp4`
madou.com 存檔文章 ID(超長) `2006372122030268417`
mod.run 自增數字 `1184759`
**三套系統完全不相容。** 不同的團隊、不同的資料庫、不同的時代。
---
### 第三階段:madou.com 新站——DNS 已死,Cloudflare 猶存
#### 使用者抓包驅動
madou.com 不再是 SSR 站,變成了 Vue SPA。我在瀏覽器 Network 面板裡抓到了一個 POST 請求:
<div><div><div></div><span>bash</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>curl <span>'https://madou.com/api/stat/landPageConfig/getByType'</span> \</span>
<span> --data-raw <span>'{"appId":888,"pageNum":1,"pageSize":10,"type":2}'</span></span>
回傳 68 筆影片。人看瀏覽器,AI 分析程式碼,配合得剛好。
分析過程中發現 madou.com DNS 已指向 0.0.0.0。但 Cloudflare 邊緣節點還沒清理快取!
<div><div><div></div><span>bash</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span><span># DNS 已死</span></span>
<span>$ dig madou.com +short</span>
<span>0.0.0.0</span>
<span></span>
<span><span># 但直連 Cloudflare 還活著</span></span>
<span>$ curl --resolve <span>"madou.com:443:104.21.0.0"</span> <span>'https://madou.com/api/stat/...'</span></span>
<span><span># → {"code":200, "data":[...]}</span></span>
**經驗:DNS 死亡 ≠ 服務死亡。** CDN 邊緣節點的快取清理有延遲,這個時間窗口就是機會。
#### 完整 CMS 後端的發現
用 `--resolve` 繞過 DNS 後,掃描後端路由:
<div><div><div></div><span>bash</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>/api/stat/media/list → {<span>"msg"</span>:<span>"no token"</span>}</span>
<span>/api/stat/media/detail → {<span>"msg"</span>:<span>"no token"</span>}</span>
<span>/api/stat/actor/list → {<span>"msg"</span>:<span>"no token"</span>}</span>
<span>/api/stat/admin/login → {<span>"code"</span>:10000, <span>"msg"</span>:<span>"Param error"</span>} ← 公開!</span>
30+ 個介面全部存在,只是鎖在 token 後面。 這是一個完整的 Go CMS——後端根本沒關,只是前端 DNS 斷了。
但沒有 token 就是沒有 token。admin/login 試了常見帳號全部不存在。
此時的總分:116 個編號。 Claude 說到頭了。
「我不信,沒有不透風的牆,昨天才關站不可能那麼徹底,肯定還有我們沒找到的線索。」
Claude 被這句話推動,重新檢視所有已有材料。回到最初下載的 196 個 HTML 頁面,提取所有外部網域。
在廣告連結、CDN 位址、統計腳本中間,找到了 7 個 CloudFront 網域。逐個探測,de1j8jm5ajr3l.cloudfront.net 回傳了一个還在運作的站——標題叫 "B 站點"。
一個存檔頁面裡的廣告位網域,指向了一個活躍的影片站。 這個站跟 M 平台用同一套技術體系。
下載其 index-BY9lizwW.js(487KB),提取到完整的 API 列表和加密設定:
<div><div><div></div><span>javascript</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span><span>// 簽名密鑰、解密密鑰、遊客登入密鑰——全部明文寫在前端 JS 裡</span></span>
<span><span>const</span> <span>Vn</span> = {</span>
<span> <span>http_request_key</span>: <span>"jR6dO6fT1yD9zY7u"</span>,</span>
<span> <span>http_response_key</span>: <span>"vEukA&w15z4VAD3kAY#fkL#rBnU!WDhN"</span>,</span>
<span> <span>guest_skey</span>: <span>"wM5wK1jP3lK7pS2t"</span>,</span>
<span>};</span>
#### 破解簽名演算法
直接呼叫回傳「非法請求」。從 JS 提取簽名函式 `N2()`:
<div><div><div></div><span>python</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span><span># HMAC-SHA1 簽名</span></span>
<span>msg = <span>f"<span>{token}</span>&<span>{api_path}</span>&<span>{x_user_agent}</span>&<span>{timestamp}</span>&<span>{nonce}</span>"</span></span>
<span>sign = hmac.new(<span>"jR6dO6fT1yD9zY7u"</span>.encode(), msg.encode(), hashlib.sha1).hexdigest()</span>
<span>header = <span>f"timestamp=<span>{ts}</span>;sign=<span>{sign}</span>;nonce=<span>{nonce}</span>"</span></span>
簽名通過了,但回應是加密的:{"data":"vA32vSvstudnfQfwmTn0U+...","hash":true}
從 JS 提取解密函式 ib(),核心是 3 輪 SHA-256 雜湊從 response_key + 12 位元 salt 派生 AES key 和 IV。
最大的坑:JS 的 Array.splice() 會修改原陣列。 密鑰派生過程中有 6 次 splice 操作,每次都改變了陣列的內容和長度。必須像 debugger 一樣逐步追蹤每個變數的狀態。
第一次解密成功時回傳的內容是:"DevID can not be null!" —— 雖然是個錯誤訊息,但解密本身是對的! 那一刻的成就感難以描述。
遊客登入回傳 code=6004, "帳戶禁止登入"。看似又要卡住了。
但 Claude 逐個測試 160+ 個介面的權限,發現好幾個不需要 token:
<div><div><div></div><span>python</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>/api/app/search/hot/words → <span>200</span> ✅</span>
<span>/api/app/publish/contents → <span>200</span> ✅ 有影片資料!</span>
<span>/api/app/media/home → 需要 <span>id</span> 參數...</span>
<span></span>
<span><span># 試試 id=1</span></span>
<span>api_call(<span>"/api/app/media/home"</span>, {<span>"id"</span>: <span>1</span>})</span>
<span><span># → code=200, mediaList: 2707 items!</span></span>
<span></span>
<span><span># id=2?!</span></span>
<span>api_call(<span>"/api/app/media/home"</span>, {<span>"id"</span>: <span>2</span>})</span>
<span><span># → code=200, mediaList: 12327 items!!! 原創影視!!</span></span>
**24,726 筆。不需要登入。簽名對了就行。**
#### 全量入庫
分類 影片數
用戶原創 2,707 **原創影視**
12,327 **海外影視**
5,501 社交實錄
3,199 吃瓜社會
821 動漫 171
**合計** **24,726**。Redis db=2 存原始 JSON,TiDB `madou` 庫存結構化資料。最終入庫 **24,342 筆**(去重後)。
---
### 技術總結
#### 完整的攻擊鏈
<div><div><div></div><span>scss</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>Wayback Machine 存檔</span>
<span> ↓ wayback_machine_downloader</span>
<span>存檔站 <span>HTML</span> (<span>196</span> 頁)</span>
<span> ↓ grep 提取外部網域 ← 關鍵線索就藏在這裡</span>
<span>發現 mod<span>.run</span>、CloudFront、CDN 網域</span>
<span> ↓ Nuxt<span>.js</span> bundle 分析</span>
<span>mod<span>.run</span> API (<span>6</span> 個介面, <span>49</span> 筆)</span>
<span> ↓ 使用者瀏覽器抓包</span>
<span>madou<span>.com</span> 新站 API (<span>1</span> 個介面, <span>68</span> 筆)</span>
<span> ↓ <span>--resolve</span> 繞過 DNS 死亡</span>
<span>發現 <span>30</span>+ 隱藏介面(需 token)</span>
<span> ↓ 存檔 <span>HTML</span> 中的 CloudFront 網域</span>
<span>de1j8jm5ajr3l<span>.cloudfront</span><span>.net</span> ("B 站點")</span>
<span> ↓ JS bundle (<span>487</span>KB) → <span>160</span>+ API + 加密設定</span>
<span>破解 HMAC-SHA1 簽名</span>
<span> ↓ 簽名通過</span>
<span>破解 AES-<span>256</span>-CBC 回應加密</span>
<span> ↓ 解密成功</span>
<span>發現 media/home 不需要登入</span>
<span> ↓ id=<span>1</span>~<span>9</span> 逐個拉取</span>
<span><span>24</span>,<span>342</span> 筆影片資料 → Redis + TiDB</span>
<div><div><div></div><span>scss</span></div><div><div> <span>體驗AI代碼助手</span></div><div> <span>代碼解讀</span></div><div>複製代碼</div></div></div>```
<span>請求簽名 (x-api-key):</span>
<span> <span>HMAC-SHA1</span>(</span>
<span> key = <span>"jR6dO6fT1yD9zY7u"</span>,</span>
<span> msg = <span>"{token}&{apiPath}&{X-User-Agent}&{timestamp}&{nonce}"</span></span>
<span> )</span>
<span></span>
<span>回應解密:</span>
<span> <span>Base64</span>(data) → <span>salt</span>(<span>12</span>B) + ciphertext</span>
<span> → <span>3</span> 輪 SHA-<span>256</span> 派生 AES <span>key</span>(<span>32</span>B) + <span>IV</span>(<span>16</span>B)</span>
<span> → AES-<span>256</span>-CBC 解密 → PKCS7 unpad → JSON</span>
#### 工具清單
工具 用途
wayback_machine_downloader Wayback Machine 整站鏡像
curl + `--resolve` 繞過 DNS 死亡直連 Cloudflare
Python (Cryptodome) AES-256-CBC 解密
Python (hmac) HMAC-SHA1 簽名
Chrome DevTools 抓包發現 API
Redis 中間資料存儲
TiDB 結構化資料入庫
hs-net (自研) HTTP 並發掃描(被限流了)
hssp (自研) 爬蟲框架,提供 Cryptodome 環境
---
### 最終成果與感悟
#### 成果
成果 數量
存檔站靜態頁面 196 頁 + 全部靜態資源
mod.run 影片資料 49 筆
madou.com 新站資料 68 筆
CloudFront 完整內容庫 **24,342 筆**
M 平台編號影片 194 筆 / 179 個編號
TG 頻道編號 212 個
破解的加密演算法 HMAC-SHA1 + AES-256-CBC
發現的 API 介面 160+ 個
#### 回頭看這個過程
整個過程中有 4 次 AI 認為「到頭了」的時刻:
1. **「存檔站沒有 API 資料」** → 換到 mod.run
2. **「mod.run 只有 49 筆」** → 找到 madou.com 新站
3. **「新站只有一個介面,68 筆」** → 繞過 DNS 發現完整後端
4. **「後端需要 token,進不去」** → 從存檔 HTML 找到 CloudFront 網域
每一次突破,都不是靠更強的技術力量,而是靠**換一個角度重新審視問題**:
- 這個站沒資料?→ 有沒有別的站?
- 這個 API 到頭了?→ 有沒有別的 API?
- DNS 掛了?→ CDN 掛了嗎?
- 登入被禁?→ 有沒有不需要登入的介面?
- 正面進不去?→ 旁邊有沒有門?
**這就是我說的「思維靈活性」。** 工具可以學,演算法可以查,但面對「看似無路可走」時選擇「再試一個方向」的思維模式——這是 AI 暫時還不具備的。
AI 時代,每個人手裡都有一把足夠鋒利的刀。**區別在於,你是對著一堵牆反覆砍,還是退後一步,發現旁邊有扇沒關嚴的窗。**
#### 經驗清單
1. **永遠不要說「到頭了」。** 每次以為資料拉完了,換個角度都能找到新入口
2. **DNS 死亡 ≠ 服務死亡。** Cloudflare/CloudFront 邊緣節點可能仍在回應
3. **存檔 HTML 是線索金礦。** 外部網域、CDN 位址、廣告連結都可能指向活躍服務
4. **JS Bundle 是 API 說明書。** 介面列表、簽名演算法、加密密鑰全在裡面
5. **關聯站點共享後端。** 看似不同的站,可能用同一套系統
6. **人機協作的最佳姿勢:** 人負責判斷和方向,AI 負責執行和分析
7. **「再試一下」三個字,價值 24,342 筆資料**
---
*本文記錄於 2026-04-03,madou.com 於前一日(4 月 2 日)宣布永久關停,本文為關停次日的資料搶救全過程。**使用工具:Claude Code (Claude Opus 4.6) + wayback_machine_downloader + curl + Python + Redis + TiDB**整個過程中,人類提供方向和判斷,AI 提供技術執行力。這就是 AI 時代的逆向工程。*
---
原文出處:https://juejin.cn/post/7624127580921626659