Bpost Android Malware

May 31, 2021 by Alexandre | 413 views



Recently, a lot of people received several text messages about a parcel delivered by Bpost. The message asks you to click on a link. Of course, this text message is a spam and most of the recent Android devices classify this message in a Spam section automatically. However, because a lot of people are ordering on the Internet, this message could seem legitimate.

In this blog post, we perform a simple and basic analysis of this potential attack.

Analysis Setup

For this analysis, we used an Android 9.0 Virtual Machine (it was not a real physical Android device). On this VM, we observe visually what happened on the device. For the technical analysis, we used a Kali 2021.1 VM with several tools.

The first step of this analysis is to click on the link provided in the text message. There exist several different links (probably regularly changed by the attackers). Our link was hosted on cmn.com.tr. The website seems to be a legitimate website with the Turkey Top Domain Level.

We can note some points:

  • The provided English version of the website is actually not in English
  • Social network buttons are not working
  • Most of the clickable images/links are redirecting to a non-existing page

On the other side, the domain name is registered for more than 20 years to a Turkish ASN and the webserver is hosted in Turkey.

But the link received is not redirecting to a browsable page of this website: cmn.com.tr/go.php?XXXXXXXXXX:

This page looks like the DHL website and asks the user to download and install an application on the device. By changing our user-agent, we noted the link is only accessible from an Android device. From a computer, the link redirects to the Google home page. From an iOS device, after several redirections, the user arrives on the Android Play Store.

Application installation

On our VM, we click on the link to download the application. We downloaded the application three times and we obtain three different applications (DHL195.apk, DHL963.apk and DHL583.apk). It is also difficult to download the application several times from the same device. Indeed, after a download, the link redirects the user to the Android Play Store. To install the application, the user has to enable the installation of unknown apps. After that, the installation is straightforward.

During the first launch, the app asks the user to obtain accessibility privileges on the device.

This permission is available to help people with eye disability for example. But this permission is also dangerous: the application is able to read anything on the screen and can interact directly with your device (simulate clicks). Of course, Android displays a warning before you give this permission to an application

Once the permission is given and the user run it again, the app asks, very briefly, the obtain storage, contacts and SMS permissions. It is brief because the app accepts automatically these permissions. The accessibility feature simulates a click on the Allow button. Then, the application does not show anything, it is a blank page.

If the user tries to go to the Applications settings to obtain more information about this DHL app. The menu will close automatically with a quick pop-up that explains the user does not have the right to go there. This app is not possible to uninstall easily from the Android device. It is possible to remove thanks to a computer and ADB (Android Debug Bridge).

Static Analysis

To decompile and analyze the application, several tools are existing: jadx, bytecode-viewer for example.

The first important point is to observe the Android Manifest file. This file declares all permissions required by the application. In this file, we can identify the Class and the Method that initiates the application. It is usually a good start point to analyze the decompiled source code.

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

The manifest asks to obtain a lot of very intrusive permissions: read_sms, write_sms, kill_background_process,... are some examples.

This part of the Manifest shows the com.eg.android.AlipayGphone.p869d02a9 activity is related to a MAIN action. If we observe the structure of the decompiled application, we note there is no package com.eg.AlipayGphone is visible.

Actually, the code is hidden and encrypted. and not directly available. It will be decrypted and loaded in memory at the application start.

It is possible to analyze all the code available to identify where the malicious code is loaded. It is very time consuming (particularly if the code is obfuscated) and require some experience. Another possibility is to pull the data from the device to a computer.

adb pull /data/data/com.eg.AlipayGphone .

By chance, this malware does not delete all the decrypted code after it is loaded in memory. The utility file indicates there are Dex files in the application data. These files can be analyzed by jadx or bytecode viewer. Inside one of them, we found com.beingyi.encrypt.BYDecoder class and com.beingyi.encryptStringPool class. The first is a class to decode a string with a password. The second class is a list of a lot of Strings.

package com.beingyi.encrypt;

