COMpfun authors spoof visa application with HTTP status-based Trojan – 10 minute mail

You may remember that in autumn 2019 we published a story about how a COMpfun successor known as Reductor infected files on the fly to compromise TLS traffic. If you’re wondering whether the actor behind the malware is still developing new features, the answer is yes. Later in November 2019 our Attribution Engine revealed a new Trojan with strong code similarities. Further research showed that it was obviously using the same code base as COMPFun.

What’s of interest inside

The campaign operators retained their focus on diplomatic entities, this time in Europe, and spread the initial dropper as a spoofed visa application. It is not clear to us exactly how the malicious code is being delivered to a target. The legitimate application was kept encrypted inside the dropper, along with the 32- and 64-bit next stage malware.

Overall infection chain. Interestingly, C2 commands are rare HTTP status codes

We observed an interesting C2 communication protocol utilizing rare HTTP/HTTPS status codes (check IETF RFC 7231, 6585, 4918). Several HTTP status codes (422-429) from the Client Error class let the Trojan know what the operators want to do. After the control server sends the status “Payment Required” (402), all these previously received commands are executed.

The authors keep the RSA public key and unique HTTP ETag in encrypted configuration data. Created for web content caching reasons, this marker could also be used to filter unwanted requests to the C2, e.g., those that are from network scanners rather than targets. Besides the aforementioned RSA public key to communicate with the C2, the malware also uses a self-generated AES-128 key.

Who is the author?

We should mention here once again that the COMPfun malware was initially documented by G-DATA in 2014; and although the company did not identify which APT was using the malware. Based mostly on victimology, we were able to associate it with the Turla APT with medium-to-low level of confidence.

What the Trojan is able to do

Its functions include the ability to acquire the target’s geolocation, gathering host- and network-related data, keylogging and screenshots. In other words, it’s a normal full-fledged Trojan that is also capable of propagating itself to removable devices.

As in previous malware from the same authors, all the necessary function addresses resolve dynamically to complicate analysis. To exfiltrate the target’s data to the C2 over HTTP/HTTPS, the malware uses RSA encryption. To hide data locally, the Trojan implements LZNT1 compression and one-byte XOR encryption.

Encrypted data Algorithm Key source
Exfiltrated keystrokes, screenshots, etc. RSA Public key from configuration data
Configuration data in .rsrc section XOR (plus LZNT1 compression) Hardcoded one-byte key
Parameters inside the HTTP GET/POST requests AES-128 (plus ETag from config) Generated by Trojan and shared in beacon
Commands and arguments from C2 for HTTP status 427 (dir, upl, usb, net) AES-128 Generated by Trojan and shared in beacon

Encryption and compression used by the Trojan for various tasks

Initial dropper

The first stage dropper was downloaded from the LAN shared directory. The file name related to the visa application process perfectly corresponds with the targeted diplomatic entities. As with all modules with a similar code base, the dropper begins by dynamically resolving all the required Windows API function addresses and puts them into structures. It then decrypts the next stage malware from its resource (.rsrc) section. The algorithm used to decrypt the next stage is a one-byte XOR using the key “0x55”, followed by LZNT1 decompression.

The following files are dropped to the disk in addition to the original application that the malware tries to mimic:

MD5 hash File name Features
1BB03CBAD293CA9EE3DDCE6F054FC325 ieframe.dll.mui 64-bit Trojan version
A6AFA05CBD04E9AF256D278E5B5AD050 ExplorerFrame.dll.mui 32-bit Trojan version

The dropper urges users to run the file as administrator (using messages such as “need to run as admin”), then drops a version corresponding to the host’s architecture and sets the file system timestamp to 2013.12.20 22:31.

Interestingly, the dropper’s abilities aren’t limited to PE lures; as an alternative, this stage is also able to use .doc and .pdf files. In such cases, the dropper will open the files using the “open” shell command instead of running the legitimate spoofed executable application.

Main module – HTTP status-based Trojan

SHA256 710b0fafe5fd7b3d817cf5c22002e46e2a22470cf3894eb619f805d43759b5a3
MD5 a6afa05cbd04e9af256d278e5b5ad050
Compiled 2015.06.26 09:42:27 (GMT)
Type I386 Windows GUI DLL
Size 593408
Internal name ExplorerFrame.dll.mui

The analysis below is based on the 32-bit sample from the table above. The legitimate ExplorerFrame.dll.mui is a language resource for the ExplorerFrame.dll file used by Windows Explorer.

Multi-threaded Trojan features such as monitoring USB devices to spread further and receiving commands as HTTP status codes


