JavaScript Magic Tricks: Invalid breakpoint

原文链接:JavaScript Magic Tricks: Invalid breakpoint - DEV Community

Under normal conditions, JavaScript code can be breakpointed in a runtime environment, for example:

<html>
<script>
var array = ["JShaman","javascript","Obfuscator"];
for(i=0 ;i< array.length; i++){
    console.log(array[i]);
}
</script>
</html>

Image description

But do you know that there are some techniques in JS programming that can effectively make breakpoints useless? For example, by rewriting the code above as:

<html>
<script>
var array = ["JShaman","javascript","Obfuscator"];
array.forEach(console.log);
</script>
</html>

If you set a breakpoint and run it at this time, you will find that: the breakpoint will only occur inside forEach, but console.log will not be interrupted:

Image description

This method also applies in Node.JS and Visual Studio Code environments, as shown in the following two figures:

Image description

Image description

Another example:

<html>
<script>
    window.onclick = function() {
        document.bgColor = "#ccc";
    }
</script>
</html>

This code snippet is used to set the background color of a webpage with document.bgColor = "#ccc";. This line of code can be set as a breakpoint. If you do not want it to be interrupted by a breakpoint, you can modify the code to the following format:

<html>
<script>
window.onclick = Object.getOwnPropertyDescriptor(Document.prototype, "bgColor").set.bind(document, "#ccc");
</script>
</html>

Object.getOwnPropertyDescriptor() is a method added to the Object object in the ES6 specification, allowing the retrieval of a descriptor for a specified property of an object. The method takes two parameters: the first is the object that contains the property, and the second is the name of the property. It returns an object. In the code mentioned above, it is used to retrieve the descriptor of the bgColor property in the document and bind it to an onclick event. When the onclick event is triggered, it will set the background color, but the set.bind(document, "#ccc") operation will not be paused by a breakpoint, and breakpoints are ineffective on it.

Another example:

<html>
<script>
    var obj = {
        name : "tom"
    };
    obj.name = "ais";
    console.log(obj);
</script>
</html>

If you do not want the breakpoint to be set for the statement obj.name = "ais" that assigns a value to name, you can make the following adjustments:
Change to:

Reflect.apply(Reflect.set, null, [obj, “name”, “ais”]);

Reflect is a new API provided in ES6 for object manipulation, which offers methods to intercept JavaScript operations:
Reflect.apply(target, thisArg, args), the apply method calls a function with a given this value and an array of arguments. The code snippet above is equivalent to obj.name = "ais".
However, breakpoints can still be set here, and the bind method can be used further:
Reflect.apply.bind(null, Reflect.set, null, [obj, "name", "aix"]);

Finally:


<html>
<script>
    var obj = {
        name : "tom"
    };
    window.onclick= Reflect.apply.bind(null, Reflect.set, null, [obj, "name", "aix"]);
    console.log(obj);
</script>
</html>

At this point, a breakpoint can be set on the line with Reflect.apply.bind, but the execution will not pause or interrupt when window.onclick is triggered.

Image description

This method can be used to protect the code that is most afraid of debugging in certain situations.
Furthermore, if the code modified using this method is then obfuscated and encrypted, it may even be impossible to locate the location of the breakpoint. As shown in the following image, encrypting the preceding code with JS-Obfuscator will result in the following form

