📜 ⬆️ ⬇️

How Android Trojan Gustuff removes cream (fiat and crypt) from your accounts



Just the other day, Group-IB reported on the activity of the mobile Android Trojan Gustuff. He works exclusively in international markets, attacking customers of the 100 largest foreign banks, users of mobile 32 crypto wallet, as well as major e-commerce resources. But the developer Gustuff - Russian-speaking cybercriminal under the nickname Bestoffer. More recently, he praised his Trojan as "a serious product for people with knowledge and experience."

Group-IB Malicious Code Analysis Specialist Ivan Pisarev in his research describes in detail how Gustuff works and what is its danger.
')

Who hunts Gustuff


Gustuff is a new generation of malware with fully automated features. According to the developer, the Trojan has become a new improved version of the AndyBot malware, which since November 2017 has been attacking Android phones and stealing money through phishing web forms disguised as mobile applications by well-known international banks and payment systems. Bestoffer reported that the rental price of Gustuff Bot was $ 800 per month.

An analysis of the Gustuff sample showed that the Trojan potentially targets customers using mobile applications of major banks, such as Bank of America, Bank of Scotland, JPMorgan, Wells Fargo, Capital One, TD Bank, PNC Bank, and Bitcoin Wallet , Cryptopay, Coinbase and others.

Originally created as a classic banking trojan, in the current version of Gustuff has significantly expanded the list of potential objects to attack. In addition to Android applications of banks, fintech companies and cryptoservices, Gustuff is aimed at users of marketplace applications, online stores, payment systems and instant messengers. In particular, PayPal, Western Union, eBay, Walmart, Skype, WhatsApp, Gett Taxi, Revolut and others.

Entry point: based on mass infection


Gustuff is characterized by a “classic” vector of penetration of Android-based smartphones via SMS distribution with links to APK. When an Android device is infected with a trojan by a server command, Gustuff can further spread to the contact database of the infected phone or to the server database. The functionality of Gustuff is designed for mass infection and maximum capitalization of the business of its operators - it has a unique “auto-fill” function in legitimate mobile banking applications and cryptographic cards, which allows you to speed up and scale the theft of money.

The study of the Trojan showed that the avtozaliva function was implemented in it using the Accessibility Service, a service for people with disabilities. Gustuff is not the first trojan that successfully bypasses protection from interacting with window elements of other applications using this Android service. However, the use of the Accessibility Service in combination with the auto-fill is still quite a rare phenomenon.

After downloading to the phone, the victim Gustuff, using the Accessibility Service, gets the opportunity to interact with the elements of windows of other applications (banking, cryptocurrency, as well as applications for online shopping, messaging, etc.), performing the necessary actions for attackers. For example, at the command of a server, a Trojan can click on buttons and change the values ​​of text fields in banking applications. Using the Accessibility Service allows the trojan to bypass the security mechanisms used by banks to counter past-generation mobile Trojans, as well as changes in security policies implemented by Google in new versions of the Android OS. So, Gustuff "can" disable the protection of Google Protect: according to the author, this function works in 70% of cases.



Gustuff can also show fake push notifications with icons of legitimate mobile apps. The user clicks on the PUSH notification and sees a phishing window downloaded from the server, where he himself enters the requested data of the bank card or cryptograph. In another Gustuff scenario, an application is opened, on whose behalf a PUSH notification was displayed. In this case, a malicious program at the server’s command through the Accessibility Service may fill out the form fields of a banking application for a fraudulent transaction.

The functionality of Gustuff also includes sending information about an infected device to the server, the ability to read / send SMS messages, send USSD requests, launch SOCKS5 Proxy, follow the link, send files (including photo scans of documents, screenshots, photos) to the server Reset device to factory settings.

Malware Analysis


Before installing a malicious Android OS application, a user is shown a window containing a list of the rights requested by Gustuff:

image alt

Installation of the application will occur only after obtaining the consent of the user. After launching the application, the trojan will show the user a window:

image alt

After that, delete its icon.

According to the author, Gustuff is packaged by FTT. After starting, the application periodically accesses the CnC server in order to receive commands. In several files examined by us, the IP address 88.99.171 [.] 105 was used as the control server (hereinafter we will denote as <% CnC%> ).

