Asia’s SMS stealers: 1,000 bots and one study

1. Introduction

Attackers have increasingly started using Telegram as a control server (C2). One example is the Lazy Koala group, which we recently discovered and set out to study. While researching bots on Telegram, we found that many are from Indonesia. We were struck by the huge numbers of messages and victims, and how new bots and chats seem to appear on Telegram by the day, so we decided to get to the bottom of this “Indonesian tsunami.”

In doing so, we found a couple chat-related SMS stealers from Indonesia. We named them SMS Webpro and NotifySmsStealer because of the string stealers in the body. Sporadic attacks against Bangladesh and India were also detected. We couldn’t determine the intentions of the attackers with any certainty. We assume that the attacks were motivated by monetary gain or to steal personal data.

Judging by the region where the malicious items were downloaded, the intended targets included Russians and Belarussians. However, the share (less than 0.1%) of the total volume of Indonesian malware downloaded in those two countries is very small.

2. Research begins

Going through the chat rooms, we noticed a lot of one-size-fits-all bots from Indonesia sending messages in the following form:

Examples of messages from Telegram bots
Figure 1. Examples of messages from Telegram bots

The number of such messages averaged between 10,000 and 30,000. In some cases, it reached 100,000 in a single chat room. It’s easy for even a casual user to figure out that such messages have something to do with their phones and the SMS messages they receive. Based on these heuristics, we decided to highlight the bots that collect data from phones.

An example of one of the bots and its chat room with the messages shared with the victims
Figure 2. An example of one of the bots and its chat room with the messages shared with the victims

From the Telegram bot messages, we extracted keywords and phrases (including “SmsManager” and “Sadap Sonic”). Then, with YARA, we filtered the chats and identified about 1,500 unique bots. In Figure 1, a slight similarity among the bot messages can be seen: they all explicitly relay data about incoming notifications or messages from certain devices. However, the average user did not link the bots in any way. Besides, most of the bots (Figure 2) use Indonesian as their primary language.

We ultimately decided to dig further and analyzed the files associated with the Telegram bots which sent the messages. They all turned out to be APK files, and had infected a huge number of Android phones across Southeast Asia.

3. Analysis of core malware

Among the files we found, two malicious APKs stood out: SMS Webpro and NotifySmsStealer. Both were used to attack users en masse. The structure of the classes, their names, and indeed the codes are identical to one another, as if they were made from a template. The only things that differ are the C2 servers within the samples, and the format or wording for sending messages to Telegram. The general set of applications also included unique examples of malware with their own code and functionality. We will discuss them in the next section.

3.1 SMS Webpro

This app is an SMS stealer. The victim installs it on the phone and gives it the permissions it asks for. And while the stealer steals the phone correspondence, the unsuspecting victim only sees a well-prepared decoy.

Let’s move on to a breakdown of the stealer itself. Upon a cursory inspection of the app, the first thing that catches your eye is the permissions required for the app to run in the manifest. They show that the app can read, send, and intercept SMS, plus access the network.

SMS Webpro Application Manifesto
Figure 3. SMS Webpro Application Manifesto

The core functionality is contained in the com.example.myapplication namespace, particularly in the MainActivity, ReceiveSms, and SendSMS classes.

SMS Webpro Classes
Figure 4. SMS Webpro Classes

Returning to the manifest, we can see that the MainActivity class is the starting point from which the app is launched. This can be seen in that this class filters the intent (Intent) of android.intent.action.MAIN and android.intent.category.LAUNCHER. The ReceiveSms andSendSMS classes, on the other hand, filter the android.provider.Telephony.SMS_RECEIVED intent that is triggered when incoming messages are received. They are receivers, meaning that the latter piece of code is triggered whenever an event occurs that matches the intentions filtering it.

Basic intentions and how they are handled by SMS Webpro
Figure 5. Basic intentions and how they are handled by SMS Webpro

First, let’s look at the main class, MainActivity. When the app is first launched, the WebView class is used. It is used to open an interactive site through a given link. This is done to divert the user’s attention from the app’s primary malicious action. Then comes the request for the permissions that the stealer needs to run properly.

MainActivity class
Figure 6. MainActivity class