As usual in this malware family’s code, a huge number of short standalone functions return all the readable strings. This is done to complicate analysis by not allowing the strings to be visible at a glance for researchers. The module’s preparation stage dynamically resolves all required Windows API function addresses into corresponding custom structures. Afterwards the malware uses indirect function calls only.

The module obtains the processor architecture (32- or 64-bit) and Windows OS version. It includes a number of anti-analysis checks for virtual machine-related devices (VEN_VMWARE, VBOX_HARDDISK, Virtual_DVD_ROM, etc.) to avoid controlled execution. It also notes which security products are running on the host (Symantec, Kaspersky, Dr.Web, Avast).

Before every communication with the C2, the malware checks if software such as debuggers (WinDbg, OllyDbg, Visual Studio) and host (Process Explorer or Monitor, etc.) or network monitoring (Wireshark, TCPView, etc.) programs are running. It also checks for internet connectivity and does not attempt to communicate if the checks fail.

The DLL also checks for potentially available launch processes that it can inject itself into. In the case of PaymentRequired, this could be system, security product or browser processes. Then the malware forms the corresponding code to drop files, delete files, etc.

The last step in the initialization procedure is to decrypt and decompress the configuration file. Decryption is done via a one-byte XOR using the 0xAA key, followed by decompression using the LZNT1 algorithm. From the configuration, the malware parses the RSA public key, ETag and IP addresses to communicate with its control servers.

Decrypted configuration data contains an RSA public key to encrypt exfiltrated data, C2 IPs and unique ETag to communicate with them

HTTP status-based communication module

Firstly, the module generates the following:

  • AES-128 encryption key used in HTTP GET/POST parameters and HTTP status code 427 (request new command);
  • 4-byte unique hardware ID (HWID) based on the host network adapters, CPU and first fixed logical drive serial number.

The module then chooses a process to inject the code into, in order of decreasing priority, starting from Windows (cmd.exe, smss.exe), security-related applications (Symantec’s nis.exe, Dr.Web’s spideragent.exe) and browsers (IE, Opera, Firefox, Yandex browser, Chrome).

The main thread checks if the C2 supports TLS in its configuration. If it does, communication will be over HTTPS and port 443; otherwise, the HTTP protocol and port 80 are used.

Config Parameter Value
Encryption key RSA public key on the image above
ETag C8E9CEAD2E084F58A94AEDC14D423E1A
C2 IPs 95.183.49[.]10

Decrypted configuration content inside the analyzed sample

The first GET request sent contains an ETag “If-Match” header that is built using data from its decrypted configuration. ETags are normally used by web servers for caching purposes in order to be more efficient and save bandwidth by not resending redundant information if an ETag value matches. The implementation of ETags means the C2 may ignore all requests that are not sent from its intended targets if they don’t have the required ETag value.

HTTP status RFC status meaning Corresponding command functionality
200 OK Send collected target data to C2 with current tickcount
402 Payment Required This status is the signal to process received (and stored in binary flag) HTTP statuses as commands
422 Unprocessable Entity (WebDAV) Uninstall. Delete COM-hijacking persistence and corresponding files on disk
423 Locked (WebDAV) Install. Create COM-hijacking persistence and drop corresponding files to disk
424 Failed Dependency (WebDAV) Fingerprint target. Send host, network and geolocation data
427 Undefined HTTP status Get new command into IEA94E3.tmp file in %TEMP%, decrypt and execute appended command
428 Precondition Required Propagate self to USB devices on target
429 Too Many Requests Enumerate network resources on target

C2 HTTP status code descriptions, including installation, USB propagation, fingerprinting, etc.

HTTP 427 can receive any of the following appended commands:

Command Command functionality
dir Send directory content to C2 encrypted with RSA public key from config
upl Send file to C2 encrypted with RSA public key from config
usb Not implemented yet. Possibly same function planned as for HTTP status 428
net Not implemented yet. Possibly same function planned as for HTTP status 429

Removable device propagation module

If initialization is successful, the malware starts one more thread for dispatching Windows messages, looking for removable devices related to a WM_DEVICECHANGE event. The module runs its own handlers in the event of a USB device being plugged into or unplugged from the host.

Other spying modules: keylogger, screenshot tool and more

The user’s activity is monitored using several hooks. All of them gather the target’s data independently of any C2 command. Keystrokes are encrypted using the RSA public key stored in the configuration data and sent once every two seconds, or when moreа than 512 bytes are recorded. These 512 characters also include left mouse button clicks (written as the “MSLBTN” string) and Windows title bar texts. For clipboard content, the module calculates an MD5 hash and if it changes, encrypts the clipboard content with the same RSA public key and then sends it.

