Published on February 19th, 2023 📆 | 3609 Views ⚑
0Android.HeHe: Malware Now Disconnects Phone Calls
FireEye Labs has recently discovered six variants of a new Android
threat that steals text messages and intercepts phone calls. We named
this sample set “Android.HeHe” after the name of the activity that is
used consistently across all samples.
Here is a list of known bot variants:
MD5 | VirusTotal Detection Ratio |
---|---|
1caa31272daabb43180e079bca5e23c1 1caa31272daabb43180e079bca5e23c1 |
2/48 2/48 |
8265041aca378d37006799975fa471d9 8265041aca378d37006799975fa471d9 |
1/47 1/47 |
2af4de1df7587fa0035dcefededaedae 2af4de1df7587fa0035dcefededaedae |
2/45 2/45 |
2b41fbfb5087f521be193d8c1f5efb4c 2b41fbfb5087f521be193d8c1f5efb4c |
2/46 2/46 |
aa0ed04426562df25916ff70258daf6c aa0ed04426562df25916ff70258daf6c |
1/46 1/46 |
9507f93d9a64d718682c0871bf354e6f 9507f93d9a64d718682c0871bf354e6f |
1/47 1/47 |
Summary
The app disguises itself as “android security” (Figure 1),
attempting to provide the users what is advertised as an OS Update. It
contacts the command-and-control (CnC) server to register itself then
goes on to monitor incoming SMS messages. The CnC is expected to
respond with a list of phone numbers that are of interest to the
malware author. If one of these numbers sends an SMS or makes a call
to an infected device, the malware intercepts the message or call,
suppresses device notifications from the device, and removes any trace
of the message or call from device logs. Any SMS messages from one of
these numbers are logged into an internal database and sent to the CnC
server. Any phone calls from these numbers are silenced and rejected.
Analysis
This app starts the main HeHe activity at startup. The constructor
of the HeHeActivity registers a handler using the
android.os.Handle, which acts as a thread waiting for an object of
type android.os.Message to perform different actions, which are
outlined below.
Because the HeHeActivity implements the standard
DailogInterfaceOnClickListener, the start of the app causes the
showAlterDailog message to be displayed (Figure 2).
The app then sends an intent to start three services in the
background. These services are explained below.
Sandbox-evasion tactic
This app checks for the presence of an emulator by calling the
isEmulator function, which does the following:
- It checks the value of the MODEL of the device
(emulators with the Google ADT bundle have the string “sdk” as a
part of the MODEL variable). - It also checks to see
if the IMSI code is “null” — emulators do not have an IMSI code
associated with them.
Here is the isEmulator code:
String v0 = TelephonyUtils.getImsi(((Context)this));
if(v0 ==
null) {
return;
}
public static boolean isEmulator()
{
boolean v0;
if((Build.MODEL.equalsIgnoreCase("sdk")) ||
(Build.MODEL.equalsIgnoreCase("google_sdk"))) {
v0 =
true;
}
else {
v0 = false;
}
return
v0;
}
The code checks whether the the app is being run in the Android QEMU emulator. It also checks whether the value of IMSI is equal to null
RegisterService
This service runs in the background. Once started the app calls the
setComponentEnabledSetting method as follows:
this.getPackageManager().setComponentEnabledSetting(new ComponentName(((Context)this), HeheActivity.class), 2, 1);
This removes the app from the main menu of the phone leading the
user to believe that the app is no longer installed on the phone. It
then goes on to check the network status of the phone as shown below
public void checkNetwork() { if(!this.isNetworkAvailable()) { this.setMobileDataEnabled(); } } After the service has been created. The onStart method is called, which checks the message provided as a part of the intent. The message types are START and LOGIN
START
If the message in the intent is START, The app calls the
sendReigsterRequest() function. The sendRegisterRequest
function first checks for the presence of an emulator as explained in
the "Sandbox-evasion tactic" section
It then collects the IMSI IMEI, phone number, SMS address and
channel ID. It packs all this information into a JSON object. Once the
JSON object is created. It is converted to a string, which is sent to
the CnC server. The CnC communication is explained below.
LOGIN
If the message in the intent is LOGIN, the app calls the
sendLoginRequest method, which in turn collects the following:
- Version number of the app (hard-coded as
"1.0.0") - The model of the phone
- The
version of the operating system - The type of network
associated with the device (GSM/CDMA)
This information is also packed into a JSON object, converted into a
string, and sent to the CnC server.
RegisterBroadcastReceiver service
This service is invoked at the start of the app as the
RegisterService. It in turn registers the
IncomeCallAndSmsReceiver(), which is set to respond to these
three intents:
-
android.provider.Telephony.SMS_RECEIVED, which notifies once
a SMS has been received on the device -
android.intent.action.PHONE_STATE, which notifies once the
cellular state of the device has changed. Examples include
RINGING and OFF_HOOK. -
android.intent.action.SCREEN_ON, which notifies once the
screen has been turned on or turned off.
Additionally, it also sets observers over Android content URIs as follows:
- The SmsObserver is set to observe the content://sms,
which enables it to access all SMS messages that are present on the
device. - The CallObserver is set to observe the
content://call_log/calls, which allows it to access the call log of
all incoming, outgoing and missed calls on the device.
ConnectionService
The main HeHe activity mentioned at the start issues the
ACTION_START intent to the ConnectionService class as follows:
Intent v2 = new Intent(((Context)this), ConnectionService.class);v2.setAction(ConnectionService.ACTION_START);
v2.setFlags(268435456); this.startService(v2); LogUtils.debug("heheActivity", "start connectionService service"); The app then starts a timer task that is scheduled to be invoked every 5000 seconds. This timed task does the following:
- Creates an object instance of the android.os.Message
class - Sets the value of "what" in the
Message object to 1 - The handler of this message that
was initiated in the constructor then gets called which, in turn
calls the showFinishBar function that displays the message
“현재 OS에서 최신 소프트웨어버전을 사용하고있습니다,” which translates to “The current OS
you are using the latest version of the software.”
Receivers
IncomeCallAndSmsReceiver
The RegisterBroadcastReceiver registers this receiver once
the app gets started. When an SMS is received on the device. The
IncomeCallAndSmsReceiver gets the intent. Because this receiver
listens for one of three intents, any intents received by this
receiver are checked for their type.
If the received intent is of type
android.provider.telephony.SMS_RECEIVED, the app extracts the
contents of the SMS and the phone number of the sender. If the first
three characters of the phone number matches the first three
characters from phone numbers in a table named tbl_intercept_info,
then the SMS intent is aborted and the SMS is deleted from the devices
SMS inbox so that the user never sees it. After the SMS notification
is suppressed, the app bundles the SMS as follows:
{ "content":"TESTING", "createTime":"2014-01-10 16:21:36", "id":null,"messageFrom":"1234567890", "token":null } From there, it sends the to the CnC server (http://108.62.240.69:9008/reportMessage)
It also records the SMS in the tbl_message_info table in its
internal database.
If the received intent is of type
android.intent.action.PHONE_STATE, the app checks the
tbl_intercept_info table in the local database. If the number of the
caller appears in this table, then the ringer mode of the phone is set
to silent to suppress the notification of the incoming call and the
phone call is disconnected. Its corresponding entry from the call logs
is also removed, removing all traces of the phone call from the device.
No actions have been defined for the
android.app.action.SCREEN_ON intent, even though the
IncomeCallAndSmsReceiver receiver is the recipient.
CnC
This app uses two hard-coded IP address to locate its CnC servers:
122.10.92.117 and 58.64.183.12. The app performs all
communications through HTTP POST requests. The contents of the
HTTP POST are encrypted using AES with a 128-bit key that is hardcoded
into the app. The app sends its lastVersion value —to
122.10.92.117, to address is where is used to check for , in which the
app sends its version of the app. The address 58.64.183.12 is used to
report incoming SMS messages
Because the IP address is no longer reachable, responses from the
server could not be analyzed. What is clear is that the server sends a
JSON object in response, which contains a "token" field.
Although the CnC server is currently unavailable, we can infer how
the app works by examining the how it processes the received responses.
The app consists of different data structures that are converted
into their equivalent JSON representations when they are sent to the
CnC. Also, All JSON object responses are converted into their
equivalent internal data structures. We have also observed the
mechanism used to populate the internal database which includes tables
(tbl_intercept_info) which contain the phone numbers to be blocked.
The app uses hxxp://122.10.92.117:9008 and hxxp://58.64.183.12:9008
to send information to the CnC server.
The mapping of URLs to their internal class data structures is as follows:
GetLastVersionRequest | /getLastVersion |
---|---|
RegisterRequest | /register |
LoginRequest | /login |
ReportRequest | /report |
GetTaskRequest | /getTask |
ReportMessage Request |
/reportMessage |
The meaning and structures of these are explained in the following sections.
GetLastVersionRequest
This request is sent when the app is first installed on the device.
The bot sends the version code of the device (currently set to 1.0.0)
to the CnC. The CnC response shall contain the URL to an update if
available. The availability of an update is signified through an
‘update’ field in the response
RegisterRequest
This request is sent when the app sends an intent with a “LOGIN”
option to the RegisterService as explained above. The request
contains the IMSI, IMEI, Phone number, SMS address (Phone number),
Channel ID, a token and the IP address being used by the app as its
CnC. This causes the infected device to be registered with the CnC.
LoginRequest
This request is sent to further authenticate the device to the CnC,
It contains the token previously received, the version of the Bot, the
model of the phone, the version of the OS, the type of network and the
other active network parameters such as signal strength. In response,
It only gets a result value.
ReportRequest
The report request sends the information present in tbl_report_info
to the CnC. This table contains information about other requests that
were sent but failed.
GetTaskRequest
This requests asks for tasks from the CnC server. The response
contains a retry interval and a sendSmsActionNotify value. It is sent
when the response to the LoginRequest is 401 instead of 200.
ReportMessageRequest
This request to the CnC sends the contents of the SMS messages that
are received on the device. It consists of the contents of the SMS
message, the time of the message and the sender of the SMS. This has
been observed in the logcat output as follows:
Conclusion
Android malware variants are mushrooming. Threats such as
Android.HeHe and Android.MisoSMS
reveal attackers' growing interest in monitoring SMS messages and
phone call logs. They also serve as a stark reminder of just how
dangerous apps from non-trusted marketplaces can be.
Gloss