JS逆向之无限debugger对抗

本文详细介绍了JavaScript中实现debugger的各种方法,包括使用定时器、大量script标签、原型链和DOM操作生成无限debugger。作者提供了针对不同情况的解决方案,如浏览器扩展和FireFox的最新版本更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JS中实现debugger的方法

首先,我们要知道,在浏览器实现debugger的方法有哪些

  1. debugger关键词 ,相当于C++内联汇编的int3,在代码中嵌入这么一个关键词方便调试
  2. eval(‘debugger’) ,原理跟第一个一样,只不过是使用eval方法来调用。这个可操作空间比较大,字符串可以经过混淆或者拼接以后最后变成debugger这个关键词即可。
  3. Function(“debugger”), 原理跟2类似,只不过是在虚拟机里面执行匿名函数,匿名函数里有debugger的方法

这些debugger方法,是实现debugger的基础,可以理解为是三元素。基于三种元素,可以形成多种多样的玩法

无限Debugger示例

Demo1

那么接下来, 我就将上面的三元素进行组合,产生各种无限debugger

setInterval('debugger', 500)

这种是利用定时器的方法,去不断间隔的创造宏任务队列,用来干扰我们的调试 。

解决方案:

  1. 右键-> Never pause here
  2. 在定时器启动之前重写 setInterval
  3. AutoResponse 直接把干扰点干掉
Demo2

html页面生产时,直接自动生成几千个script标签,标签里只写一个debugger

 <script>
        !function (){debugger}()
    </script>
    <script>
        !function (){debugger}()
    </script><script>
        !function (){debugger}()
    </script><script>
        !function (){debugger}()
    </script><script>
        !function (){debugger}()
    </script><script>

如果是这种方式的话,刚刚那种解决方案就不行了。解决方案:AutoResponse 直接把干扰点干掉

Demo3
for (let i=0;i<=5000;i++)
{
    Function('debugger')()  // 原型链 获取Function
    eval('debugger')
    debugger;
}

解决方案

  1. Never pause here
  2. 干掉这个循环进入的函数
  3. AutoResponse 直接把干扰点干掉
Demo4

添加script标签,插入debugger

for (let i=0;i<=5000;i++)
{
	cont = document.body
	var newScript = document.createElement('script');
	newScript.type = 'text/javascript';
	newScript.innerHTML = 'debugger';
	cont.appendChild(newScript);
}

解决方案: document.createElement里面把script重写

总结
  1. 优先尝试 Never pause here (最方便快捷,但是最卡,也最容出问题)
  2. 次优先尝试重写调用函数
  3. 使用 AutoResponse/mapping/overrides 替换

无限Debugger实战

这个是猿人学第五十四题,大家也可以自己动手体验下。

在这里插入图片描述

进入到目标网站,直接打开调试器,就出现了一个反调试

在这里插入图片描述

通过调用栈找到上一层,可以看到这个反调试的函数

s(s(11))
ƒ eval() { [native code] }

直接在控制台敲一下s11,可以看到这个就是eval函数

s(38)+s(56)+s(62)+s(50)
'debugger'

执行一下这四个字符串,就可以看到是debugger这个字符串。

这个反调试只有一层的话,就可以直接Never pause here就可以过掉,也可以采用HOOK的方法,重写一个eval函数,让这个地方不会断下来。

_eval = eval;
eval= function()
{
	if ([arguments[0]].indexOf('debugger'))
	return eval(arguments[0])
}

这样这个反调试的点就过掉了,然后我们进行一个翻页,又出现一个无限debugger,查看一下当前的堆栈

在这里插入图片描述

这里用循环的方式一直去添加一个o的节点,

在这里插入图片描述

o实际上就是一个带debugger关键字的标签,按照之前的思路,我们应该把appendChild这个函数给hook掉。

_appendChild = Node.prototype.appendChild
Node.prototype.appendChild = function()
{
	if (arguments[0].innerHTML && arguments[0].innerHTML.indexOf('debugger') != -1)
    {
		 arguments[0].innerHTML = ''
	}
	return _appendChild.apply(this, arguments)
}

执行一下这段代码,这个无限Debugger就过掉了。

在这里插入图片描述

继续运行,这里也有个无限Debugger,直接右键Never pause here解决

在这里插入图片描述

然后刷新一下页面,这里就会出现一个新的无限debugger,这里有一堆的debugger标签

在这里插入图片描述

这里用Overrides把这几百个debugger关键词替换掉。

在这里插入图片描述

重新刷新页面,这样就过掉了这个无限Debugger

在这里插入图片描述

再继续,这里又出现了一个无限Debugger,因为这个位置只有一行,不管多复杂,其实都可以右键Never pause here搞定,也可以直接Overrides删掉,混淆的太厉害了,原理就不看了。

到这里,整个无限Debugger的案例就结束了。

无限Debugger秒破方案

我们来想这么一个问题,之前我们都是通过HOOK的方式来解决掉debugger关键字的,那么有没有一种HOOK方案,可以一劳永逸直接干掉所有无限Debugger呢?

答案当然是有,不过这个HOOK需要下到浏览器层。你自己编译一份谷歌浏览器,然后呢,在cpp层,将js层的debugger给他hook掉,改成其他的,就是把debugger这个关键字给他失效,不让他生效。

这个方法听起来,有一点费劲,基本跟重新编译一份安卓系统差不多了。既然有这么一个思路在,那有没有已经造好的可以拿来用的轮子,当然有,火狐浏览器帮我们把这个事情做了。

The Firefox Debugger now includes a new feature: an option to disable the debugger; keyword on the current page. This feature is accessible via a new checkbox in the Breakpoints side panel labeled Pause on debugger statement, located next to the existing Pause on exceptions checkbox. By default, this option is enabled, meaning that the debugger statements are active unless manually disabled.

上面这个是firefox 更新Version 121.0的一条更新日志, 更新日志写的很明白 , 取消勾选Pause on debugger statement(在调试器语句暂停) ,就可以过掉所有的反调试,自己打的断点不受影响。

在这里插入图片描述

我这里下载了最新版的火狐浏览器,在开发者工具里面勾选上这一项,就可以过掉所有的无限Debugger了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼手56

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值