1.函數重定義
防止在當前上下文中使用輸出語句觀察結果。
console.log("Hello World");
var fake = function() {};
window['console']['log'] = fake;
console.log("You can't see me!");
console.log("Normal function");
//
var original = window['console']['log'];
//
var fake = function(argument) {
if (argument === "Ka0labs") {
original("Spoofed!");
} else {
original(argument);
}
}
window['console']['log'] = fake;
console.log("This is unaltered");
console.log("Ka0labs");
console.log("Bye bye!");
2.使用debugger語句
如果在chrome中打開了開發者模式,通過debugger語句可以阻塞當前執行流程。在很多頁面中我們也會看到這種用法。
console.log("See me!");
debugger;
console.log("See me!");
3.利用時間差判斷是否處於調試狀態
performance對象可以用來進行性能分析。performance.now() 方法返回從頁面初始化到調用該方法時的毫秒數。
函數輸出的是相對於performance.timing.navigationStart的時間。當在開發者模式(DevTools)下執行時,執行時間會顯著增加。因此可以用來判斷是否處於開發者模式下。
setInterval(function(){
var startTime = performance.now(), check, diff;
for (check = 0; check < 1000; check++){
console.log(check);
console.clear();
}
diff = performance.now() - startTime;
if (diff > 200){
alert("Debugger detected!");
}
}, 500);
其次結合debugger,來判斷兩點的時間。
var startTime = performance.now();
debugger;
var stopTime = performance.now();
if ((stopTime - startTime) > 1000) {
alert("Debugger detected!")
}
4.自定義div的getter方法進行Devtools環境檢測
創建一個div,並定義該div id的屬性描述對象。當在devtools環境下通過console.log輸出div對象時,瀏覽器會自動嘗試獲取div的id。那麼這時自定義的get方法會被調用。因此檢測出devtools環境。
let div = document.createElement('div');
let loop = setInterval(() => {
console.log(div);
console.clear();
});
Object.defineProperty(div, "id", {get: () => {
clearInterval(loop);
alert("Dev Tools detected!");
});
5.檢測窗口大小變化
如果打開Devtools,window.outerWidth/Height和window.innerWidth/Height
將會變化,因此可以在一個循環中嘗試檢測。
const widthThreshold = window.outerWidth - window.innerWidth > threshold;
const heightThreshold = window.outerHeight - window.innerHeight > threshold;
const orientation = widthThreshold ? 'vertical' : 'horizontal';
https://github.com/sindresorhus/devtools-detect 項目提供了devtools檢測的方法。
6. 函數調用蹤跡識別
通過arguments.callee.caller可以獲取調用蹤跡。並通過獲取的蹤跡生成一個哈希值,並以該hash值爲key對加密的代碼揭祕。一個加密的代碼有多部分組成,後一部分的加密代碼通過前一部分的代碼生成的key揭祕得到並執行。如果代碼被修改後續揭祕會發生錯誤。隨後我們可以捕獲異常,並將執行流程重定向到一個錯誤的錯誤的路徑上。
function getCallStack() {
var stack = "#", total = 0, fn = arguments.callee;
while ( (fn = fn.caller) ) {
stack = stack + "" +fn.name;
total++
}
return stack
}
function test1() {
console.log(getCallStack());
}
function test2() {
test1();
}
function test3() {
test2();
}
function test4() {
test3();
}
test4();
7.計算函數哈希值
通過函數的toString獲取函數代碼字符串。接着計算該字符串的hash值,從而來判斷代碼是否被重定義。對這個功能可以用來檢查函數是否被重定義。
function a() {
console.log("a");
}
a.toString();
8.代理對象
我們可以通過toString length屬性檢測代理對象的使用。
chrome下document.createElement.toString().length
結果爲 42
當我們創建一個代理時,這個值會發生變化。
const handler = {
apply: function(target, thisArg, args) {
console.log("Intercepted call");
return target.apply(thisArg, args);
}
}
document.createElement = new Proxy(document.createElement, handler);
document.createElement.toString().length
返回結果爲29
因此可以進行檢測。
if (document.createElement.toString().length < 30) {
console.log("I saw your proxy");
}
else {
console.log("Not a proxy");
}
該方法不能用於window對象,但在思路上有一定啓發作用。即創建一個代理對象後某些函數結果或屬性會發生變化,利用這些差異去進行檢測。
9.環境檢測
這類檢查思路就是利用不同環境裏的差異進行檢測。
例如檢測hostname
if (location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.hostname === "") {
console.log("Don't run me here!")
}
NodeJS detected!!!!
window對象檢測
try {
.. console.log(window);
} catch(e){
.. console.log("NodeJS detected!!!!");
}
nodejs 環境檢測
//Under the browser
console.log(global)
VM104:1 Uncaught ReferenceError: global is not defined
at <anonymous>:1:13
//Under NodeJS
console.log(global)
{ console:
Console {
log: [Function: bound log],...
...