You can also view the link in your browser. In this case, the app is masquerading as a wedding invitation and there is nothing malicious about the page that opens. Wedding invitations are just one of the many decoys that SMS Webpro uses. We’ll get to this more later.

Example of a website that opens when the .apk is launched
Figure 7. Example of a website that opens when the .apk is launched

Then, it makes a request for the permissions required to steal SMS messages. If successful, a message is sent to the bot stating that the SMS Webpro .apk was installed and that a new user is now connected. Each user is identified by the unique parameters of their phone:

  • Build.FINGERPRINT is the unique identifier of the build;
  • Build.TIME is the UNIX build time, expressed in milliseconds.

Going back to the original manifest, we can see that the ReceiveSms and SendSMS classes in the same namespace both receive the SMS receive event:

SMS Webpro Manifesto
Figure 8. SMS Webpro Manifesto

Let’s look at the ReceiveSms class. This class checks whether a desired event has occurred or not. If the android.provuder.Telephony.SMS_RESEVED event is triggered, the text and phone number of the sender are extracted from the event. Then, a message is generated and sent to the Telegram bot.

ReceiveSms class
Figure 9. ReceiveSms class

The SendSMS class takes the same events as input and sends messages to the server in the same way, but with one key difference. If the message received (without special characters “&” and “#”) starts with line 55555 and fits the following pattern, a message with the original text is sent to the phone number extracted from the event.

55555,<telephone_num>,<sms_text>
 

From the logic of this action, we should assume that this is how attackers can intercept messages with certain confirmation codes.

3.2 NotifySmsStealer

This piece of malware can be considered an extension of SMS Webpro, as it reuses the RecieveSms and SendSMS classes. The overall logic is the same: it’s a stealer that conceals its activity by opening a page in the browser. But the important difference with this piece of malware is that it can steal not only messages but also notifications.

If you look at the manifest, you will see that it requires a far larger number of permissions. You may notice that the app now has the ability to recover after a reboot as well as track your phone notifications in the background.

NotifySmsStealer Manifesto
Figure 10. NotifySmsStealer Manifesto

In the applications section of the manifest, we find the same intent filters as in the previous malware. However, a server is added to filter incoming notifications, which is handled by the NotificationService class. The rest of the filter elements belong to the standard androidx namespace and relaunch the app after a reboot.

Declaration of NotificationService in the manifest
Figure 11. Declaration of NotificationService in the manifest

The namespace and classes haven’t changed much, particularly in name. The MainActivityAlias class extends the MainAcivity class to add a guaranteed default simulation of a web page, basically a google.com page.

NotifySmsStealer classes
Figure 12. NotifySmsStealer classes

In the MainActivity class, a new onNotice class element, BroadcastReceiver, has been added to handle events from the NotificationService class. For it to start processing events, it has to be registered dynamically. This is done by the registerReciver method at the very end of the onRequestPermissionsResult function to listen for intentions labeled msg.

Creation of a local administrator account
Figure 13. Creation of a local administrator account

But the actual NotificationService simply receives notification events on the phone. It extracts the Title, Text, and Data parameters from the event received.

Notification service class
Figure 14. Notification service class

An intent is then created with the msg label. All extracted data are added to it as additional parameters. This intent is sent to the app using sendBroadcast. Since BroadcastReciver was already configured in the MainActivity class for this intent, it falls into the class we were originally interested in.

Receiver onNotice
Figure 15. Receiver onNotice

In the onNotice receiver created, the OnRecive method is triggered when the necessary intent is received as input. It retrieves the previously described message parameters that contain info about the incoming notification. Then, a message is generated to be sent to the Telegram bot.

4. Analysis of unique samples

During the analysis, there were also outlying “freaks,” which cannot be attributed to any of the types of stealers above (or they are a rare modification of one of the other stealers). The Telegram bots that used such samples as C2 only had a connection to a single file. A few instances with non-standard names, message formats, or code features are discussed below.

4.1 Gallery Stealer

In early February 2024, a bot called Sms Bombing Gallery Hack was registered. None of the messages it forwarded contained any text. Only pictures were sent. This caught our attention and we decided to investigate the app associated with this bot further.

Example chat content from Sms Bombing Gallery Hack
Figure 16. Example chat content from Sms Bombing Gallery Hack

Although English was the main language used in the chat room, the pictures depicted Asian people and cities in India. From this, we can conclude that the attacks mainly target India.

Let’s check out how the app works. It requires quite a few permissions upon launch, from the predictable one for memory access to the rather mystifying one for turning on vibration. To top it all off, it requires read and write access for contacts, as well as the ability to set default contacts. The last three are specific to apps like contact managers. However, the app only filters the intent to run it. From the logic of the manifest, the MainActivity class will be launched first.

Gallery Stealer Manifesto
Figure 17. Gallery Stealer Manifesto

Let’s check out the MainActivity class in the com.my.newproject39 namespace. When started, a decoy is launched using the OnCreate method. After initializing the GUI and creating input fields, the app requires the user to enter a phone number and some random number. If one of the fields is blank, it displays the messages Enter Number or Enter Amount. After doing so, the user sees a message confirming that an SMS has been sent. In this case, the phone number entered is actually sent to the bkashotp-siam[.]vercel[.]app server via four different URLs. After a few thousand such requests, the phone “cheerfully” vibrates.

Code to create a decoy in Gallery Stealer
Figure 18. Code to create a decoy in Gallery Stealer

In the background (if the user has approved the necessary permissions), the real app activity starts with the initializeLogic method. The app tries to get the names of all .jpg files using the getJpgFilesinDirectory function. The input is the path to the /storage/emulated/0/DCIM/Camera folder, which is where photos are stored, and the output is an array of file names. Iterating through the list of found files, the stealer reads the image file and sends it to the C2 server using the TelegramImageUploader function.

Collection of photos
Figure 19. Collection of photos

Turning to the method for sending photos to Telegram, we come across a rather unsurprising functionality. A POST request to the Telegram API is created, sendPhoto, where the Telegram bot token appears. The data is sent in raw form, with the beginning and end of the photo separated by the characters *****.

Sending pictures to the Telegram bot
Figure 20. Sending pictures to the Telegram bot

Notably, the project has many unused methods and even classes. This indicates some shoddy project development or poor programming skills on the part of the developer.

Inside the stealer, the developer left a button with a link to his Dark_Cyber_Security telegram channel, as well as the note: “Developed By Abu Talha Al Nayeem.” Various social media accounts for Abu Talha Al Nayeem can be found by searching the name.

Back-End Developer
Figure 21. Back-End Developer

The Instagram account is in Bengali, and the Telegram channel publishes posts from Bangladesh. Naturally then, the developer of the stealer is from Bangladesh. In addition, there is a threads.net account with that name, with a picture of the hacker.

Photo of the hacker on social networks
Figure 22. Photo of the hacker on social networks

In one account, Abu Talha Al Nayeem has his hometown listed as Alekhar Char, Chittagong, Bangladesh, supporting the conclusion above.

4.2 Modification of SMS Webpro

The sample discussed in this chapter is a modification of the regular SMS Webpro stealer. The stealer was spotted thanks to unusual messages on the HACK SMS BOT telegram bot. Since December last year, the chat room with this bot has received about 19 thousand messages. When the C2 app is installed and replayed by a Telegram bot, a message is sent with the header Aplikasi Sudah Terisntal, and includes a lot of info about the corresponding device.

Messages in the HACK SMS BOT
Figure 23. Messages in the HACK SMS BOT

Unfortunately, we were not able to obtain the APK file itself, only one of its DEX files. However, the class names in the com.example.myapplication namespace are utterly identical to those in the regular version of SMS Webpro. When we open the MainActivity class, it is immediately apparent why there is such a large data flow in Telegram. The following additional parameters from the public Build class are sent to the bot when collecting device info:

  • ID
  • User
  • Product
  • Brand
  • Device
  • Board
  • BOOTLOADER
  • DISPLAY
  • FINGERPRINT
  • HARDWARE
  • HOST
  • MANUFACTURER
  • MODEL
  • TAGS
  • TYPE
  • Product

Otherwise, the application is no different from the classic SMS Webpro stealer. Although the number of chat messages has reached 19,000, the number of unique victims is only 16, going by unique device ID.

4.3 FalseCaller

We discovered MyNotificationListenerBot, a bot with a non-standard message format. The first chat message is dated December 26, 2023. We found the associated bot app Truecaller_13.47.9_sign.apk, downloaded from India.

MyNotificationListnerBot
Figure 24. MyNotificationListnerBot

Despite the name, you can see that this is not a real app: its certificate was hastily generated and the signing company is named fast, whereas for a real app it would be Truecaller. Notably, the country code in the chat is Indian, which supports our theory about the outbound attack vector. Since it imitates the original app, we named this stealer FalseCaller.

Certificate Subject FalseCaller Clean TrueCaller
Distinguished Name C:IN, CN:fast, ST:IN CN:truecaller
Common Name fast truecaller
Country Code IN
State IN

Let’s take a look inside the app itself. There are about 1,000 lines in the manifest. Most of them belong to the actual Truecaller app. However, there are three entries at the very end of the manifest that have nothing to do with Truecaller (highlighted in purple in Figure 25). The com.truecaller.MyNotificationListener, com.truecaller.SMSReceiver, and com.truecaller.AnswerCallBroadcastReceiver classes filter intentions to receive notifications, SMS, and calls, respectively.

Supplementing the manifest with malicious classes
Figure 25. Supplementing the manifest with malicious classes

However, this begs the question: doesn’t the Truecaller app have its own handlers for the same intentions? And in that case, how would the service and receivers work if they are filtering the same intent? The point is that if the intent filter is prioritized, the handler with the highest priority will run.

For AnswerCallBroadcastReceiver and SmsReceiver classes, that’s not good: Truecaller has a higher priority filter set. However, for the notification service, the priorities are the same. That means that the message is given to a random service. When checking the messages on the management server, it appears that only notification messages reached it.

Let’s take a closer look at the server itself. The server extends the NotificationListenerService class originally defined in the system. So we’re 100% certain that all notification messages will arrive here. The rewritten onNotificationPosted method, called when a notification appears, performs two functions of interest: a and b.

Method onNotificationPosted
Figure 26. Method onNotificationPosted

Although the firstAction function gains info about the system, the results of the request go nowhere. But the secondAction function calls the Async_TelegramNotifySender class, which is an asynchronous class that is a child of the AsyncTask class.

Calling an asynchronous class
Figure 27. Calling an asynchronous class

In that case, the doInBackground method will be called first (if there is no method before initialization). It calls an internal backgroundTask function that collects standard notification information as well as data about the device’s charge level, carrier, and name on the local Bluetooth network.

Creating and sending a message in Telegram
Figure 28. Creating and sending a message in Telegram

Studying the messages in the Telegram bot, we found 24 victims of this stealer among 100,000 messages. Half of the numbers belonged to Bharti Airtel and the rest to Reliance Jio Infocomm. Both telecom companies operate mainly in India. We can assume that the malware is only distributed within India.

4.4 ICARD

Another bot that we discovered was ICARD. The name of the APK file for the malware was noteworthy: ICICI BANK.apk.apk. This suggests that the attackers were imitating the real ICICI Bank app. That said, the official name of the app on Google Play is different, it’s called iMobile Pay. The malicious app’s certificate is clearly fake, although it’s noticeably better than the previous stealer and looks authentic. Without a professional eye, you probably wouldn’t notice anything suspicious. However, the fake certificate is quite standard and has nothing to do with the name of the app. See below for a comparison of the certificates of the original and fake app.

Certificate Subject ICARD iMobile Pay
Distinguished Name C:US, CN:Android, L:Mountain View, O:Android, ST:California, OU:Android, email:android@android.com C:91, CN:ICICI BANK, L:MUMBAI, O:ICICI BANK, ST:MAHARASHTRA, OU:ICICI BANK
Common Name Android ICICI BANK
Country Code US 91
State California MAHARASHTRA

Let’s check out the manifesto. In addition to the previously encountered usual permissions for SMS stealers, two more are required. The oppo.permission.OPPO_COMPONENT_SAFE and com.huawei.permission.external_app_settings.USE_COMPONENT permissions are required to access the app’s charge saving features.

ICARD Manifesto and the required permissions
Figure 29. ICARD Manifesto and the required permissions

The main class called when the application starts is in the nn.nn namespace and is called MainActivity.

ICARD main class
Figure 30. ICARD main class

In addition, there are several receivers that process the intentions of incoming messages. However, most of them only have a class template, without any functionality. This may indicate that the stealer is still under development.

ICARD Primary Receiver
Figure 31. ICARD Primary Receiver

The first thing we notice about the MainActivity class is that most of the strings are encrypted. Let’s move on to the decoder function. The class implements a rather simple algorithm for string decryption: all strings first undergo base64 decryption, and then a cyclic Xor with UTF-8 key string is applied to the resulting byte array.

ICARD string decryption class
Figure 32. ICARD string decryption class

Now, with this info, you can get to know the basic functionality of the bot. When you open the bot, you don’t see anything interesting in the OnCreate method: the method checks the current permissions and runs the basic functions of the stealer.

The OnCreate method in ICARD
Figure 33. The OnCreate method in ICARD

In the MainFun function, we find the classic method for hiding a malicious action by opening a browser page, but there is a nuance: here, the .html is an internal resource of the stealer itself.

Hiding functionality with an internal HTML page
Figure 34. Hiding functionality with an internal HTML page

Let’s check out the stealer’s resources of the and what the page looks like. On startup, the ICICI Bank logo appears and after a while, the website authentication form loads up. The attackers timed out the loading of the registration page to convincingly simulate the launch of the app.

Fake ICICI Bank Entry Form
Figure 35. Fake ICICI Bank Entry Form

When entering any values into the form, the user is redirected to the next page, showing a picture stating that the service is not available for technical reasons. This trick not only distracts users, but also forces them to log in again after some time, guaranteeing another launch of the malware.

Cover image
Figure 36. Cover image

If you delve deeper into the app’s resources, you’ll find some unused pictures unrelated to ICICI Bank.

Pictures in the ICICI Bank resources
Figure 37. Pictures in the ICICI Bank resources

As you can see, most of them feature the BIG BAZAAR logo. This logo and name belong to an eponymous chain of Indian flagship stores. This company also offers a mobile app for online shopping. We can assume that the attacker had previously used the same method of hiding malicious activity, but used the online store as bait.

Let’s return to the main class. Once a user has opened a phishing page, the stealer extracts the Telegram bot ID and the chat ID from the resources to communicate with the C2 server.

Obtaining resources for communicating with the C2 server
Figure 38. Obtaining resources for communicating with the C2 server

The app then checks that there have been no more than five attempts to run this function. Upon launch, the app tries to configure auto-start for OPPO brand phones. The stealer then sends a welcome message. But besides the make and model of the phone, the stealer also tries to get the IMSI info. To do so, it uses a method that doesn’t require any additional permissions, but only works for Android version 11.

Obtaining IMSI
Figure 39. Obtaining IMSI

The siminfo phone database is accessed with the following request:

Query = getApplicationContext().getContentResolver().query( Uri.parse(“content://telephony/siminfo”), new String[]{ “_id”, “sim_id”, “imsi”,”icc_id”,”number”,”display_name” }, “0=0”, new String[0], null );
 

In such a query, the attacker retrieves all rows of data from all the columns above. However, going through all the results, it only extracts the number and display_name fields, which it sends to the server along with the welcome message.

Nothing of note happens in the receiver for incoming texts. In a now classic scheme, the text and the sender are extracted from the message. The data, tagged with the brand and model of the phone as an identifier, is then sent to the server.

ICARD receiver
Figure 40. ICARD receiver

The bank posted a warning about the proliferation of the fake app on its official LinkedIn page. The chain of infection starts with SMS and WhatsApp messages masquerading as notifications from a bank employee that the current version of the bank’s app is not working. As a solution, a supposedly new, updated app is sent, which is actually an APK file containing the malware.

5. Name source

According to news reports in the Indonesian media, the main vector for the spread of the stealers in Indonesia is WhatsApp. An article by CNN Indonesia claims that the developers of such stealers earn money from selling malware. This explains the uniformity among the apps and their mass distribution.

Such activity has not gone unnoticed and has been covered by researchers in the past, as covered in this article on SMS stealers. But it only covers the tip of the iceberg.

As for the method of malware delivery, phishing is most common. The victim is sent a message with an APK file attached. Users click on the attachment without noticing its extension. Then, an SMS stealer is installed on their phones. The malicious app masquerades as different sorts of services and documents: package courier deliveries, wedding invitations, electronic traffic fines, online bills, job openings, or voting committee notifications.

Example of phishing via WhatsApp
Figure 41. Example of phishing via WhatsApp

In addition to phishing, there is another, less popular way of spreading malware through phishing sites. During our analysis, we found several links from which malicious apps were downloaded. Since they have long since expired, you can ascertain what the phishing sites were masquerading as just by the name of the applications downloaded from them.

http[:]//otp-bni.rf[.]gd https[:]//pinjaman-pribadi[.]com https[:]//wwwww.hengwin888.biz[.]id https[:]//octoclicks.quizfinansial[.]cloud https[:]//665c7425f6ef0924050d5bc7812d2870.cdn.bubble[.]io https[:]//281057a700b761e04b22986e2c5809f2.cdn.bubble[.]io https[:]//18598dc911409c4f002efc088d87a908.cdn.bubble[.]io https[:]//upgradekartukrediitdbs00.getnew.my.id
 

The articles above list various types of app cloaking that are consistent with our statistics on the distracting links contained in malicious APKs. We extracted such links from all the samples we collected. Surprisingly, most of the addresses are fake invitations, mostly wedding invitations. The second largest share was phishing links mimicking banking apps or the official pages of real banks. Next are delivery sites, links to apps on Google Play, and various kinds of forms to fill out (questionnaires). The more exotic links include a mock check transaction, a site for buying and selling real estate, a photo collection on Pinterest depicting check printouts, and even an article on learning English.

Table 1. Statistics on types of bait used

Many of them used a google.com link for phishing. We hypothesize that the attackers may have used some sort of stealer template. If so, the link to the search page could have been left as a default page in the template. If we exclude such data from our study, the following picture emerges. Usually, cloud-based platforms and online website builders such as Vercel, Bubble, and Tilda were used to deploy phishing services. Open Indonesian services for creating online wedding invitations, such as Our Wedding or Undang Kami, are also hugely popular. The classic short link building services such as s.id are still in use.

Table 2. The most popular phishing domains

The main target of such an attack is ordinary users. SMS messages often come with one-time codes. They are used to confirm logins on, for example, messaging apps. But one-time passwords from bank accounts are the most vulnerable: having intercepted one, an attacker can make withdrawals from the victim’s account.

6. Conclusion

We found over 1,000 Telegram bots being used as control servers for malware. Their presumed purpose is to attack users to steal money and possibly personal data.

Despite the large number of attacks, the lion’s share of the malware falls under two types of stealers: SMS Webpro and NotifySmsStealer. This suggests that the stealers were not written from scratch. A builder or template for them has been purchased. The only thing the attackers change is their C2 server on Telegram.

Amongst this mass of stealers, there are a few unique cases. Despite the differences in the code and execution of the stealers, the tool deployed remains the same: SMS and user notifications. Unique stealers operate across India and Bangladesh.

The chain of infection starts with a typical phishing attack on WhatsApp. With few exceptions, the attacker uses phishing sites posing as a bank to get users to download apps from them.

According to our observations, the statistics for the countries from which the malware samples were downloaded show that the largest number of victims are Indonesian nationals. The number of alleged victims in Indonesia is in the thousands. In countries such as India and Singapore, the number of malware downloads did not exceed a few dozen. More isolated cases include potential attacks on Russia, Belarus, and Malaysia. These statistics are not surprising; the most common decoy is aimed at Indonesians.

To protect yourself from such an attack, simply follow basic safety rules:

  • Check the extensions of any files that you receive.
  • Don’t download apps from a number you don’t know, even if the sender appears to be a bank employee.
  • When downloading an app from Google Play, make sure that the name of the app is correct by cross-checking it with official sources.
  • Do not download or install apps that require permissions that are suspicious given the type of app.

Author:
Varvara Akhapkina, Information Security Threat Researcher, PT ESC

Source: Original Post