本帖最后由 xxkz 于 2024-03-20 21:48 编辑
在調試前可先用fiddler 等工具固定滑塊頁面,這樣會方便很多 跟n值生成位置第一種方法在滑動滑塊前先下個script 斷點,然後會斷在這裡 這時去看網路面板,可以發現滑塊的驗證是通過nocaptcha/analyze.jsonp 這個接口,其中最關鍵的參數就是n 簡單跟下棧就能找到n 的生成位置,o.__fy_options 固定就可以 第二種方法這種方法是在別的大佬的文章看到的,一開始我是用第一種方法找到的,但第二種方法感覺也挺好的,特此記錄一下 下個全局的的mousedown 斷點 斷下後走幾步會到這裡,看到它添加了一個mousemove 事件,跟入s 看看 經過一些操作後進入i ,繼續深入i 看看 前面先移除了各種事件,最後進入了m 函數 然後m 函數就是n 值生成的位置 本地&瀏覽器調試通常我找到密文生成位置後,會先嘗試導出相關函數,然後在本地簡單補下環境,先讓其出值( 雖然這個值大概率還不能使用 ) 本地出值由於我比較懶,我是直接將幾個可能用到的js文件放到本地的環境,然後通過導出相關函數來生成n 值。 如下所示,按awsc.js 、et_f.js 、fireyejs.js 、nc.js 的順序 在導出加密函數o.__fy.getFYToken 時發現要先初始化一些環境,跟棧找到m.init ,這裡直接導出m 本地調用如下: 然後就可以導出o.__fy.getFYToken 的o 對象 ( 代碼最好不要格式化,防止有檢測 ) 本地調用如下: 在awsc.js 、et_f.js 、fireyejs.js 、nc.js 這幾個環境初始化時,或者是在getFYToken 加密的過程中,需要手動補瀏覽器的環境,以下是部份我遇到要補的環境: - 調用
getComputedStyle 取了body所有的屬性,然後放到pe中
具體效果如這兩句代碼一致 t = getComputedStyle(document.body); pe = [].slice.call(t)
Performance.prototype.getEntriesByType font 指紋
// 1 ke = Ee[re] != y[J] // 2 ke = Ee[Be] != B[J]
補著補著就能出值了,這是個好的開始 AST解混淆在進行瀏覽器跟值這一步前,強烈建議先解一解fireyejs.js 的混淆( 主要邏輯在這個js文件裡 )。 ( 一開始我唔信邪硬剛左一個星期,跟值跟到自閉,無奈只能放棄哩個on9做法… ) 由於我ast比較菜,所以只解到了多層switch →單switch 那裡,但由於變量作用域等問題,多層switch →單switch 的代碼無法替換瀏覽器裡原本的代碼( 簡單來說就是用不了 )。 雖然不能直接替換使用,但在分析時( 向上跟值、跟調用順序 )卻大有用處,眾所周知控制流平坦化是無法直接通過跟棧來找到上一步的,只能通過控制流的狀態變量一步一步往上跟,而只有一層的switch控制流比起多層嵌套的switch控制流就容易跟值多了。 舉例來說,以下是只有一層的switch控制流,假如狀態變量是li ,我想跟case 5157 的上一步是哪,直接搜li = 5157 ,若有多個結果就全部下斷,看它走哪裡
case 5157: S = b = [U + 64 * ye]; li = 19041; break; case 5184: R = k = f; if (bo = (P = (fe = fe < 15) * fe) > (Y = (A = 215 | (bo = !hi)) << 25)) { li = 1349; } else { li = 14688; } break; case 5185: to = Ke = to; lo = ao; go = ze; qo = ho; To = (Xo = ne)[ei]; Lo = To[Wo](zo); Eo = i[Je](Lo, 36, to, 0, lo, 1); No = Xo[_o](Eo, eo); eo = i[Je](Lo, 36, to, No, go); li = 13380; break;
瀏覽器跟值主要目標是找到軌跡相關的邏輯 跟進o.__fy.getFYToken ,會走到i(40, e) 這裡 單步走幾步,發現s 數組,看它的內容很像是一個環境的特徵數組,s[90] 還特別像是與軌跡有關,經測試後發現確實如此( 所謂測試就是鼠標多滑幾下或少滑幾下,看看這個s[90] 的長度是否符合預期 ),接下來看看這個s 數組的某幾項: s[5] :鼠標點擊前的軌跡數組長度 - 1 ( 計mousedown那一下的軌跡 )s[46] :與s[5] 類似,但不計mousedown那一下的軌跡,因此比s[5] 小1,由i(25) 觸發s[26] :前兩項是WebGLRenderingContext 的東西,第3項的"undefined" 是觸發DeviceOrientationEvent 事件而來,第4、5項是觸發MouseEvent 而來,鼠標在頁面不同位置時,對應的target ( html頁面中的某個元素 )也不一樣,取的是target["id"]
s[23] :由ScriptProcessorNode 的onaudioprocess 事件生成,而onaudioprocess 事件是通過觸發全局的mousedown 而來,具體值的來源是AnalyserNode.prototype.getFloatFrequencyData
s[48] :與timestamp有關的數組
s[91] :promise的回調( 看堆棧就知道 )
s[52] :同樣是某個promise的回調觸發的
s[3] :由FocusEvent 觸發
s[90] :最重要的軌跡數組,有以下幾個要點:
- 由
mousedown 、mousemove 觸發( 全局正常會有2個mousemove 、mousedown 事件,要用第2個 ),每次會生成一個軌跡 - 軌跡主要取
MouseEvent.clientX 、MouseEvent.clientY 、timestamp 、MouseEvent.pageY 、MouseEvent.pageX 等,並進行了異或等咚悖虼酥苯涌碻s[90]`會與軌跡值對不上 - 這個軌跡數組並非鼠標點擊後才開始push,而是只要在頁面上動就會一直在push,因此軌跡數組可能要分成點擊前和點擊後
- 有兩種軌跡,分別是length為
17 和length為18 的,嘗試過找為什麼有兩種不同的軌跡,但放棄了,最後我在本地手動構建軌跡時發現我的s[90] 同樣有這兩種,就沒有深究了 快速獲取軌跡的方法:在i 函數一開始下條件斷點
o instanceof MouseEvent && ( window.slideArr ? window.slideArr.push({"pageX":o.pageX, "pageY":o.pageY, "clientX":o.clientX, "clientY":o.clientY}) : window.slideArr = [], false)
本地調用結果
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|