詳解JavaScript常用的Hook腳本
本文Hook腳本 來自 包子
頁面最早加載代碼Hook時(shí)機(jī)
- 在source里 用dom事件斷點(diǎn)的script斷點(diǎn)
- 然后刷新網(wǎng)頁,就會斷在第一個(gè)js標(biāo)簽,這時(shí)候就可以注入代碼進(jìn)行hook
監(jiān)聽 鍵盤 與 鼠標(biāo) 事件
// 判斷是否按下F12 onkeydown事件
/*
提示:?與 onkeydown 事件相關(guān)聯(lián)的事件觸發(fā)次序:
onkeydown
onkeypress
onkeyup
*/
// F12的鍵碼為 123,可以直接全局搜索 keyCode == 123, == 123 ,keyCode
document.onkeydown = function() {
if (window.event && window.event.keyCode == 123) {
// 改變鍵碼
event.keyCode = 0;
event.returnValue = false;
// 監(jiān)聽到F12被按下直接關(guān)閉窗口
window.close();
window.location = "about:blank";
}
}
;
// 監(jiān)聽鼠標(biāo)右鍵是否被按下方法 1, oncontextmenu事件
document.oncontextmenu = function () { return false; };
// 監(jiān)聽鼠標(biāo)右鍵是否被按下方法 2,onmousedown事件
document.onmousedown = function(evt){
// button屬性是2 就代表是鼠標(biāo)右鍵
if(evt.button == 2){
alert('監(jiān)聽到鼠標(biāo)右鍵被按下')
evt.preventDefault() // 該方法將通知 Web 瀏覽器不要執(zhí)行與事件關(guān)聯(lián)的默認(rèn)動作
return false;
// 監(jiān)聽用戶工具欄調(diào)起開發(fā)者工具,判斷瀏覽器的可視高度和寬度是否有改變,有改變則處理,
// 判斷是否開了開發(fā)者工具不太合理。
var h = window.innerHeight, w = window.innerWidth;
window.onresize = function(){
alert('改變了窗口高度')
// hook代碼
(function() {
//嚴(yán)謹(jǐn)模式 檢查所有錯(cuò)誤
'use strict';
// hook 鼠標(biāo)選擇
Object.defineProperty(document, 'onselectstart', {
set: function(val) {
console.log('Hook捕獲到選中設(shè)置->', val);
return val;
}
});
// hook 鼠標(biāo)右鍵
Object.defineProperty(document,'oncontextmenu',{
set:function(evt){
console.log("檢測到右鍵點(diǎn)擊");
return evt
});
})();webpack hook 半自動扣
//在加載器后面下斷點(diǎn) 執(zhí)行下面代碼
// 這里的f 替換成需要導(dǎo)出的函數(shù)名
window.zhiyuan = f;
window.wbpk_ = "";
window.isz = false;
f = function(r){
if(window.isz)
{
// e[r]里的e 是加載器里的call那里
window.wbpk_ = window.wbpk_ + r.toString()+":"+(e[r]+"")+ ",";
}
return window.zhiyuan(r);
}
//在你要的方法加載前下斷點(diǎn) 執(zhí)行 window.isz=true
//在你要的方法運(yùn)行后代碼處下斷點(diǎn) 執(zhí)行 window.wbpk_ 拿到所有代碼 注意后面有個(gè)逗號
function o(t) {
if (n[t])
return n[t].exports;
var i = n[t] = {
i: t,
l: !1,
exports: {}
};
console.log("被調(diào)用的 >>> ", e[t].toString());
// 這里進(jìn)行拼接,bb變量需要在全局定義一下
// t 是模塊名, e[t] 是模塊對應(yīng)的函數(shù), 也就是key:value形式
bb += `"${t}":${e[t].toString()},`
return e[t].call(i.exports, i, i.exports, o),
i.l = !0,
i.exports
bz = o;如果只是調(diào)用模塊,不用模塊里面的方法, 那么直接獲取調(diào)用模塊的時(shí)候所有加載過的模塊,進(jìn)行拼接
document下的createElement()方法的hook,查看創(chuàng)建了什么元素
(function() {
'use strict'
var _createElement = document.createElement.bind(document);
document.createElement = function(elm){
// 這里做判斷 是否創(chuàng)建了script這個(gè)元素
if(elm == 'body'){
debugger;
}
return _createElement(elm);
}
})();
之前我不知道我用的是 var _createElement = document.createElement 導(dǎo)致一直報(bào)錯(cuò) Uncaught TypeError: Illegal invocation
原來是需要綁定一下對象 var _createElement = document.createElement.bind(document);
headers hook 當(dāng)header中包含Authorization時(shí),則插入斷點(diǎn)
var code = function(){
var org = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function(key,value){
if(key=='Authorization'){
debugger;
}
return org.apply(this,arguments);
}
}
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);請求hook 當(dāng)請求的url里包含MmEwMD時(shí),則插入斷點(diǎn)
var code = function(){
var open = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, url, async){
if (url.indexOf("MmEwMD")>-1){
debugger;
}
return open.apply(this, arguments);
};
}
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);docuemnt.getElementById以及value屬性的hook
//?docuemnt.getElementById?以及value屬性的hook,可以參考完成innerHTML的hook
document.getElementById?=?function(id)?{
????var?value?=?document.querySelector('#'?+?id).value;
????console.log('DOM操作?id:?',?id)
????try?{
????????Object.defineProperty(document.querySelector('#'+?id),?'value',?{
????????????get:?function()?{
????????????????console.log('getting?-',?id,?'value?-',?value);
????????????????return?value;
????????????},
????????????set:?function(val)?{
????????????????console.log('setting?-',?id,?'value?-',?val)
????????????????value?=?val;
????????????}
????????})
????}?catch?(e)?{
????????console.log('---------華麗的分割線--------')
????}
????return?document.querySelector('#'?+?id);
}過debugger 阿布牛逼
function Closure(injectFunction) {
return function() {
if (!arguments.length)
return injectFunction.apply(this, arguments)
arguments[arguments.length - 1] = arguments[arguments.length - 1].replace(/debugger/g, "");
return injectFunction.apply(this, arguments)
}
}
var oldFunctionConstructor = window.Function.prototype.constructor;
window.Function.prototype.constructor = Closure(oldFunctionConstructor)
//fix native function
window.Function.prototype.constructor.toString = oldFunctionConstructor.toString.bind(oldFunctionConstructor);
var oldFunction = Function;
window.Function = Closure(oldFunction)
window.Function.toString = oldFunction.toString.bind(oldFunction);
var oldEval = eval;
window.eval = Closure(oldEval)
window.eval.toString = oldEval.toString.bind(oldEval);
// hook GeneratorFunction
var oldGeneratorFunctionConstructor = Object.getPrototypeOf(function*() {}).constructor
var newGeneratorFunctionConstructor = Closure(oldGeneratorFunctionConstructor)
newGeneratorFunctionConstructor.toString = oldGeneratorFunctionConstructor.toString.bind(oldGeneratorFunctionConstructor);
Object.defineProperty(oldGeneratorFunctionConstructor.prototype, "constructor", {
value: newGeneratorFunctionConstructor,
writable: false,
configurable: true
})
// hook Async Function
var oldAsyncFunctionConstructor = Object.getPrototypeOf(async function() {}).constructor
var newAsyncFunctionConstructor = Closure(oldAsyncFunctionConstructor)
newAsyncFunctionConstructor.toString = oldAsyncFunctionConstructor.toString.bind(oldAsyncFunctionConstructor);
Object.defineProperty(oldAsyncFunctionConstructor.prototype, "constructor", {
value: newAsyncFunctionConstructor,
// hook dom
var oldSetAttribute = window.Element.prototype.setAttribute;
window.Element.prototype.setAttribute = function(name, value) {
if (typeof value == "string")
value = value.replace(/debugger/g, "")
// 向上調(diào)用
oldSetAttribute.call(this, name, value)
;
var oldContentWindow = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "contentWindow").get
Object.defineProperty(window.HTMLIFrameElement.prototype, "contentWindow", {
get() {
var newV = oldContentWindow.call(this)
if (!newV.inject) {
newV.inject = true;
core.call(newV, globalConfig, newV);
}
return newV過debugger—1 constructor 構(gòu)造器構(gòu)造出來的
var _constructor = constructor;
Function.prototype.constructor = function(s) {
if (s == "debugger") {
console.log(s);
return null;
}
return _constructor(s);
}過debugger—2 eval的
(function() {
'use strict';
var eval_ = window.eval;
window.eval = function(x) {
eval_(x.replace("debugger;", " ; "));
}
;
window.eval.toString = eval_.toString;
}
)();JSON HOOK
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {
//這里可以添加其他邏輯比如 debugger
console.log("json_stringify params:",params);
return my_stringify(params);
};
var my_parse = JSON.parse;
JSON.parse = function (params) {
//這里可以添加其他邏輯比如 debugger
console.log("json_parse params:",params);
return my_parse(params);
};對象屬性hook 屬性自定義
(function(){
// 嚴(yán)格模式,檢查所有錯(cuò)誤
'use strict'
// document 為要hook的對象 ,屬性是cookie
Object.defineProperty(document,'cookie',{
// hook set方法也就是賦值的方法,get就是獲取的方法
set: function(val){
// 這樣就可以快速給下面這個(gè)代碼行下斷點(diǎn),從而快速定位設(shè)置cookie的代碼
debugger; // 在此處自動斷下
console.log('Hook捕獲到set-cookie ->',val);
return val;
}
})
})();
cookies - 1 (不是萬能的 有些時(shí)候hook不到 自己插入debugger)
var cookie_cache = document.cookie;
Object.defineProperty(document, 'cookie', {
get: function() {
console.log('Getting cookie');
return cookie_cache;
},
set: function(val) {
console.log("Seting cookie",val);
var cookie = val.split(";")[0];
var ncookie = cookie.split("=");
var flag = false;
var cache = cookie_cache.split("; ");
cache = cache.map(function(a){
if (a.split("=")[0] === ncookie[0]){
flag = true;
return cookie;
}
return a;
})
}
})cookies - 2
var code = function(){
var org = document.cookie.__lookupSetter__('cookie');
document.__defineSetter__("cookie",function(cookie){
if(cookie.indexOf('TSdc75a61a')>-1){
debugger;
}
org = cookie;
});
document.__defineGetter__("cookie",function(){return org;});
}
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
// 當(dāng)cookie中匹配到了?TSdc75a61a, 則插入斷點(diǎn)。window attr
// 定義hook屬性
var window_flag_1 = "_t";
var window_flag_2 = "ccc";
var key_value_map = {};
var window_value = window[window_flag_1];
// hook
Object.defineProperty(window, window_flag_1, {
get: function(){
console.log("Getting",window,window_flag_1,"=",window_value);
//debugger
return window_value
},
set: function(val) {
console.log("Setting",window, window_flag_1, "=",val);
window_value = val;
key_value_map[window[window_flag_1]] = window_flag_1;
set_obj_attr(window[window_flag_1],window_flag_2);
});
function set_obj_attr(obj,attr){
var obj_attr_value = obj[attr];
Object.defineProperty(obj,attr, {
get: function() {
console.log("Getting", key_value_map[obj],attr, "=", obj_attr_value);
//debugger
return obj_attr_value;
},
set: function(val){
console.log("Setting", key_value_map[obj], attr, "=", val);
obj_attr_value = val;
});
}eval/Function
window.__cr_eval = window.eval;
var myeval = function(src) {
// src就是eval運(yùn)行后 最終返回的值
console.log(src);
console.log("========= eval end ===========");
return window.__cr_eval;
}
var _myeval = myeval.bind(null);
_myeval.toString = window.__cr_eval.toString;
Object.defineProperty(window, 'eval',{value: _myeval});
window._cr_fun = window.Function
var myfun = function(){
var args = Array.prototype.slice.call(arguments, 0, -1).join(","), src = arguments[arguments.lenght -1];
console.log("======== Function end =============");
return window._cr_fun.apply(this, arguments)
myfun.toString = function() {return window._cr_fun + ""} //小花招,這里防止代碼里檢測原生函數(shù)
Object.defineProperty(window, "Function",{value: myfun})eval 取返回值
_eval = eval;
eval = (res)=>{
res1 = res // 返回值
return _eval(res)
}
eval(xxxxxxxxx)eval proxy代理 https://segmentfault.com/a/1190000025154230
// 代理eval
eval = new Proxy(eval,{
// 如果代理的是函數(shù) 查看調(diào)用 就用apply屬性
// 第二個(gè)參數(shù)是prop 這里用不上 因?yàn)槭菍傩?,eval只是個(gè)函數(shù) 所以prop為undefind 這里設(shè)置了下劃線 ——
apply: (target,_,arg)=>{
// target 是被代理的函數(shù)或?qū)ο竺Q,當(dāng)前是[Function: eval]
// arg是傳進(jìn)來的參數(shù),返回的是個(gè)列表
console.log(arg[0])
}
})
// eval執(zhí)行的時(shí)候就會被代理攔截
// 傳入的如果是字符串 那么只會返回字符串,這里是匿名函數(shù) 直接執(zhí)行 return了內(nèi)容
eval(
(function(){return "我是包子 自己執(zhí)行了"})()
)
// 結(jié)果 : 我是包子 自己執(zhí)行了websocket hook
// 1、webcoket 一般都是json數(shù)據(jù)格式傳輸,那么發(fā)生之前需要JSON.stringify
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {
//這里可以添加其他邏輯比如 debugger
console.log("json_stringify params:",params);
return my_stringify(params);
};
var my_parse = JSON.parse;
JSON.parse = function (params) {
console.log("json_parse params:",params);
return my_parse(params);
// 2 webScoket 綁定在windows對象,上,根據(jù)瀏覽器的不同,websokcet名字可能不一樣
//chrome window.WebSocket firfox window.MozWebSocket;
window._WebSocket = window.WebSocket;
// hook send
window._WebSocket.prototype.send = function (data) {
console.info("Hook WebSocket", data);
return this.send(data)
}
Object.defineProperty(window, "WebSocket",{value: WebSocket})hook 正則 —— 1
(function?()?{
????var?_RegExp?=?RegExp;
????RegExp?=?function?(pattern,?modifiers)?{
????????console.log("Some?codes?are?setting?regexp");
????????debugger;
????????if?(modifiers)?{
????????????return?_RegExp(pattern,?modifiers);
????????}?else?{
????????????return?_RegExp(pattern);
????????}
????};
????RegExp.toString?=?function?()?{
????????return?"function?setInterval()?{?[native?code]?}"
????};
})();
hook 正則 2 加在sojson頭部過字符串格式化檢測
(function() {
var _RegExp = RegExp;
RegExp = function(pattern, modifiers) {
if (pattern == decodeURIComponent("%5Cw%2B%20*%5C(%5C)%20*%7B%5Cw%2B%20*%5B'%7C%22%5D.%2B%5B'%7C%22%5D%3B%3F%20*%7D") || pattern == decodeURIComponent("function%20*%5C(%20*%5C)") || pattern == decodeURIComponent("%5C%2B%5C%2B%20*(%3F%3A_0x(%3F%3A%5Ba-f0-9%5D)%7B4%2C6%7D%7C(%3F%3A%5Cb%7C%5Cd)%5Ba-z0-9%5D%7B1%2C4%7D(%3F%3A%5Cb%7C%5Cd))") || pattern == decodeURIComponent("(%5C%5C%5Bx%7Cu%5D(%5Cw)%7B2%2C4%7D)%2B")) {
pattern = '.*?';
console.log("發(fā)現(xiàn)sojson檢測特征,已幫您處理。")
}
if (modifiers) {
console.log("疑似最后一個(gè)檢測...已幫您處理。")
console.log("已通過全部檢測,請手動處理debugger后盡情調(diào)試吧!")
return _RegExp(pattern, modifiers);
} else {
return _RegExp(pattern);
}
}
;
RegExp.toString = function() {
return _RegExp.toString();
}
;
}
)();
hook canvas (定位圖片生成的地方)
(function() {
'use strict';
let create_element = document.createElement.bind(doument);
document.createElement = function (_element) {
console.log("create_element:",_element);
if (_element === "canvas") {
debugger;
}
return create_element(_element);
}
})();setInterval 定時(shí)器
(function() {
setInterval_ = setInterval;
console.log("原函數(shù)已被重命名為setInterval_")
setInterval = function() {}
;
setInterval.toString = function() {
console.log("有函數(shù)正在檢測setInterval是否被hook");
return setInterval_.toString();
}
;
}
)();
setInterval 循環(huán)清除定時(shí)器
for(var i = 0; i < 9999999; i++) window.clearInterval(i)
console.log 檢測例子 (不讓你輸出調(diào)試)
var oldConsole = ["debug", "error", "info", "log", "warn", "dir", "dirxml", "table", "trace", "group", "groupCollapsed", "groupEnd", "clear", "count", "countReset", "assert", "profile", "profileEnd", "time", "timeLog", "timeEnd", "timeStamp", "context", "memory"].map(key=>{
var old = console[key];
console[key] = function() {}
;
console[key].toString = old.toString.bind(old)
return old;
}
)
檢測函數(shù)是否被hook例子
if (window.eval == 'native code') {
console.log('發(fā)現(xiàn)eval函數(shù)被hook了 開始死循環(huán)');
}
到此這篇關(guān)于JavaScript常用的Hook腳本的文章就介紹到這了,更多相關(guān)js hook腳本內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript將數(shù)組轉(zhuǎn)換為鏈表的方法
這篇文章主要介紹了JavaScript將數(shù)組轉(zhuǎn)換為鏈表的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
javascript-簡單的計(jì)算器實(shí)現(xiàn)步驟分解(附圖)
輸入內(nèi)容的判斷,對于事件對象的來源的判斷以及數(shù)學(xué)運(yùn)算“+,-,*,/”的使用,感興趣的朋友可以學(xué)習(xí)下2013-05-05
javascript模板方法模式和職責(zé)鏈模式實(shí)例分析
這篇文章主要介紹了javascript模板方法模式和職責(zé)鏈模式,結(jié)合實(shí)例形式較為詳細(xì)的分析了模板方法模式和職責(zé)鏈模式基本原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2023-07-07
JavaScript必知必會(十) call apply bind的用法說明
這篇文章主要介紹了JavaScript必知必會(十) call apply bind的用法說明 的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
基于JS實(shí)現(xiàn)移動端訪問PC端頁面時(shí)跳轉(zhuǎn)到對應(yīng)的移動端網(wǎng)頁
不想通過CSS自適應(yīng)在PC端和移動端分別顯示不同的樣式,那么只能通過在移動端訪問PC端網(wǎng)頁時(shí)跳轉(zhuǎn)到對應(yīng)的移動端網(wǎng)頁了,那么怎么跳轉(zhuǎn)呢,網(wǎng)上也有很多文章說明,以下實(shí)現(xiàn)思路經(jīng)過小編測試過,需要的朋友可以參考下2016-04-04

