[JS逆向] 喜馬拉雅登錄案例 -- 補環境

博客配套代碼發布于github:喜馬拉雅登錄?(歡迎順手Star一下?)

相關知識點:webpack?補環境

相關爬蟲專欄:JS逆向爬蟲實戰??爬蟲知識點合集??爬蟲實戰案例?逆向知識點合集


此案例目標為逆向成功對應的參數,并成功返回對應請求。

一、爬取工作準備

進入網址:喜馬拉雅登錄,再點擊右上角那個小電腦,進入密碼登錄界面。

手機號輸入123456789,密碼輸入123456,點開F12,再點擊登錄,就可以開始我們的表演了。

一看就知道這個就是我們要的數據,再看載荷:

能看出我們大致要破解的四個參數:account,nonce,password,signature.

老規矩,直接復制這個數據包到curl to python,并將其復制到py運行查看結果(步驟在以往JS逆向案例有,不懂的直接看往期操作即可)

可以看到運行結果應是這個。如果并非這個結果說明參數傳遞錯誤。

二、逆向入口分析

直接encrypt搜,搜到七個,分析發現只有下面四個長得像,依次打上斷點。

只剩這倆地方斷的住。

試著從第二個開始找,我們直接選擇最下層的這個匿名,進去查看下:巧了不是,account,password,nonce都看到了,這兒還有這么完美的四大參數,不是這我吃。現在再挨個分析即可。

account:

account是n,n是→這里getEncryptPwd點進去的確可以進入到下層棧然后接著找,再補環境,但未免落了下成。往上再捋捋看看a的位置在哪。一直翻翻翻,終于看到:看到a=r(19),webpack與加載器,看到這就很開心了,后面可以直接一套公式流webpack過掉,輕輕又松松啊。

password:

password是i,i是→跟上面的account近乎一個樣,也是webpack,處理近乎一致。

nonce:

nonce是t,t是→

呃,是傳入參數。而且這個t還是個一直變動的值。找不到上下層堆棧。

別急:當你看到檢測參數較多而且某個值似乎無法通過溯源找到適,可以看看其他的數據包:

果然,是從另一個數據包獲得的nonce,那我們只需要通過單獨向這個數據包發請求獲得nonce即可。

signature:

siganture是e,e是→可以將其簡化,即:

var e = a.getSignature({
? ? ? ? ? ? ? ? account: n,
? ? ? ? ? ? ? ? password: i,
? ? ? ? ? ? ? ? nonce: t
? ? ? ? ? ? })

乍一看,也是用了a加載器,直接像上面的賬密一樣...不行!

這里有個坑,而且非常隱蔽,筆者在這里就搗鼓了好久才知曉原因。

如果你用的是加載器的方式得到,它最后作為參數是錯誤的。原因極大概率是因為其獲取方式與常規加載器的邏輯不同。這里說一下此處的分析思路應如何。

正常來講是會去想到直接去用加載器,但用前一定先在控制臺打印觀察下。此處可以看到打印出來格式為哈希算法,則:盡可能別用加載器,加密算法的邏輯就單獨用算法方式解決,兩者獲取可能會沖突。

點進a.getSiganture看對應層邏輯:

?

這里選中的是e.toUpperCase()),能看到它是一個很長的由上方拼接獲取的字符

同時我們再把這一串打印進控制臺:

發現沒有:在同一時間線(同個ajax請求)下,獲得的兩個算法最終答案相近,但后者(加密算法)才對。

同時這里能通過分析哈希算法長度,即40位,基本確定其為sha1算法。

但還是有點不放心。我們這里是想直接用sha1的加密邏輯得到,但不確定它有沒有加鹽(魔改)算法,到SHA1加密網絡轉換器里,將e.toUpeerCase()的東西輸入進去看下(記得去掉引號)

與上述答案一致。那么就可以放心直接用算法了,至此這個邏輯基本完成。

綜上,所有參數分析完畢后可以開始我們的正式操作了。

三、破解逆向

1.補webpack

這段就老生常談的公式了,盡量簡化描述:

(如需更詳細的步驟請參考我往期寫的webpack處理公式)

選中加載器,刷新頁面并進去里面,全選復制粘貼過來并簡單處理掉里面的html元素,并在頂部寫個window=global。再把刷新進去位置的函數(function i(r)),設置個console.log('r:::',r)與window.loader=i

最后再將傳入代碼寫作:

一般如果webpack里是r('GSGX')這種還能依靠直接搜'GSGX'復制粘貼過來,但如果是像上圖這種r(19)的webpack,就得通過源函數來進入了:

選中r(19):進入里面這個棧并全局復制到mod01即可(對應的是數組,不用分析半天究竟是誰)

