如何基于JS截獲動(dòng)態(tài)代碼
這篇文章主要介紹了JS注入eval, Function系統(tǒng)函數(shù)并截獲動(dòng)態(tài)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
正文
現(xiàn)在很多網(wǎng)站都上了各種前端反爬手段,無(wú)論手段如何,最重要的是要把包含反爬手段的前端javascript代碼加密隱藏起來(lái),然后在運(yùn)行時(shí)實(shí)時(shí)解密動(dòng)態(tài)執(zhí)行。
動(dòng)態(tài)執(zhí)行js代碼無(wú)非兩種方法,即eval和Function。那么,不管網(wǎng)站加密代碼寫(xiě)的多牛,我們只要將這兩個(gè)方法hook住,即可獲取到解密后的可執(zhí)行js代碼。
注意,有些網(wǎng)站會(huì)檢測(cè)eval和Function這兩個(gè)方法是否原生,因此需要一些小花招來(lái)忽悠過(guò)去。
掛鉤代碼
首先是eval的掛鉤代碼:
(function() {
if (window.__cr_eval) return
window.__cr_eval = window.eval
var myeval = function (src) {
console.log("================ eval begin: length=" + src.length + ",caller=" + (myeval.caller && myeval.caller.name) + " ===============")
console.log(src);
console.log("================ eval end ================")
return window.__cr_eval(src)
}
var _myeval = myeval.bind(null) // 注意:這句和下一句就是小花招本招了!
_myeval.toString = window.__cr_eval.toString
Object.defineProperty(window, 'eval', { value: _myeval })
console.log(">>>>>>>>>>>>>> eval injected: " + document.location + " <<<<<<<<<<<<<<<<<<<")
})();
這段代碼執(zhí)行后,之后所有的eval操作都會(huì)在控制臺(tái)打印輸出將要執(zhí)行的js源碼。
同理可以寫(xiě)出Function的掛鉤代碼:
(function() {
if (window.__cr_fun) return
window.__cr_fun = window.Function
var myfun = function () {
var args = Array.prototype.slice.call(arguments, 0, -1).join(","), src = arguments[arguments.length - 1]
console.log("================ Function begin: args=" + args + ", length=" + src.length + ",caller=" + (myfun.caller && myfun.caller.name) + " ===============")
console.log(src);
console.log("================ Function end ================")
return window.__cr_fun.apply(this, arguments)
}
myfun.toString = function() { return window.__cr_fun + "" } // 小花招
Object.defineProperty(window, 'Function', { value: myfun })
console.log(">>>>>>>>>>>>>> Function injected: " + document.location + " <<<<<<<<<<<<<<<<<<<")
})();
注意:和eval不同,F(xiàn)unction是個(gè)有變長(zhǎng)參數(shù)的構(gòu)造方法,需要處理this
另外,有些網(wǎng)站還會(huì)用類似的機(jī)制加密頁(yè)面內(nèi)容,然后通過(guò)document.write輸出動(dòng)態(tài)解密的內(nèi)容,因此同樣可以掛鉤document.write,掛鉤方法類似eval,這里就不重復(fù)了。
注入方式
另外,還有個(gè)問(wèn)題需要關(guān)注,就是掛鉤代碼的注入方法。
最簡(jiǎn)單的就是F12調(diào)出控制臺(tái),直接執(zhí)行上面的代碼,但這樣只能hook住執(zhí)行之后的eval調(diào)用,如果希望從頁(yè)面剛加載時(shí)就注入,那么可以用以下幾種方式:
- 油猴注入,油猴可以監(jiān)聽(tīng)文檔加載的幾種不同狀態(tài),并在特定時(shí)刻執(zhí)行js代碼。我沒(méi)有太多研究,具體請(qǐng)參見(jiàn)油猴手冊(cè)
- 代理注入,修改應(yīng)答數(shù)據(jù),在<head>標(biāo)簽內(nèi)的第一個(gè)位置插入<script>節(jié)點(diǎn),確保在其它js加載執(zhí)行前注入;Fiddler, anyproxy等都可以編寫(xiě)外部規(guī)則,具體請(qǐng)參見(jiàn)附錄部分
- 使用chrome-devtools-protocol, 通過(guò)Page.addScriptToEvaluateOnNewDocument注入外部js代碼
- 附錄
不少人沒(méi)用過(guò)代理規(guī)則,這里寫(xiě)一下Fiddler和anyproxy的規(guī)則編寫(xiě)方法:
1. 如何添加Fiddler代理規(guī)則
Fiddler菜單里Rules > Customize Rules 打開(kāi)腳本編輯器
在腳本編輯器里找OnBeforeResponse方法,方法內(nèi)添加下面C#代碼:
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "html")){
oSession.utilDecodeResponse(); // Remove any compression or chunking
var b = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
var r = /<head[^>]*>/i;
var js = "..."; // 要注入的js源碼,見(jiàn)正文
b = b.replace(r, "$0<script>" + js + "</script>");
oSession.utilSetResponseBody(b); // Set the response body back
}
這樣就會(huì)在所有html文檔頭部自動(dòng)添加js代碼了
2. 如何添加anyproxy代理規(guī)則
編輯一個(gè)rule.js保存在anyproxy根目錄下,內(nèi)容如下:
function injectEval() {
if (window.__cr_eval) return
... // 見(jiàn)正文,此處略
console.log(">>>>>>>>>>>>>> eval injected: " + document.location + " <<<<<<<<<<<<<<<<<<<")
}
module.exports = {
summary: 'a rule to hook all eval',
*beforeSendResponse(requestDetail, {response}) {
if (response.header["Content-Type"].indexOf("text/html") >= 0) {
response.body = (response.body + "").replace(/<head[^>]*>/i, `$&<script>(${injectEval})();</script>`)
return {response}
}
},
};
帶規(guī)則啟動(dòng)anyproxy
anyproxy -r rule.js
可以看到,使用基于js的工具鏈有其天然優(yōu)勢(shì),即注入代碼可以以源碼而不是字符串形式和規(guī)則代碼共存,這樣可以利用到IDE的語(yǔ)法檢查、自動(dòng)完成等機(jī)制,能夠大大提高生產(chǎn)力。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
欄 目:JavaScript
下一篇:js實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊頁(yè)面彈出自定義文字效果
本文標(biāo)題:如何基于JS截獲動(dòng)態(tài)代碼
本文地址:http://www.jygsgssxh.com/a1/JavaScript/9398.html
您可能感興趣的文章
- 04-02包含javascript舍的詞條
- 01-10利用JS如何獲取form表單數(shù)據(jù)
- 01-10Angular如何由模板生成DOM樹(shù)的方法
- 01-10微信小程序如何獲取地址
- 01-10Vue中axios攔截器如何單獨(dú)配置token
- 01-10如何基于JavaScript判斷圖片是否加載完成
- 01-10uni-app如何實(shí)現(xiàn)增量更新功能
- 01-10基于jQuery實(shí)現(xiàn)掛號(hào)平臺(tái)首頁(yè)源碼
- 01-10微信小程序基于movable-view實(shí)現(xiàn)滑動(dòng)刪除效果
- 01-10JS如何實(shí)現(xiàn)網(wǎng)站中PC端和手機(jī)端自動(dòng)識(shí)別并跳轉(zhuǎn)對(duì)應(yīng)的代碼


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02javascript點(diǎn)線,點(diǎn)線的代碼
- 04-02javascript潛力,javascript強(qiáng)大嗎
- 04-02javascript替換字符串,js字符串的替換
- 04-02javascript移出,js 移入移出
- 04-02包含javascript舍的詞條
- 04-02javascript并行,深入理解并行編程 豆瓣
- 04-02javascript匿名,js匿名方法
- 04-02javascript警報(bào),JavaScript警告
- 04-02javascript遮蓋,JavaScript遮蓋PC端頁(yè)面
- 04-02javascript前身,javascript的前身
隨機(jī)閱讀
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什


