package de.tudarmstadt.informatik.hostage.ui; import java.util.ArrayList; import java.util.HashMap; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; import android.os.IBinder; import android.support.v4.app.FragmentActivity; import android.support.v4.content.LocalBroadcastManager; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.ToggleButton; import android.widget.ViewAnimator; import de.tudarmstadt.informatik.hostage.Hostage; import de.tudarmstadt.informatik.hostage.Hostage.LocalBinder; import de.tudarmstadt.informatik.hostage.R; import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper; /** * MainActivity is the central activity for the GUI of the application. * MainActivity is launched when the application is first started. It shows the * user:
* - information about the network
* - light indicators for recorded attacks on each protocol
* - amount of attacks on each protocols
* The user can start and stop services. * * @author Mihai Plasoianu * @author Lars Pandikow * @author Wulf Pfeiffer */ public class MainActivity extends FragmentActivity { /** * Integer representing a grey light. */ public static final int LIGHT_GREY = 0x01; /** * Integer representing a green light. */ public static final int LIGHT_GREEN = 0x02; /** * Integer representing a red light. */ public static final int LIGHT_RED = 0x03; /** * Integer representing a yellow light. */ public static final int LIGHT_YELLOW = 0x04; private SharedPreferences connectionInfo; private Hostage mService; private boolean serviceBound; // variables for the swipe animation private ViewAnimator viewAnimator; private GestureDetector gestureDetector; private Animation animFlipInLR; private Animation animFlipOutLR; private Animation animFlipInRL; private Animation animFlipOutRL; private ListView listView; private ListViewAdapter adapter; /** * Connection to bind the background service * * @see Hostage */ private ServiceConnection mConnection = new ServiceConnection() { /** * After the service is bound, check which has been clicked and start * it. * * @see android.content.ServiceConnection#onServiceConnected(android.content.ComponentName) */ @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = ((LocalBinder) service).getService(); serviceBound = true; updateUI(); } /** * After the service is unbound, delete reference. * * @see android.content.ServiceConnection#onServiceDisconnected(android.content.ComponentName) */ @Override public void onServiceDisconnected(ComponentName name) { mService = null; serviceBound = false; } }; /** * Receiver for custom broadcast. * * @see #BROADCAST */ private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Update user interface. updateUI(); updateConnectionInfText(); } }; SimpleOnGestureListener simpleOnGestureListener = new SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { float sensitvity = 50; if ((e1.getX() - e2.getX()) > sensitvity) { swipeRightToLeft(); } else if ((e2.getX() - e1.getX()) > sensitvity) { swipeLeftToRight(); } return true; } }; /** * Called when User presses on/off button. * * @param view */ public void buttonOnOffClick(View view) { if (((ToggleButton) view).isChecked()) { if (isParanoid()) { String[] protocols = getResources().getStringArray(R.array.protocols); for (String protocol : protocols) { mService.startListener(protocol); } } else { if (mService.isRunning("SMB")) { mService.stopListener("SMB"); } else { mService.startListener("SMB"); } } } else { mService.stopListeners(); stopAndUnbind(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.action_settings: startActivity(new Intent(this, SettingsActivity.class)); break; case R.id.action_about: startActivity(new Intent(this, AboutActivity.class)); break; default: } return super.onOptionsItemSelected(item); } @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } /** * Starts the ViewLog activity, when the Button is pressed. * * @see ViewLog * @param view * View elements which triggers the method call. */ public void showLog(View view) { // startActivity(new Intent(this, ViewLog.class)); } public void startPlayGround(View view) { startActivity(new Intent(this, PlayGroundActivity.class)); } /** * Binds service to Activity * * @see Hostage */ private void bindService() { bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE); } /** * Returns an intent to start HoneyService. * * @return An Intent to start HoneyService */ private Intent getServiceIntent() { return new Intent(this, Hostage.class); } /** * Initializes the ListView. Creating its contents dynamic from protocol * res/values/protocols.xml */ private void initListView() { ArrayList> data = new ArrayList>(); for (String protocol : getResources().getStringArray(R.array.protocols)) { HashMap d = new HashMap(); d.put("light", String.valueOf(R.drawable.light_grey)); d.put("protocol", protocol); d.put("connections", "-"); data.add(d); } listView = (ListView) findViewById(R.id.listViewProtocols); adapter = new ListViewAdapter(getLayoutInflater(), data); listView.setAdapter(adapter); listView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { String protocolName = (String) ((HashMap) adapter.getItem(position)).get("protocol"); if (mService.isRunning(protocolName)) { mService.stopListener(protocolName); } else { mService.startListener(protocolName); } } }); } /** * Initializes variables for screen animation */ private void initViewAnimator() { viewAnimator = (ViewAnimator) findViewById(R.id.viewAnimator); gestureDetector = new GestureDetector(this, simpleOnGestureListener); animFlipInLR = AnimationUtils.loadAnimation(this, R.anim.in_left_to_right); animFlipOutLR = AnimationUtils.loadAnimation(this, R.anim.out_left_to_right); animFlipInRL = AnimationUtils.loadAnimation(this, R.anim.in_right_to_left); animFlipOutRL = AnimationUtils.loadAnimation(this, R.anim.out_right_to_left); } /** * Checks if user selected paranoid mode. * * @return True when paranoid mode is selected, else returns false. */ private boolean isParanoid() { return ((CheckBox) findViewById(R.id.checkBoxParanoid)).isChecked(); } /** * Checks if a {@link Hostage} instance is running. * * @return True if {@link Hostage} is running, else false. */ private boolean isServiceBound() { return serviceBound; } /** * Checks if a {@link Hostage} instance is running. * * @return True if {@link Hostage} is running, else false. */ private boolean isServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (service.service.getClassName().equals(Hostage.class.getName())) { return true; } } return false; } /** * Register broadcast receiver for custom broadcast. * * @see #BROADCAST */ private void registerReceiver() { LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(getString(R.string.broadcast))); } /** * If mobile phone is connected to a wireless network starts the background * service ands binds itself to it. Else notifies the user that service * could not be started. */ private void startAndBind() { startService(getServiceIntent()); bindService(); } /** * Stops service and unbinds it. * * @see Hostage */ private void stopAndUnbind() { unbindService(); stopService(getServiceIntent()); } /** * Called when a swipe to the Right is registered. */ private void swipeLeftToRight() { if (viewAnimator.getDisplayedChild() == 1) { viewAnimator.setInAnimation(animFlipInLR); viewAnimator.setOutAnimation(animFlipOutLR); viewAnimator.setDisplayedChild(0); } } /** * Called when a swipe to the Left is registered. */ private void swipeRightToLeft() { if (viewAnimator.getDisplayedChild() == 0) { viewAnimator.setInAnimation(animFlipInRL); viewAnimator.setOutAnimation(animFlipOutRL); viewAnimator.setDisplayedChild(1); } } /** * Unbinds service. * * @see Hostage */ private void unbindService() { unbindService(mConnection); } /** * Unregisters broadcast receiver for custom broadcast. * * @see #BROADCAST */ private void unregisterReceiver() { LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); } /** * Gets Information about connection state and updates the GUI. */ private void updateConnectionInfText() { TextView ssidView = (TextView) findViewById(R.id.textViewSSIDValue); TextView bssidView = (TextView) findViewById(R.id.textViewBSSIDValue); TextView internalIPView = (TextView) findViewById(R.id.textViewInternalIPValue); TextView externalIPView = (TextView) findViewById(R.id.textViewExternalIPValue); // externalIPView.setText("Loading..."); // Get connection information String ssid = connectionInfo.getString(getString(R.string.connection_info_ssid), null); String bssid = connectionInfo.getString(getString(R.string.connection_info_bssid), null); String internalIP = connectionInfo.getString(getString(R.string.connection_info_internal_ip), null); String externalIP = connectionInfo.getString(getString(R.string.connection_info_external_ip), null); // Set text fields if (ssid != null) ssidView.setText(ssid); else ssidView.setText("-"); if (bssid != null) bssidView.setText(bssid); else bssidView.setText("-"); if (internalIP != null) internalIPView.setText(internalIP); else internalIPView.setText("-"); if (externalIP != null) externalIPView.setText(externalIP); else externalIPView.setText("-"); } /** * Sets the connections count for a given protocol. * * @param connections * New value for recorded connections. * @param protocolName * Name of the protocol which should be updated. */ private void updateProtocolConnections(int connections, String protocolName) { for (int i = 0; i < adapter.getCount(); ++i) { HashMap d = (HashMap) adapter.getItem(i); if (d.get("protocol").equals(protocolName)) { d.put("connections", String.valueOf(connections)); } } adapter.notifyDataSetChanged(); } /** * Sets the light indicator for a given protocol. * * @param light * Integer code to set the light color. * @param protocolName * Name of the protocol which should be updated. */ private void updateProtocolLight(int light, String protocolName) { for (int i = 0; i < adapter.getCount(); ++i) { HashMap d = (HashMap) adapter.getItem(i); if (d.get("protocol").equals(protocolName)) { switch (light) { case LIGHT_GREY: d.put("light", String.valueOf(R.drawable.light_grey)); d.put("connections", "-"); break; case LIGHT_GREEN: d.put("light", String.valueOf(R.drawable.light_green)); break; case LIGHT_RED: d.put("light", String.valueOf(R.drawable.light_red)); break; case LIGHT_YELLOW: d.put("light", String.valueOf(R.drawable.light_yellow)); break; } } } adapter.notifyDataSetChanged(); } /** * Sets the big light indicator. * * @param light * Integer code to set the light color. * @see #LIGHT_GREY * @see #LIGHT_GREEN * @see #LIGHT_RED * @see #LIGHT_YELLOW */ private void updateStatusLight(int light) { switch (light) { case LIGHT_GREY: ((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_grey_large); break; case LIGHT_GREEN: ((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_green_large); break; case LIGHT_RED: ((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_red_large); break; case LIGHT_YELLOW: ((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_yellow_large); break; } } /* ############# Help functions for animation ################## */ /** * Updates Information shown by the GUI. */ private void updateUI() { boolean activeListeners = false; boolean activeHandlers = false; boolean yellowLight = false; // Check for all protocols if listeners are active and attacks have been // recorded // Update protocol lights and connection information. for (String protocol : getResources().getStringArray(R.array.protocols)) { if (isServiceBound()) { // Check if protocol is active if (mService.isRunning(protocol)) { activeListeners = true; int handlerCount = mService.getNumberOfActiveConnections(protocol); // Check if attacks have been recorded in this session. if (handlerCount > 0) { activeHandlers = true; updateProtocolLight(LIGHT_RED, protocol); updateProtocolConnections(handlerCount, protocol); } else { // Check if the bssid of the wireless network has // already // been recorded as infected. HostageDBOpenHelper dbh = new HostageDBOpenHelper(this); if (dbh.bssidSeen(protocol, connectionInfo.getString(getString(R.string.connection_info_bssid), null))) { updateProtocolLight(LIGHT_YELLOW, protocol); yellowLight = true; } else { updateProtocolLight(LIGHT_GREEN, protocol); } updateProtocolConnections(0, protocol); } } else { updateProtocolLight(LIGHT_GREY, protocol); } } else { updateProtocolLight(LIGHT_GREY, protocol); } } // Update the big attack indicator. if (activeListeners) { if (activeHandlers) { updateStatusLight(LIGHT_RED); } else { if (yellowLight) { updateStatusLight(LIGHT_YELLOW); } else { updateStatusLight(LIGHT_GREEN); } } ((ToggleButton) findViewById(R.id.toggleButtonOnOff)).setChecked(true); findViewById(R.id.checkBoxParanoid).setEnabled(false); } else { updateStatusLight(LIGHT_GREY); ((ToggleButton) findViewById(R.id.toggleButtonOnOff)).setChecked(false); findViewById(R.id.checkBoxParanoid).setEnabled(true); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); connectionInfo = getSharedPreferences(getString(R.string.connection_info), Context.MODE_PRIVATE); // Create dynamic view elements initViewAnimator(); initListView(); // Initialize Class variables startAndBind(); } @Override protected void onDestroy() { // Unbind running service if (!mService.hasRunningListeners()) { stopAndUnbind(); } super.onDestroy(); } @Override protected void onStart() { super.onStart(); // Register Broadcast Receiver registerReceiver(); // Bind service if running, else check for connection change and delete // sessionData if (isServiceRunning()) { bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE); } // Update UI updateConnectionInfText(); } @Override protected void onStop() { // Unregister Broadcast Receiver unregisterReceiver(); super.onStop(); } }