After starting the program starts sending messages to the server http: // <% CnC%> /api/v1/get.php .

The response is expected JSON in the following format:

{ "results" : "OK", "command":{ "id": "<%id%>", "command":"<%command%>", "timestamp":"<%Server Timestamp%>", "params":{ <%Command parameters as JSON%> }, }, } 

Each time you access the app, it sends information about the infected device. The message format is shown below. It should be noted that the fields full , extra , apps and permission are optional and will be sent only in the case of a request command from CnC.

 { "info": { "info": { "cell":<%Sim operator name%>, "country":<%Country ISO%>, "imei":<%IMEI%>, "number":<%Phone number%>, "line1Number":<%Phone number%>, "advertisementId":<%ID%> }, "state": { "admin":<%Has admin rights%>, "source":<%String%>, "needPermissions":<%Application needs permissions%>, "accesByName":<%Boolean%>, "accesByService":<%Boolean%>, "safetyNet":<%String%>, "defaultSmsApp":<%Default Sms Application%>, "isDefaultSmsApp":<%Current application is Default Sms Application%>, "dateTime":<%Current date time%>, "batteryLevel":<%Battery level%> }, "socks": { "id":<%Proxy module ID%>, "enabled":<%Is enabled%>, "active":<%Is active%> }, "version": { "versionName":<%Package Version Name%>, "versionCode":<%Package Version Code%>, "lastUpdateTime":<%Package Last Update Time%>, "tag":<%Tag, default value: "TAG"%>, "targetSdkVersion":<%Target Sdk Version%>, "buildConfigTimestamp":1541309066721 }, }, "full": { "model":<%Device Model%>, "localeCountry":<%Country%>, "localeLang":<%Locale language%>, "accounts":<%JSON array, contains from "name" and "type" of accounts%>, "lockType":<%Type of lockscreen password%> }, "extra": { "serial":<%Build serial number%>, "board":<%Build Board%>, "brand":<%Build Brand%>, "user":<%Build User%>, "device":<%Build Device%>, "display":<%Build Display%>, "id":<%Build ID%>, "manufacturer":<%Build manufacturer%>, "model":<%Build model%>, "product":<%Build product%>, "tags":<%Build tags%>, "type":<%Build type%>, "imei":<%imei%>, "imsi":<%imsi%>, "line1number":<%phonenumber%>, "iccid":<%Sim serial number%>, "mcc":<%Mobile country code of operator%>, "mnc":<%Mobile network codeof operator%>, "cellid":<%GSM-data%>, "lac":<%GSM-data%>, "androidid":<%Android Id%>, "ssid":<%Wi-Fi SSID%> }, "apps":{<%List of installed applications%>}, "permission":<%List of granted permissions%> } 

Configuration Storage


Gustuff stores important information for work in a preference file. The file name, as well as the names of the parameters in it, is the result of the calculation of the MD5 sum from line 15413090667214.6.1 <% name%> , where <% name%> is the original name-value. Python interpretation of the name generation function:

  nameGenerator(input): output = md5("15413090667214.6.1" + input) 

In the following we will denote as nameGenerator (input) .

Thus, the name of the first file: nameGenerator ("API_SERVER_LIST") , it contains values ​​with the following names:

Variable nameValue
nameGenerator ("API_SERVER_LIST")Contains a list of CnC addresses as an array.
nameGenerator ("API_SERVER_URL")Contains the cnc address.
nameGenerator ("SMS_UPLOAD")The default flag is set. If the flag is set, sends SMS messages to CnC.
nameGenerator ("SMS_ROOT_NUMBER")The phone number to which SMS messages received by the infected device will be sent. The default is null.
nameGenerator ("SMS_ROOT_NUMBER_RESEND")The default flag is cleared. If set - when an infected device receives an SMS, it will be sent to the root number.
nameGenerator ("DEFAULT_APP_SMS")The default flag is cleared. If this flag is set, the application will process incoming SMS messages.
nameGenerator ("DEFAULT_ADMIN")The default flag is cleared. If the flag is set, the application has administrator rights.
nameGenerator ("DEFAULT_ACCESSIBILITY")The default flag is cleared. If the flag is set, a service is running that uses the Accessibility Service.
nameGenerator ("APPS_CONFIG")The JSON object contains a list of actions that must be performed when an Accessibility event is triggered associated with a specific application.
nameGenerator ("APPS_INSTALLED")Stores the list of applications installed on the device.
nameGenerator ("IS_FIST_RUN")The flag at the first start is cleared.
nameGenerator ("UNIQUE_ID")Contains a unique identifier. Generated when the bot is first launched.

