語言:js、python
工具:pycharm、chrome瀏覽器F12調試、chatgpt(補充js第三方庫,轉python)、node.js(js運行)(必須)
目標:學習掌握基本js逆向知識。
對象: 有道翻譯?;原因:1、平臺加密相對而言,比較簡單。2、但是相較于一般平臺,已加入了混淆;適合入門進階
讀了此文,你可以得到??能夠了解逆向的整體流程和手段。具有一定指導性意義; chatgpt在逆向中的應用。
基本邏輯:
????????通過xhr debug、棧debugger、事件定位等多種調試手段,在js文件中找到完整的核心js函數、變量。摳出來,通過chatgpt補全第三方的引用,最后通過chatgpt轉為python。
筆者說
? ? ? ? 本文使用有道翻譯作為逆向對象。請不要對它做出任何學習之外的惡意破壞。保護好這個逆向入門網站。
逆向
????????逆向實際上就是破解平臺的一些防騷擾的算法機制。能夠有效的排除掉爬蟲或者惡意程序的干擾。其本質就是通過對一些參數加上一些算法計算,再對代碼進行混淆,建立起一種技術壁壘,來防止惡意程序實現自動化騷擾。
? ? ? ? 但是,web端、app端、小程序端,在進行加解密時,實際上都已經把加解密的代碼開放了出去。只是通過代碼混淆壓縮來建立了一層壁壘。
平臺分析
每輸入一個詞,都會發起3個請求,逐個看每個請求的功能。
第一個請求:https://dict.youdao.com/webtranslate/key
? ? ? ? 接口入參中,有很多參數,大部分都是固定的。有一個sign(簽名算法一般都使用這個名字)是每次都會變。每次調用都改變一般就和時間戳有關系。所以在入參中還有一個mysticTime,時間戳。
?????????接口返回如下:含有secretkey,aeskey和aesIv。其中aes加解密相關的key和Iv對應的就是aes加密解密(對稱式)需要的key和偏移量。
? ? ? ? 而且,連續幾次請求用的都是同一個key和iv。這個和翻譯之后的數據解密有關。
? ? ? ? (如果不了解aes加密,即使看到了這兩個參數,實際上也是會一臉懵的)
?
{"data": {"secretKey": "fsdsogkndfokasodnaso","aesKey": "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl","aesIv": "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4"},"code": 0,"msg": "OK"
}
第二個請求:https://dict.youdao.com/webtranslate
????????這個是實現翻譯的核心接口。簡單先看一下入參和返回
? ? ? ? 入參也是有一大串的。但是變化的就是sign和時間戳。其它都是固定的。
?
????????返回的是 一大串加密后的字符串,要解析就需要使用上面第一個接口返回的aeskey和iv
? ? ? ? 有道的兩層防守手段,第一層是sign簽字。但是這一層的代碼應該有兩年都沒有變化過了。
? ? ? ? 高明的是這個第二層的,將結果進行加密,可以有效的防止通過返回來分析規則。
Z21kD9ZK1ke6ugku2ccWu4n6eLnvoDT0YgGi0y3g-v0B9sYqg8L9D6UERNozYOHqf2QTmhAp9WGaulUyTQ4s3ranWlk7VID05DYO_x8OdLrxURRu0VER-u407MPgt1GF9jL87ya3ywgMjI4dogesKMFrUn8JkXGvgwGAWE7qMheCHpc-IP6wyUkLABQ4qGhPKC-WPVfy4cfiIJm3g7hJu_7FlPywY8hRHD6QPkawOYIgBcFEQjNI97SNhcnOAIrNmTVM-q_OzgrzXxzs8R99HMEISgzcFMllP91KfYX6shvvGFYYmwmjHElaKhdiqr-yLfZPIsUJ0ku8ocrARJh1UrbwC81Kz8EFdecwtUhKWrsi5NR3iH50GWiZxbntDq55jSU2zKFIPwmBjsrdeuQ3XmW-z6P6LqZrHuvNhqFIxtejFwZHJip836njYi9yhnfgkr57e4xC3NNgFB62M1cy8id-IZtqrHbIkverpN9i4_l6oL7aDciL3P_GcyQvm3j7DpaQ0w-DcEOCj69q0U6wksxTe3YcKXz4HYXECs4ej7UwMbyB6WpT_Qqg3yVev7ksXAmxtUqQxg-Tg65_uGOEvCqo8nEirTjTKyHFDthxi4zAPK88ke1qp4RoM6qLsmcMiMSZTPM-PzmtcWCk0sbMn6V7t-qbqU_-c4IzvSIaok-OGsIqtAHC7LZEODcQQsc8WcirWpWE5mvqHwGsGzRI-9 v5QBe4PNOnLcNda_Lb50YyPcSvOBDGvxd2V1VHuB7Jf-i6xLcelejuQXtwt1Uc9yUW8z4oLJWw_iBV7cJ89tstcPxP1B9MtMiHHl7DT9TOzx7-5 NMzJQKLSk8imT6SJ4oWHvSIa39EoOcfjU-ABZZPLbe3VP8aUnCrSdGMRfC3peaOIAa1xXLfz8OzOA3FzUYTBzN0FnAwow4EAEvqwW38tztPqzO9jVIQrDYlG91DAA7a8b-EpAd7Ynq8D_ui3uBY-AjtYkT_25JVuCHurjsIGAyvJGmhfkhDJr6uZNe01u5MqJUK8MFJed26byYHQHm-ZnmnssqdnOa1jRiIpJCkfYClX9uMqztqkmpVmxH6bdWbmpdVW1LMW3UFL1T01_qqzZFWDV03ORaqogkOnsKWH1vp3xEX7jR7x3bmNM8FoM6ZKzrTZ2dxx5cR-F2Ehu2genVUZGg11rX4apk-UQ77tIUrFGXz4_ZZSZ-AYUWIzxSCmMGCUIupG572i_Idp4pGmUmPlUfMIgnhHAK_z1689vdki_ldjrd_qnbjPbSNAJK68YM5yc31P45ltQ72cYCLgVHlxjicMsQCS6XK3x8NKGyQEvHNiDe_5Eknz4_4YOdofL-KYVhQck84lSnCGp3QaAwO-5 DFnpyZj1UpQ5kSzWRP5b1IBeyIqTG5EgAF
這個接口的入參中有兩個參數:每次調用時,都會發生改變,這個
第三個接口:https://dict.youdao.com/keyword/key
? ? ? ? 入參就是我們的輸入的待翻譯的文本“技術”
?
??????????返回是一個空的。確認的內容。由此可見,需要處理的就是前面兩個接口的內容。
{"code":0,"message":"SUCCESS","data":[]}
?明確逆向目標
? ? ? ? 由此可見,如果我們想完成有道的逆向,就需要完成第一層,解開sign相關加密邏輯,第二層:response的aes解析。
選擇定位、調試手段
? ? ? ? 很多適合,定位核心代碼都是一套組合拳定位。
方法 | 適配? | |
事件斷點 | 適合監控點擊事件;是監控變化,自動發出的請求。 | |
全局搜索 | 適合帶關鍵字的,比如sign。 在本示例中是可行的。可以直接定位。 | |
xhr斷點 | ?適合接口定位,支持接口關鍵字篩選;挺好,可以監控到所有的xhr請求。還可以過濾接口。 | |
棧分析 | 適合,很酷的方法,幾乎可以媲美xpath在爬蟲中的定位。 |
2024年5月24日 閃了一下,編輯好的,都快弄完了。結果全部退回到昨天保存的了。都不想寫了
第一層:逆向sign
? ? ? ? 如何定位sign簽字,幾乎每一個接口都有sign,換句話說,通過xhr指定一個接口,然后通過逐步調試是一定能夠找到這句核心代碼的。
? ? ? ? 但是通過sign:來進行搜索也是很快。但是這個靠運氣。
? ? ? ? 后續可以培養一個分析思路,是接口涉及的就通過xhr debug來。xhr是什么?就是下面這個。高級在,能夠自動取捕獲接口,并產生斷點。
? ? ? ? xhr加上,棧幾乎無敵。棧斷點是什么?是下面這個。記錄了一個完整的調用鏈路。通過棧幾乎一定可以找到你想要的那個邏輯。
? ? ? ? 因為混淆,所以每一行其實是一個函數,從上到下,從最新到最初。
? ? ? ? ?隨便點擊一個La:進入了我現在O函數的上一個函數。(在下面的第二層你能學習到。)
? ? ? ? ?那就繼續:定位到sign后,通過查看函數的方式,你會發現,代碼居然都在一塊。S函數,S函數中調用的_函數,這個名字有點奇怪"_", 不過也在上面有的。至此,搞定。
????????為什么不繼續看i函數的定義了。因為經驗告訴我,這個是一個crypto的第三方庫,如果繼續調試,會進入三方庫的代碼中,沒有必要。好在js逆向常見的集中算法,aes、md5、base64都有明顯的一些函數特征,見過幾次都一眼知道了。
?
????????然后就是把代碼扣下來。扣下來之后的代碼,一般是不能運行的。缺乏變量輸入什么的。而且也需要進行三方庫引用的替換,冗余項的刪除,函數的優化。
變量補全 | 補全可以通過調試是,查看變量的值。而后在摳出來的文件中使用const定義。 |
三方庫引用的替換 | 通過chatgpt,添加第三方引用; 比如crypto,md5這些事需要轉成本地第三方庫的。 |
函數的優化 | 1、冗余項的刪除,有些函數的返回值中有很多參數,和目標參數不相關的都可以刪除掉。 2、可以把最后的返回retrun 變為console.log,降低報錯風險。 3、轉python只需要chatgpt一句話即可 |
如下,比如crypto的引用。
const e = "fsdsogkndfokasodnaso"
// const t= "fsdsogkndfokasodnaso"
const d = "fanyideskweb"
const u = "webfanyi"const crypto = require('crypto');function _(e) {const hash = crypto.createHash('md5');hash.update(e.toString());return hash.digest('hex');
}function S(e, t) {return _(`client=${d}&mysticTime=${e}&product=${u}&key=${t}`)
}function k(e) {const o = (new Date).getTime();console.log(o)sign = S(e, o)console.log(sign)
}k(e)
第二層:返回值逆向解析aes解密
????????通過xhr debug或者通過棧 debug幾乎都能定位到decodeData這句核心代碼。在這里出現了待加密的數據o,這個也就是translateWeb接口的返回值。
? ? ? ? 在這里打上斷點后,不要直接通過調試來進入decodeData的代碼。新手這樣就進入了無限循環的代碼中了,因為混淆,加上跳轉,加上單步調試,有時會直接進入了第三方庫的內部,里面幾乎是一些算法邏輯的實現,很容易暈頭。
????????而且如果是采用扣代碼的方式,每一次跳轉一個新地方,都意味著需要采集這一步的代碼,這幾乎是不可能完成的。這也是新手容易進入的誤區。
? ? ? ? ?正確的處理方法是:? 選中_a這個奇怪的對象。會彈窗這個對象的內容,選中A,因為decodeData的加密函數來自A,發現在A中我們可以找到decodeData的名字,這樣就簡單了。右鍵這個函數,居然可以跳轉到函數定義。? ??
? ? ? ? 函數的定義,其實很簡單。轉16進制,
? ? ? ? 扣出來如下:可能你會注意到,在上面是s.alloc,i.createDecipheriv,這些在摳出來之后都變了引用。其實這些是引用的第三方庫的內容,完全可以在扣出來之后,從新引用第三方庫來搞定。如果你繼續調試進入到createDecipheriv這個函數,你會發現進入了一個算法。在混淆之后的代碼中去扣一個加密算法是很有難度的。
? ? ? ? 所以直接調用第三方庫也好。這也是新手逆向需要總結的一個經驗。他能夠避免新手走入無限的死循環中,好在逆向的算法幾乎都是aes、md5、base64,見幾次幾乎就知道了。
function tt(e, t, o) {if (!e)return null;const a = Buffer.alloc(16, T(t)), n = Buffer.alloc(16, T(o)), r = crypto.createDecipheriv("aes-128-cbc", a, n);let l = r.update(e, "base64", "utf-8");return l += r.final("utf-8");
}
? ? ? ? 差點遺漏了。這里還有一個函數T。T(t)、T(o)。相同的方式,右鍵好像沒有調出來顯示定義。但是,彈框中顯示了函數定義在哪里。點擊鏈接。
? ? ? ? 是一個簡單的md5加密。摳出來。使用第三方庫搞定了。? ? ? ??
?
第二層完整代碼如下:
const e = "Z21kD9ZK1ke6ugku2ccWu4n6eLnvoDT0YgGi0y3g-v0B9sYqg8L9D6UERNozYOHq4CkCZNz7GphbExY0aTIyrsa9Cq7T1ujm-y1-Z41UJGr2t68llVA1tycni4mhWuRwKlhfrgxpSuWj15TCakNruiYKMr3HGq_XWpB-dMezH0iHY9DEFu1IU-YzjbPGr9XVRLmXqKbQg1nCHZ9rmAMFDXxqqCdPiA_04b69hMTmvloCcEd6pQ2bfTs7gnzVfWMjWww_3vq0qrZ0R1xytgrCuOft_88XsQzxVJ20qgEGrXiP9s51LSz8_nACzmbfZCMHXPBiq6vEOg93r7wZq5Klvu4Wpk3lbQtoUmhSmPO0guhMWJntjCBBydX9Z13ScPSPQsmZwskc4D7qI0vDdQck-X14hKaYb-zKcjx4ccLpPln8w1R04UVuwSQUkMRbkGCcmHosL3rwfw4eydByQ-Ifqw==";
const t = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl";
const o = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4";const crypto = require('crypto');
const s = crypto.createHash('sha256');function T(e) {const hash = crypto.createHash('md5');hash.update(e);return hash.digest();
}function tt(e, t, o) {if (!e)return null;const a = Buffer.alloc(16, T(t)), n = Buffer.alloc(16, T(o)), r = crypto.createDecipheriv("aes-128-cbc", a, n);let l = r.update(e, "base64", "utf-8");return l += r.final("utf-8");
}console.log(tt(e,t,o));
?
?ps:? 下面是幾個簡單的實例,很適合入門閱讀
【JavaScript 逆向】某升學助考網登錄參數逆向,Hook + 跟棧_f12跟棧-CSDN博客文章瀏覽閱讀2.9k次,點贊5次,收藏20次。使用 Hook 注入及直接跟棧方式實現對某升學助考網登錄加密參數的逆向_f12跟棧https://blog.csdn.net/Yy_Rose/article/details/125870549
跟棧調試逆向https://segmentfault.com/a/1190000040741361
本文引用(原文鏈接)
AES加密算法原理的詳細介紹與實現-CSDN博客
https://www.cnblogs.com/starwolf/p/3365834.html
js逆向技巧分享 - 知乎
?