缺這玩意兒就全局搜并全部復制(注意這個搜索的是var xx,切記把這個var去掉不然沒法上升為全局變量),再給個mod02補上,并require過來(注意require的順序):

看到這里就能確定webpack環節結束,接下來到補環境階段。

2.補環境

卻啥補啥,補到此時:

有點怪,好像不太好補。那就把我們的監控器遞出來吧↓

(監控器具體用法在文章?[逆向知識] 補環境 -- 讓本地逆向如魚得水?處有講,建議在這里看一看)

function setProxy(proxyObjArr) {for (let i = 0; i < proxyObjArr.length; i++) {const handler = `{get: function(target, property, receiver) {console.log("方法:", "get  ", "對象:", "${proxyObjArr[i]}", "  屬性:", property, "  屬性類型:", typeof property, ", 屬性值:", target[property], ", 屬性值類型:", typeof target[property]);return target[property];},set: function(target, property, value, receiver) {console.log("方法:", "set  ", "對象:", "${proxyObjArr[i]}", "  屬性:", property, "  屬性類型:", typeof property, ", 屬性值:", value, ", 屬性值類型:", typeof target[property]);return Reflect.set(...arguments);}}`;eval(`try {${proxyObjArr[i]};${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});} catch (e) {${proxyObjArr[i]} = {};${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});}`);}
}setProxy(['window', 'document','canvas'])

document補全,看到:

很明顯知道canvas少了個toDataURL,加進去即可。

同樣,其他補環境邏輯也大致相同,陸續為setProxy加東西即可,只有一個點要注意下:

大大的userAgent,這玩意兒就不要再傳空值或空func,直接控制臺打印個丟過來不好嗎

這個點也是不太好處理,但只要全局搜就可以了,搜到發現隸屬于document對象,仿寫過來就行。同理,后面好幾個環境也可以靠這樣補。

最終成功補完沒再報錯,將setProxy的代理與之前console.log的r都注釋掉,

這個是window對象,也補上環境就消失了,

最終輸出:賬戶與密碼的邏輯搞定。

3.py與js代碼互傳

首先我們要確定py與js互傳的方式。分為execjs與subprocess。正好這里都會用到。execjs用于構建環境較簡單,沒有很多瀏覽器原生的bom/dom,api或更復雜的模擬環境這些;subprocess則用于如之前代碼中復雜的環境模擬,最終輸出。

(1) execjs

它的使用方式相較非常簡單,直接傳遞即可。這里我們以siganture的獲得舉例

cryptoJs = require("crypto-js")function y(t) {var e = "", r = Object.keys(t).sort((function (t, e) {return (t = t.charCodeAt(0)) - (e = e.charCodeAt(0))})), n = r.length;return r.forEach((function (r, o) {var i = t[r];e += "".concat(r, "=").concat(i),o < n - 1 && (e += "&")})),e
}function getSignature() {var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, e = y(t) + "&" + "WEB-V1-PRODUCT-E7768904917C4154A925FBE1A3848BC3E84E2C7770744E56AFBC9600C267891F";return e.toUpperCase(),cryptoJs.SHA1(e.toUpperCase()).toString()
}

這個signature在js中的構建邏輯,而在py中,我們只需要通過如下的代碼即可獲取對應js生成的代碼。

js_compile = execjs.compile(open('sign.js',encoding='utf8').read())
data = {'account': enc_account,'password': enc_password,'nonce': nonce_val}
signature = js_compile.call('getSignature',data)

其中data是傳遞進去的參數,'getSignature'則是用于選擇這個文件的這個函數。

(2) subprocess

其使用相較就復雜很多,這里也是分別放js與py文件對應代碼:

function get_all(account, password) {function get_account() {return (0, a.getEncryptPwd)(account)}function get_pwd() {return (0, a.getEncryptPwd)(password)}return {account:get_account(),pwd:get_pwd(),}
}act = process.argv[2]
pwd = process.argv[3]
const ret = get_all(act,pwd)
res = JSON.stringify(ret)
console.log(res)process.exit()

在js文件中,通過process.argv獲取傳遞過來的原始賬密并傳遞給get_all,再生成后打印到控制臺上。py文件再通過控制臺的消息對應接收過來。本質上可以理解為雙方是靠終端來接收各自的數據。

all_ = subprocess.check_output(f'node get_sign.js "{account}" "{password}"') # 分別獲得傳遞
all_ = all_.decode('utf8').strip()
# 通過json傳遞取出對應值
js_data = json.loads(all_)
account = js_data['account']
pwd = js_data['pwd']

注意:這里我用的是json數據來互傳。因為js傳遞過來的數據是個長字符串,用json格式才方便將其轉化為字典格式以提取。

