Qealler — The Silent Java Credential Thief

January 17, 2019 David Cohen

Qealler is a new type of malware that CyberArk Labs recently detected in a spam campaign targeting corporate mailboxes in the UK. At first sight, it looks to be a simple, harmless file that can be detected by antivirus software. However, our analysis shows that there’s more to it.

Qealler very efficiently hides a dropper and credential stealing script. Bypassing antivirus protection, it can capture more than 20 third-party software and Windows credentials and use them to access sensitive files.

In this blog, we’ll share our malware analysis – including insight into the information returned to the attacker. We’ll also share best practices for protecting against it.

Qealler in the Wild

Figure 1 Older Qealler samples found, only 5/61 positives on VirusTotal (VT).

Qealler was first detected in August 2018 by James_inthe_box[i] [fig. 1] and determined to be mainly hosted on UK websites. Since it has a very low engine detection rate, as shown in the screenshot above, a lot of antiviruses consider it to be a safe file and don’t block it.  In short, the door is open for the execution of this malware without any problems.

As seen in the detected samples in figure 2 from URLhaus[ii]Qealler disguises itself as a Remittance Advice File[iii]URLhaus is a project by abuse.ch with the goal of sharing malicious URLs being used for malware distribution.

Figure 2 URLs hosting the malware are from UK.

Most recently, we detected Qealler in a spam campaign targeting UK users. As you can see in figure 1, it’s mostly present as a Jar file, which is a package file format typically used to aggregate many Java class files and their associated metadata and resources (text, images, etc.) into one file for distribution. It’s acting as an executable running in the Java Virtual Machine[iv].

Technical Analysis

Qealler can be difficult to detect because of its high-level and multi-layer self-encryption, which has different keys for each malware sample coupled with tricky obfuscation in every sub-file. This means that it can decrypt and compile itself in multiple steps. Basically, using a signature-based approach, as most of the anti-viruses do for this kind of malware, would not protect against other Qealler samples.

Here we’ll examine the recent sample we found: 61a8b7f9260d163d0f20059bf21d6c55954ee77b0588610bfab4907dd964cf6a[v].

The first question is: how do we know it’s a malicious file? Some versions have a really low detection rate on VirusTotal (VT) [fig. 1]. Moreover, when we ran it for the first time, nothing seemed to happen. If we run it a second time, a message box [fig. 3] appears. That’s strange for remittance advice.

Let’s see what we can learn from procmon logs about its behavior.

Figure 3 What happens when Qealler is run more than two times.

Using procmon, we see that Qealler is trying to communicate with 146[.]185[.]139[.]123:7766, but fails. Indeed, this IP was already down the day of the analysis. Instead, we’ll try to use the first IP in the table in figure 2 (i.e., 159[.]65[.]84[.]42:11530), which was online at the time of writing this. How can we redirect all the packets sent to the active server?

Figure 4 ProxyCap configuration to redirect IP.

In our case, we use ProxyCap[vi]. ProxyCap enables you to redirect your computer’s network connections through proxy servers. You can tell ProxyCap which applications to connect to the internet through a proxy and under what circumstances. This is done through a user-friendly interface without the need to reconfigure any of your internet clients.

Figure 5 Successfully redirected packet and received packets!

Configuring ProxyCap is an easy game. You have to define two things: 1.) the proxy server – the destination IP address where redirected packets should be sent; and 2.) the rule – the indicator needed to spot, according to their initial destination IP addresses, which packets to redirect . After configuring ProxyCap [fig. 5], let’s try  to open the Qealler file again and check the behavior on procmon.

Congratulations! The redirection was a success and, in return, we received a packet triggering a new set of events from Qealler. Let’s dig into the huge procmon log for more good stuff.

One thing we like to check before everything else when using procmon is the process create event.

Figure 6 Process created by Qealler.

Qealler created two processes [fig.6]:

  • … executable, decompressing another file in the windows temporary folder referred as %TEMP%. The exact command executed by this executable is:
%TEMP%\7z_<RANDOM_NB>.exe x %TEMP%\_<RANDOM_NB>.tmp -o %TEMP% 
-p "<PW>" -mmt -aoa -y
  • exe executed with the following parameters:
