Android devices of Internet users are subjected to an ever growing variety of malware, as the Android threat landscape continues to evolve. To be one step ahead of the threat actors, malware analysts must familiarize themselves with a diverse set of such malware, ranging from banking trojans to info stealers.
While each of these malware possess different characteristics, thereby posing different challenges for analysis, in this article we will be focusing on an infostealer that disguises itself as a fake Android update.
Eagerness to keep mobile devices updated with the latest security patches grows, as users’ awareness about mobile security increases. And it is exactly this noble intention that the attackers exploit by presenting fake Android update apps to victims.
But how do attackers get victims to install such malware? Attackers have several tricks up their sleeve, including generating fake warnings on victims’ phones advising them about installing “updates” to remove malware that has infected their phones
Recently, during one of F-Secure Android’s routine tests, we came across one such fake Android update sample – Android Güncelleme, that proved to be evasive and exhibited interesting exfiltration characteristics. Although the sample is not novel (some features have already been covered in other articles on the Internet), it nevertheless combines several malicious actions together, such as anti-analysis and anti-uninstallation, making it a more potent threat.
In this article, we will be analyzing this malware sample and studying how it achieves its malicious goals of stealing personal user information such as credentials and banking info.
Initial analysis and information gathering
Although typically malware analysis begins with static analysis, it is only a recommendation that should be taken with a pinch of salt. When analyzing Android malware, the norm is to start by analyzing AndroidManifest.xml.
However, another approach is also to directly start by installing the sample on a mobile device and observing its behavior. For the sample that we analyzed, we followed a stepwise cyclical approach wherein we progressed from static to behavioral analysis and looped back and used the information gathered in the previous step to perform next level static and behavioral analysis.
“Fake update” installation
At the onset we should acquaint ourselves with the malware sample and gather simple preliminary information. To achieve this, we install it on a rooted Android test device by using adb. Once the installation is successful, a quick look on the phone shows the installed malicious app (as shown in Figure 2).
The name that the sample uses is Android Güncelleme, which means “Android Update” in Turkish (courtesy Google Translate). Also, the icon being used by the sample is the Android robot icon. At this stage, we now suspect that the malware is masquerading as a fake Android update app.
To check what happens further, we launch the malicious app and observe the behavior. We notice the following:
- The malware requests for Accessibility Service permission by showing a decoy screen (Figure 3.). The decoy screen is used to trick the user into granting the essential permission, with no malicious actions happening. If the decoy screen is however, ignored, or closed, it keeps popping again periodically till the user grants the requested permission.
- The malware then disappears from the app drawer on the phone. This is possibly to trick the user into believing that the update is done. But, in reality, it continues running in the background.
We proceed by granting the Accessibility Service permission. We note that the screen in Figure 5. appears briefly.
However, before the user can grant or revoke access to make the malware app a device admin app, the screen disappears and we see that irrespective of user choice, the app has already made itself a device admin app (as shown in Figure 6.) In short, it is evident that granting of accessibility service permission is misused by the app into making itself a device admin app.
Device admin apps are typically used in the enterprise setup to allow company IT administrators to enforce policies and restricitons on company managed Android devices. An example policy would be enforcing password requirements on Android devices thereby protecting company devices from unauthorised access. By their design, device admin apps provide rich control over the managed devices.
Having performed preliminary information gathering we now come to static analysis. We start with AndroidManifest.xml file which must be included in every Android app. This file declares components of the app, including all activities, services, broadcast receivers, and content provider.
Additionally, it declares the permissions that the app needs. Finally, the XML also declares a launcher activity (if any) which defines what will happen when a user clicks on the app to start it. As such it is a rich source of information to get a detailed understanding of the app.
Let us study the AndroidManifest.xml file now, to identify various internal details of the malware. We use the Jadx tool to perform static analysis.
App name and permissions
The app name is a good place to start with in the AndroidManifest.xml. In our case, we have already gathered this information from our preliminary behavioral analysis. Therefore verifying the name in the AndroidManifest.xml (Figure 7.) serves to merely provide confirmation.
Upon inspecting the AndroidManifest.xml file, we note that the malicious app requests a lot of permissions. This gives us an idea of the actions that it may be intending to perform. Some of these permissions that immediately arouse suspicion are:
- REQUEST_INSTALL_PACKAGES – allows an app to request installing packages
- REQUEST_DELETE_PACKAGES – allows an app to request deleting packages
- READ_PHONE_STATE – Allows read only access to phone state, including the current cellular network information, the status of any ongoing calls, and a list of any PhoneAccounts registered on the device
- RECEIVE_SMS – Allows an application to receive SMS messages
More details about Android permissions can be found in their documentation.
Apart from these permissions, we can also verify in AndroidManifest.xml the request for Accessibility Service and Device Admin permissions as well. We already expect the presence of these, based on the gathering of our preliminary information.
As shown in Figure 8. the Accessibility Service permission is being requested by the malware. Malicious apps, however, use this permission to perform swiping or tapping activities in the background, unbeknownst to the user.
Accessibility Service permission in the hands of a wrong app can be misused to enable or permissions and actions. For our malicious sample, from Figure 8. we see that a resource “@xml/yhgyleyqcfv” is used to handle the Accessibility Service. This resource defines the events typeWindowContentChanged and typeWindowStateChanged that will be received by this service.
So, we can surmise at this stage that when the malware is granted the Accessibility Service permission, any time the window content or state is changed, the app will be notified and the app would then potentially be able to override any window state changes. An example would be overriding the “device admin disable” request from the user.
Device Admin API
Android provides device administration support for enterprises at the system level via the Device Admin API. Once device admin app is enabled, such apps can then be used to deploy policies.
For an app to use the device admin API, among other things, the manifest must include the BIND_DEVICE_ADMIN permission, and the ability to response to the ACTION_DEVICE_ADMIN_ENABLED intent. As shown in Figure 9., we see these requirements being fulfilled in AndroidManifest.xml. In fact from the XML, we also see an expressed ability to respond to ACTION_DEVICE_ADMIN_DISABLE_REQUESTED and DEVICE_ADMIN_DISABLED.
These are hints to some activities or responses happening when a user tries to disable admin app. At this stage we make a note of this.
Among multiple types of entry points, the most common one used is the Launcher activity. This is the activity that is started when a user taps on the application’s icon.
The launcher activity is declared in the AndroidManifest.xml with two intents – MAIN and LAUNCHER. For our sample, it is evident from the manifest file, as shown in Figure 10.
We can now also identify the class that implements the Launcher activity. It is com.hrzauzlmanpvzrkw.lckkyqkdocriqwa.ntnzfmbdmbez.
However, the Launcher activity class is part of the payload and can only be analysed after the payload is extracted.
We use the Frida tool to perform dynamic analysis to extract the payload.
To load a bundled payload, the malware must first write the payload to disk (FileOutputStream.write) and then use Android’s DexClassLoader, to load non-system classes from disk. Therefore, for our sample, we create the hooks as shown in Figure 11.
We are particularly interested in whether the “write” method is invoked, and if yes, with what argument. Secondly, we want to see if DexClassLoader was called and with what argument.
We write the above hooks and execute the malicious app on a test phone. Upon executing this malicious sample, we see the following output, as shown in Figure 12.
We can confirm that the “write” method was indeed invoked, albeit, strangely, on a JSON file. The JSON file is also loaded later by the DexClassLoader. We can therefore surmise at this stage that the payload, actually an APK, is being evasive and hiding as a JSON file.
Now that we know the file path for the payload (xTPEoT.json), we can use Android Debug Bridge (adb) to extract this file from the mobile device on our PC for further analysis. Upon extracting the files from the malware APK (Figure 13.), we see that the payload is bundled with the sample, under the assets directory.
Analyzing the payload
After acquiring the json payload and renaming it as APK (because json is a just a façade), we are now ready for analysis of the payload. We used jadx to analyze this newly acquired payload.
We start by adding the payload to the existing project in jadx. Doing this enables us to have all related files under one project and linked for easy maneuvering between classes.
As shown in Figure 14, we see classes from the payload now. We continue where we left our static analysis, with the class assigned with Launcher activity – com.hrzauzlmanpvzrkw.lckkyqkdocriqwa.ntnzfmbdmbez.
First glance at the Launcher activity class, as shown in Figure 15. shows that it is heavily obfuscated. A typical tactic used by threat actors to delay analysis of the sample; this further strengthens our suspicion that the sample is malicious.
Analyzing such obfuscated code line by line is extremely time consuming and might still be ineffective. We must alter our analysis tactics at this stage.
As shown in Figure 15, we can still identify some patterns in variable names being used by the code – .Ia, c.Oa, c.Ma and c.ge.
They all follow the same and peculiar style of obfuscation.
Following the variable declarations, we can observe that the variable values are also obfuscated, and perhaps decoded with some function called b?
There are approximately 300 such variables and knowing these values is essential to our understanding of the flow of the malware. The decoding algorithm used by the sample is not straightforward and jumps through several obfuscated hoops. Following Figure 17. explains a high–level overview of the decoding process.
To summarise, the encodedvariable is split into two – first 12 characters (which are ignored), and the remaining characters. These remaining characters are first Base64 decoded, then a series of left rotation operations is performed on every character, followed by an EXOR operation on every character.
At each step, there are prepopulated key arrays used to complement for example, the left rotation as well as ex-or operations. A series of binary operations then yield the decoded strings. At this step, it is imperative for us to write a script to perform this decoding operation, as manual decoding is nearly impossible.
We wrote such a script, repeating the operations performed by the malware itself, to obtain all the decoded variable strings. Figure 18. shows a snapshot of the clear text strings.
These clear text strings are much easier to understand and give us a better understanding of the functionality of the malicious app. Figure 18. shows a few interesting strings highlighted.
We can already see an IP address, that could potentially be a Command and Control (C2) channel IP. Additionally, we also note a few stats related variables that could likely exfiltrate that data. Especially interesting are the variable names related to SMS and Bank. The app could be spying on this information and then exfiltrating it.
In this section, we will focus on the question – what does the malware do? We wish to steer our analysis in the direction of identifying what malicious activities the malware does and particularly whether it exfiltrates any data to the C2 that we identified at the end of the previous section.
We verify our deduction by checking whether the malware makes any HTTP(S) requests, to achieve exfiltration. As shown in Figure 19., we can see that the malware does indeed make HTTP connections.
Now that we also have our clear text strings, we can easily check what a.Ka decodes to. In our case, it decodes to POST. This confirms our suspicion that data is being exfiltrated. We can also guess at this point, that the C2 sends back some commands in the form of a response. We can perform a static check of the decoded clear text strings that we obtained at the end of the last section. Manually going through these strings is easily possible, as there are not that many strings. The goal behind this inspection is to filter out any noteworthy strings. Strings that may indicate malware actions, network behavior, etc.
Such a scan of the clear text strings reveals a few interesting strings as shown in Figure 20. We can see actions (or commands) being used such as – botCheck, sendSMSLogs, registration, etc. The commands allude to that they might be used in C2 communication.
By retracing our steps in Figure 19. and the arguments passed to that method, we eventually reach the code shown in Figure 20. This code contains some C2 communication strings.
After carefully analyzing this piece of code, we reach a conclusion that not all the strings found in the code are being used. The ones used are shown in Figure 21.
As the C2 has been taken down, it is no longer responding to our malicious sample. However, we were still able to find request sent by the mobile device to an IP address (Figure 22).
The first request shows that the device is sending some data to gate.php, with the action command “botcheck”. The data being sent is base64 encoded. We hook into the method that encodes the data, to get the plaintext data before it gets encoded. The hooks are shown in Figure 23. and the output in Figure 24.
In Figure 24, we also have added the key used by the malware to encode the data before sending to C2.
From Figure 24., we can see several of the noteworthy strings that we saw in Figure 18. are being used in communicating with C2. The malware collects all this data, encodes the information and sends the request to the C2. At this point, we know that the malware will perform further actions based on what command the C2 responds.
In this section, we focus on the possibilities of how victims can remove or uninstall the malware on their own by “normal” means in case their devices get infected. The malicious app employs several tricks to make it harder to uninstall.
We observe that the app could not be uninstalled and instead we were able to identify several approaches that the app takes to prevent its removal.
As found in the “Initial analysis and information gathering” section, once the app is launched, it removes itself from the applications tray. This is achieved by the app by executing the “setComponentEnabled” function and passing appropriate parameters, as shown in Figure 25.
We tested this method on two Android API versions – 28 and 29. For API 28, this method worked and the app was able to hide itself. However, this did not work in API 29 (Android Q)
Since the app is hidden while running, it is not possible to easily identify it and therefore uninstallation is not as straightforward as uninstalling a “normal” app.
Policy manager error
In the “Initial analysis and information gathering” section, we also found that granting of accessibility service permission is misused by the app into making itself a device admin app.
The device admin apps are typically used by enterprises. Just like laptops can be managed by IT services, the device admin apps make it possible for companies to manage employees’ phones.
In such scenarios, the user is expected to install the company’s app on their phones to let the company manage the mobile device. Once this admin right is granted, the user cannot uninstall the app.
The sample that we are analyzing does the same thing, by granting itself device admin rights. Because the app makes itself a device admin app, it is now not possible to uninstall the app. Any attempts to uninstall using even adb leads to a “DELETE_FAILED_DEVICE_POLICY_MANAGER” error.
“Remove admin app” reversal
As we cannot uninstall the app (because it is hidden), nor can we remove it using adb, the next step to try is to disable the app’s device admin access.
However, upon disabling this via Settings à Security à Device admin apps, we see that the control simply goes back to the previous screen. And the app continues to be a device admin app. The functionality of going back to the settings screen is implemented by the malicious app, to prevent any uninstallation.
Factory reset prevention
As a last resort, we try to perform a factory reset on the device, and this too, is prevented by the malicious app. The same functionality as above, takes the user back to the home page of settings screen, upon any attempt to do a factory reset.
As we can see, the malware takes extra steps to prevent its uninstallation so that it can continue to exfiltrate data. Eventually for successful removal, we followed the following steps:
- Login to the device through adb shell
- Delete all malware package related files in /system and /data
- Remove malware package traces from /data/system/device_policies.xml (or replace this file with the original default one)
- Reboot phone
- Uninstall the malicious app.
The analyzed malware sample has a bundled payload which it loads at runtime with DexClassLoader. After extracting the payload, we find it to be heavily obfuscated to make analysis difficult. The app takes multiple steps to prevent easy detection and uninstallation. Additionally, it also prevents factory resets.
The app likely exfiltrates SMS and bank data once communication with C2 is established.
To avoid being infected by such malware, we recommend that the users:
- avoid downloading any separate apps for official updates (e.g. updates or update apps for traditional WhatsApp to add new features, or apps that provide Android updates)
- avoid downloading apps outside of the official app stores
- be wary of providing the Accessibility Service permission to apps
- be wary of providing any extra permissions to apps than what seems required (for example, the Device Admin permission)
- use endpoint protection applications on your Android device to pre-emptively prevent infection
F-Secure detects this sample as “Trojan:Android/Generic!Online”.
- http:// 65[.]109[.]168[.]30