Command processing module from the server


The application stores the addresses of CnC servers as an array of Base85-encoded strings. The list of CnC servers can be changed when a corresponding command is received, in which case the addresses will be stored in a preference file.

In response to the request, the server sends the command to the application. It is worth noting that the commands and parameters are presented in JSON-format. The application can handle the following commands:
TeamDescription
forwardstartStart sending SMS messages received by the infected device to the CnC server.
forwardStopStop sending SMS messages received by the infected device to the CnC server.
ussdRunRun USSD request. The number to which the USSD request is to be made is in the “number” JSON field.
sendSmsSend one SMS-message (if necessary, the message is “split” into parts). As a parameter, the command takes a JSON object that contains the “to” fields — the destination number and “body” —the message body.
sendSmsAbSend SMS messages (if necessary, the message is “split up” into parts) to everyone from the contact list of the infected device. The interval between sending messages is 10 seconds. The body of the message is in the JSON-field "body"
sendSmsMassSend SMS messages (if necessary, the message is “split up” into parts) to the contacts specified in the command parameters. The interval between sending messages is 10 seconds. As a parameter, the command accepts a JSON array (the “sms” field), the elements of which contain the “to” fields — the destination number and the “body” - message body.
changeServerThis command can take a value with the key “url” as a parameter - then the bot will change the nameGenerator (“SERVER_URL”) value, or “array” - then the bot will write the array into the nameGenerator (“API_SERVER_LIST”). Thus, the application changes the address of the CnC servers.
adminNumberThe command is designed to work with root number. The command accepts a JSON object with the following parameters: “number” - change nameGenerator (“ROOT_NUMBER”) to the received value, “resend” - change nameGenerator (“SMS_ROOT_NUMBER_RESEND”), “sendId” - send to nameGenerator (“ROOT_NUMBER”) uniqueID.
updateInfoSend information about the infected device to the server.
wipeDataThe command is intended to delete user data. Depending on which name the application was launched, there is either a complete erasure of data with a device reboot (primary user), or the removal of only user data (secondary user).
socksStartRun the proxy module. The operation of the module is described in a separate section.
socksStopStop the proxy module.
openLinkFollow the link. The link is in the JSON parameter by the key "url". To open the link, use "android.intent.action.VIEW".
uploadAllSmsSend all received SMS messages to the server.
uploadAllPhotosSend images to the URL from an infected device. URL comes as a parameter.
uploadFileSend a file from an infected device to a URL. URL comes as a parameter.
uploadPhoneNumbersSend phone numbers from the contact list to the server. If the JSON-object value with the key “ab” comes as a parameter, the application receives a list of contacts from the phone book. If the JSON object with the “sms” key comes as a parameter, the application reads the list of contacts from senders of SMS messages.
changeArchiveThe application loads the file from the address that comes in as a parameter using the key “url”. The downloaded file is saved with the name "archive.zip". After this, the application unzips the file, using the password for the archive “b5jXh37gxgHBrZhQ4j3D”, if necessary. Unzipped files are saved to the [external storage] / hgps directory. In this directory, the application stores web-fakes (described below).
actionsThe command is designed to work with the Action Service, which is described in a separate section.
testDoing nothing.
downloadThe command is intended for downloading a file from a remote server and saving it in the “Downloads” directory. The URL and the file name come as a parameter, the fields in the JSON object parameter, respectively: “url” and “fileName”.
removeRemoves a file from the “Downloads” directory. The file name comes in a JSON parameter with the key "fileName". The default file name is “tmp.apk”.
notificationShow notification with description and header text, defined by the managing server.