import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class BYDecoder {
    public static String s1 = "fff";
    public static String s2 = "fsghff";

    public static String decode() {
        return decode(StringPool.s1, "#pass");

    public static String decode(String text, String pass) {
        byte[] result;
        int hexlen = text.length();
        if (hexlen % 2 == 1) {a
            result = new byte[(hexlen / 2)];
            text = "0" + text;
        } else {
            result = new byte[(hexlen / 2)];
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = (byte) Integer.parseInt(text.substring(i, i + 2), 16);
        byte[] decrypt = null;
        try {
            Key key = new SecretKeySpec(pass.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(2, key);
            decrypt = cipher.doFinal(result);
        } catch (Exception e) {
        return new String(decrypt);

This class is very simple. Basically, the decode method decrypts a String previously encrypted with the AES algorithm.

  /* renamed from: AnIUoˋٴˈᵎʾᵢᵎˆˑיᵢ゙ⁱᵎﹶʽﹳˆᴵˏᐧⁱˈﹶٴˋˉᴵˈˆyxijd  reason: contains not printable characters */
    public static String f16AnIUoyxijd = "e81e512926fd037e898fd73615353eb7";

    /* renamed from: AyRoCᵎـᵎٴˏיʻᐧˑˉﹶᴵʾˎˈﹳⁱﹶˉʼـᐧˆˋˆˑˉˑʿיaXkwe  reason: contains not printable characters */
    public static String f17AyRoCaXkwe = "e43ade427fc567e2b449ee7461239032";

    /* renamed from: BkslCᵢʽʻᵢˊיʾﹳⁱ゙ˑᴵˏﹶˏיﹶᵎٴˊˋʼˎ゙ٴˉʽʿᵢˎETuYW  reason: contains not printable characters */
    public static String f18BkslCETuYW = "71ae1445f5304e3e0f0fcd6d9d8632d0";

The class StringPool contains a lot of Strings that seems random. The Strings are probably encoded or encrypted and are not readable directly.

A third class is very interesting: cn.beingyi.sub.apps.SubApp.SubApplication. This class uses a lot of string from the class StringPool and uses the decode method several times. There is a method called onCreate, this method is called to start an activity. It should be called only once during the application lifecycle. It is a good start point to completely reverse the application. There is a method that encodes a String thanks to a key. This method could be used to encrypt data before sending it to a C&C server.

    public static byte[] m30(byte[] data, String key) {
        byte[] keyBytes = key.getBytes();
        byte[] encryptBytes = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            encryptBytes[i] = (byte) (data[i] ^ keyBytes[i % keyBytes.length]);
        return encryptBytes;

As previously mentioned, it is possible to completely reverse and deobfuscate the application. It requires a lot of time and it is not always easy. This blog post is a simple analysis, we do not go deeper into this static analysis.

Dynamic Analysis

The last step of our basic analysis is the dynamic one. We set up an HTTPS proxy with Burp Suite on the Kali machine to be able to intercept all messages from the app.

We observe several messages to several addresses The message is encrypted and not understandable. We try to decode it thanks to CyberChef and its Magical method (several attempts to find correct decoding) and we observe some message in Chinese. These messages are not really interesting. It seems to be some random phrases, expression, text... But it is really plausible the app detects it is running on a VM and modifies its behaviour.

But it is possible to obtain a few more information about the IP addresses uses by the malware. We noted most of the IP addresses are located in South Korea, Uzbekistan, The domain names used are random String often with the Russian Top Domain Level. The domains are registered and paid until April 2022.

On a physical mobile device, it should be possible to perform a more complete analysis. Frida is a well-known tool: it can hook function at execution to obtain information usually hidden or not accessible.

To go further

A security researcher, Jeroen Beckers perform a complete and deeper analysis of this kind of malware for the NVISO Labs: https://blog.nviso.eu/2021/04/19/how-to-analyze-mobile-malware-a-cabassous-flubot-case-study/. In his analysis, he uses a physical Android phone and was able to decode the packets send to distant servers. The application uses a Domain Generation Algorithm: it generates some pseudo-random domain name to send information to different servers and evade some detectors. Concretely, the application will scan all other applications installed on the device and send this list to the server. For some application (basically banking applications), the mobile device receives HTML code that imitates the banking app to steal the credentials.

This kind of malware uses an overlay attack. This attack takes advantages of an Android features that allows the app to be on the top of others application (the Facebook Messenger app uses this features). Concretely, the application will open a fake layout of a legitimate banking application on top of your real app. The users think to interact with the banking app, instead, the banking information is provided to the malware application.

The application also sends all the contact to the server. The hackers obtain very easily a large number of phone number to spread to the application link.

How to protect yourself

  • The basic recommendation is to not click on suspicious links from a text message, Messenger, What's App,...
  • Download application exclusively from Play Store (or official store like Amazon or Samsung store)
  • Disable application installation from unknown sources
  • Pay attention to the asked permissions: particularly accessibility permission
  • Update the software of your device
  • Enable the Play Protect features on your device. Play Protect is able to detect a lot of malware or suspicious applications.