In a separate thread, the Trojan takes a bitmap screenshot using the GDIPlus library, compresses it with the LZNT1 algorithm, encrypts it using the key from the configuration data and sends it to the control server. A screenshot will be taken of the target and sent anyway, independently of any C2 command.

Last but not least

There are several choices – albeit not major additional technical ones – that the malware author made which we consider to be noteworthy.

The COM-hijacking-based persistence method injects its corresponding code and structure as a parameter into a legitimate process’s memory. The malware geolocates victims using legitimate web services:, and

The unusual thread synchronization timeout calculation in the HTTP status thread is peculiar. Mathematically, the partial sum of the series is precisely:

This series, in the case of a full sum, is just a representation of the exponent. The developers probably used the exponent to make timeouts in the communication thread more unpredictable and grow at a fast rate, and the compiler calculated it this way.

So what did the COMPFun authors achieve?

We saw innovative approaches from the COMpfun developers twice in 2019. First, they bypassed TLS encrypted traffic via PRNG system function patching, and then we observed a unique implementation of C2 communications using uncommon HTTP status codes.

The malware operators retained their focus on diplomatic entities and the choice of a visa-related application – stored on a directory shared within the local network – as the initial infection vector worked in their favor. The combination of a tailored approach to their targets and the ability to generate and execute their ideas certainly makes the developers behind COMPFun a strong offensive team.

Indicators of compromise

File MD5 Hashes
Trojan 32-bit: A6AFA05CBD04E9AF256D278E5B5AD050
Trojan 64-bit: 1BB03CBAD293CA9EE3DDCE6F054FC325


