真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

人均瑞數(shù)系列,瑞數(shù) 4 代 JS 逆向分析

創(chuàng)新互聯(lián)公司專注于企業(yè)全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、青島網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5頁(yè)面制作商城系統(tǒng)網(wǎng)站開(kāi)發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為青島等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。

聲明

本文章中所有內(nèi)容僅供學(xué)習(xí)交流使用,不用于其他任何目的,不提供完整代碼,抓包內(nèi)容、敏感網(wǎng)址、數(shù)據(jù)接口等均已做脫敏處理,嚴(yán)禁用于商業(yè)用途和非法用途,否則由此產(chǎn)生的一切后果均與作者無(wú)關(guān)!

本文章未經(jīng)許可禁止轉(zhuǎn)載,禁止任何修改后二次傳播,擅自使用本文講解的技術(shù)而導(dǎo)致的任何意外,作者均不負(fù)責(zé),若有侵權(quán),請(qǐng)?jiān)诠娞?hào)【K哥爬蟲(chóng)】聯(lián)系作者立即刪除!

前言

瑞數(shù)動(dòng)態(tài)安全 Botgate(機(jī)器人防火墻)以“動(dòng)態(tài)安全”技術(shù)為核心,通過(guò)動(dòng)態(tài)封裝、動(dòng)態(tài)驗(yàn)證、動(dòng)態(tài)混淆、動(dòng)態(tài)令牌等技術(shù)對(duì)服務(wù)器網(wǎng)頁(yè)底層代碼持續(xù)動(dòng)態(tài)變換,增加服務(wù)器行為的“不可預(yù)測(cè)性”,實(shí)現(xiàn)了從用戶端到服務(wù)器端的全方位“主動(dòng)防護(hù)”,為各類 Web、HTML5 提供強(qiáng)大的安全保護(hù)。

瑞數(shù) Botgate 多用于政企、金融、運(yùn)營(yíng)商行業(yè),曾一度被視為反爬天花板,隨著近年來(lái)逆向大佬越來(lái)越多,相關(guān)的逆向文章也層出不窮,真正到了人均瑞數(shù)的時(shí)代了,這里也感謝諸如 Nanda、懶神等逆向大佬,揭開(kāi)了瑞數(shù)神秘的面紗,總結(jié)的經(jīng)驗(yàn)讓后來(lái)人少走了不少?gòu)澛贰?/p>

過(guò)瑞數(shù)的方法基本上有以下幾種:自動(dòng)化工具(要隱藏特征值)、RPC 遠(yuǎn)程調(diào)用、JS 逆向(硬扣代碼和補(bǔ)環(huán)境),本文介紹的是 JS 逆向硬扣代碼,盡可能多的介紹各種細(xì)節(jié)。

瑞數(shù)特征以及不同版本的區(qū)別

對(duì)于絕大多數(shù)使用了瑞數(shù)的網(wǎng)站來(lái)說(shuō),有以下幾點(diǎn)特征(可能有特殊版本不一樣,先僅看主流的):

1、打開(kāi)開(kāi)發(fā)者工具(F12)會(huì)依次出現(xiàn)兩個(gè)典型的無(wú)限 debugger:

2、瑞數(shù)的 JS 混淆代碼中,變量、方法名大多類似于 _$xx,有眾多的 if-else 控制流,新版瑞數(shù)還可能會(huì)有 jsvmp 以及眾多三目表達(dá)式的情況:

3、看請(qǐng)求,會(huì)有典型的三次請(qǐng)求,首次請(qǐng)求響應(yīng)碼是 202(瑞數(shù)3、4代)或者 412(瑞數(shù)5代),接著單獨(dú)請(qǐng)求一個(gè) JS 文件,然后再重新請(qǐng)求頁(yè)面,后續(xù)的其他 XHR 請(qǐng)求中,都帶有一個(gè)后綴,這個(gè)后綴的值是由 JS 生成的,每次都會(huì)變化,后綴的值第一個(gè)數(shù)字為瑞數(shù)的版本,比如 MmEwMD=4xxxxx 就是4代瑞數(shù),bX3Xf9nD=5xxxxx 就是5代瑞數(shù):