Command format notification :

 { "results" : "OK", "command":{ "id": <%id%>, "command":"notification", "timestamp":<%Server Timestamp%>, "params":{ "openApp":<%Open original app or not%>, "array":[ {"title":<%Title text%>, "desc":<%Description text%>, "app":<%Application name%>} ] }, }, } 

The notification created by the examined file looks identical to the notifications created by the application specified in the app field. If the openApp field value is True, when the notification is opened, the application specified in the app field is launched. If the openApp field value is False, then:


The result of the execution of any command is sent by the application to <% CnC%> \ set_state.php as a JSON object of the following format:

 { "command": { "command":<%command%>, "id":<%command_id%>, "state":<%command_state%> } "id":<%bot_id%> } 

ActionsService

The list of commands that the application handles is action . When a command is received, the command processing module accesses this service in order to execute the extended command. As a parameter, the service accepts a JSON object. The service can execute the following commands:

1. PARAMS_ACTION - when receiving such a command, the service first of all receives the value from the JSON parameter by the Type key, it can be the following:


2. PARAMS_ACTIONS - the same as PARAMS_ACTION , only comes JSON-array of commands.

It seems that many will be interested in what the function of interaction with elements of the window of another application looks like. This is how this functionality is implemented in Gustuff:

 boolean interactiveAction(List aiList, JSONObject action, JsonObject res) { int count = action.optInt("repeat", 1); Iterator aiListIterator = ((Iterable)aiList).iterator(); int count = 0; while(aiListIterator.hasNext()) { Object ani = aiListIterator.next(); if(1 <= count) { int index; for(index = 1; true; ++index) { if(action.has("focus")) { if(((AccessibilityNodeInfo)ani).performAction(1)) { ++count; } } else if(action.has("click")) { if(((AccessibilityNodeInfo)ani).performAction(16)) { ++count; } } else if(action.has("actionId")) { if(((AccessibilityNodeInfo)ani).performAction(action.optInt("actionId"))) { ++count; } } else if(action.has("setText")) { customHeader ch = CustomAccessibilityService.a; Context context = this.getApplicationContext(); String text = action.optString("setText"); if(performSetTextAction(ch, context, ((AccessibilityNodeInfo)ani), text)) { ++count; } } if(index == count) { break; } } } ((AccessibilityNodeInfo)ani).recycle(); } res.addPropertyNumber("res", Integer.valueOf(count)); } 