Temp Mails ( is a new free temporary email addresses service. This service provide you random 10 minutes emails addresses. It is also known by names like: temporary mail, disposable mail, throwaway email, one time mail, anonymous email address… All emails received by Tempmail servers are displayed automatically in your online browser inbox.

Hiding in plain sight: PhantomLance walks into a market – 10 minute mail

In July 2019, Dr. Web reported about a backdoor trojan in Google Play, which appeared to be sophisticated and unlike common malware often uploaded for stealing victims’ money or displaying ads. So, we conducted an inquiry of our own, discovering a long-term campaign, which we dubbed “PhantomLance”, its earliest registered domain dating back to December 2015. We found dozens of related samples that had been appearing in the wild since 2016 and had been deployed in various application marketplaces including Google Play. One of the latest samples was published on the official Android market on November 6, 2019. We informed Google of the malware, and it was removed from the market shortly after.

The latest example of spyware in Google Play disguised as a browser cleaner

During our investigation, we discovered various overlaps with reported OceanLotus APT campaigns. Thus, we found multiple code similarities with the previous Android campaign, as well as macOS backdoors, infrastructure overlaps with Windows backdoors and a few cross-platform resemblances.

Besides the attribution details, this document describes the actors’ spreading strategy, their techniques for bypassing app market filters, malware version diversity and the latest sample deployed in 2020, which uses Firebase to decrypt the malicious payload.

Our report is broken down into several sections.

  1. Malware versions – technical description of versions found, their features and relationships between them.
  2. Spread – information on specific tactics used by the threat actors for distributing their malware.
  3. Infrastructure – further details on uncovered infrastructure pieces as well as overlaps found.
  4. Victimology – thoughts on the actors’ interests in choosing their targets.
  5. Overlaps with previous campaigns – details of similarities with all related campaigns that we have identified.

More information on PhantomLance is available to customers of Kaspersky Intelligence Reporting. For more information, contact [email protected]

Malware versions

For the purposes of the research, we divided samples we found into a series of “versions” based on technical complexity: from the basic Version 1 to the highly sophisticated Version 3. Note that they do not fully correlate with the chronological order of their appearance ITW: for example, we observed Version 1 samples in late 2019 and in 2017, the year that we also saw Version 3.

Functionality of all samples are similar – the main purpose of spyware was to gather sensitive information. While the basic functionality was not very broad, and included geolocation, call logs, contact access and SMS access, the application could also gather a list of installed applications, as well as device information, such as model and OS version. Furthermore, the threat actor was able to download and execute various malicious payloads, thus, adapting the payload that would be suitable to the specific device environment, such as Android version and installed apps. This way the actor is able to avoid overloading the application with unnecessary features and at the same time gather information needed.

Version 1

We attribute the latest Google Play sample (MD5: 2e06bbc26611305b28b40349a600f95c) to this version. This is a clear payload, and unlike the other versions, it does not drop an additional executable file. Our main theory about the reasons for all these versioning maneuvers is that the attackers are trying to use diverse techniques to achieve their key goal, to bypass the official Google marketplace filters. And achieve it they did, as even this version passed Google’s filters and was uploaded to Google Play Store in 2019 (see Spreading for details).

No suspicious permissions are mentioned in the manifest file; instead, they are requested dynamically and hidden inside the dex executable. This seems to be a further attempt at circumventing security filtering. In addition to that, there is a feature that we have not seen before: if the root privileges are accessible on the device, the malware can use a reflection call to the undocumented API function “setUidMode” to get permissions it needs without user involvement.

Note that this trick only works with Android SDK version 19 or higher.

Most of the aforementioned operations naturally require root access, but we believe that the root exploit may be delivered as payload in a server response to collected device info. Also, some of the applications that the malware mimics will have notified the user that they only work on rooted devices. For instance, Browser Cleaner can only clean up the browser cache if it is given root permissions.

Version 2

Specimens of this version were also detected in 2019 and earlier. One of the samples was located in Google Play Store in November 2019 and described in the Dr. Web blog. Based on our detection statistics and spotted version stamps, we believe that this version is a replacement for Version 3, which we did not observe in 2019.

Below are the most valuable points and main differences from the Version 1.

The malicious payload APK is now packed in an encrypted file in the assets directory and is decrypted by the first stage using an AES algorithm. A decryption key and initialization vector (IV) are located in the first 32 + 16 bytes of the encrypted payload.

After decryption, the asset file will look like this.

As you can see, before the APK magic, the file header contains strings that are used for making further reflection calls to payload methods. Here is the first-stage code fragment with explanations regarding the payload loading process.

All Version 2 payloads use the same package name, “”, which probably mimics the official Google Play Games package, “”.

Moreover, we spotted developer version stamps in decrypted payloads.

MD5 Developer version stamp
65d399e6a77acf7e63ba771877f96f8e 5.10.6084
6bf9b834d841b13348851f2dc033773e 5.10.6090
8d5c64fdaae76bb74831c0543a7865c3 5.10.9018
3285ae59877c6241200f784b62531694 5.10.9018
e648a2cc826707aec33208408b882e31 5.10.9018

It is worth mentioning payload manifests, which do not contain any permission requests. As stated in the description of Version 1, permissions required by the malicious features are granted via an undocumented Android API.

We have found two different certificates used for signing Version 2 payloads.

MD5 Certificate
6bf9b834d841b13348851f2dc033773e Serial Number: 0xa4ed88e620b8262e

Issuer: CN=Lotvolron

Validity: from = Wed Jan 20 11:30:49 MSK 2010

8d5c64fdaae76bb74831c0543a7865c3 Serial Number: 0xd47c08706d440384

Issuer: CN=Ventoplex

Validity: from = Wed Apr 13 05:21:26 MSK 2011


Although validity dates look spoofed in both cases and do not point to any real deployment times, by analyzing all payload certificates, we discovered that the second one (Ventoplex) was used to sign Version 3 payloads as well.

Version 2.1

The latest samples of PhantomLance discovered in the early 2020 introduced a new technique for decrypting payloads: the malicious payload was shipped with its dropper, encrypted with AES. The key is not stored anywhere in the dropper itself but sent to the device using Google’s Firebase remote config system. The other technical features are very similar to the ones we observed in Version 2, so we tagged this generation as Version 2.1.

We were able to make a valid request to PhantomLance’s Firebase API. The response consisted of a JSON struct containing the AES decryption key, where the “code_disable” value is the decryption key for payload.

What is important, the dropper expects that the AES decryption key will be stored in a parameter named “code”, so this specific variant should not function properly. Besides, we noticed that Firebase previously returned one more field, named “conf_disable”, which has the same value as the “code_disable”, so we assume that the actors are still tinkering with this new feature.

Another interesting technique that the actors are trying to implement is a third-stage payload implant. The second-stage payload (MD5: 83cd59e3ed1ba15f7a8cadfe9183e156) contains an APK file named “data” (MD5: 7048d56d923e049ca7f3d97fb5ba9812) with a corrupted header in the assets path.

The second stage reads this APK file, decrypts it and rewrites its first 27 bytes as described below.

This results in an APK file (MD5: c399d93146f3d12feb32da23b75304ba) that appears to be a typical PhantomLance payload configured with already known C2 servers (cloud.anofrio[.]com, video.viodger[.]com, api.anaehler[.]com). This third-stage APK is deployed with a custom native library named “data.raw”, also stored at the assets path. This library is used for achieving persistence on the infected device and appears to be a custom daemonized ELF executable based on the open-source “daemon.c” Superuser tool component, while in previous samples, we saw MarsDaemon used for this purpose.

Code comparison of the library used to daemonize the third stage payload with daemon.c source code hosted on Github

Version 3

While we have found that Version 2 has been used as a replacement for this one, as we have not observed any new deployments of Version 3 in 2019, it still looks more advanced in terms of technical details than Version 2. According to our detection statistics and deployment dates on application markets, Version 3 was active at least from 2016 to 2018.

Below are the most valuable points and main differences between Version 3 and Version 2.

The first-stage dropper appears even more obfuscated than that in Version 2; it uses a similar way of decrypting the payload, but it has minor differences. The encrypted content is split into multiple asset files under 10256 bytes in size plus an encrypted config file, and contains payload decryption details.

Below is the payload decryption sequence.

  1. Decrypt the payload config file from the assets with both a hardcoded name and AES key.
  2. Read the following values from the decrypted payload config file in this order:
    • AES key for APK payload decryption
    • Class and method names for reflection calls to the payload
    • MD5 for APK payload integrity check
    • Number and names of the split APK payload parts
  3. Decrypt the APK payload header hardcoded in the first stage with the AES key from the payload config. Write it to the APK payload file.
  4. Using decrypted names of the split payload parts, decrypt their content and append them to the APK payload file one by one.
  5. Check the integrity of the resulting APK payload file by comparing with the MD5 value decrypted from the payload config.
  6. Load and run the APK payload.

The following reversed code fragment represents the actual payload decryption process.

Each Version 3 payload has the same package name, “”, and is signed with the same certificate (CN=Ventoplex), used to sign some of the Version 2 payloads.

The only developer version stamp that we have found in Version 3 payloads is “10.2.98”.

Another notable finding is the 243e2c6433815f2ecc204ada4821e7d6 sample, which we believe belongs to a Version 3 payload. However, no related dropper has been spotted in the wild, and unlike the other payloads, it is signed with a debug certificate and not obfuscated at all, revealing all variable/class/method names and even BuildConfig values. Our guess that this is a debug developer version that somehow got leaked.

As a conclusion to this technical review, it is worth saying that all payloads across the different versions, even Version 1, which is in fact a clear payload without a dropper, share a code structure and locations where sensitive strings, such as С2 addresses, are stored.


The main spreading vector used by the threat actors is distribution through application marketplaces. Apart from the com.zimice.browserturbo, which we have reported to Google, and  com.physlane.opengl, reported by Dr. Web, we have observed tracks indicating that many malicious applications were deployed to Google Play in the past and have now been removed.

These search results contain a link to already-removed malware in Google Play

Some of the applications whose appearance in Google Play we can confirm.

Package name Google Play persistence date (at least)
com.zimice.browserturbo 2019-11-06
com.physlane.opengl 2019-07-10
com.unianin.adsskipper 2018-12-26
com.codedexon.prayerbook 2018-08-20 2018-08-20 2018-08-20
com.zonjob.browsercleaner 2018-08-20
com.linevialab.ffont 2018-08-20

Besides, we have identified multiple third-party marketplaces that, unlike Google Play, still host the malicious applications, such as https://apkcombo[.]com, https://apk[.]support/, https://apkpure[.]com, https://apkpourandroid[.]com and many others.

Example of a malicious application with a description in Vietnamese that is still available in a third-party marketplace (hxxps://androidappsapk[.]co/detail-cham-soc-be-yeu-babycare/)

In nearly every case of malware deployment, the threat actors try to build a fake developer profile by creating a Github account that contains only a fake end-user license agreement (EULA). An example is the one below, reported by us to Google.

This Google Play page contains a fake developer email

 Here is a related Github account with the same handle, registered on October 17, 2019.

A Github profile that is part of the fake developer identity

The account contains only one report with one file described as some type of EULA.

During our extensive investigation, we spotted a certain tactic often used by the threat actors for distributing their malware. The initial versions of applications uploaded to app marketplaces did not contain any malicious payloads or code for dropping a payload. These versions were accepted because they contained nothing suspicious, but follow-up versions were updated with both malicious payloads and code to drop and execute these payloads. We were able to confirm this behavior in all of the samples, and we were able to find two versions of the applications, with and without a payload.

An example of this behavior can be seen in Ads Skipper (https://apkpure[.]ai/ads-skipper), in ApkPure.

Versions of Ads Skipper with (v. 2.0) and without (v. 1.0) a malicious payload in ApkPure

Third-party marketplaces like those mentioned in the table above often serve as a mirror for Google Play: they simply copy applications and metadata from Google Play to their own servers. Therefore, it is safe to assume that the samples listed in the table were copied from Google Play as well.


While analyzing the С2 server infrastructure, we quickly identified multiple domains that shared similarities with previous ones but were not linked to any known malware samples. This allowed us to uncover more pieces of the attackers’ infrastructure.

Example of related infrastructure

Tracking PhantomLance’s old infrastructure, which dated back four years, we noticed that the expired domain names had been extended. The maintenance suggested that the infrastructure might be used again in the future.

Domain Registered Last updated
osloger[.]biz 2015-12-09 2019-12-01
log4jv[.]info 2015-12-09 2019-11-26
sqllitlever[.]info 2015-12-09 2019-11-26
anofrio[.]com 2017-05-16 2020-03-30
anaehler[.]com 2017-05-16 2020-03-30
viodger[.]com 2017-05-16 2020-04-07

The PhantomLance TTPs indicate that samples are configured only with subdomains as C2 servers, while most, but not all, parent domains do not have their own IP resolution. We checked the ones that did have a valid resolution and found that they all resolved to the same IP address: 188.166.203[.]57. It belongs to the DigitalOcean cloud infrastructure provider and, according to Domaintools, hosts a total of 129 websites.

Looking up records for this IP address in our passive DNS database suggests that a few dozen of these websites are legitimate, as well as the aforementioned PhantomLance domains and two more interesting overlaps with OceanLotus infrastructure:

  • browsersyn[.]com: known domain used as a C2 in a previously publicly reported sample (MD5: b1990e19efaf88206f7bffe9df0d9419) considered by the industry to be the OceanLotus APT.
  • cerisecaird[.]com: privately received information indicates that this domain is related to OceanLotus as well.


We have observed around 300 infection attacks on Android devices in India, Vietnam, Bangladesh, Indonesia, etc. starting in 2016. Below is a rough cartographic representation of countries with top attempted attacks.

We have also seen a number of detections in Nepal, Myanmar and Malaysia. As you can see, this part of South Asia seems to be targeted by the actors the most.

Note that due to the chosen distribution vector (publication of malicious samples on publicly available application stores), there should be secondary infection of random victims not directly related to the actors’ interests.

To get more details on targeted victims, we looked at the types of applications that the malware mimicked. Apart from common luring applications, such as Flash plugins, cleaners and updaters, there were those that specifically targeted Vietnam.

  • luxury.BeerAddress – “Tim quan nhau | Tìm quán nhậu” (“Find each other | Find pubs” in Vietnamese). An application for finding the nearest pub in Vietnam.
  • codedexon.churchaddress – “Địa Điểm Nhà Thờ” (“Church Place”)

    Publisher description (hxxps:// translated from Vietnamese:
    Information about churches near you or the whole of Vietnam, information about patronies, priests, phone numbers, websites, email, activities, holidays…

  • – “Tin 247 – Đọc Báo Hàng Ngày” (“Read Daily Newspaper”)

Mimics the Vietnamese mobile news application.

Overlaps with previous campaigns

In this section, we provide a correlation of PhantomLance’s activity with previously reported campaigns related to the OceanLotus APT.

OceanLotus Android campaign in 2014-2017

In May 2019, Antiy Labs published a report in which they described an Android malware campaign, claiming that it was related to OceanLotus APT. We checked the provided indicators using information from our telemetry and found that the very first tracks of these samples date back to December 2014.

It is important to note that according to our detection statistics, the majority of users affected by this campaign were located in Vietnam, with the exception of a small number of individuals located in China.

The main infection vector seems to be links to malicious applications hosted on third-party websites, possibly distributed via SMS or email spearphishing attacks. Examples below.

Referring URL for victim Malware URL First request Last request
hxxp://[.]vn/android/download/nhaccuatui-downloader/31798 hxxp://[.]apk 2015-03-03 2015-03-22
hxxp://[.]apk 2014-12-29 2015-03-19
hxxp://[.]apk hxxp://[.]apk 2015-04-07 2017-01-04


The latest registered malware download event occurred in December 2017. We observed a small amount of activity in 2018, but judging by the volume of hosted malware and the number of detections we observed, the main campaign took place from late 2014 to 2017.

To best visualize the similarities we discovered, we made a code structure comparison of the sample from the old reported OceanLotus Android campaign (MD5: 0e7c2adda3bc65242a365ef72b91f3a8) and the only unobfuscated (probably a developer version) PhantomLance payload v3 (MD5: 243e2c6433815f2ecc204ada4821e7d6).

Code structure comparison of a sample linked to OceanLotus and PhantomLance payload v3.

 Despite the multiple differences, we observed a similar pattern used in malware implementation. It seems that the developers have renamed “module” to “plugin”, but the meaning remains the same. Overlapping classes look quite similar and have the same functionality. For example, here is a comparison of the methods contained in the Parser classes.

Parser from 0e7c2adda3bc65242a365ef72b91f3a8 ParserWriter/Reader from 243e2c6433815f2ecc204ada4821e7d6
public void appendBoolean(boolean f) public void appendBoolean(boolean value)
public void appendByte(byte data) public void appendByte(byte value)
public void appendBytes(byte[] data) public void appendBytes(byte[] value)
public void appendDouble(double val) public void appendDouble(double value)
public void appendInt(int val) public void appendInt(int value)
public void appendLong(long val) public void appendLong(long value)
private void appendNumber(Object value)
public void appendShort(short val) public void appendShort(short value)
public void appendString(String str) public void appendString(String value)
 public byte[] getContents() public byte[] getContents()
public void appendFloat(float val)
public boolean getBoolean() public boolean getBoolean()
public byte getByte() public byte getByte()
public byte[] getBytes() public byte[] getBytes()
public double getDouble() public double getDouble()
public float getFloat()
public int getInt() public int getInt()
public long getLong() public long getLong()
public short getShort() public short getShort()
byte getSignal()
public String getString() public String getString()

Using our malware attribution technology, we can see that the PhantomLance payloads are at least 20% similar to the ones from the old OceanLotus Android campaign.

OceanLotus macOS backdoors

There are multiple public reports of macOS backdoors linked by the industry to OceanLotus. We examined these in order to find possible overlaps, with the caveat that it was really difficult to compare malware implemented for two completely different platforms, since two different programming languages were obviously used for the implementation process. However, during the analysis of the macOS payload (MD5: 306d3ed0a7c899b5ef9d0e3c91f05193) dated early 2018, we were able to catch a few minor tracks of the code pattern used in the Android malware implementation described above. In particular, three out of seven main classes had the same names and similar functionality: “Converter”, “Packet” and “Parser”.

Summary of overlaps

Another notable attribution token that applies to most of OceanLotus malware across platforms is usage of three redundant, different C2 servers by each sample, mostly subdomains. Below is an example of this from the samples examined above and OceanLotus Windows malware described in our private report.

MD5 C2 servers Description
0d5c03da348dce513bf575545493f3e3 mine.remaariegarcia[.]com



PhantomLance Android
d1eb52ef6c2445c848157beaba54044f sadma.knrowz[.]com



OceanLotus Android campaign 2014-2017
306d3ed0a7c899b5ef9d0e3c91f05193 ssl.arkouthrie[.]com



OceanLotus MacOS backdoor
51f9a7d4263b3a565dec7083ca00340f ps.andreagahuvrauvin[.]com



OceanLotus Windows backdoor

Based on the complete analysis of previous campaigns, with the actors’ interests in victims located in Vietnam, infrastructure overlaps between PhantomLance and OceanLotus for Windows, multiple code similarities between an old Android campaign and MacOS backdoors, we attribute the set of the Android activity (campaign 2014-2017 and PhantomLance) to OceanLotus with medium confidence.

Considering the timeline of the Android campaigns, we believe that the activity reported by Antiy Labs is a previous campaign that was conducted by OceanLotus until 2017, and PhantomLance is a successor, active since 2016.

In summarizing the results of this research, we are able to assess the scope and evolution of the actors’ Android set of activity, operating for almost six years.


Kaspersky Lab products verdicts



Android campaign linked to OceanLotus (2014-2017)

macOS campaign linked to OceanLotus



PhantomLance malware


PhantomLance payload-free versions


Android campaign 2014-2017


Domains and IP addresses



Android campaign 2014-2017


Temp Mails ( is a new free temporary email addresses service. This service provide you random 10 minutes emails addresses. It is also known by names like: temporary mail, disposable mail, throwaway email, one time mail, anonymous email address… All emails received by Tempmail servers are displayed automatically in your online browser inbox.

Loncom packer: from backdoors to Cobalt Strike – 10 minute mail

The previous story described an unusual way of distributing malware under disguise of an update for an expired security certificate. After the story went out, we conducted a detailed analysis of the samples we had obtained, with some interesting findings. All of the malware we examined from the campaign was packed with the same packer, which we named Trojan-Dropper.NSIS.Loncom. The malware uses legitimate NSIS software for packing and loading shellcode, and Microsoft Crypto API for decrypting the final payload. Just as the earlier find, this one was not without its surprises, as one of the packaged samples contained software used by APT groups.

Primary analysis

Loncom utilizes NSIS for running shellcode contained in a file with a name that consists of numbers. In our example, the file is named 485101134:

Overview of the NSIS archive contents

Once the shellcode is unpacked to the hard disk and loaded into the memory, an NSIS script calculates the starting position and proceeds to the next stage.

What the shellcode does

Before proceeding to decrypt the payload, the shellcode starts decrypting itself piece by piece, using the following algorithm:

  • Find position for next 0xDEADBEEF dword.
  • Read dword: size of data to decrypt.
  • Read dword: first part of key.
  • Read dword: second part of key.
  • Find suitable key: check the numbers consequently, starting at 0, while xor(i, second part of key) != first part of key. This part is needed to hold up execution and prevent AV detection. After simplification, key = i = xor(first part, second part).
  • Decrypt next part of shellcode (xor), move on to it.

Decrypting the next part of the shellcode

Here’s the code that performs the algorithm described above:

After several such iterations of block decryption, the shellcode switches to active steps, loading libraries and retrieving the addresses of required functions with the help of the APIHashing technique. This helps avoid stating the names of requested functions directly, providing their hashes instead. When searching for functions by hash, a hash will be calculated for each element from the library export table until it matches the target.

Then, Loncom decrypts the payload contained in the same file as the shellcode and proceeds to run it. The payload is encrypted with an AES-256 block cipher. The decryption key is stated in the code, and the payload offset and size are passed from the NSIS script.

The main part of the shellcode: decrypting the payload


For automated Loncom unpacking, we need to find out how data is stored in the packed NSIS installers, obtain the payload offset and size from the NSIS script, and pull the key from the shellcode.

Unpacking the NSIS

After a brief analysis, we managed to find that the NSIS installers have the following structure:

  • an MZPE NSIS interpreter containing in its overlay the data to be processed: the flag, the signatures, the size of the unpacked header, and the total size of the data, and then the containers, i.e. the compressed data itself.
  • Containers in the following format: dword (data size):zlib_deflate(data). The 0th container has the header, the first container has our file with the shellcode and the payload, and the second one has the DLL with the NSIS plugin.
  • The header contains a table of operation codes for the NSIS interpreter, a string table and a language table.

As we have obtained the encrypted file, now all we need is to find the payload offset and size, and proceed to decrypting the payload and the shellcode.

NSIS data structure

As all arguments in the NSIS operation codes when using plugins are passed as strings, we need to retrieve from the header string table all strings that look like numbers within the logical limits: from 0 to (file size – shellcode size).
NSIS unpacking code:

To simplify determining the payload offset and size, we can recall the structure of the file with the shellcode: encrypted blocks are decrypted from the smallest address to the largest, top to bottom, and the payload is located above the shellcode. Thus, we can determine the position of the 0xDEADBEEF byte and consider it the end of the encrypted data (aligning as required, because AES is a block cipher).

Decrypting the shellcode

To decrypt the payload, we need to:

  • decrypt the shellcode blocks;
  • determine where the AES key is;
  • retrieve the key;
  • try to decrypt the payload for offsets received from the NSIS;
  • stop after obtaining the first two bytes = ‘MZ’.

Step one can be performed by slightly modifying the code that performs the decryption algorithm in IDA Pro. The key can be determined with the help of a simple regular expression: ‘xC7x45.(….)xC7x45.(….)xC7x45.(….)xC7x45.(….)xE8’ — “mov dword ptr” 4 times, then “call” (pseudocode in the main part of the shellcode).
The other steps do not require a detailed explanation. We will now describe the actual malware that was packed with Loncom.

What’s inside

Besides Mokes and Buerak, which we mentioned in the previous article, we noticed packed specimens of Backdoor.Win32.DarkVNC and Trojan-Ransom.Win32.Sodin families, also known as REvil and Sodinokibi. The first is a type of backdoor used for controlling an infected machine via the VNC protocol. The second is a ransomware that encrypts the victim’s information and threatens to publish it.
However, the most exciting find was the Cobalt Strike utility, used both by legal pentesters and by various APT groups. The command center of the sample that contained Cobalt Strike had previously been seen distributing CactusTorch, a utility for running shellcode present in Cobalt Strike modules, and the same Cobalt Strike packed with a different packer.

We continue monitoring Trojan-Dropper.NSIS.Loncom and hope to share new findings soon.


BB00BA9726F922E07CF243D3CCFC2B6E (Backdoor.Win32.DarkVNC)
EBE191BF77044961684DF51B88CA8D05 (Backdoor.Win32.DarkVNC)
4B4C98AC8F04680F7C529956CFE8519B (Trojan-Ransom.Win32.Sodin)
AEF8FBB5C64734093E78EB13E6FA7849 (Cobalt Strike)

Temp Mails ( is a new free temporary email addresses service. This service provide you random 10 minutes emails addresses. It is also known by names like: temporary mail, disposable mail, throwaway email, one time mail, anonymous email address… All emails received by Tempmail servers are displayed automatically in your online browser inbox.