规避JavaScript反调试技术

原文信息: 查看原文查看原文

Evading JavaScript Anti-Debugging Techniques

- veritas

调试器是开发者不可或缺的工具,它允许开发者在任何时刻暂停代码执行并深入分析其行为。通过使用调试器,开发者可以高效地识别和解决代码中的问题,使其成为工具箱中不可或缺的一部分。

Chromium的开发者工具调试器

Chromium的开发者工具调试器

对于逆向工程师来说,调试器同样是宝贵的工具,特别是当处理那些经常使用变量和函数名称混淆技术的混淆代码时。通过使用调试器,逆向工程师可以获得对模糊函数功能的关键见解。使用客户端保护的公司意识到了这一点,因此制定了策略来挫败对受保护代码进行调试的尝试。

很久以前,每当你尝试在Supreme的网站打开你的开发者工具时,你会发现自己陷入了一个烦人的调试器循环中。这使得逆向工程他们的反机器人脚本变得非常恼火。

明显的方法

在许多浏览器中,有一个选项可以禁用所有断点触发。虽然这种方法可以防止陷入循环,但它带来了一个权衡——调试器的进一步分析功能变得不可用。

在Chromium中停用断点

在Chromium中停用断点

对于像Supreme使用的反机器人这样的复杂脚本,这种方法显然不是一个选项。

尝试一个扩展

像Anti Anti-debugger这样的Greasyfork脚本尝试通过覆盖调用者的函数体,移除调试器语句,并eval新函数来绕过这些调试器陷阱。虽然这种方法看起来很有希望,但不幸的是,它并不能成功应对JScrambler保护的脚本,因为调试器陷阱在不同的上下文中进行评估。

它们还使用完整性检查1并将调试器调用隐藏在进一步混淆的eval函数中2

JScrambler的调试器陷阱从eval上下文中被调用

JScrambler的调试器陷阱从eval上下文中被调用

最终方法

我的朋友Jordin和我最终采用的方法是完全重命名调试器关键字。通过将其重命名为像"banana"这样的东西,调试器将不再在debugger关键字的出现上触发。为了实现这一点,我们构建了一个定制版本的Firefox。如果你有兴趣尝试这个,请看我们想出的补丁。

--- a/js/src/frontend/ReservedWords.h
+++ b/js/src/frontend/ReservedWords.h
@@ -20,7 +20,7 @@
   MACRO(catch, catch_, TokenKind::Catch)                \
   MACRO(const, const_, TokenKind::Const)                \
 MACRO(continue, continue_, TokenKind::Continue)       \
-  MACRO(debugger, debugger, TokenKind::Debugger)        \
+  MACRO(ticket_debugger, debugger, TokenKind::Debugger) \
   MACRO(default, default_, TokenKind::Default)          \
   MACRO(delete, delete_, TokenKind::Delete)             \
 MACRO(do, do_, TokenKind::Do)                         \
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -107,7 +107,7 @@
   MACRO_(currencySign, currencySign, "currencySign")  \
   MACRO_(day, day, "day")                             \
 MACRO_(dayPeriod, dayPeriod, "dayPeriod")           \
-  MACRO_(debugger, debugger, "debugger")              \
+  MACRO_(ticket_debugger, debugger, "ticket_debugger")\
   MACRO_(decimal, decimal, "decimal")                 \

找到这个很令人畏惧,因为阅读浏览器的代码库从来都不是一件愉快的事情。一个简单的grep搜索像"debugger"这样的关键字可能会产生数千个结果,使搜索更加具有挑战性。

经过多次构建后,我们通过加载反机器人脚本ticket.js并钩住Array.prototype.slice3来调用我们的新ticket_debugger关键字来测试我们的补丁。

我们的新ticket_debugger关键字触发了一个断点

我们的新ticket_debugger关键字触发了一个断点

它奏效了!

我们引入了一个新的ticket_debugger关键字,它不仅触发了一个断点,还解决了之前调试器无限循环的问题。我们还扩展了这个定制浏览器,以自动检索反机器人的混淆加密轮密钥并将它们转换回原始形式,但我将在稍后的文章中介绍这个 :)

分享于 2024-08-23

访问量 37

预览图片