package de.tudarmstadt.informatik.hostage.ui;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
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.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
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.HoneyService;
import de.tudarmstadt.informatik.hostage.HoneyService.LocalBinder;
import de.tudarmstadt.informatik.hostage.R;
import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
import de.tudarmstadt.informatik.hostage.logging.LogResultReceiver;
import de.tudarmstadt.informatik.hostage.logging.LogResultReceiver.Receiver;
import de.tudarmstadt.informatik.hostage.logging.Logger;
import de.tudarmstadt.informatik.hostage.logging.UglyDbHelper;
/**
* 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 Activity implements Receiver {
/**
* Flag for root acces. True if phone has root acces, else false.
*/
public static boolean isRooted = false;
/**
* Flag for porthack. True if porthack is installed, else false.
*/
public static boolean porthackInstalled = false;
/**
* 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;
public LogResultReceiver logResultReceiver;
private SharedPreferences connectionInfo;
private HoneyService 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;
private boolean isBssidSeen = false;
/**
* Connection to bind the background service
*
* @see HoneyService
*/
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 void onReceiveResult(int resultCode, Bundle resultData) {
isBssidSeen = resultData.getBoolean("result");
}
@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 HoneyService
*/
private void bindService() {
bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE);
}
/**
* Checks if the phone ist rooted and if porthack is installed. Sets flags
* {@link isRooted} and {@link porthackInstalled}
*/
private void checkRootAndPorthack() {
isRooted = false;
porthackInstalled = false;
Process p;
try {
String found = "Found";
String notFound = "Not found";
String command = "[ -f /data/local/p ] && echo " + found
+ " || echo " + notFound;
p = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
BufferedReader in = new BufferedReader(new InputStreamReader(
p.getInputStream()));
/*
* int av = byte[] b = new byte[av]; if (av != 0) { in.read(b); }
*/
String echoResponse = in.readLine();
Log.i("MainAc", echoResponse);
if (echoResponse.equals(found)) {
isRooted = true;
porthackInstalled = true;
} else if (echoResponse.equals(notFound)) {
isRooted = true;
}
} catch (Exception e) {
e.printStackTrace();
}
Log.i("MainAc", "Rooted: " + isRooted + " Porthack: "
+ porthackInstalled);
}
/**
* Returns an intent to start HoneyService.
*
* @return An Intent to start HoneyService
*/
private Intent getServiceIntent() {
return new Intent(this, HoneyService.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 HoneyService} instance is running.
*
* @return True if {@link HoneyService} is running, else false.
*/
private boolean isServiceBound() {
return serviceBound;
}
/**
* Checks if a {@link HoneyService} instance is running.
*
* @return True if {@link HoneyService} 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(
HoneyService.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 HoneyService
*/
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 HoneyService
*/
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.
Logger.isBssidSeen(getApplicationContext(), protocol,
HelperUtils.getBSSID(getApplicationContext()),
logResultReceiver);
UglyDbHelper dbh = new UglyDbHelper(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);
logResultReceiver = new LogResultReceiver(new Handler());
setContentView(R.layout.activity_main);
connectionInfo = getSharedPreferences(
getString(R.string.connection_info), Context.MODE_PRIVATE);
// Create dynamic view elements
initViewAnimator();
initListView();
// Initialize Class variables
checkRootAndPorthack();
startAndBind();
}
@Override
protected void onDestroy() {
// Unbind running service
if (!mService.hasRunningListeners()) {
stopAndUnbind();
}
super.onDestroy();
}
@Override
protected void onStart() {
super.onStart();
// Register Broadcast Receiver
registerReceiver();
logResultReceiver.setReceiver(this);
// 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();
logResultReceiver.setReceiver(null);
super.onStop();
}
}