除此之外,也有人會透過把 console.log 覆蓋成空函數來讓分析者沒辦法順利使用 console 來 debug 。
偵測是否在 Debug五、比較視窗寬度高度DevTools 開啟會佔用螢幕空間,如果能偵測到高度差異,便有可能知道使用者是否有打開 DevTools 。在 JavaScript,可以透過 innerHeight / innerWidth 與 outerHeight / outerWidth 來取得網頁本身大小(inner)以及整個視窗的大小(outer),如果兩者相異過大,也許就代表 DevTools 正在開啟導致 innerHeight / innerWidth 縮小了 。
123456setInterval(() => {if (outerWidth - innerWidth > threshold ||outerHeight - innerHeight > threshold) {// DevTools are open.}}, 500); 這個方法的缺點有二:首先,並非每個會改變 innerHeight / innerWidth 的都是 DevTools,其他如書籤列之類的也都會改變之,這樣會導致 false positive;此外,如果在另一個視窗開啟 DevTools 便可以不改變 innerHeight / innerWidth,造成 false negative 。六、Log Custom Getter這個方法比較像是一系列 anti-debugging 方法的分類而非特定的方法 。當 DevTools 開啟時,可能會因為各種原因而讓 DevTools 去存取一些 object 的特定 method 或 attribute,透過在這些 method 或 attribute 上設 getter,就可以知道有沒有任何 code 去嘗試存取之 。
舉例來說,在過去三年,只要 DevTools 開啟時,基於某些原因,DevTools 會去存取 object 的 id,所以可以在 id 上設定一個 getter,如果發現有程式嘗試存取之,就知道 DevTools 被打開了 。不過這方法目前失效了 。
1 2 3 4 5 6 7 8 91011// https://stackoverflow.com/a/30638226let checkStatus;let element = document.createElement('any');element.__defineGetter__('id', function() {// DevTools are open.});setInterval(function() {// This function call would access `id` if the DevTools are open.console.log(element);}, 1000); 另一個方法則是,console.log 的字串會一直 delay 到 console 被打開的那一刻才會被 render,所以如果去監視一個物件的 toString 有沒有被呼叫,就可以知道 DevTools 有沒有打開 。不過這方法目前一樣是失效了 。12345let logme = function(){ };logme.toString = function() {// DevTools are open.}console.log('%c', logme); 可惜這些技巧所用的 bug 幾乎都已經被 patch 了 。上述兩個方法都屬於使用 DevTools 的基本性質來做偵測,這些方法通常很容易被繞過或是被 patch 。下面三者則會嘗試使用時間的特性來偵測 Debugger 是否有被開啟 。
七、監視已知 Breakpoint 執行時間如同在第二點所說,如果 DevTools 有開啟,則遇到 debugger 時會進入 breakpoint,讓分析者使用 debugger 時感到很困擾 。但除了造成困擾以外,我們也可以透過檢查 debugger 指令的執行時間來知道現在 DevTools 是否有被開啟 。簡單來說,假設 DevTools 有開啟,執行時 breakpoint 會把 runtime 暫停,則重新開始後會發現過了一段時間,可是假設 DevTools 沒有開啟,則 breakpoint 被忽略,如此 debugger 將非常快地被略過 。透過這個性質就可以知道 DevTools 有沒有開啟 。
123456789function measure() {const start = performance.now();debugger;const time = performance.now() - start;if (time > 100) {// DevTools are open.}}setInterval(measure, 1000); 這個方法雖然就跟第二點一樣,可以很輕易地透過關掉所有或特定區段的 breakpoint 來解決,然而我們在此的目的是偵測 DevTools 是否有開啟,換言之,就算分析者之後關掉 breakpoint,只要第一次有成功卡住分析者,我們就知道這個使用者會使用 debugger 了 。然而這個方法有個缺點是,它非常明顯 。一個有經驗的分析者如果發現自己被預設的 breakpoint 卡住,可能就會懷疑他是否已經被發現了 。
八、監視 setInterval 兩次執行時間間距另一個方法則是監測 setInterval 所設定的 function 的執行間距,理想上兩次緊鄰的執行應該時間差距要非常接近於一開始設定的 interval,只要出現顯著變化,就可能是分析者在任何一個地方下了 breakpoint 以致 function 沒有準時執行 。然而缺點就是,如果分析者完全沒用到 breakpoint,則這個方法將不會奏效 。此外,如果使用者切換到其他 tab,JS 的計時器可能會變不準確,所以還要額外檢查目前是否在這個 tab 上(document.focus) 。
123456789let threshold = 350;function measure() {const diff = performance.now() - timeSinceLast;if (document.hasFocus() && diff > threshold) {// DevTools are open.}timeSinceLast = performance.now();}setInterval(measure, 300);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 工厂模式:将对象的创建与使用分离,提高程序可维护性和可扩展性
- 从不同维度分析:Linux与Windows的区别
- 你应该知道的18个Python函数
- 周冬雨|周冬雨戛纳造型惨遭网友嫌弃,网友言语粗鄙,但说的好有道理!
- 自驾318川藏线,有哪些值得推荐的景点?我选了这5个地方
- 如何更好的选择白酒?
- 松茸和姬松茸的区别您知道多少
- 刚从街道办事处辞职,我来告诉你们事业编的真实工资
- 自动挡上的P、R、N、D、S、L和M,表示什么意思?一句口诀教会你
- 车险的5种买法,优缺点对比,看看哪种更适合您
