package de.tudarmstadt.informatik.hostage; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.Socket; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.net.ConnectivityManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.Toast; import de.tudarmstadt.informatik.hostage.commons.HelperUtils; import de.tudarmstadt.informatik.hostage.logging.MyLocationManager; import de.tudarmstadt.informatik.hostage.logging.UglyDbHelper; import de.tudarmstadt.informatik.hostage.protocol.Protocol; import de.tudarmstadt.informatik.hostage.protocol.ProtocolSettings; import de.tudarmstadt.informatik.hostage.ui.MainActivity; /** * Background service running as long as at least one protocol is active. * Service controls start and stop of protocol listener. Notifies GUI about * events happening in the background. Creates Notifications to inform the user * what it happening. * * @author Mihai Plasoianu * @author Lars Pandikow * @author Wulf Pfeiffer */ public class HoneyService extends Service { private static Context context; /** * Returns the application context. * * @return context. */ public static Context getContext() { return HoneyService.context; } private ArrayList listeners = new ArrayList(); private NotificationCompat.Builder builder; private SharedPreferences sessionPref; private Editor editor; public List getListeners() { return listeners; } private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { public HoneyService getService() { return HoneyService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onCreate() { super.onCreate(); HoneyService.context = getApplicationContext(); sessionPref = getSharedPreferences(MainActivity.SESSION_DATA, Context.MODE_PRIVATE); editor = sessionPref.edit(); createNotification(); for (Protocol protocol : getProtocolArray()) { listeners.add(new HoneyListener(this, protocol)); } registerNetReceiver(); getLocationData(); new QotdTask().execute(new String[] {}); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // We want this service to continue running until it is explicitly // stopped, so return sticky. return START_STICKY; } @Override public void onDestroy() { cancelNotification(); super.onDestroy(); unregisterNetReceiver(); } /** * Starts an Instance of MyLocationManager to set the location within this * class. */ private void getLocationData() { // TODO Put time and attempts in settings MyLocationManager locationManager = new MyLocationManager(this); locationManager.getUpdates(60 * 1000, 3); } /** * Deletes all session related data. */ private void deleteSessionData() { editor.clear(); editor.commit(); } /** * Register broadcast receiver for connectivity changes */ private void registerNetReceiver() { // register BroadcastReceiver on network state changes IntentFilter intent = new IntentFilter(); intent.addAction(ConnectivityManager.CONNECTIVITY_ACTION); // "android.net.conn.CONNECTIVITY_CHANGE" registerReceiver(netReceiver, intent); } /** * Unregister broadcast receiver for connectivity changes */ private void unregisterNetReceiver() { unregisterReceiver(netReceiver); } /** * Receiver for connectivity change broadcast. * * @see MainActivity#BROADCAST */ private BroadcastReceiver netReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String bssid_old = sessionPref.getString(MainActivity.BSSID, ""); String bssid_new = HelperUtils.getBSSID(context); // TODO INFORM UI // TODO CHECK IF OTHER NETWORKS WORK TOO if (bssid_new == null || !bssid_new.equals(bssid_old)) { getLocationData(); String[] protocols = getResources().getStringArray( R.array.protocols); for (String protocol : protocols) { editor.remove(protocol + MainActivity.HANDLER_COUNT); } notifyUI("SERVICE", "CONNECTIVITY_CHANGE"); } } }; /** * Creates a Notification in the notification bar. */ private void createNotification() { UglyDbHelper dbh = new UglyDbHelper(this); boolean activeHandlers = false; boolean bssidSeen = false; for (String protocol : getResources().getStringArray(R.array.protocols)) { int handlerCount = sessionPref.getInt(protocol + MainActivity.HANDLER_COUNT, 0); if (handlerCount > 0) { activeHandlers = true; } if (dbh.bssidSeen(protocol, HelperUtils.getBSSID(getApplicationContext()))) { bssidSeen = true; } } builder = new NotificationCompat.Builder(this).setContentTitle( getString(R.string.app_name)).setWhen( System.currentTimeMillis()); if (activeHandlers) { builder.setSmallIcon(R.drawable.ic_service_red); builder.setContentText("Network is infected!"); } else if (bssidSeen) { builder.setSmallIcon(R.drawable.ic_service_yellow); builder.setContentText("Network has been infected in previous session!"); } else { builder.setSmallIcon(R.drawable.ic_service_green); builder.setContentText("Everything looks fine!"); } TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(new Intent(this, MainActivity.class)); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(1, builder.build()); } /** * Updates the notification when a attack is registered. */ private void updateNotification() { SharedPreferences defaultPref = PreferenceManager .getDefaultSharedPreferences(this); String strRingtonePreference = defaultPref.getString( "pref_notification_sound", "content://settings/system/notification_sound"); builder = new NotificationCompat.Builder(this) .setContentTitle(getString(R.string.app_name)) .setTicker("Honeypot under attack!") .setContentText("Network is infected!") .setSmallIcon(R.drawable.ic_service_red).setAutoCancel(true) .setWhen(System.currentTimeMillis()) .setSound(Uri.parse(strRingtonePreference)); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(new Intent(this, MainActivity.class)); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(resultPendingIntent); if (defaultPref.getBoolean("pref_vibration", false)) { builder.setVibrate(new long[] { 100, 200, 100, 200 }); } NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(1, builder.build()); } /** * Cancels the Notification */ private void cancelNotification() { NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(1); } /** * Creates a instance of each protocol defined in /res/values/protocols.xml * and puts it in a List * * @return ArrayList of * {@link de.tudarmstadt.informatik.hostage.protocol.Protocol * Protocol} */ private ArrayList getProtocolArray() { String[] protocols = getResources().getStringArray(R.array.protocols); String packageName = Protocol.class.getPackage().getName(); ArrayList protocolArray = new ArrayList(); for (String protocol : protocols) { try { protocolArray.add((Protocol) Class.forName( String.format("%s.%s", packageName, protocol)) .newInstance()); } catch (Exception e) { e.printStackTrace(); } } return protocolArray; } /** * Determines if there are running listeners. * * @return True if there is a running listener, else false. */ public boolean hasRunningListeners() { for (HoneyListener listener : listeners) { if (listener.isRunning()) return true; } return false; } /** * Notifies the GUI about a event. * * @param protocol * The protocol where the event happened. * @param key * The key for the event. */ public void notifyUI(String sender, String key) { // Send Notification if (key.equals(MainActivity.HANDLER_COUNT)) { updateNotification(); } else if (key.equals("CONNECTIVITY_CHANGE")) { createNotification(); } Log.i("HoneyService", key); // Inform UI of Preference Change Intent intent = new Intent(MainActivity.BROADCAST); intent.putExtra("SENDER", sender); intent.putExtra("SENDER", key); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } /** * Starts all listeners which are not already running */ public void startListeners() { for (HoneyListener listener : listeners) { if (!listener.isRunning()) { listener.start(); } } Toast.makeText(getApplicationContext(), "SERVICES STARTED!", Toast.LENGTH_SHORT).show(); } /** * Stops all running listeners. */ public void stopListeners() { for (HoneyListener listener : listeners) { if (listener.isRunning()) { listener.stop(); } } Toast.makeText(getApplicationContext(), "SERVICES STOPPED!", Toast.LENGTH_SHORT).show(); } /** * Starts the listener for the specified protocol. * * @param protocolName * Name of the protocol that should be started. */ public void startListener(String protocolName) { for (HoneyListener listener : listeners) { if (listener.getProtocolName().equals(protocolName)) { if (!listener.isRunning()) { listener.start(); } } } Toast.makeText(getApplicationContext(), protocolName + " SERVICE STARTED!", Toast.LENGTH_SHORT).show(); } /** * Stops the listener for the specified protocol. * * @param protocolName * Name of the protocol that should be stopped. */ public void stopListener(String protocolName) { for (HoneyListener listener : listeners) { if (listener.getProtocolName().equals(protocolName)) { if (listener.isRunning()) { listener.stop(); } } } Toast.makeText(getApplicationContext(), protocolName + " SERVICE STOPPED!", Toast.LENGTH_SHORT).show(); } /** * Toggles a listener for specified protocol. * * @param protocolName * Name of the protocol that should be toggled. */ public void toggleListener(String protocolName) { for (HoneyListener listener : listeners) { if (listener.getProtocolName().equals(protocolName)) { if (listener.isRunning()) { stopListener(protocolName); } else { startListener(protocolName); } } } } /** * Task for accuiring a qotd from one of four possible servers. * * @author Wulf Pfeiffer */ private class QotdTask extends AsyncTask { @Override protected String doInBackground(String... unused) { String[] sources = new String[] { "djxmmx.net", "ota.iambic.com", "alpha.mike-r.com", "electricbiscuit.org" }; SecureRandom rndm = new SecureRandom(); StringBuffer sb = new StringBuffer(); try { Socket client = new Socket(sources[rndm.nextInt(4)], 17); BufferedReader in = new BufferedReader(new InputStreamReader( client.getInputStream())); while (!in.ready()) ; while (in.ready()) { sb.append(in.readLine()); } in.close(); client.close(); } catch (Exception e) { e.printStackTrace(); } return sb.toString(); } @Override protected void onPostExecute(String result) { if (result != null) ProtocolSettings.setHttpQotd(result); else ProtocolSettings.setHttpQotd(new String(HelperUtils .getRandomString(100, false))); } }; }