4、看 Cookie,瑞數(shù) 3、4 代有以 T 和 S 結(jié)尾的兩個(gè) Cookie,其中以 S 開(kāi)頭的 Cookie 是第一次的 201 那個(gè)請(qǐng)求返回的,以 T 開(kāi)頭的 Cookie 是由 JS 生成的,動(dòng)態(tài)變化的,T 和 S 前面一般會(huì)跟 80 或 443 的數(shù)字,Cookie 值第一個(gè)數(shù)字為瑞數(shù)的版本(為什么可以通過(guò)第一個(gè)數(shù)字來(lái)判斷版本?難道相同版本第一個(gè)數(shù)字不會(huì)變嗎?這些問(wèn)題我們?cè)诜治?JS 的時(shí)候可以找到答案),比如:

  • FSSBBIl1UgzbN7N80T=37Na97B.nWX3....:數(shù)字 80 是 http 協(xié)議的默認(rèn)端口號(hào),對(duì)應(yīng) http 請(qǐng)求,其值第一位為 3,表示 3 代瑞數(shù);
  • FSSBBIl1UgzbN7N443T=4a.tr1kEXk.....:數(shù)字 443 是 https 協(xié)議的默認(rèn)端口號(hào),對(duì)應(yīng) https 請(qǐng)求,其值第一位為 4,表示 4 代瑞數(shù)。

瑞數(shù) 5 代也有以 T 和 S 結(jié)尾的兩個(gè) Cookie,但有些特殊的 5 代瑞數(shù)也有以 O 和 P 結(jié)尾的,同樣的,以 O 開(kāi)頭的是第一次的 412 那個(gè)請(qǐng)求返回的,以 P 開(kāi)頭的是由 JS 生成的,Cookie 值第一個(gè)數(shù)字同樣為瑞數(shù)的版本,和 3、4 代不同的是,5 代沒(méi)有加端口號(hào)了,比如:

  • vsKWUwn3HsfIO=57C6DwDUXS.....:以 O 結(jié)尾,其值第一位為 5,表示 5 代瑞數(shù);
  • WvY7XhIMu0fGT=53.9fybty......:以 T 結(jié)尾,其值第一位為 5,表示 5 代瑞數(shù)。

5、看入口,瑞數(shù)有個(gè)流程是在虛擬機(jī) VM 中加載 1w+ 行的代碼,加載此代碼的入口,不同版本也不一樣(這個(gè)入口具體在哪里?怎么定位?在后續(xù)逆向分析中再詳細(xì)介紹),示例如下:

  • 3 代:_$aW = _$c6[_$l6()](_$wc, _$mo);_$c6 實(shí)際上是 eval,_$l6() 實(shí)際上是 call;

  • 4 代:ret = _$DG.call(_$6a, _$YK);,_$DG 實(shí)際上是 eval,有關(guān)鍵字 ret,call 是明文;

  • 5 代:5 代種類比較多了,最初和 4 代的類似,比如 ret = _$Yg.call(_$kc, _$mH);,有關(guān)鍵字 ret,call 是明文,也有沒(méi)有 ret 關(guān)鍵字的版本,比如 _$ap = _$j5.call(_$_T, _$gp);,也有像 3 代那樣全部混淆了的,比如:_$x8 = _$mP[_$nU[15]](_$z3, _$Ec);_$mP 實(shí)際上是 eval,_$nU[15] 實(shí)際上是 call,混淆的 call 與 3 代的區(qū)別就是 5 代是在一個(gè)數(shù)組里取值得到的;

當(dāng)然要想精準(zhǔn)區(qū)分不同版本,得各個(gè)條件結(jié)合起來(lái)看,最主要的還是得看看內(nèi)部的實(shí)現(xiàn)邏輯,以及頁(yè)面的代碼結(jié)構(gòu),比如 4 代有一個(gè)生成假 Cookie 的步驟,而 5 代沒(méi)有,有的特殊版本雖然看起來(lái)是 5 代,但是加了 jsvmp 和三目表達(dá)式,和傳統(tǒng)的 5 代又有區(qū)別,偶爾愚人節(jié)啥的突然來(lái)個(gè)新版本,也會(huì)不一樣,各版本在分析一遍之后,就很容易區(qū)分了。

Cookie 入口定位

本文案例中瑞數(shù) 4 代網(wǎng)站為:aHR0cDovL3d3dy5mYW5nZGkuY29tLmNuL25ld19ob3VzZS9uZXdfaG91c2VfZGV0YWlsLmh0bWw=

