JavaScript逆向時,常用的11個hook
在逆向分析JavaScript代碼時,開發者經常使用一些用于hook(鉤子)的技術來監視或修改程序的行為。以下是一些常用的hook技術及其示例代碼。
1、dom操作
在JS逆向油猴腳本中,DOM操作是最常用的一種Hook方式。通過修改DOM元素的屬性和樣式,我們可以實現對網頁的控制和修改。
// 修改DOM元素的屬性
document.getElementById('elementId').setAttribute('attrName', 'attrValue');
// 修改DOM元素的樣式
document.getElementById('elementId').style.property = 'value';
2、Cookie操作
Cookie Hook 用于定位 Cookie 中關鍵參數生成位置,以下代碼演示了當 Cookie 中匹配到了 __dfp 關鍵字, 則插入斷點:
(function () {
'use strict';
var cookieTemp = '';
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.indexOf('__dfp') != -1) {
debugger;
}
console.log('Hook捕獲到cookie設置->', 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;
});
})();
3、事件監聽操作
事件監聽也是JS逆向油猴腳本中常用的一種Hook方式。通過監聽網頁上的事件,我們可以觸發自定義的操作和行為。
// 監聽按鈕點擊事件
document.getElementById('buttonId').addEventListener('click', function() {
// 自定義操作和行為
});
4、AJAX攔截操作
AJAX攔截也是JS逆向油猴腳本中常用的一種Hook方式。通過攔截網頁上的AJAX請求,我們可以實現對數據的控制和修改。
// 攔截AJAX請求
XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
// 自定義操作和行為
this._send.apply(this, arguments);
};
5、函數替換操作
函數替換也是JS逆向油猴腳本中常用的一種Hook方式。通過替換網頁上的函數,我們可以實現對函數的控制和修改。
// 替換原有函數
var originalFunction = window.functionName;
window.functionName = function() {
// 自定義操作和行為
originalFunction.apply(this, arguments);
};
6、Header操作
Header Hook 用于定位 Header 中關鍵參數生成位置,以下代碼演示了當 Header 中包含 Authorization 關鍵字時,則插入斷點:
(function () {
var org = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
if (key == 'Authorization') {
debugger;
}
return org.apply(this, arguments);
};
})()
7、URL操作
URL Hook 用于定位請求 URL 中關鍵參數生成位置,以下代碼演示了當請求的 URL 里包含 login 關鍵字時,則插入斷點:
(function () {
var open = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, url, async) {
if (url.indexOf("login") != 1) {
debugger;
}
return open.apply(this, arguments);
};
})();
8、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);
}
})();
9、JSON.parse操作
JSON.parse() 方法用于將一個 JSON 字符串轉換為對象,在某些站點的加密過程中可能會遇到,以下代碼演示了遇到 JSON.parse() 時,則插入斷點:
(function() {
var parse = JSON.parse;
JSON.parse = function(params) {
console.log("Hook JSON.parse ——> ", params);
debugger;
return parse(params);
}
})();
10、eval操作
JavaScript eval() 函數的作用是計算 JavaScript 字符串,并把它作為 腳本代碼來執行。如果參數是一個表達式,eval() 函數將執行表達式。如果參數是 Javascript 語句,eval() 將執行 Javascript 語句,經常被用來動態執行 JS。以下代碼執行后,之后所有的 eval() 操作都會在控制臺打印輸出將要執行的 JS 源碼:
(function() {
// 保存原始方法
window.__cr_eval = window.eval;
// 重寫 eval
var myeval = function(src) {
console.log(src);
console.log("=============== eval end ===============");
debugger;
return window.__cr_eval(src);
}
// 屏蔽 JS 中對原生函數 native 屬性的檢測
var _myeval = myeval.bind(null);
_myeval.toString = window.__cr_eval.toString;
Object.defineProperty(window, 'eval', {
value: _myeval
});
})();
11、Function操作
以下代碼執行后,所有的函數操作都會在控制臺打印輸出將要執行的 JS 源碼:
(function() {
// 保存原始方法
window.__cr_fun = window.Function;
// 重寫 function
var 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
});
})();