%TEMP%\qealler\python\Python.exe %TEMP%\qealler\qazagne\main.py all

Looking at the first process created, it appears Qealler is decrypting a password-protected file using 7z after receiving a packet from the server. Procmon logs give us more information: Qealler has created four files: three related to 7zip executable (two dlls and one executable) and the password-protected archive. So, finally, Qealler is either including those files (using a packer[vii]) or downloading them. The second option seems more logical if we look at the size of the malware. First, let’s dive deeper into this archive and then reverse Qealler to understand the exact way it works.

Figure 7 File tree of the downloaded archive using TreeSize.

The password-protected archive contains two folders [fig. 7]. One contains a python script called Qazagne and the other contains the python software with all of the  libraries required to run the script.

The script is not called Qazagne for nothing. Indeed, the script is a compact version of the famous credential recovery tool Lazagne.[viii] The LaZagne project is an open source application used to retrieve lots of passwords stored on a local computer [fig. 8]. Each software stores its passwords using different techniques (plaintext, Windows APIs, custom algorithms, databases, etc.). This tool was developed for the purpose of finding these passwords for the most commonly used software. The output is a list of credentials in JSON format.

Why does Qealler steal all those credentials? Why is it bypassing AVs? Is it a dropper or a packed malware? Let’s dig deeper.

Figure 8 Lazagne credentials target very similar to Qazagne target [ix].

Reversing Qealler

In order to learn more about Qealler’s inner workings, we decided to reverse it. A JAR archive can be easily decompressed using different tools (WinRAR, JarExplorer, Java Decompressor etc.). Once decompressed, you get all the compiled Java class files. The next step is to decompile them with tools like JD-Eclipse, Cavaj Java Decompiler or JBVD. Let’s apply this to our sample.

Figure 9 Content inside the Jar archive decompressed with JavaDecompressor.

At a first look [fig. 9], the files obtained from JavaDecompressor seem weird. There’s only one class file (com.aglyphodonta.naiadaceous.Piezoelectric) and other files with unknown extensions. In other words, the files seem to be encrypted.

Let’s focus on the Piezoelectric.class file and decompile it with JBVD[x] . The decompiled source code obtained [fig. 10] is quite simple. It uses the ScriptEngineManager object configured in Javascript mode in order to execute the script defined in the abettors’ variable.

Figure 10 Decompiled Piezoelectric file.

The serious part begins now. The JavaScript part [fig. 11] is our key to decrypt some of the encrypted files in the archive. As you can see in figure 11, it is obfuscated. Nonetheless, the main function calls (purple) and their definitions in the java documentation suggest that it’s a decryption process and you can identify the decryption key as well. The variable [fig. 11] in green contains everything:

  • Decrypted class package name: enterprise.reaqtor.reaqtions.standartbootstrap
  • Decrypted class name: Header
  • File to decrypt: com/agliphodonta/eparchies/Reticulatocoalescent.ski
  • File size in bytes: 6251
  • Decryption key: xml1JzxHQcBFVSiJ

Figure 11 JS script embedded in the main java class.

So, now we have everything. The script decrypted the file com/agliphodonta/eparchies/Reticulatocoalescent.ski using AES-256 with the key xml1JzxHQcBFVSiJ.
The decrypted file (with a file size of 6256 bytes) is saved in a file called Header (also the name of the class) in the package qua.enterprise.reaqtor.reaqtions.standartbootstrap. Finally, the class is instantiated and executes the constructor and main function of the Header Class.

Now that we understand the behavior, we can easily write a function that does the same thing and save the decrypted file in order to be able to read it.

Figure 12 Script to decrypt the Reticulatocoalescent.ski file.

The output of our script [fig.12] is a java class called Header. It contains a map. By changing the source code a little to look at the content stored in the map object, we discovered that it stores all the remaining encrypted files and their original file names. It was not clear at first because it uses the map to decrypt only three files (Head, Loader$1 and Loader$1$1) out of a lot of files.

Another important point is that there are not only AES encrypted files this time (using a different key than before), but also a Gzip compressed file. Even with the high obfuscation, we can still identify the next decrypted class that will be instantiated afterwards (aka Head class).

