參照:
JS 逆向之 Hook
JS Hook 與 過 debugger
一、常用Hook
1. eval
(function() {let _eval = eval;eval = function(val) {if (val.indexof('debugger') === -1) {_eval_cache(obj);}}
})();
2. JSON.parse()
(function () {var parse_ = JSON.parse;JSON.parse = function (arg) {console.log(arg);debugger;return parse_(arg);};
})();
?3.JSON.stringify
JSON.stringify()
?方法用于將 JavaScript 值轉換為 JSON 字符串,在某些站點的加密過程中可能會遇到,以下代碼演示了遇到?JSON.stringify()
?時,則插入斷點:
(function() {var stringify = JSON.stringify;JSON.stringify = function(params) {console.log("Hook JSON.stringify ——> ", params);debugger;return stringify(params);}
})();
3.XMLHttpRequest(URL)
一般獲取請求中的參數
(function () {var _open = window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open = function (method, url, async) {if (url.indexOf("參數名稱") != -1) {debugger;}return _open.apply(this, arguments);};
})();
4.XMLHttpRequest(Header)
一般獲取header中的參數
(function () {var _setRequestHeader = window.XMLHttpRequest.prototype.setRequestHeader;window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {if (key == "header 的參數 key") {debugger;}return open.apply(this, arguments);};
})();
5.cookie
(function() {var cookieTemp = '';Object.defineProperty(document, 'cookie', {set: function (val) {if (val.indexOf('cookie 關鍵字') != -1) {debugger;}console.log(val);cookieTemp = val;return val;},get: function() {return cookieTemp;},});
})();(function () {'use strict';var org = document.cookie.__lookupSetter__('cookie');document.__defineSetter__('cookie', function (cookie) {if (cookie.indexOf('__dfp') != -1) {debugger;}org = cookie;});document.__defineGetter__('cookie', function () {return org;});
})();
6. Function
(function() {// 保存原始方法window.__cr_fun = window.Function;// 重寫 functionvar myfun = function() {var args = Array.prototype.slice.call(arguments, 0, -1).join(","),src = arguments[arguments.length - 1];console.log(src);console.log("=============== Function end ===============");debugger;return window.__cr_fun.apply(this, arguments);}// 屏蔽js中對原生函數native屬性的檢測myfun.toString = function() {return window.__cr_fun + ""}Object.defineProperty(window, 'Function', {value: myfun});
})();
?
二、無限 debugger
debugger 使用 Function.constructor / setInterval / eval?
1.?setInterval
比如setInterval(function () { debugger; }, 500);1. 方法置空setInterval = function() {};
2.eval
//通常以下代碼是加密構造出來的, eval 執行的是一個字符串變量。
eval("debugger;")
eval("(function() {var a = new Date(); debugger; return new Date() - a > 100;}())")1.使用字符串 replace("debugger;"," ") 方法,進行替換 debugger ,為防止對字符串進行長度檢測,常常使用等長的空格替換2.Hook(function() {var _eval = eval;eval = function(val) {if (val.indexof('debugger') === -1) {_eval_cache(obj);}}})();3.置空eval = function() {};
3.Function
// 常見形式
Function('debugger')()
(function(){return false;})['constructor']('debugger')['call']();xxx.constructor("debugger").call("action")1. Hook
Function.prototype.__constructor_back = Function.prototype.constructor;Function.prototype.constructor = function() {if(arguments && typeof arguments[0]==='string'){//alert("new function: "+ arguments[0]);if("debugger" === arguments[0]){//arguments[0]="console.log(\"anti debugger\");";//arguments[0]=";";return;}}return Function.prototype.__constructor_back.apply(this,arguments);
}
三、Object.defineProperty()
基本語法:Object.defineProperty(obj, prop, descriptor)
,它的作用就是直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,接收的三個參數含義如下:
obj
:需要定義屬性的當前對象;
prop
:當前需要定義的屬性名;
descriptor
:屬性描述符,可以取以下值:
屬性名 | 默認值 | 含義 |
---|---|---|
get | undefined | 存取描述符,目標屬性獲取值的方法 |
set | undefined | 存取描述符,目標屬性設置值的方法 |
value | undefined | 數據描述符,設置屬性的值 |
writable | false | 數據描述符,目標屬性的值是否可以被重寫 |
enumerable | false | 目標屬性是否可以被枚舉 |
configurable | false | 目標屬性是否可以被刪除或是否可以再次修改特性 |
?通常情況下,對象的定義與賦值是這樣的:
var people = {}
people.name = "Bob"
people["age"] = "18"console.log(people)
輸出{ name: 'Bob', age: '18' }
使用 Object.defineProperty() 方法:
var people = {}Object.defineProperty(people, 'name', {value: 'Bob',writable: true // 是否可以被重寫
})
//這個是重寫了people的name方法console.log(people.name) // 'Bob'people.name = "Tom"console.log(people.name) // 'Tom'
在 Hook 中,使用最多的是存取描述符,即 get 和 set。
get:屬性的 getter 函數,如果沒有 getter,則為 undefined,當訪問該屬性時,會調用此函數,執行時不傳入任何參數,但是會傳入 this 對象(由于繼承關系,這里的 this 并不一定是定義該屬性的對象),該函數的返回值會被用作屬性的值。
set:屬性的 setter 函數,如果沒有 setter,則為 undefined,當屬性值被修改時,會調用此函數,該方法接受一個參數,也就是被賦予的新值,會傳入賦值時的 this 對象。
用一個例子來演示:
var people = {name: 'Bob',
};
var count = 18;// 定義一個 age 獲取值時返回定義好的變量 count
Object.defineProperty(people, 'age', {get: function () {console.log('獲取值!');return count;},set: function (val) {console.log('設置值!');count = val + 1;},
});console.log(people.age);people.age = 20;console.log(people.age);