大家好,今天来分享一种防止 JS 对象属性被修改的方法。
冻结对象
在 JS 逆向中,有时候会遇到 console.xxx
被覆盖的情况,如果遇到基本上对应的方法都会被重写成一个空方法,也就是说无论执行什么方法,都不会输出任何内容。这个时候无论是插桩或者 hook
都无法获得日志输出,对于调试很不利,非常影响效率。而且除非我们能一步步的找到被覆盖的地方,否则可能再也无法输出日志了。
Object.freeze
这个时候我们可以考虑使用 Object.freeze
,freeze
方法可以冻结一个对象,一个冻结的对象再也不行被修改,不能向这个对象添加新的属性,不能删除已有的属性,不能修改该对象已有属性的值,对这个对象的原型的修改也会被禁止。
在非严格模式,对被冻结对象的属性修改操作会成功,但是实际上修改是无效的,在严格模式中,对于被冻结的属性的修改会抛出 TypeError
错误。
实战
理论知识铺垫完了,下面来实战试试。以下题目节选自猿人学内部练习平台 web 题第 21 题。
这是一道套了轻度 OB 混淆的 webpack
的题目,题目不算难,主要是它覆盖了 console
的几个方法,先来看看效果:
无论调用什么方法,都无法正常输出日志。
解决方案就是使用 Object.freeze
来冻结 console
对象,但是记得在网页自身的 JS 代码执行前进行冻结,不然冻结的就是被覆盖后的方法了。
油猴脚本
为了可以在网页 JS 代码执行前进行冻结,需要使用油猴脚本,新建一个油猴脚本,写入以下代码:
// ==UserScript==
// @name demo
// @namespace Violentmonkey Scripts
// @match https://www.python-spider.com/*
// @grant none
// @version 1.0
// @author -
// @description 2025/2/25 21:20:14
// @run-at document-start
// ==/UserScript==
(function () {
Object.freeze(console);
console.log('freeze success!')
})();
默认情况下油猴脚本会在网页的 JS 代码执行后再执行,所以别忘了添加一行注释:@run-at document-start
,它会让油猴脚本在网页的 JS 代码执行前先执行我们的油猴脚本。
hook
操作也是一样的原理,要先执行 hook
逻辑,再执行正常的代码,才能正确执行 hook
操作。
保存油猴脚本,刷新网页看看:
可以看到,打印出来了冻结成功的消息,并且后续在使用 log
方法也是可以正常使用的。
可能有小伙伴会问,为什么 debug
方法还是没有输出呢,那是因为 Chrome 控制台的默认日志级别是 info
,将其改成 debug
即可正常显示所有的日志。
将详细勾选上,即可正常显示所有的日志了。
查找覆盖点
到了这里其实问题就解决了,但是如果冻结操作被检测到了怎么办?
因为冻结操作是可以通过 Object.isFrozen
方法检测的,如果传入被冻结的对象就会返回 true
。或者在严格模式下,如果混淆代码中对 console
对象进行属性覆盖操作,就会报错,错误可能会被检测到进而走不同的分支。
这个时候,我们可能真的需要详细分析混淆代码了,找到方法是在哪里被冻结的,然后针对性的 pass
掉检测代码。那如何找到覆盖点呢?可以尝试一下直接输出被冻结对象,然后从下面的路径中查找被覆盖后的函数:
可以看到现在 log
方法被覆盖了,但是可以看到覆盖点是 webpack
这个 JS 中的某个方法,点击一下跳过去打个断点看看:
断点断在了空函数的位置,果然被替换成了空函数,然后找找调用栈是哪里调用了 _0x56b1f7
函数(绿色箭头),是在 _0x291e45
这个函数(红色箭头)里面,通过各种赋值,最终在循环中将 console
的各个方法覆盖成了空函数,见下图箭头所指:
既然找到了覆盖的位置,就可以针对性的反混淆了,可以直接将 _0x291e45
这个函数注释掉试试,让其不再被调用,也就不会覆盖 console
对象了。感兴趣的小伙伴可以自行尝试,我就不演示了。
总结
以上冻结操作中,Object.freeze
是浅冻结,如果被冻结的对象中还有其他的对象,其他的对象是可以被修改的。需要深冻结的话,需要递归冻结每个类型为对象的属性,用到了递归要注意不要死循环,也可以使用开源库来实现。这里就不演示了,有需求的小伙伴可以自行尝试一下。
本文章首发于个人博客 LLLibra146's blog
本文作者:LLLibra146
更多文章请关注公众号 (LLLibra146):
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。