Now that we know the map contains all of the remaining files, what happens if we can do it all over again, but this time add in some code to save all the files in the decryption function? We tried and obtained something astonishing.

Figure 13 Files obtained decrypting all the content of the map.

The result is, as you can see [fig. 12], very obfuscated. Moreover, a lot of obfuscation mechanisms are used: useless functions with long and closed names; functions that return the object itself; filenames above 256 characters, which cause problems with a lot of software (including Windows Explorer); etc.

We could have spent a lot of time refactoring and simplifying the code to have something that can at least be compiled (though still obfuscated), but instead we chose to analyze the malware’s behavior based on the static analysis (i.e., looking for static analysis’ indicators in the reverse source code).

Figure 14 Encrypted URL found in the source code.

Let’s quickly look  at those files to see if something can help us. In this type of malware, you’ll usually look for the next stage it will download from a URL or unpack from within. Indeed, figure 13 contains the variables found in one of the obfuscated files. Clearly, we can detect two important variables: LIB_7Z_URL and LIB_QEALLER_URL, which prove that Qealler is a dropper.

Thanks to our knowledge of the behavior so far, in the Head file, which is the real main class, we easily spotted the part of the code responsible for downloading 7z and the Qealler archive from the server [fig. 13], decompressing it and executing the python Qazagne script. Moreover, after the execution of the script, Qealler is looking for #ff# and #fs# strings in the output of the python script.

Interestingly, that is exactly what we got: a JSON format output with those strings at the start and the end of the output. These are clearly not correct JSON syntax and so there must be a difference between the original Lazagne script and this compressed and fake one. All the important information is between those tags.

The next step is to send them to the server. From there, we got everything from the script : the JSON is encrypted using AES 256 bytes again with another key and the packet data will contain “output=XXX” with XXX being the encrypted message. We found it on Wireshark and using decryption on it with the key found by reversing Qealler gives you the exact content of the JSON.

So how do we protect against similar threats? A multi-layer protection strategy is best.

An updated and well-configured antivirus solution should be your first wall of defense. While an antivirus will detect and block some threats, dynamic, rapidly evolving and highly obfuscated threats like Qealler will likely go undetected.

Case in point: In June, only 5 out of 61 well known and widely deployed AV engines detected it as a threat [fig.2]. As Qealler’s old samples signatures are being added to AV databases, Qealler can still improve and reinforce its obfuscation mechanism so that it can continue to bypass AV signatures.

Moreover, AVs and a lot of protection tools have been built to block known attacks and attacks using the same techniques, but cannot block new attacks. As a consequence, AVs are clearly not enough.

Qealler executes a python script targeting sensitive resources. Having defense in depth on the endpoint is a good way to prevent this kind of new attack. For example, solutions like CyberArk’s Endpoint Privilege Manager (EPM) can protect endpoint credential stores that reside in memory, registry or files. EPM also has the ability to block lateral movement like Pass-the-hash, Pass-the-ticket and more. With this product, it does not matter if the malware bypasses traditional security protections: you can rest assured that critical resources are protected.


[i] https://twitter.com/James_inthe_box/status/1035190253697396737

[ii] https://urlhaus.abuse.ch/browse/tag/Qealler/

[iii] https://en.wikipedia.org/wiki/Remittance_advice

[iv] https://www.javaworld.com/article/3272244/core-java/what-is-the-jvm-introducing-the-java-virtual-machine.html

[v] https://www.virustotal.com/#/file/61a8b7f9260d163d0f20059bf21d6c55954ee77b0588610bfab4907dd964cf6a/detection

[vi] http://www.proxycap.com/

[vii] https://en.wikipedia.org/wiki/Executable_compression

[viii] https://github.com/AlessandroZ/LaZagne

[ix] https://github.com/AlessandroZ/LaZagne

[x] https://github.com/Konloch/bytecode-viewer

Previous Article
Securing Identity and Access Management Solutions
Securing Identity and Access Management Solutions

This blog provides a technical overview of IAM and the risks associated when IAM on-premises agents are not...

Next Article
How I Hacked Play-with-Docker and Remotely Ran Code on the Host
How I Hacked Play-with-Docker and Remotely Ran Code on the Host

CyberArk Labs set out to try and escape the mock container in an effort to run code on the Docker host -- a...