四、完整邏輯構建

如上,我們基本已完成了相關具體邏輯與所有代碼的構建。

最終我們將其模塊化打包輸出:

if __name__ == '__main__':account = '123456789'password = '123456'cur_nonce = get_nonce()enc_account,enc_pwd = get_encrypt(account, password)signature = get_signature(enc_account,enc_pwd,cur_nonce)ret = login(enc_account,enc_pwd,cur_nonce,signature)print(ret)

答案獲取成功,逆向完成。

由于代碼量過大,本文并未將所有代碼都放上來。但可以看我的github開源代碼,來進一步全面分析。

📌 項目代碼 + 后續案例合集 全部發布在 GitHub 倉庫中,持續更新中,歡迎收藏!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87146.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87146.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87146.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大語言模型推理系統綜述

摘要 近年來&#xff0c;隨著 ChatGPT 等服務推動大語言模型&#xff08;LLM&#xff09;的快速普及&#xff0c;一批專門面向 LLM 推理的系統相繼涌現&#xff0c;如 vLLM、SGLang、Mooncake 和 DeepFlow。這些系統設計工作的核心動因是 LLM 請求處理過程中所特有的自回歸特性…

用Firecrawl輕松獲取網站數據,提升AI應用的效率!

&#x1f525; Firecrawl&#xff1a;助力AI應用的強大工具&#xff01; 在數字化信息爆炸的時代&#xff0c;如何高效地從海量網頁中提取有用數據變得尤其重要。Firecrawl的問世&#xff0c;為我們揭開了一種便捷的方法來應對這一挑戰。它不僅能夠將整個網站的數據轉化為適用…

【王陽明代數講義】谷歌編程智能體Gemini CLI 使用指南、架構詳解與核心框架分析

Gemini CLI 使用指南、架構詳解與核心框架分析 Gemini CLI 使用指南、架構詳解與核心框架分析Gemini CLI 使用指南Gemini CLI 架構詳解Gemini CLI 核心框架總結 Gemini CLI 使用指南、架構詳解與核心框架分析 Gemini CLI 使用指南 1. 安裝與配置 環境要求&#xff1a; Node.…

camera調試:安卓添加xml注冊

對接安卓的平臺時&#xff0c;需要注冊對應的camera設備&#xff0c;供安卓標準api進行操作&#xff0c;rk的平臺需要在HAL層配置camera3_profiles.xml文件&#xff0c;適配驅動的信息&#xff0c;進行注冊camera設備。該xml對應的內容很多&#xff0c;很多CTS測試問題都是該文…

使用 Ansys Discovery 為初學者準備幾何結構

介紹 設計幾何體通常會包含一些特征&#xff0c;使其無法直接導入我們的仿真工具&#xff0c;例如 Ansys Mechanical、LS-DYNA、Fluent 等。有些干擾或錯位雖然適合制造&#xff0c;但在我們的仿真工具中卻會造成問題。有時&#xff0c;一些小特征&#xff08;例如孔或圓角&am…

推客系統全棧開發指南:從架構設計到商業化落地

一、推客系統概述 推客系統&#xff08;TuiKe System&#xff09;是一種結合社交網絡與內容分發的創新型平臺&#xff0c;旨在通過用戶間的相互推薦機制實現內容的高效傳播。這類系統通常包含用戶關系管理、內容發布、智能推薦、數據分析等核心模塊&#xff0c;廣泛應用于電商…

大數據開發實戰:如何做企業級的數據服務產品

1.背景 數據服務通常以解決方案的形式進行組織&#xff0c;面向一個應用場景的所有數據需求或數據內容可以通過一個解決方案進行封裝&#xff0c;統一對外服務。一個數據需求或數據接口以一個數據服務實例的形式存在于解決方案之下。 下游消費方可以通過統一API進行數據消費&…

基于IndexTTS的零樣本語音合成

IndexTTS 項目采用模塊化設計&#xff0c;將 BPE 文本編碼、GPT 單元預測、dVAE 語音特征抽取和 BigVGAN 音頻生成串聯為完整的語音合成流程。系統通過統一的配置文件和模型目錄規范&#xff0c;實現高效的文本到語音轉換&#xff0c;支持命令行與 Web 界面雙模式操作&#xff…

基于go-zero的短鏈生成系統

go-zero框架 gozero&#xff08;又稱go-zero&#xff09;是一款由知名開發者kevwan設計的Golang微服務框架&#xff0c;專注于高性能、低延遲和易用性。其核心目標是簡化分布式系統的開發&#xff0c;提供開箱即用的工具鏈&#xff0c;涵蓋API網關、RPC服務、緩存管理、數據庫…

Linux-修改線上MariaDB服務端口號