首先過(guò)掉無(wú)限 debugger(過(guò)不過(guò)其實(shí)無(wú)所謂,后面的分析其實(shí)這個(gè)基本上沒(méi)影響),直接右鍵 Never pause here 永不在此處斷下即可:

定位 Cookie,首選 Hook 來(lái)的最快,通過(guò) Fiddler 等抓包工具、油猴腳本、瀏覽器插件等方式注入以下 Hook 代碼:

(function() {
    // 嚴(yán)謹(jǐn)模式 檢查所有錯(cuò)誤
    'use strict';
    // document 為要hook的對(duì)象 這里是hook的cookie
	var cookieTemp = "";
    Object.defineProperty(document, 'cookie', {
		// hook set方法也就是賦值的方法 
		set: function(val) {
				// 這樣就可以快速給下面這個(gè)代碼行下斷點(diǎn)
				// 從而快速定位設(shè)置cookie的代碼
				console.log('Hook捕獲到cookie設(shè)置->', val);
                debugger;
				cookieTemp = val;
				return val;
		},
		// hook get 方法也就是取值的方法 
		get: function()
		{
			return cookieTemp;
		}
    });
})();

Hook 發(fā)現(xiàn)會(huì)有生成兩次 Cookie 的情況,斷下之后往上跟棧,可以看到組裝 Cookie 的代碼,類似如下結(jié)構(gòu):

仔細(xì)觀察這兩次 Cookie 生成的地方,分別往上跟棧,你就會(huì)發(fā)現(xiàn)兩個(gè) Cookie 分別是經(jīng)過(guò)了兩個(gè)不同方法得到的,如下圖所示:

這里的代碼存在于 VM 虛擬機(jī)中,且是 IIFE 自執(zhí)行代碼,我們還得往前跟??纯催@些 VM 代碼是從哪里加載出來(lái)的,跟棧來(lái)到首頁(yè)(202頁(yè)面)帶有 call 的位置:

我們?cè)谖恼麻_(kāi)頭介紹的這個(gè)位置就是這么分析得來(lái)的,這個(gè)位置通常在分析瑞數(shù)的時(shí)候作為入口,圖中 _$te 實(shí)際上是 eval 方法,傳入的第一個(gè)參數(shù) _$fY 是 Window 對(duì)象,第二個(gè)對(duì)象 _$F8 是我們前面看到的 VM 虛擬機(jī)中的 IIFE 自執(zhí)行代碼。

在知道了瑞數(shù)大致的入口之后,我們也可以使用事件監(jiān)聽(tīng)中的 Script 斷點(diǎn),一直下一個(gè)斷點(diǎn)(F8)就可以走到 202 頁(yè)面,然后搜索 call 關(guān)鍵字就能快速定位到入口,Script 斷點(diǎn)中的兩個(gè)選項(xiàng),第一個(gè)表示運(yùn)行 JS 腳本的第一條語(yǔ)句時(shí)斷下,第二個(gè)表示 JS 因?yàn)閮?nèi)容安全政策而被屏蔽時(shí)斷下,一般選擇第一個(gè)就可以了,如下圖所示:

文件結(jié)構(gòu)與邏輯

想要后續(xù)分析 Cookie 的生成,我們不得不要觀察一下 202 頁(yè)面的代碼,meta 標(biāo)簽有個(gè) content 內(nèi)容,引用了一個(gè)類似于 c.FxJzG50F.dfe1675.js 的 JS 文件,接著跟一個(gè)自執(zhí)行的 JS,如下圖所示:

第1部分 meta 標(biāo)簽的 content 內(nèi)容,每次都是變化的,第2部分引用的這個(gè)外部 JS 在不同頁(yè)面也有所差別,但是同一個(gè)網(wǎng)站同一個(gè)頁(yè)面 JS 里的內(nèi)容一般是固定不會(huì)變的,第3部分自執(zhí)行代碼每次變化的只是變量名,整體邏輯不變,后續(xù)我們?cè)诳鄞a的時(shí)候,也會(huì)用到這里的部分方法。自執(zhí)行代碼里同樣也是有很多 if-else 控制流,開(kāi)頭的那個(gè)數(shù)組,比如上圖中的 _$Dk 就是用來(lái)控制后續(xù)的控制流的。