Text replacement function:

 boolean performSetTextAction(Context context, AccessibilityNodeInfo ani, String text) { boolean result; if(Build$VERSION.SDK_INT >= 21) { Bundle b = new Bundle(); b.putCharSequence("ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE", ((CharSequence)text)); result = ani.performAction(0x200000, b); // ACTION_SET_TEXT } else { Object clipboard = context.getSystemService("clipboard"); if(clipboard != null) { ((ClipboardManager)clipboard).setPrimaryClip(ClipData.newPlainText("autofill_pm", ((CharSequence)text))); result = ani.performAction(0x8000); // ACTION_PASTE } else { result = false; } } return result; } 

Thus, if the managing server is properly configured, Gustuff is able to fill in the text fields in the banking application and click on the buttons necessary for the transaction. The trojan does not even need to be authorized in the application - it is enough to send a command to demonstrate the PUSH notifications and then open the previously installed banking application. The user himself will be authorized, after which Gustuff will be able to make avtozaliv.

SMS Processing Module


The application sets an event handler to receive an SMS message from an infected device. The investigated application can receive commands from the operator that come in the body of an SMS message. Commands come in the format:

7! 5 = <% Base64 encoded command%>

The application searches for all incoming SMS messages line 7! 5 = , when a line is detected - decodes a line from Base64 at offset 4 and executes the command. Commands are similar to commands with CnC. The result of the performance is sent to the same number from which the command was received. Answer format:

7 * 5 = <% Base64 encode of "result_code command"%>

Optionally, the application can send all received messages to the Root number. To do this, the Root number must be specified in the preference file and the message redirect flag must be set. The SMS message is sent to the number of the attacker in the format:

<% From number%> - <% Time format: dd / MM / yyyy HH: mm: ss%> <% SMS body%>

Also, the application can optionally send messages to CnC. The SMS message is sent to the server in JSON format:

 { "id":<%BotID%>, "sms": { "text":<%SMS body%>, "number":<%From number%>, "date":<%Timestamp%> } } 

If the nameGenerator flag is set (“DEFAULT_APP_SMS”) , the application stops processing the SMS message and clears the list of incoming messages.

Proxy module


In the application under study, there is a Backconnect Proxy module (hereinafter referred to as Proxy module), which has a separate class that includes static fields with configuration. Configuration data is stored in the open sample:

image alt


All actions performed by the proxy module are logged into files. To do this, the application in External Storage creates a directory called “logs” (the ProxyConfigClass.logsDir field in the configuration class) in which the log files are stored. Logging occurs in files with the names:

  1. main.txt - the operation of the class called CommandServer is logged to this file. Further, the str logging into this file will be denoted as mainLog (str).
  2. session - <% id%>. txt - the log data associated with a particular proxy session is saved to this file. In the future, logging the str string to this file will be referred to as sessionLog (str).
  3. server.txt - all data written to the above files is logged to this file.

Log data format:

<% Date%> [Thread [<% thread id%>], id []]: log-string

Exceptions that occur during the operation of the Proxy module are also logged to a file. For this, the application generates a JSON format object:

 { "uncaughtException":<%short description of throwable%> "thread":<%thread%> "message":<%detail message of throwable%> "trace": //Stack trace info [ { "ClassName": "FileName": "LineNumber": "MethodName": }, { "ClassName": "FileName": "LineNumber": "MethodName": } ] } 

Then it converts it into a string representation and logs it.

The launch of the Proxy-module is carried out after the arrival of the appropriate command. When a command is received to start the proxy module, the application starts a service called MainService , which is responsible for managing the operation of the proxy module — starting and stopping it.

Stages of service start:

1. Starts the timer, which is triggered once a minute and checks the activity of the proxy module. If the module is not active, it starts it.
Also, when the android.net..nn.CONNECTIVITY_CHANGE event is triggered, a Proxy module is launched.

2. The application creates a wake-lock with the PARTIAL_WAKE_LOCK parameter and captures it. Thus, it does not allow the device's CPU to go to sleep.

3. Runs the processing class of commands of the Proxy module, pre-logging the mainLog line ("start server") and

Server :: start () host [<% proxy_cnc%>], commandPort [<% command_port%>], proxyPort [<% proxy_port%>]

where proxy_cnc, command_port and proxy_port are the parameters obtained from the proxy server configuration.

The command processing class is called CommandConnection . Immediately after starting it performs the following actions:

4. Connects to ProxyConfigClass.host : ProxyConfigClass.commandPort and sends there data about the infected device in JSON format:

 { "id":<%id%>, "imei":<%imei%>, "imsi":<%imsi%>, "model":<%model%>, "manufacturer":<%manufacturer%>, "androidVersion":<%androidVersion%>, "country":<%country%>, "partnerId":<%partnerId%>, "packageName":<%packageName%>, "networkType":<%networkType%>, "hasGsmSupport":<%hasGsmSupport%>, "simReady":<%simReady%>, "simCountry":<%simCountry%>, "networkOperator":<%networkOperator%>, "simOperator":<%simOperator%>, "version":<%version%> } 

Where:


5. . :


:

mainLog(«Header { sessionId<%id%>], type[<%command%>], length[<%length%>] }»)

:

NameCommandDataDescription
connectionId0Connection ID
SLEEP3TimeProxy-
PING_PONGfour-PONG-

PONG- 4 : 0x04000000 .

connectionId ( ) CommandConnection ProxyConnection .


  { "id":<%connectionId%> } 

SOCKS5-, , . ̆ end . :

image alt

̆


̆ CnC- SSL. JSON-. :


Recommendations


, , .

, . , , .

– - , , -, , , , , .

:



, Group-IB.

Source: https://habr.com/ru/post/446948/


All Articles