您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JavaScript 的 Anti-Debugging 技術

时间:2023-05-20 14:02:17  来源:今日头条  作者:闪念基因

 

JAVAScript 運行在客戶端,多數 Browser 亦有很強的 debugger,有時為了保護程式碼的邏輯不被破解或想要藏惡意程式之類的,會想辦法讓分析者沒辦法輕易分析原始碼。通常又可以分為阻撓靜態分析(例如 obfuscation)和動態分析(例如 anti-debugging)。這篇文章會介紹 JavaScript 的一些 anti-debugging 的方法,討論可以如何讓分析者沒辦法在 browser 上用 debugger 或甚至偵測自己是否正在被 debug,並分析他們的優劣與可能破解方法。

這篇文章是 U Can’t Debug This: Detecting JavaScript Anti-Debugging Techniques in the Wild 的部份重點整理,該文發表於 USENIX Security 2021。該文其實遠不只 anti-debugging 技術,不過因為他們分析做得很好,所以想針對這部份做重點整理。

背景

雖然我猜會看這篇文章的人應該都有概念 debugging 長怎樣,不過還是簡單講一下。一般來說,如果要在 browser 上做 debugging,通常會使用 DevTool 給的 Debugger。召喚方法大概是這樣的:對著網頁(恩,你現在就正在看的)點右鍵,按「檢視」 / “Inspect”(至少在 Firefox 上長這樣),就會看到 DOM 被解析的樣子,然後點 Debugger,便可以看到 JavaScript code,也可以下 breakpoint。除了人工上 breakpoint,也可以在 JavaScript code 裡面用 debugger 直接下 breakpoint。

為了避免自己的 code 分析,有些人會希望阻撓 manual analysis,或更好的狀況是,知道自己正在被 debug,也許可以有不同的行為(例如很多 malware 可能發現自己正在被分析,就開始裝死以隱藏其原先的 behavior)。我們大致可以把策略分成三種:阻礙 debug、改變 debugger 行為、偵測是否在 debug。

阻礙 Debugger 開啟

一、攔截 DevTools 開啟的快捷鍵

一種雖然無腦但偶而會有效的方法是,直接禁止使用者嘗試打開 DevTools,自然也就沒辦法使用 debugger 了。一般來說打開 DevTools 有三種方法:按 F12、點右鍵選「檢視」(如前述)、從瀏覽器選單找到 DevTools。前兩種方法在使用時都會在網頁上觸發一些 event,例如按鍵盤會有 keydown,滑鼠點右鍵會有 oncontextmenu,只要去聽特定的 event 並阻撓其行為,就可以避免 DevTools 開啟。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
window.addEventListener("keydown", function(event){
    if (event.key == "F12") {
        event.preventDefault();
        return false;
    }
});
window.oncontextmenu = (event) => {
    event.preventDefault();
    return false;
};

然而破解方法也很簡單,一來是如果要看 source code,大可直接用 view-source: ...,二來是就算真的想用 DevTools,從瀏覽器選單選 DevTools 就可以了。

二、塞入大量 breakpoint

另一種惱人的方法是,在 code 裡面塞一堆 debugger 來預設 breakpoint,一般來說執行時 runtime 會直接忽略這些 breakpoint,但只要分析者一打開 debugger,把上就會被一堆 breakpoint 阻撓,完全沒辦法順利 debug。

不過要阻止的方法很簡單。首先,有些 browser 可以設定忽略特定 breakpoint,不過可以透過不斷建立新的 anonymous function 並在其中塞 debugger 來解決(因為對 browser 來說,anonymous function 的 breakpoint 是全新、未見過的)。另一個方法則是直接忽略特定區段裡面的所有 debugger,有些 browser extension 可以作到這件事。

三、不斷清除 console

有些人 debug 的習慣是把訊息 output 到 console,或是可以透過在 console 執行一些 code 來改變變數數值,藉此分析程式行為。因此,如果不斷地用 console.clear 把 console 清空,會對分析者造成不小的困擾。

1
2
3
setInterval(function() {
    console.clear();
}, 100);

改變 Debugger 行為

四、覆蓋掉預設 function 的行為

JavaScript 有個令人又愛又恨的特性是,幾乎所有的內建 function 都可以被覆蓋。許多人 debug 時會仰賴 console.log 或 alert,只要覆蓋掉某些 function,就有機會阻止分析者 debug,甚至適時地回報某個分析者可能正在嘗試 debug。

舉例來說,Spotify 之前有一段 code 就覆蓋掉 alert 預設的行為,因為不少 bug hunter 會用 alert來檢驗 XSS 有沒有成功,如此則就算 XSS 成功呼叫 alert,也只會偷偷地回傳參數,而不會真的噴出彈跳視窗。

1
2
3
4
5
6
7
8
// WrApping funcs in a naive attempt to catch externally found XSS vulns
(function(fn) {
	window.alert = function() {
		var args = Array.prototype.slice.call(arguments);
		_doLog('alert', args);
		return fn.apply(window, args);
	};
}(window.alert));