引用的 c.FxJzG50F.dfe1675.js 直接打開(kāi)看是亂碼的,而自執(zhí)行 JS 的主要作用是將這 JS 亂碼還原成 VM 里的 1w+ 行的正常代碼,并且定義了一個(gè)全局變量 window.$_ts 并賦了許多值,這個(gè)變量在后續(xù) VM 中作用非常大,meta 標(biāo)簽的 content 內(nèi)容同樣也會(huì)在 VM 里用到。

由于很多值、變量都是動(dòng)態(tài)變化的,肯定不利于我們的分析,所以我們需要固定一套代碼到本地,打斷點(diǎn)、跟棧都會(huì)更加方便,隨便保存一份 202 頁(yè)面的代碼,以及該頁(yè)面對(duì)應(yīng)的外鏈 JS 文件,如 c.FxJzG50F.dfe1675.js 到本地,使用瀏覽器自帶的 overrides 重寫(xiě)功能、或者瀏覽器插件 ReRes、或者抓包工具的響應(yīng)替換功能(如 Fiddler 的 AutoResponder)進(jìn)行替換。

VM 里面的代碼是生成 Cookie 的主要代碼,包含眾多的 if-else 控制流,無(wú)疑增加了我們分析代碼的成本,這里就可以使用 AST 技術(shù)做一下反混淆,比如 Nanda 就將 if-else 控制流轉(zhuǎn)換成了 switch-case 的,同一個(gè)控制流下的代碼放在了同一個(gè) case 下,然后在 call 入口那個(gè)地方,將 VM 代碼做一下本地替換,具體可以參考 Nanda 的文章:《某數(shù)4代邏輯分析》,感興趣的可以試試,不了解 AST 的可以看看以前的文章《逆向進(jìn)階,利用 AST 技術(shù)還原 JavaScript 混淆代碼》,后續(xù)有時(shí)間 K 哥再寫(xiě)寫(xiě) AST 還原瑞數(shù)代碼的實(shí)戰(zhàn),本文咱們選擇硬剛!

VM 代碼以及 $_ts 變量獲取

前面我們了解了 VM 代碼和 $_ts 的重要性,所以我們第一步是要想辦法拿到他們,至于在什么時(shí)候有用到,文章后續(xù)再說(shuō),復(fù)制外鏈 JS,即 c.FxJzG50F.dfe1675.js 的代碼和 202 頁(yè)面的自執(zhí)行代碼到文件,本地直接運(yùn)行即可,需要輕度補(bǔ)一下環(huán)境,缺啥補(bǔ)啥,大致補(bǔ)一下 window、location、document 就行了,補(bǔ)的具體內(nèi)容可以直接在瀏覽器控制臺(tái)使用 copy() 命令復(fù)制過(guò)來(lái),然后 VM 代碼我們就可以直接 Hook eval 的方式得到,大致的補(bǔ)環(huán)境代碼如下:

var eval_js = ""

window = {
    $_ts:{},
    eval:function (data) {
        eval_js = data
    }
}

location = {
    "ancestorOrigins": {},
    "href": "http://www.脫敏處理.com.cn/new_house/new_house_detail.html",
    "origin": "http://www.脫敏處理.com.cn",
    "protocol": "http:",
    "host": "www.脫敏處理.com.cn",
    "hostname": "www.脫敏處理.com.cn",
    "port": "",
    "pathname": "/new_house/new_house_detail.html",
    "search": "",
    "hash": ""
}

document = {
    "scripts": ["script", "script"]
}

觀察 $_ts 的 key 和 value,和瀏覽器中得到的是一樣的:

注意事項(xiàng):c.FxJzG50F.dfe1675.js 外鏈 JS 如果你直接下載下來(lái)用編輯器打開(kāi)可能會(huì)被自動(dòng)編碼,和原始數(shù)據(jù)有出入,導(dǎo)致運(yùn)行報(bào)錯(cuò),這里建議直接在瀏覽器在線訪問(wèn)這個(gè)文件,手動(dòng)復(fù)制過(guò)來(lái),或者在抓包軟件里將響應(yīng)內(nèi)容復(fù)制過(guò)來(lái),觀察以下兩種情況,第一種情況就可能會(huì)導(dǎo)致運(yùn)行出錯(cuò),第二種是正常的:

扣代碼

前面說(shuō)了這么多,現(xiàn)在終于可以進(jìn)入主題了,那就是扣代碼,找個(gè)好椅子,準(zhǔn)備把屁股坐穿,此時(shí)你的鍵盤(pán)只有 F11 有用,不斷單步調(diào)試,只需要億點(diǎn)點(diǎn)細(xì)節(jié),就完事兒了!