準備工作&#xff08;很重要&#xff01;&#xff01;&#xff01;&#xff09;&#xff1a; 提前做好Linux服務器快照 提前做好數據庫數據備份 1. 修改配置文件 首先&#xff0c;我們需要找到MariaDB的配置文件。通常情況下&#xff0c;這個文件位于以下位置&#xff1a;…

Spring Cloud 微服務(負載均衡策略深度解析)

&#x1f4cc; 摘要 在微服務架構中&#xff0c;負載均衡是實現高可用、高性能服務調用的關鍵機制之一。Spring Cloud 提供了基于客戶端的負載均衡組件 Ribbon&#xff0c;結合 Feign 和 OpenFeign&#xff0c;實現了服務間的智能路由與流量分配。 本文將深入講解 Spring Clo…

HTML/CSS基礎

1.html:超文本標記語言。它是一種標識性的語言&#xff0c;非編程語言&#xff0c;不能使用邏輯運算。通過標簽將網絡上的文本格式進行統一&#xff0c;使用分散網絡資源鏈接為一個邏輯整體&#xff0c;屬于標記語言。 超文本&#xff1a;就是指頁面內可以包含圖片&#xff0…

C# 事件驅動編程的核心:深度解析發布者_訂閱者模式

適用場景&#xff1a;GUI交互、消息隊列、微服務通信等需要解耦事件生產與消費的系統 &#x1f9e9; 模式核心組件解析 發布者&#xff08;Publisher&#xff09; 作用&#xff1a;定義事件并管理訂閱者列表關鍵行為&#xff1a; 提供和-運算符注冊/注銷訂閱者通過Invoke()方…

華為云Flexus+DeepSeek征文 | 從零開始搭建Dify-LLM應用開發平臺:華為云全流程單機部署實戰教程

華為云FlexusDeepSeek征文 | 從零開始搭建Dify-LLM應用開發平臺&#xff1a;華為云全流程單機部署實戰教程 前言一、華為云Dify-LLM平臺介紹1. Dify-LLM解決方案簡介2. Dify-LLM解決方案地址3. Dify-LLM單機架構介紹4. 預估成本說明 二、華為云Maas平臺介紹1. 華為云ModelArts …

oracle集合三嵌套表(Nested Table)學習

嵌套表 嵌套表(Nested Table)是Oracle中的一種集合數據類型&#xff0c;它允許在表中存儲多值屬性&#xff0c;類似于在表中嵌套另一個表。 嵌套表具有以下特點&#xff1a; 是Oracle對象關系特性的一部分 可以看作是一維數組&#xff0c;沒有最大元素數量限制 存儲在單獨…

Python學習之——單例模式

Python學習之——單例模式 參考1 利用__metaclass__實現單例super的用法class Singleton(type)元類 2 重載__new__方法實現單例模式3 利用裝飾器實現單例考慮一個類如果繼承一個單例類的問題 參考 python之metaclasssingleton&#xff08;一&#xff09; python之metaclasssin…

【Linux】U-boot常用命令總結

U-Boot 是嵌入式系統中常用的引導加載程序&#xff08;bootloader&#xff09;&#xff0c;它提供了一套命令行接口&#xff0c;用于調試、加載操作系統鏡像以及進行硬件測試等操作。 1、變量操作命令 這些命令用于管理 U-Boot 的環境變量。 命令功能說明setenv name value設…

【Linux】不小心又創建了一個root權限賬戶,怎么將它刪除?!

一.前言 今天在學習linux提權的時候&#xff0c;把新建的一個普通賬戶權限提升成了root&#xff0c; 當我練習完提權&#xff0c;想要把這個賬戶刪掉的時候。 發現… 好家伙&#xff0c;這個根本刪不掉 隨后試了各種各樣的方法&#xff0c;都不行&#xff0c;后來突然想到是否…

數據結構:數組(Array)

目錄 什么是數組&#xff08;Array&#xff09;&#xff1f; &#x1f50d;為什么數組的下標要從 0 開始&#xff1f; 一、內存地址與偏移量的關系&#xff1a;從 0 開始是最自然的映射 二、指針的起點就是第 0 個元素的地址 三、歷史原因&#xff1a;BCPL → B → C → …

視頻內存太大怎么壓縮變小一點?視頻壓縮的常用方法

視頻傳生活或者工作中很常見&#xff0c;如發送視頻郵件、在線視頻播放、視頻上傳下載等。未壓縮的大內存視頻文件傳輸時&#xff0c;不僅會消耗大量的網絡帶寬資源&#xff0c;還會使傳輸時間大幅增加。在網速有限的情況下&#xff0c;發送一個幾 GB 的未壓縮視頻可能需要數小…