<html>
<script>
    function _0x4bfaa1(_0x4f04df,_0x46ffc7,_0x157578,_0x297168,_0x5a371e){return _0x497c(_0x46ffc7- -0x1f8,_0x297168);}function _0x40ba00(_0x265865,_0x51dc79,_0x267b51,_0x3b1913,_0x2ac5f5){return _0x497c(_0x267b51-0xcc,_0x3b1913);}(function(_0x15f460,_0x18170b){function _0x3440c3(_0x3f98c7,_0x197e80,_0x48af91,_0x537374,_0x4fa527){return _0x497c(_0x48af91-0x2d6,_0x197e80);}var _0x40fdd0=_0x15f460();function _0xc97ade(_0x1c2d14,_0x273c74,_0x2d7a20,_0x2347d2,_0x4fe5df){return _0x497c(_0x2d7a20-0x2b5,_0x4fe5df);}function _0x551607(_0x3e01fd,_0x110b1d,_0x2eeec9,_0x17b1d5,_0x145826){return _0x497c(_0x3e01fd- -0x22d,_0x110b1d);}function _0xa1f138(_0x387226,_0x1f0366,_0x1b6130,_0xb0bfb3,_0x2b254a){return _0x497c(_0x2b254a- -0x2b1,_0x1f0366);}function _0x486f8e(_0x173deb,_0x592ea4,_0xb13e25,_0xb03b2e,_0x14e4f9){return _0x497c(_0xb13e25- -0x3bb,_0xb03b2e);}while(!![]){try{var _0x2d2b91=parseInt(_0x551607(-0x22a,-0x227,-0x229,-0x22b,-0x221))/0x1+-parseInt(_0xc97ade(0x2be,0x2c4,0x2c6,0x2bf,0x2c4))/0x2*(-parseInt(_0xc97ade(0x2b9,0x2ad,0x2b5,0x2b9,0x2b0))/0x3)+parseInt(_0xa1f138(-0x2a4,-0x2ab,-0x2af,-0x2af,-0x2aa))/0x4+-parseInt(_0x3440c3(0x2e2,0x2e1,0x2e3,0x2e3,0x2e5))/0x5+parseInt(_0x3440c3(0x2d7,0x2d8,0x2e0,0x2da,0x2e6))/0x6+-parseInt(_0xc97ade(0x2bc,0x2bb,0x2ba,0x2b4,0x2b3))/0x7*(parseInt(_0xa1f138(-0x2ab,-0x2a7,-0x2a9,-0x2a3,-0x2a2))/0x8)+-parseInt(_0x3440c3(0x2de,0x2e1,0x2e4,0x2ec,0x2dd))/0x9*(-parseInt(_0x486f8e(-0x3be,-0x3b6,-0x3b7,-0x3be,-0x3b0))/0xa);if(_0x2d2b91===_0x18170b){break;}else{_0x40fdd0["\u0070\u0075\u0073\u0068"](_0x40fdd0["\u0073\u0068\u0069\u0066\u0074"]());}}catch(_0x45ceea){_0x40fdd0["\u0070\u0075\u0073\u0068"](_0x40fdd0["\u0073\u0068\u0069\u0066\u0074"]());}}})(_0x5a63,0x95c8c);function _0x5a63(){var _0x45b434=["\u0034\u0031\u0035\u0030\u0031\u0039\u0032\u0050\u0043\u0065\u0050\u0050\u0054","\u006c\u006f\u0067","dnib".split("").reverse().join(""),"\u0031\u0032\u0034\u0038\u0031\u0032\u0036\u0079\u0065\u0069\u004c\u0048\u0066","eman".split("").reverse().join(""),"\u0061\u0069\u0078","WrBRpq0878165".split("").reverse().join(""),"yxfsXT01521".split("").reverse().join(""),"\u0032\u0033\u0032\u0078\u0062\u004a\u0069\u0067\u0058","\u0061\u0070\u0070\u006c\u0079","GvgsnD41".split("").reverse().join(""),"LoNwch907911".split("").reverse().join(""),"mot".split("").reverse().join(""),"kcilcno".split("").reverse().join(""),"thpllB6243101".split("").reverse().join(""),"szBFSp023".split("").reverse().join(""),"pytQaz290402".split("").reverse().join(""),"tes".split("").reverse().join("")];_0x5a63=function(){return _0x45b434;};return _0x5a63();}var _0xc=0x4+0x1;var obj={"\u006e\u0061\u006d\u0065":_0x4bfaa1(-0x1f1,-0x1f7,-0x1f6,-0x1f8,-0x1f5)};_0xc=0x2+0x7;function _0x7b3856(_0x298c79,_0x37904f,_0x2e5981,_0x37e404,_0x363429){return _0x497c(_0x37e404-0x250,_0x363429);}function _0x497c(_0x2e43ba,_0x5a63b9){var _0x497cff=_0x5a63();_0x497c=function(_0x6145ca,_0x364243){_0x6145ca=_0x6145ca-0x0;var _0x46f7f9=_0x497cff[_0x6145ca];return _0x46f7f9;};return _0x497c(_0x2e43ba,_0x5a63b9);}window["\u006f\u006e\u0063\u006c\u0069\u0063\u006b"]=Reflect["\u0061\u0070\u0070\u006c\u0079"]["\u0062\u0069\u006e\u0064"](null,Reflect["\u0073\u0065\u0074"],null,[obj,_0x7b3856(0x25b,0x261,0x257,0x25b,0x25a),_0x7b3856(0x259,0x253,0x25c,0x25c,0x257)]);console["\u006c\u006f\u0067"](obj);
</script>
</html>

Image description

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值