DEF CON 33 - Breakin 'Em All – Overcoming Pokemon Go's Anti Cheat Mechanism - Tal Skverer
三句話摘要
破解Pokémon GO通信協議與加密簽名,從零開發非官方API的67小時黑客馬拉松之旅。 多層次逆向工程技術(動態與靜態分析、主動與被székPassive探測、社群協作)結合對加密與通信協議的深入理解,能在短時間內突破商業應用的防禦機制,創造出惠及社區的工具。 第一,講者透過HTTP代理嗅探流量,識別協議使用Google protobuff序列化格式,RequestContainer包含請求清單,其中類型106的GetMapObjects請求接受S2網格ID作輸入,返回該格子內寶可夢的確切位置——這成為掃描器的核心機制。
重點整理
重點- 1
第一,講者透過HTTP代理嗅探流量,識別協議使用Google protobuff序列化格式,RequestContainer包含請求清單,其中類型106的GetMapObjects請求接受S2網格ID作輸入,返回該格子內寶可夢的確切位置——這成為掃描器的核心機制。
- 2
第二,當Niantic啟用證書固定防禦時,講者團隊使用Frida框架鉤取Niantic Trust Manager的checkServerTrusted函數,在執行前將待驗證的代理證書替換為真實伺服器證書,使應用仍信任HTTP代理而繞過了該防禦。
- 3
第三,新版本新增必填欄位Unknown 6(加密簽名),講者透過被動分析發現其結構為32字節時間種子+256倍數加密資料,使用IDA追蹤時間函數交叉引用找到簽名生成函數,發現採用CBC模式加密,並用14,000行反編譯C代碼復製了加密邏輯。
- 4
第四,簽名由6個必填欄位組成,字段10與20是位置的xxhash32雜湊(字段10另含認證資訊),字段22與24使用xxhash64對請求位元組進行雜湊,最後一個欄位無須特定輸入可任意值——講者團隊透過逐步刪除欄位進行主動探測而發現這些規則。
實用技巧與重點
乾貨- 工具
- HTTP代理:Fiddler Classic
- 反編譯:Jadex(Java)、IDA Pro(本地代碼)、Ghidra
- 動態逆向工程:Frida(JavaScript鉤取)、Xposed
- S2 Geometry庫:座標↔S2 cell ID轉換(15級網格)
- 協議核心
- RequestContainer欄位:請求ID、位置、認證資訊、重複請求清單
- GetMapObjects(類型106):輸入S2 cell ID → 輸出寶可夢座標
- S2 cell 64位標識符由GPS座標計算得出
- 加密簽名結構(Unknown 6)
- 總長度:256N + 32位元組(N為加密分塊數)
- 前32字節:時間戳種子(srand輸入)
- 中間256N字節:CBC加密資料(每塊前一塊密文作IV)
- 後32字節:填充餘數指示
- 必填簽名欄位
- 欄位10:xxhash32(認證資訊) + xxhash32(位置)
- 欄位20:xxhash32(位置)
- 欄位22:未知函數輸出(可任意值)
- 欄位24:清單,每個請求對應一個xxhash64(請求位元組)
- 時間線
- 凌晨1點:發現證書固定
- 第1天白天:Protobuff逆向、動態替換證書
- 第2天上午:被動分析Unknown 6結構、發現時間相關性
- 第2天下午:Discord社群爆發(最終10,000成員),分隊破解加密與簽名
- 第2天晚上~第3天:識別xxhash、必填欄位結構
- 第3天晚7點(67小時):成功發送第一個API請求
- 社群與結果
- 黑客社區:Pogdev(Reddit/Discord協作)
- 非官方API維護期:約1.5年
- 應用場景:讓地處寶可夢稀缺區域的玩家能遠端查詢
結論
結論“多層次逆向工程技術(動態與靜態分析、主動與被székPassive探測、社群協作)結合對加密與通信協議的深入理解,能在短時間內突破商業應用的防禦機制,創造出惠及社區的工具。”
完整解析
詳細2016年Pokémon GO發布,住在鄉村的講者Taur四周幾乎沒有寶可夢,只能跑到遠處才能玩。為了改善體驗,他決定開發一款寶可夢掃描器。開發之初,他使用Fiddler Classic攔截應用與伺服器的通信,發現雖然Content-Type宣稱是form-url-encoded,但實際為二進制protobuff序列化資料。透過protoc的decode_raw功能與多層分析技巧——觀察已知值(如OpenID令牌)推斷欄位類型、將十六進制轉換為浮點數發現座標、對比不同操作下的消息變化——他成功逆向出RequestContainer結構及其內部的重複請求欄位。關鍵發現是類型106的GetMapObjects請求能根據S2網格ID返回該區域內的全部寶可夢座標。
當Niantic發布新版本時,掃描器立刻失效。講者加入Pogdev社區的Discord頻道後,全球黑客開始了一場67小時的馬拉松破解。主要防禦是證書固定機制,講者使用Frida框架鉤取Niantic Trust Manager的checkServerTrusted方法,在執行前替換待驗證的代理證書為真實伺服器證書,巧妙繞過了防禦而無需修改應用邏輯。隨後團隊發現RequestContainer新增了一個必填的Unknown 6欄位——加密簽名。
透過被動分析多個簽名樣本,講者們注意到Unknown 6的大小總是256的倍數加32字節,且每個樣本的前32字節只在設備時鐘設置相同秒數時才相同。這強烈暗示了時間戳與加密的關係。使用IDA Pro分析libniantic_manager本地庫,講者追蹤時間函數的交叉引用,定位到生成簽名的函數。該函數先用時間戳調用srand生成32字節隨機種子,隨後使用CBC模式加密將輸入分塊加密。一個分隊利用IDA反編譯該函數並用14,000行C代碼重新實現了整個加密流程。
同時,另一個分隊專注簽名結構分析,透過主動探測逐步刪除簽名欄位並觀察伺服器錯誤反應,發現原本預期的眾多欄位中只有6個是必填的。他們識別出欄位10與20使用xxhash32(一種快速雜湊算法)對位置進行雜湊,字段10另結合認證資訊,字段22與24則使用xxhash64對每個請求的位元組進行雜湊。最後一個必填欄位最為神秘——它不依賴任何輸入,可以是任意值。在第三天晚上7點,經過近三日夜的協作與多維度技術運用,他們終於成功發送了第一個完整的非官方API請求,隨後PogoDev社區基於此維護了約1.5年的非官方API。
關鍵時刻
Pipeline v2帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。
事實查核
Pipeline v2說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