除此之外,也有人會透過把 console.log 覆蓋成空函數來讓分析者沒辦法順利使用 console 來 debug。

偵測是否在 Debug

五、比較視窗寬度高度

DevTools 開啟會佔用螢幕空間,如果能偵測到高度差異,便有可能知道使用者是否有打開 DevTools。在 JavaScript,可以透過 innerHeight / innerWidth 與 outerHeight / outerWidth 來取得網頁本身大小(inner)以及整個視窗的大小(outer),如果兩者相異過大,也許就代表 DevTools 正在開啟導致 innerHeight / innerWidth 縮小了。

1
2
3
4
5
6
setInterval(() => {
    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
 9
10
11
// https://stackoverflow.com/a/30638226
let 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 有沒有打開。不過這方法目前一樣是失效了。

1
2
3
4
5
let 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 有沒有開啟。

1
2
3
4
5
6
7
8
9
function 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)。

1
2
3
4
5
6
7
8
9
let threshold = 350;
function measure() {
    const diff = performance.now() - timeSinceLast;
    if (document.hasFocus() && diff > threshold) {
        // DevTools are open.
    }
    timeSinceLast = performance.now();
}
setInterval(measure, 300);

九、灌爆 console

另一個有趣的 side-channel 是透過大量寫入各種資訊並衡量所需時間。

以前有一種方法是,不斷地建立新的 DOM element,並計算所需時間,如果所需時間太長,可能就是 DevTools 有開啟,因為當 DevTools 開啟時若 DOM tree 有改變則會需要在 DevTools 中標示出改變,這個動作很吃效能,會導致新增 DOM element 的速度變慢。然而這方法已經不能用了。

現在有另一個方法是,不斷寫資料到 console 並計算所需時間,如果所需時間過長,可能就是瀏覽器忙著把資料輸出到 DevTools,代表 DevTools 有開啟。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function measure() {
    const start = performance.now();
    for (let i = 0; i < 100; i++) {
        console.log(i);
        console.clear();
    }
    const time = performance.now() - start;
    if (time > threshold) {
        // DevTools are open.
    }
}
setInterval(measure, 1000);

這個方法的一個缺陷是,如果使用者電腦太慢,可能會導致 false positive 或是拖垮網頁效能。

後記

以上總共討論了九種 anti-debugging 的方法。方法與 code 主要出自 U Can’t Debug This: Detecting JavaScript Anti-Debugging Techniques in the Wild,除了少數幾個範例為了呈現品質而有調整。另外我也參考了這篇 Stackoverflow 問題。如果想對這議題有更多了解,例如該怎麼偵測 anti-debugging techniques、哪些方法被廣泛使用之類的,可以看看原始論文。

  • Author: Allen Chou
  • Link: https://blog.allenchou.cc/post/js-anti-debugging/


Tags:JavaScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除。
▌相关推荐
JavaScript 運行在客戶端,多數 Browser 亦有很強的 debugger,有時為了保護程式碼的邏輯不被破解或想要藏惡意程式之類的,會想辦法讓分析者沒辦法輕易分析原始碼。通常又可以分...【详细内容】
2023-05-20  Tags: JavaScript  点击:(0)  评论:(0)  加入收藏
作为前端开发领域的初学者,您应该知道 Javascript 是创建超酷动态网站的关键。这门脚本语言可以让您向页面添加各种很酷的功能,但是有这么多功能,很容易迷失在其中。别担心, 在...【详细内容】
2023-05-12  Tags: JavaScript  点击:(26)  评论:(0)  加入收藏
对于网络平台而言,WebAssembly 的出现无疑是意义重大的,它能让各种语言编写的代码以接近原生的速度在 Web 中运行&mdash;&mdash;那么在各种语言中,Java 会是其中最流行的吗?原文...【详细内容】
2023-05-09  Tags: JavaScript  点击:(13)  评论:(0)  加入收藏
1 JavaScript 简介JavaScript 压缩、混淆和加密技术对于网页来说,其逻辑是依赖于JavaScript来实现的,JavaScript 有如下特点: JavaScript 代码运行于客户端,也就是它必须要在用...【详细内容】
2023-05-07  Tags: JavaScript  点击:(9)  评论:(0)  加入收藏
1.检查元素是否在屏幕可见区域内我们如何获得元素的点击率?主要取决于用户点击元素的次数和元素在页面上显示的次数。我们可以很容易地获取到用户的点击次数,但是如何获取一...【详细内容】
2023-04-26  Tags: JavaScript  点击:(27)  评论:(0)  加入收藏
我们一起来了解一下如何仅使用 JavaScript 将任何 HTML 页面或表单转化为 PDF文件。使用 jspdf 库,我们可以轻松地将任何 HTML 页面或表单转换为 PDF:例如:import { jsPDF } fr...【详细内容】
2023-04-24  Tags: JavaScript  点击:(35)  评论:(0)  加入收藏
作者:shichuan文末彩蛋等你揭晓前言在实际的开发工作过程中,积累了一些常见又超级好用的 Javascript 技巧和代码片段,包括整理的其他大神的 JS 使用技巧,今天筛选了 9 个,以供大...【详细内容】
2023-04-20  Tags: JavaScript  点击:(3)  评论:(0)  加入收藏
在本文中,我想与您分享 13个基本的 JavaScript 函数,如果您是 Web前端开发人员,您应该熟悉这些函数。 您可以将本文所有 JavaScript 函数加入收藏至您的工具箱,以便在您的软件...【详细内容】
2023-04-12  Tags: JavaScript  点击:(35)  评论:(0)  加入收藏
作者:京东科技 周明亮AST 基础与功能在前端里面有一个很重要的概念,也是最原子化的内容,就是 AST ,几乎所有的框架,都是基于 AST 进行改造运行,比如:React / Vue /Taro 等等。 多端...【详细内容】
2023-04-10  Tags: JavaScript  点击:(35)  评论:(0)  加入收藏
1.可选链接可选链接是 JavaScript 中的一项新功能,它允许开发人员编写更简洁、更易于阅读的代码。使用可选链接,您可以访问对象的嵌套属性,而不必担心这些属性是否存在。const...【详细内容】
2023-04-10  Tags: JavaScript  点击:(36)  评论:(0)  加入收藏
▌简易百科推荐
JavaScript 運行在客戶端,多數 Browser 亦有很強的 debugger,有時為了保護程式碼的邏輯不被破解或想要藏惡意程式之類的,會想辦法讓分析者沒辦法輕易分析原始碼。通常又可以分...【详细内容】
2023-05-20  闪念基因  今日头条  Tags:JavaScript   点击:(0)  评论:(0)  加入收藏
前言熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。但我一直奉行一个原则,就是...【详细内容】
2023-05-18    趣谈前端  Tags:Javascript   点击:(9)  评论:(0)  加入收藏
作为前端开发领域的初学者,您应该知道 Javascript 是创建超酷动态网站的关键。这门脚本语言可以让您向页面添加各种很酷的功能,但是有这么多功能,很容易迷失在其中。别担心, 在...【详细内容】
2023-05-12    web前端开发  Tags: Javascript   点击:(26)  评论:(0)  加入收藏
最近有一位00后的小妹妹粉丝私信小编说自己很喜欢编程,目前在某公司实习前端开发工作,说到现在为止还没有搞懂JavaScript中深拷贝和浅拷贝这个问题,同时也在网上看了很多关于深...【详细内容】
2023-05-12  Echa攻城狮  今日头条  Tags:JavaScript   点击:(19)  评论:(0)  加入收藏
TypeScript是一种静态类型检查的编程语言,它内置了许多基本数据类型,如字符串、数字和布尔型等。除了基本数据类型,当某种类型对于大多数代码来说都非常有用时,它们就会被添加...【详细内容】
2023-05-12    大转转FE  Tags:TypeScript   点击:(17)  评论:(0)  加入收藏
1 JavaScript 简介JavaScript 压缩、混淆和加密技术对于网页来说,其逻辑是依赖于JavaScript来实现的,JavaScript 有如下特点: JavaScript 代码运行于客户端,也就是它必须要在用...【详细内容】
2023-05-07  程序员梓羽同学  今日头条  Tags:JavaScript   点击:(9)  评论:(0)  加入收藏
基于Canvas和WebGL,我们可以快速实现各种复杂的前端动画、特效渲染,如果,自己完全原生写法,一个是工作量会比较大,另外,处理不好会引发一些奇怪的问。这里分享几个帮助开发人员更...【详细内容】
2023-05-03  自学编程之道  今日头条  Tags:JS库   点击:(30)  评论:(0)  加入收藏
面试官最爱问的JavaScript数组方法和属性都在这里,下面是 JavaScript 常用的数组方法和属性介绍,以及简单的代码示例:JavaScript数组方法和属性一、数组属性:1、length:返回数组...【详细内容】
2023-04-28  老汤前端  今日头条  Tags:JavaScript   点击:(17)  评论:(0)  加入收藏
1.检查元素是否在屏幕可见区域内我们如何获得元素的点击率?主要取决于用户点击元素的次数和元素在页面上显示的次数。我们可以很容易地获取到用户的点击次数,但是如何获取一...【详细内容】
2023-04-26    web前端开发  Tags:JavaScript   点击:(27)  评论:(0)  加入收藏
我们一起来了解一下如何仅使用 JavaScript 将任何 HTML 页面或表单转化为 PDF文件。使用 jspdf 库,我们可以轻松地将任何 HTML 页面或表单转换为 PDF:例如:import { jsPDF } fr...【详细内容】
2023-04-24  web前端开发  微信公众号  Tags:JavaScript   点击:(35)  评论:(0)  加入收藏
站内最新
站内热门
站内头条