扣代碼步驟太多,不可能每一步都截圖寫(xiě)出來(lái),只寫(xiě)一下比較重要的,如有遺漏的地方,那也沒(méi)辦法,首先先在我們替換的 202 頁(yè)面里,自執(zhí)行代碼開(kāi)始的地方手動(dòng)加個(gè) debugger,一進(jìn)入頁(yè)面就斷下,方便后續(xù)的分析:

通過(guò)前面我們的分析,已經(jīng)知道了入口在 call 的地方,快速搜索并下斷點(diǎn):

通過(guò)前面我們的分析,我們也知道了有兩次生成 Cookie 的地方,快速搜索 (5),搜索結(jié)果第二個(gè)即為入口:

首先單步跟假 Cookie,雖然是假的,但是后續(xù)生成真 Cookie 中會(huì)用到,在跟的時(shí)候你會(huì)走到這個(gè)邏輯里面:

有一步會(huì)調(diào)用 _$8e() 方法,而 _$8e = _$Q9,_$Q9 又嵌套在 _$d0 里的,搜索一下哪里調(diào)用了 _$d0,發(fā)現(xiàn)是代碼開(kāi)頭:

那么傳入的參數(shù) _$Wn 是啥呢?單步跟入,是一個(gè)方法,作用就是取 202 頁(yè)面的 content 內(nèi)容,那么我們?cè)诒镜鼐椭苯觿h掉這個(gè) _$Wn 方法,直接傳入 content 的值即可,如下圖所示:

另外,我們發(fā)現(xiàn),代碼有非常多的在數(shù)組里面按索引取值的情況,比如上圖中的 _$PV[68] 的值,實(shí)際上就是字符串 content,很顯然我們要把這個(gè)數(shù)組的來(lái)源找到,直接搜索 _$PV =,可以找到疑似定義和賦值的地方:

所以我們得看看這個(gè) _$iL 方法,傳入了一個(gè)非常長(zhǎng)的字符串,打斷點(diǎn)進(jìn)去看看,果然生成了 _$PV,是一個(gè) 725 位的數(shù)組:

接下來(lái)在扣代碼的過(guò)程中,你會(huì)經(jīng)常遇到一個(gè)變量,在本文中是 _$sX

有沒(méi)有很熟悉?這個(gè)值就是我們前面拿到的 $_ts 變量,在開(kāi)頭就可以看到是將 window.$_ts 賦值給了 _$sX

繼續(xù)走,會(huì)走到以下邏輯中:

這里會(huì)遇到六個(gè)數(shù)組,他們都已經(jīng)有值了,所以我們得找到他們是咋來(lái)的,任意搜索其中一個(gè)數(shù)組名稱,會(huì)找到定義和賦值的地方:

賦值明顯是調(diào)用了 _$rv 方法,再搜 _$rv 方法,發(fā)現(xiàn)是開(kāi)頭就調(diào)用了:

后續(xù)沒(méi)有什么特別的,一直單步,最后有個(gè) join('') 操作,就生成了假 Cookie:

接下來(lái)是生成 Cookie 的名字 FSSBBIl1UgzbN7N80T,然后將 Cookie 賦值給 document.cookie,然后又向 localStorage 里面的 $_ck 賦了個(gè)值,localStorage 的內(nèi)容可以直接復(fù)制下來(lái),沒(méi)有太大影響。

單步跟真 Cookie,在本文中也就是 _$ZN(768, 1);,可以看到開(kāi)始進(jìn)入了無(wú)窮無(wú)盡的 if-else 控制流:

這里本地應(yīng)該怎樣處理呢?我的做法是以 _$Hn 和其值命名函數(shù),function _$Hn768(){} 就表示所有走 768 號(hào)控制流的方法,繼續(xù)跟,生成真 Cookie 的方法基本上在 747 號(hào)控制流,后續(xù)我們主要以 747 號(hào)控制流的各個(gè)步驟來(lái)看,747 號(hào)控制流扣出來(lái)的代碼大致如下:

單步跟 747 號(hào)控制流,會(huì)有個(gè)進(jìn)入第 709 號(hào)控制流的步驟,會(huì)取先前生成的假 Cookie,經(jīng)過(guò)一系列操作之后返回一個(gè)數(shù)組:

