, I've been studying the JavaScript - related anti debugging skills. But when I search related information online, I find that there are not many articles on this website, and even if there are, there are also very incomplete ones. So in this article, I'm going to summarize the JavaScript counter - debugging skills with you. It is worth mentioning that some of these methods have been widely used by network criminals in malware.


for JavaScript, you only need to spend a little time to debug and analysis, you can see the logic function of the JavaScript code. And what we're going to discuss can make it more difficult for those who want to analyze your JavaScript code. However, our technology is unrelated to code confusion, and we mainly focus on how to add difficulties to the active debugging of the code. Methods

described in this paper is as follows:

1. to detect unknown execution environment (the code we just want to be executed in the browser);

2. detection debugging tools (such as DevTools);


4. code integrity control; flow integrity control;

5. simulation;

in short, if we detect the "normal" operation, the process will be changes in the program, and jump to the code block forgery, and "hidden" function of the real code.

1. The function redefines

, which is the most basic and most commonly used code counter - debugging technique. In JavaScript, we can redefine the functions that are used to collect information. For example, the console.log () function can be used to collect information, such as functions and variables, and display it in the console. If we redefine this function, we can modify its behavior and hide specific information or display forged information.

can be run directly in DevTools this function to understand its function:

 console.log ("HelloWorld"); VAR (fake = function) {}; window['console']['log']= fake; console.log ("Youcan't see me!"); 

after the operation we will see:

VM48:1 Hello World

you will find second information does not show, because we re define the function, that is "disabled" its original function. But we can also let it show forged information. Such as:

 console.log ("Normalfunction"); //First we save a reference to the original console.log function var original //Next we create = window['console']['log']; our fake function //Basicly we check the argument and if match we call original function with otherparam. there is no match / / If pass the argument to the original function var = fake function (argument) {if (argument = Ka0labs) {original ("Spoofed!");} else {original}} (argument); / / We redefine now console.log as our fake function window['console']['log']= fake //Then we call console.log with any; argument console.log ("Thisis unaltered"); //Now we should see other text in console different to "Ka0labs" console.log ("Ka0labs"); //Aaaand Everything still OK console.log ("Byebye!"); 

if everything is normal it:

Normal function
VM117:11 This is unaltered
VM117:9 Spoofed
VM117:11 Bye bye!

! In fact, in order to control the generation of code execution, we also can be more clever ways to modify the function. For example, we can build a code segment based on the above code and redefine the eval function. We can pass the JavaScript code to the eval function, and the next code will be calculated and executed. If we define this function, we can run different code:

 //Just a normal Eval Eval ("console.log ('1337') //Now we Repat"); the process... Var original var = Eval; fake = function (argument) the code to {/ / If be evaluated contains1337 if (argument.indexOf... ("1337")! ==-1 we just) {/ /... Execute a different code original ("for (I = 0; I 10; < i++; console.log) {(I)}");} else {original}} (argument); eval= fake; Eval ("console.log ('Weshould see this...')"); //Now we should see the execution of a for loop instead of what is expected Eval ("console.log ('Too1337 for you! ')"); 

operating results are as follows:

< p>1337
VM146:1We should see this... VM147:10

says, although this method is very clever, but it is also a very basic and common method, it is easier to be detected.

two, breakpoint

, in order to help us understand the function of the code, JavaScript debugging tools (such as DevTools) can prevent the execution of script code by setting breakpoints, and breakpoints are the most basic in code debugging.

if you have studied the debugger or the x86 architecture, you may be more familiar with the 0xCC instructions. In JavaScript, we have a similar instruction called debugger. When we declare the debugger function in the code, the script code will stop running here in the debugger instruction. For example,

 console.log ("Seeme!"); debugger; console.log ("Seeme!"); 

, many commercial products will define an infinite loop debugger instruction in code, but some browsers will block such code, while others will not. The main purpose of this approach is to let those who want to debug your code of people feel bored, because infinite loop means the code will continue to pop-up window to ask you if you want to run the script code:

setTimeout (function) ({while (true) {eval ("debugger")

, three time difference this is a kind of traditional anti reversing techniques borrowed from over time based on anti debugging techniques. When script executes in DevTools and other tools, it will run very slowly (long time), so we can decide whether the script is being debugged according to the running time. For example, we can measure the running time between two sets of points in code, and use this value as a reference. If run time exceeds this value, it means that script is running in debugger at present.

 set demo code is as follows: Interval (function (startTime) {var = (check, diff), for (0; check = 1000; check; < check++) {console.log (check); (console.clear);} diff = (startTime) - if (diff; > 200) {alert ("Debugger detected!");}}, 500); 

four, DevTools

(Chrome) detection using this technique is the ID attribute in the div element, when the div element is sent to the console (such as console.log (DIV)), the browser will automatically try to get the element ID. If the code is invoked after the console.log, the getter method is invoked, indicating that the console is currently running. The proof of concept code

simple as follows:

 let div = document.createElement ('div'); let (loop = setInterval (=>); {console.log (DIV); (console.clear);}); Object.defineProperty (div, ID, {get: (>) =; {clearInterval (loop); alert ("Dev Tools detected!");}}); control 

when we try to code for anti aliasing when dealing with

five, implicit flow integrity, we will first try to rename some functions or variables, but in JavaScript we can detect the function name has been modified, or that we can directly access its original name or calling sequence through the stack trace. The function

arguments.callee.caller can help us before creating a stack trace to storage have been carried out as follows:

 demo code, function (getCallStack) {var stack = "#", total = 0, FN (=arguments.callee; while (FN = fn.caller)) {stack = stack + "total++ return stack";} function (test1) {console.log} ((getCallStack));} function {test1 (test2) (function) (test3);} {test2}); (function) test4 (test3);} {(test4); 

(Note: the confusion degree of source code is stronger, the effect of this technology the better.

six, proxy object

proxy object is the most useful tool in JavaScript at present. This object can help us understand other objects in code, including modifying its behavior and triggering object activities in specific environment. For example, we can create a 2 miles object and track every document.createElemen call, then record the relevant information:

 const handler Our hook to = {/ / keep the track apply: function (target, thisArg, args) {console.log ("Intercepted a call tocreateElement with args: + args); return target.apply (thisArg, args)}} document.createElement= new Proxy (document.createElement, handler) Create our proxy object withour hook / ready to intercept document.createElement 

('div'); next, we can record the relevant parameters and information on the console:

VM64:3 Intercepted a call to createElement with args: div

we can use these information and through the interception of certain Function to debug code, but the main purpose of this article is to introduce anti debug technology. So how do we detect whether the other party uses proxy objects? In fact, this is a game of "cat and mouse" game, for example, we can use the same code, and then try to call the toString method and

 //Call a capture exception: 

"virgin" createElement: try (}catch) {document.createElement.toString; (E) {console.log ("I saw your proxy!");}

the following information:

 function createElement ([native) {code]} 

"but when we use a proxy

 //Then apply the 

: hook consthandler {apply: = function (target, thisArg, args) {console.log (" Intercepted a call tocreateElement with args: + args (thisArg, target.apply); return args document.createElement= new Proxy)}} (document.createElement, handler); //Callour not-so-virgin-after-that-party CreateElement try {document.createElement.toString ();}catch (E) {console.log ("I saw your proxy}

!"); yes, indeed we can detect

VM391:13 I saw agent: your proxy!

we can also add the toString method:

 const handler (target, function = {apply: thisArg, args) {console.log ("Intercepted a call tocreat

This concludes the body part