至此我們?cè)诒镜赝娇鄣拇a,如果正常的話,返回的數(shù)組也應(yīng)該是一樣的(后續(xù)的數(shù)據(jù)就不一樣了,有一些時(shí)間戳之類的參數(shù)參與運(yùn)算):

自動(dòng)化工具檢測(cè)

繼續(xù)跟 747 號(hào)控制流,會(huì)進(jìn)入 268 號(hào)控制流,接著進(jìn)入 154 號(hào)控制流,這里面會(huì)針對(duì)自動(dòng)化工具做一些檢測(cè),如下圖所示:

這里定義了一個(gè)變量 _$iL,檢測(cè)不通過(guò)就是1,后續(xù)又把這個(gè)變量賦值給了 _$aW,所以我們本地保持一致,也為 false 即可(其實(shí)我們不用自動(dòng)化工具的話,這一段檢測(cè)就不用管直接返回 false 就行):

20 位核心數(shù)組

繼續(xù)跟 268 號(hào)控制流,會(huì)進(jìn)入 668 號(hào)控制流,668 號(hào)控制流就兩個(gè)操作,一是生成一個(gè) 16 位數(shù)組,二是取 $_ts 里面的 4 個(gè)變量,加到前面的 16 位后面,組成一個(gè) 20 位數(shù)組,這 20 位數(shù)組的最后 4 位是瑞數(shù)核心,其中的映射關(guān)系搞錯(cuò)了請(qǐng)求是通不過(guò)的,在五代中這部分的處理邏輯會(huì)更加復(fù)雜。

這里不是單純的取 $_ts 里的鍵值對(duì),你在扣代碼的時(shí)候,你也許會(huì)發(fā)現(xiàn)怎么本地到這里取值的時(shí)候,取出來(lái)的不是數(shù)字,而是字符串呢?就像下面這種情況:

實(shí)際上我們最開(kāi)始得到的 $_ts 值,是經(jīng)過(guò)了二次處理的,我們以第一個(gè) _$sX._$Xb 為例,直接搜索 _$sX._$Xb,可以發(fā)現(xiàn)這么一個(gè)地方:

很明顯這里給 _$sX._$Xb 重新賦值了一遍,我們可以看到等號(hào)右邊,先取了一次 _$sX._$Xb,其值為 _$Rm,這和我們初始 $_ts 里面對(duì)應(yīng)的值是一樣的,然后我們就得再看看 _$sX["_$Rm"] 又是何方神圣,直接搜索發(fā)現(xiàn)是開(kāi)頭賦值了一個(gè)方法,通過(guò)調(diào)用這個(gè)方法來(lái)生成新的值:

另外其他三個(gè)值也是同樣的套路,賦值的代碼分別為:

_$sX._$Xb = _$sX[_$sX._$Xb](_$BH, _$DP);
_$sX._$oI = _$sX[_$sX._$oI](_$ZJ, _$DS)
_$sX._$EN = _$sX[_$sX._$EN]();
_$sX._$D9 = _$sX[_$sX._$D9](_$iL);

實(shí)際上應(yīng)該是:

_$sX._$Xb = _$sX["_$Rm"](_$BH, _$DP);
_$sX._$oI = _$sX["_$Nw"](_$ZJ, _$DS)
_$sX._$EN = _$sX["_$Uh"]();
_$sX._$D9 = _$sX["_$ci"](_$iL);

進(jìn)一步來(lái)說(shuō),實(shí)際上是:

_$sX._$Xb = _$1k(_$BH, _$DP);
_$sX._$oI = _$jH(_$ZJ, _$DS)
_$sX._$EN = _$9M();
_$sX._$D9 = _$oL(_$iL);

靜態(tài)分析沒(méi)問(wèn)題,我們可以先固定下來(lái),但是實(shí)際應(yīng)用當(dāng)中這些值都是動(dòng)態(tài)的,那我們應(yīng)該怎么處理呢?先來(lái)多看幾個(gè)對(duì)比一下找找規(guī)律:

可以發(fā)現(xiàn)每次對(duì)應(yīng)的位次都不一樣,但是實(shí)際上相同位置的方法點(diǎn)進(jìn)去都是一樣的,也就是說(shuō),變的只有方法名和變量名,實(shí)現(xiàn)的邏輯是不變的,所以我們只要知道了這四個(gè)值分別對(duì)應(yīng)的位置,就能夠拿到正確的值,在本地,我們就可以這樣做:

1、先利用正則匹配出這四個(gè)值,如:[_$sX._$Xb, _$sX._$oI, _$sX._$EN, _$sX._$D9];

2、再匹配出 VM 代碼開(kāi)頭的 20 個(gè)賦值的語(yǔ)句,如:_$sX._$RH = _$wI; _$sX._$i5 = _$n5; 等;

3、然后通過(guò) $_ts 取這四個(gè)值對(duì)應(yīng)的值,相當(dāng)于:_$sX._$Xb = _$ts._$Xb = _$Rm;然后再找這四個(gè)值所定義的方法在 20 個(gè)賦值語(yǔ)句中的位置,相當(dāng)于:查找 _$sX._$Rm = _$1k; 在 20 個(gè)賦值語(yǔ)句中的位置為 7(索引從 0 開(kāi)始)

4、我們知道了這四個(gè)方法在 20 個(gè)賦值語(yǔ)句中的位置,那么我們直接匹配本地對(duì)應(yīng)位置的名稱,進(jìn)行動(dòng)態(tài)替換即可,當(dāng)然前提是咱們本地已經(jīng)扣了一套代碼出來(lái)了:

經(jīng)過(guò)這樣處理后,就能夠保證這四個(gè)值的準(zhǔn)確性了。

其他用到 $_ts 值的地方

除了上面說(shuō)的 20 位數(shù)組里用到了 4 個(gè) $_ts 的值以外,還有其他地方有 7 個(gè)值也用到了,直接搜索就能定位,這 7 個(gè)值相對(duì)較簡(jiǎn)單,每次都是固定取 $_ts 里面的第 2、3、4、15、16、17、19 位的值,同樣的,找到對(duì)應(yīng)位置,進(jìn)行動(dòng)態(tài)替換即可:

注意事項(xiàng)

特別注意 VM 代碼開(kāi)頭,會(huì)直接調(diào)用執(zhí)行一些方法,某些變量的值就是通過(guò)這些方法生成的,當(dāng)你一步一步跟的時(shí)候發(fā)現(xiàn)某些參數(shù)不對(duì),或者沒(méi)有,那么就得注意開(kāi)頭這些方法了,可能一開(kāi)始就已經(jīng)生成了。

后綴 MmEwMD 生成邏輯

后續(xù)的其他 XHR 請(qǐng)求中,都帶有一個(gè)后綴,這個(gè)后綴的值同樣是由 JS 生成的,每次都會(huì)變化,當(dāng)然不同網(wǎng)站,后綴名不一定都是一樣的,本例中是 MmEwMD,先下一個(gè) XHR 斷點(diǎn),當(dāng) XHR 請(qǐng)求中包含了 MmEwMD= 時(shí)就斷下,然后刷新網(wǎng)頁(yè):

可以看到后傳入 l.open() 的 URL 還是正常的,斷下后到 l.send() 就帶有后綴了,再看 l.open() 其實(shí)就是 xhr.open(),明顯和正常的有區(qū)別,同樣這個(gè)方法也在 VM 代碼里,應(yīng)該是重寫(xiě)了方法,可以和正常的做對(duì)比:

跟到 VM 代碼里去看看,經(jīng)過(guò)了 _$sd(arguments[1]) 方法就變成了帶有后綴的完整鏈接了:

跟進(jìn) _$sd 方法,前面都是對(duì) url 做一些處理,后面有個(gè)進(jìn)入第 779 號(hào)控制流的流程,實(shí)際上就是原來(lái)我們生成 Cookie 的步驟,跟一下就行了。

善用 Watch 跟蹤功能

開(kāi)發(fā)者工具的 Watch 功能能夠持續(xù)跟蹤某個(gè)變量的值,對(duì)于這種控制流很多的情況,設(shè)置相應(yīng)的變量跟蹤,能夠讓你知道你現(xiàn)在處于哪個(gè)控制流中,以及生成的數(shù)組的變化,不至于跟著跟著不知道到哪一步了。

結(jié)果驗(yàn)證

如果整個(gè)流程沒(méi)問(wèn)題,代碼也扣得正確,攜帶正確的 Cookie 和正確的后綴,就能成功訪問(wèn):


分享標(biāo)題:人均瑞數(shù)系列,瑞數(shù) 4 代 JS 逆向分析
標(biāo)題鏈接:http://weahome.cn/article/dsogggc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部