Browse Source

solved merge conflict

Alexander Brakowski 9 years ago
parent
commit
de38bfd0a7

BIN
assets/payload/bind.arm


BIN
assets/payload/bind.x86


+ 24 - 0
assets/payload/redirect-ports.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# redirects ports below 1024 to a higher range using iptables, so they can be used without elevated rights
+# MySQL SIP (3306 and 5060) are left out because they are >= 1024 anyways
+
+#             ECHO  FTP   HTTP  HTTPS SMB (NETBIOS UDP & TCP) SSH   TELNET
+protocol=(    "tcp" "tcp" "tcp" "tcp" "udp" "udp" "tcp" "tcp" "tcp" "tcp" )
+origin=(       7     21    80    443   137   138   137   139   22    23   )
+destination=( 28144 28169 28217 28580 28274 28275 28274 28276 28159 28160 ) # simply offset by 1024 + 27113
+length=${#protocol[@]} # count protocol elements
+
+# for (( i=0; i<$length; i++ ))
+for i in `seq 0 9` # fix for android's annoyingly limited bash
+do
+	# echo ${protocol[$i]} ${origin[$i]} ${destination[$i]} # debug
+
+	# delete previous rules to avoid duplicates
+	iptables -t nat -D PREROUTING -p ${protocol[$i]} --dport ${origin[$i]} -j REDIRECT --to-ports ${destination[$i]}
+	iptables -t nat -D OUTPUT -p ${protocol[$i]} --dport ${destination[$i]} -j REDIRECT --to-ports ${origin[$i]}
+
+	# add new rules
+	iptables -t nat -A PREROUTING -p ${protocol[$i]} --dport ${origin[$i]} -j REDIRECT --to-ports ${destination[$i]}
+	iptables -t nat -A OUTPUT -p ${protocol[$i]} --dport ${destination[$i]} -j REDIRECT --to-ports ${origin[$i]}
+done

+ 33 - 3
res/layout/fragment_settings.xml

@@ -14,28 +14,58 @@
 				android:textAppearance="?android:attr/textAppearanceMedium"
 				android:text="@string/device_rooted"
 				android:id="@+id/record_details_text_ssid" android:textStyle="bold"/>
+		<TextView
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:textAppearance="?android:attr/textAppearanceMedium"
+				android:text="@string/iptables_available"
+				android:id="@+id/iptables_available"
+				android:layout_below="@+id/record_details_text_ssid" android:layout_alignParentLeft="true"
+				android:layout_alignParentStart="true" android:textStyle="bold"/>
 		<TextView
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
 				android:textAppearance="?android:attr/textAppearanceMedium"
 				android:text="@string/porthack_installed"
 				android:id="@+id/txtP2PSubheader"
-				android:layout_below="@+id/record_details_text_ssid" android:layout_alignParentLeft="true"
+				android:layout_below="@+id/iptables_available" android:layout_alignParentLeft="true"
 				android:layout_alignParentStart="true" android:textStyle="bold"/>
 		<TextView
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
 				android:textAppearance="?android:attr/textAppearanceMedium"
 				android:text="@string/yes"
-				android:id="@+id/settings_device_rooted" android:layout_above="@+id/txtP2PSubheader"
+				android:id="@+id/settings_device_rooted" android:layout_above="@+id/iptables_available"
 				android:layout_alignParentRight="true" android:layout_alignParentEnd="true"/>
 		<TextView
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
 				android:textAppearance="?android:attr/textAppearanceMedium"
 				android:text="@string/yes"
-				android:id="@+id/settings_porthack_installed" android:layout_below="@+id/settings_device_rooted"
+				android:id="@+id/settings_iptables_available" android:layout_below="@+id/settings_device_rooted"
 				android:layout_alignParentRight="true" android:layout_alignParentEnd="true"/>
+		<TextView
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:textAppearance="?android:attr/textAppearanceMedium"
+				android:text="@string/yes"
+				android:id="@+id/settings_porthack_installed" android:layout_below="@+id/iptables_available"
+				android:layout_alignParentRight="true" android:layout_alignParentEnd="true"/>
+		<Button
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:text="@string/install_porthack"
+				android:id="@+id/settings_deploy_porthack"
+				android:layout_below="@+id/txtP2PSubheader" android:layout_alignParentLeft="true"
+				android:layout_alignParentStart="false" android:layout_alignParentEnd="true"/>
+		<Button
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:text="@string/uninstall_porthack"
+				android:id="@+id/settings_uninstall_porthack"
+				android:layout_below="@+id/settings_deploy_porthack" android:layout_alignParentLeft="true"
+				android:layout_alignParentStart="false" android:layout_alignParentEnd="true"
+				android:background="@color/holo_red" android:textColor="@android:color/white"/>
 	</RelativeLayout>
 	<FrameLayout
 			android:layout_width="fill_parent"

+ 3 - 0
res/values/strings.xml

@@ -105,6 +105,9 @@
 
     <string name="device_rooted">Device rooted</string>
     <string name="porthack_installed">Porthack installed</string>
+	<string name="iptables_available">IPTables available</string>
+	<string name="install_porthack">Install Porthack</string>
+	<string name="uninstall_porthack">Uninstall Porthack</string>
     <string name="yes">Yes</string>
     <string name="no">No</string>
 

+ 14 - 0
src/de/tudarmstadt/informatik/hostage/Handler.java

@@ -257,6 +257,19 @@ public class Handler implements Runnable {
 		Logger.log(Hostage.getContext(), createMessageRecord(type, packet));
 	}
 
+
+    //just for debugging purpose
+    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+    public static String bytesToHex(byte[] bytes) {
+        char[] hexChars = new char[bytes.length * 2];
+        for ( int j = 0; j < bytes.length; j++ ) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 2] = hexArray[v >>> 4];
+            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+        }
+        return new String(hexChars);
+    }
+
 	/**
 	 * Communicates with a client using the corresponding protocol
 	 * implementation.
@@ -280,6 +293,7 @@ public class Handler implements Runnable {
 			}
 		}
 		while (!thread.isInterrupted() && (inputLine = reader.read()) != null) {
+            System.out.println("inputLine "+bytesToHex(inputLine.getBytes()));
 			outputLine = protocol.processMessage(inputLine);
 			log(TYPE.RECEIVE, inputLine.toString());
 			if (outputLine != null) {

+ 20 - 1
src/de/tudarmstadt/informatik/hostage/commons/HelperUtils.java

@@ -1,5 +1,7 @@
 package de.tudarmstadt.informatik.hostage.commons;
 
+import junit.framework.Assert;
+
 import org.apache.http.HttpVersion;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpPost;
@@ -16,12 +18,22 @@ import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.protocol.HTTP;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.security.KeyStore;
 import java.security.SecureRandom;
 
+import android.app.Activity;
 import android.content.Context;
+import android.content.res.AssetManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.wifi.WifiInfo;
@@ -29,10 +41,13 @@ import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.preference.PreferenceManager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import de.tudarmstadt.informatik.hostage.logging.Record;
 import de.tudarmstadt.informatik.hostage.logging.formatter.TraCINgFormatter;
 import de.tudarmstadt.informatik.hostage.net.MySSLSocketFactory;
+import de.tudarmstadt.informatik.hostage.system.Device;
+import de.tudarmstadt.informatik.hostage.ui.activity.MainActivity;
 
 /**
  * Helper class with some static methods for general usage.
@@ -427,4 +442,8 @@ public final class HelperUtils {
 		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
 		return activeNetworkInfo != null && activeNetworkInfo.isConnected();
 	}
-}
+
+    public static int getRedirectedPort(int port){
+        return port + 1024 + 27113;
+    }
+}

+ 18 - 10
src/de/tudarmstadt/informatik/hostage/net/MyServerSocketFactory.java

@@ -10,6 +10,7 @@ import java.net.SocketImpl;
 
 import javax.net.ServerSocketFactory;
 
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.system.Device;
 import de.tudarmstadt.informatik.hostage.system.PrivilegedPort;
 import de.tudarmstadt.informatik.hostage.system.PrivilegedPort.TYPE;
@@ -24,16 +25,23 @@ public class MyServerSocketFactory extends ServerSocketFactory {
 			socket = new ServerSocket();
 			socket.setReuseAddress(true);
 			socket.bind(new InetSocketAddress(port));
-		} else if (Device.isPorthackInstalled()) {
-			FileDescriptor fd = new PrivilegedPort(TYPE.TCP, port).getFD();
-			socket = new ServerSocket();
-			try {
-				SocketImpl impl = getImpl(socket);
-				injectFD(fd, impl);
-				setBound(socket);
-			} catch (NoSuchFieldException e) {
-			} catch (IllegalAccessException e) {
-			} catch (IllegalArgumentException e) {
+		} else if (Device.isRooted()) {
+			if (Device.isPorthackInstalled()) {
+				FileDescriptor fd = new PrivilegedPort(TYPE.TCP, port).getFD();
+				socket = new ServerSocket();
+				try {
+					SocketImpl impl = getImpl(socket);
+					injectFD(fd, impl);
+					setBound(socket);
+				} catch (NoSuchFieldException e) {
+				} catch (IllegalAccessException e) {
+				} catch (IllegalArgumentException e) {
+				}
+			} else if (Device.isPortRedirectionAvailable()) { // use ip tables
+				int redirectedPort = HelperUtils.getRedirectedPort(port);
+				socket = new ServerSocket();
+				socket.setReuseAddress(true);
+				socket.bind(new InetSocketAddress(redirectedPort));
 			}
 		}
 		return socket;

+ 23 - 3
src/de/tudarmstadt/informatik/hostage/protocol/SMB.java

@@ -10,7 +10,9 @@ import android.preference.PreferenceManager;
 import de.tudarmstadt.informatik.hostage.Hostage;
 import de.tudarmstadt.informatik.hostage.R;
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
+import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBDSType;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBNS;
+import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBNSType;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NMB;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.SMBPacket;
 import de.tudarmstadt.informatik.hostage.wrapper.Packet;
@@ -129,11 +131,29 @@ public class SMB implements Protocol {
 		return false;
 	}
 
+    //just for debugging purpose
+    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+    public static String bytesToHex(byte[] bytes) {
+        char[] hexChars = new char[bytes.length * 2];
+        for ( int j = 0; j < bytes.length; j++ ) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 2] = hexArray[v >>> 4];
+            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+        }
+        return new String(hexChars);
+    }
+
 	@Override
 	public List<Packet> processMessage(Packet requestPacket) {
-		if (requestPacket != null)
-			lastMessage = requestPacket.getBytes();
-		smbPacket.prepareNextResponse(lastMessage);
+        if (requestPacket != null && requestPacket.getBytes().length != 0){
+            lastMessage = requestPacket.getBytes();
+            System.out.println("request packet " + bytesToHex(lastMessage));
+            smbPacket.prepareNextResponse(lastMessage);
+        }
+        else{
+            //something needs to be done, if there is no message
+            smbPacket.prepareNextResponse(0);
+        }
 		byte smbCommand = smbPacket.getSmbCommand();
 		byte[] response;
 		List<Packet> responsePackets = new ArrayList<Packet>();

+ 7 - 4
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NMB.java

@@ -24,8 +24,10 @@ public class NMB extends Thread {
 	private String ip;
 	private String[] ipParts;
 	private InetAddress dst;
-	private int nbnsPort = 137;
-	private int nbdsPort = 138;
+	private final int nbnsOriginPort = 137;
+	private final int nbdsOriginPort = 138;
+    private final int nbnsPort = 34897;
+    private final int nbdsPort = 34898;
 	private String username;
 	private String workgroup;
 	private NBNS nbns;
@@ -229,6 +231,7 @@ public class NMB extends Thread {
 			MyDatagramSocketFactory factory = new MyDatagramSocketFactory();
 			nbnsSocket = factory.createDatagramSocket(nbnsPort);
 			nbdsSocket = factory.createDatagramSocket(nbdsPort);
+
 		} catch (SocketException e) {
 			e.printStackTrace();
 		} catch (IOException e) {
@@ -273,7 +276,7 @@ public class NMB extends Thread {
 		
 		announceHost();	
 		
-//		talk();
+		talk();
 		
 		nbnsSocket.close();
 		nbdsSocket.close();
@@ -289,7 +292,7 @@ public class NMB extends Thread {
 	 */
 	private void checkForAnswers() {
 		try {
-			nbnsSocket.setSoTimeout(1000);
+			nbnsSocket.setSoTimeout(3000);
 			try {
 				while (!masterAnswered) {
 					nbnsSocket.receive(receive);					

+ 207 - 81
src/de/tudarmstadt/informatik/hostage/system/Device.java

@@ -1,104 +1,230 @@
 package de.tudarmstadt.informatik.hostage.system;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
 
 import android.app.Activity;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
 import android.util.Log;
 
-import de.tudarmstadt.informatik.hostage.Hostage;
-import de.tudarmstadt.informatik.hostage.R;
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
+import de.tudarmstadt.informatik.hostage.ui.activity.MainActivity;
 
 
 public class Device {
-
-	@SuppressWarnings("unused")
-	// DO NOT REMOVE, NEEDED FOR SINGLETON INITIALIZATION
-	private static final Device INSTANCE = new Device();
-
+	private static String porthackFilepath = "/data/local/bind";
 	private static boolean initialized = false;
-	private static boolean root = false;
-	private static boolean pp = false;
-
-    private Device() {
-
-        new Thread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-                    String portBinder = "[ -e /data/local/bind ]";
-
-					Process su = new ProcessBuilder("su", "-c", portBinder).start();
-					switch (su.waitFor()) {
-					case 0:
-						root = true;
-						pp = true;
-						break;
-					case 1:
-						root = true;
-						pp = false;
-						break;
-					case 127:
-						root = false;
-						pp = false;
-						break;
-					}
-				} catch (InterruptedException e) {
-				} catch (IOException e) {
-				} finally {
-					initialized = true;
-					Log.d("hostage", "Root: " + Boolean.toString(root));
-					Log.d("hostage", "PP: " + Boolean.toString(pp));
-				}
+	private static boolean root = false; // device is rooted
+	private static boolean porthack = false; // porthack installed
+	private static boolean iptables = false; // iptables redirection confirmed working
+
+    public static void checkCapabilities() {
+		// assume worst case
+		initialized = false;
+		root = false;
+		porthack = false;
+		iptables = false;
+
+		porthackFilepath = getPorthackFilepath();
+		String porthackExists = "[ -e "+porthackFilepath+" ]"; // checks existence of porthack
+
+		try {
+			Process p = new ProcessBuilder("su", "-c", porthackExists).start();
+			switch (p.waitFor()) {
+			case 0: porthack = true;
+			// fall through and don't break
+			case 1: root = true; // 0 and 1 are valid return values of the porthack
+				break;
+
+			case 127: // command not found or executable
+				root = false;
+				porthack = false;
+				break;
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+
+		final String ipTablesList = "iptables -L -n -t nat"; // list all rules in NAT table
+		try {
+			Process p = new ProcessBuilder("su", "-c", ipTablesList).start();
+			switch (p.waitFor()) {
+				case 0: // everything is fine
+					iptables = true; // iptables available and working
+					break;
+
+				case 3: // no such table
+				case 127: // command not found
+				default: // unexpected return code
+					// while testing code 3 has been returned when table NAT is not available
+					iptables = false;
 			}
-		}).start();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+
+		initialized = true;
 	}
 
 	public static boolean isRooted() {
-		while (!initialized)
-			;
+		assert(initialized);
 		return root;
 	}
 
 	public static boolean isPorthackInstalled() {
-		while (!initialized)
-			;
-		return pp;
+		assert(initialized);
+		return porthack;
 	}
 
-    /**
-     * Called after auto-loading porthack. To update the local variables.
-     */
-
-    public static boolean updatePorthack (){
-        try {
-            String portBinder = "[ -e /data/local/bind ]";
-
-            Process su = new ProcessBuilder("su", "-c", portBinder).start();
-            switch (su.waitFor()) {
-                case 0:
-                    root = true;
-                    pp = true;
-                    break;
-                case 1:
-                    root = true;
-                    pp = false;
-                    break;
-                case 127:
-                    root = false;
-                    pp = false;
-                    break;
-            }
-        } catch (InterruptedException e) {
-        } catch (IOException e) {
-        } finally {
-            initialized = true;
-            Log.d("hostage", "Root: " + Boolean.toString(root));
-            Log.d("hostage", "PP: " + Boolean.toString(pp));
-        }
-        return (pp && root);
-    }
+	public static boolean isPortRedirectionAvailable() { // using iptables
+		assert(initialized);
+		return iptables;
+	}
+	/**
+	 * copies an asset to the local filesystem for later usage
+	 * (used for port hack and shell scripts)
+	 * @param assetFilePath
+	 * @param destFilePath
+	 * @return true on success
+	 */
+	private static boolean deployAsset(String assetFilePath, String destFilePath) {
+		Activity activity = MainActivity.getInstance();
+		File file = new File(activity.getFilesDir(), destFilePath);
+		try {
+			OutputStream os = new FileOutputStream(file);
+			try {
+				InputStream is = activity.getAssets().open(assetFilePath);
+				byte[] buffer = new byte[4096];
+				int bytesRead;
+				while ((bytesRead = is.read(buffer)) != -1) {
+					os.write(buffer, 0, bytesRead);
+				}
+				is.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			os.close();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			return false;
+		} catch (IOException e) {
+			e.printStackTrace();
+			return false;
+		}
+
+		//Log.i("FILEPATH", file.getAbsolutePath());
+		return true; // SUCCESS!
+	}
+
+	public static void executePortRedirectionScript() {
+		assert(iptables); // we need iptables for our next trick
+		if (deployAsset("payload/redirect-ports.sh", "redirect-ports.sh")) {
+			String scriptFilePath = new File(MainActivity.getInstance().getFilesDir(), "redirect-ports.sh").getAbsolutePath();
+			Process p = null;
+			try {
+				p = new ProcessBuilder("su", "-c", "sh "+scriptFilePath).start();
+				p.waitFor(); // stall the main thread
+				// TODO: check return value?
+			} catch (IOException e) {
+				e.printStackTrace();
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+		}
+	}
 
+	/**
+	 * @return name of porthack binary for device architecture
+	 */
+	private static String getPorthackName() {
+		String porthack = "bind";
+
+		// determine system architecture to return the correct binary
+		String arch = System.getProperty("os.arch");
+		// TODO: handle more architectures
+		if (arch.equals("i686")) { // this is what genymotion reports
+			porthack += ".x86";
+		} else if (arch.startsWith("arm")) {
+			/*
+			possible values:
+			armv4
+			armv4t
+			armv5t
+			armv5te
+			armv5tej
+			armv6
+			armv7
+			 */
+			porthack += ".arm";
+		} else if (arch.equals("mips")) {
+			porthack += ".mips";
+		}
+
+		return porthack;
+	}
+
+	/**
+	 * @return filepath to deployed porthack binary
+	 */
+	public static String getPorthackFilepath() {
+		File file = new File(MainActivity.getInstance().getFilesDir(), getPorthackName());
+		return file.getAbsolutePath();
+	}
+
+	public static boolean deployPorthack() {
+		String porthack = getPorthackName();
+		if (!deployAsset("payload/"+porthack, porthack)) {
+			return false; // :(
+		}
+
+		// make port hack executable
+		try {
+			Process p = new ProcessBuilder("su", "-c", "chmod 700 "+getPorthackFilepath()).start();
+			if (p.waitFor() != 0) {
+				logError(p.getErrorStream());
+				return false;
+			}
+			logOutput(p.getInputStream());
+		} catch (IOException e) {
+			return false;
+		} catch (InterruptedException e) {
+			return false;
+		}
+
+		return true; // SUCCESS!
+	}
+
+	public static void uninstallPorthack() {try {
+		Process p = new ProcessBuilder("su", "-c", "rm "+getPorthackFilepath()).start();
+		if (p.waitFor() != 0) {
+			logError(p.getErrorStream());
+		}
+		logOutput(p.getInputStream());
+	} catch (IOException e) {
+	} catch (InterruptedException e) {
+	}
+	}
+
+	// copied from PrivilegedPort.java
+	private static void logOutput(InputStream stdout) throws IOException {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
+		String line;
+		while ((line = reader.readLine()) != null) {
+			Log.i("HelperUtils", line);
+		}
+	}
+
+	private static void logError(InputStream stderr) throws IOException {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(stderr));
+		Log.e("HelperUtils", reader.readLine());
+	}
 }

+ 4 - 2
src/de/tudarmstadt/informatik/hostage/system/PrivilegedPort.java

@@ -13,6 +13,7 @@ import android.preference.PreferenceManager;
 import android.util.Log;
 
 import de.tudarmstadt.informatik.hostage.Hostage;
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
 public class PrivilegedPort implements Runnable {
 
@@ -56,8 +57,9 @@ public class PrivilegedPort implements Runnable {
 
 	@Override
 	public void run() {
-
-        String command = String.format("/data/local/bind %s %d", type.toString(), port);
+		String porthack = Device.getPorthackFilepath();
+		Log.i("privileged port", porthack);
+        String command = String.format(porthack+" %s %d", type.toString(), port);
 
 		try {
 			Process p = new ProcessBuilder("su", "-c", command).start();

+ 8 - 0
src/de/tudarmstadt/informatik/hostage/ui/activity/MainActivity.java

@@ -39,6 +39,7 @@ import de.tudarmstadt.informatik.hostage.R;
 import de.tudarmstadt.informatik.hostage.model.Profile;
 import de.tudarmstadt.informatik.hostage.persistence.ProfileManager;
 import de.tudarmstadt.informatik.hostage.sync.android.SyncUtils;
+import de.tudarmstadt.informatik.hostage.system.Device;
 import de.tudarmstadt.informatik.hostage.ui.model.LogFilter;
 import de.tudarmstadt.informatik.hostage.ui.adapter.DrawerListAdapter;
 import de.tudarmstadt.informatik.hostage.ui.fragment.AboutFragment;
@@ -220,6 +221,13 @@ public class MainActivity extends Activity {
 		setContentView(R.layout.activity_drawer_main);
 		mProfileManager = ProfileManager.getInstance();
 
+		// check for the porthack and iptables
+		Device.checkCapabilities();
+		if (Device.isPortRedirectionAvailable()) {
+			// redirect all the ports!!
+			Device.executePortRedirectionScript();
+		}
+
 		// init threat indicator animation
 		ThreatIndicatorGLRenderer.assets = getAssets();
 		ThreatIndicatorGLRenderer.setThreatLevel(ThreatIndicatorGLRenderer.ThreatLevel.NOT_MONITORING);

+ 35 - 26
src/de/tudarmstadt/informatik/hostage/ui/fragment/HomeFragment.java

@@ -290,32 +290,36 @@ public class HomeFragment extends Fragment {
 		if (mSwitchChangeListener == null) {
 			mSwitchChangeListener = new CompoundButton.OnCheckedChangeListener() {
 				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-					if (!HelperUtils.isNetworkAvailable(getActivity())) {
-						new AlertDialog.Builder(getActivity()).setTitle(R.string.information).setMessage(R.string.network_not_connected_msg)
-								.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-									public void onClick(DialogInterface dialog, int which) {
+					if (isChecked) { // switch activated
+						// we need a network connection
+						if (!HelperUtils.isNetworkAvailable(getActivity())) {
+							new AlertDialog.Builder(getActivity()).setTitle(R.string.information).setMessage(R.string.network_not_connected_msg)
+									.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+										public void onClick(DialogInterface dialog, int which) {
 
-									}
-								}).setIcon(android.R.drawable.ic_dialog_info).show();
+										}
+									}).setIcon(android.R.drawable.ic_dialog_info).show();
 
-						setStateNotActive();
-						setStateNotConnected();
-					} else {
-						if (isChecked) {
+							setStateNotActive();
+							setStateNotConnected();
+						} else { // network available
 							boolean protocolActivated = false;
 							if (ProfileManager.getInstance().getCurrentActivatedProfile() == null) {
-								MainActivity.getInstance().startMonitorServices(Arrays.asList(getResources().getStringArray(R.array.protocols)));
+								MainActivity.getInstance().startMonitorServices(Arrays.asList(
+										getResources().getStringArray(R.array.protocols)));
 							} else {
 								ProfileManager profileManager = ProfileManager.getInstance();
 
 								if (profileManager.isRandomActive()) {
-									profileManager.randomizeProtocols(profileManager.getRandomProfile());
+									profileManager
+											.randomizeProtocols(profileManager.getRandomProfile());
 								}
 
-								Profile currentProfile = profileManager.getCurrentActivatedProfile();
+								Profile currentProfile = profileManager
+										.getCurrentActivatedProfile();
 								List<String> protocols = currentProfile.getActiveProtocols();
 
-								if(protocols.size() > 0 || currentProfile.mGhostActive){
+								if (protocols.size() > 0 || currentProfile.mGhostActive) {
 									protocols.add("GHOST");
 									MainActivity.getInstance().startMonitorServices(protocols);
 									protocolActivated = true;
@@ -325,22 +329,27 @@ public class HomeFragment extends Fragment {
 							if (protocolActivated) {
 								setStateActive();
 							} else {
-								new AlertDialog.Builder(getActivity()).setTitle(R.string.information).setMessage(R.string.profile_no_services_msg)
-										.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-											public void onClick(DialogInterface dialog, int which) {
-
-											}
-										}).setIcon(android.R.drawable.ic_dialog_info).show();
+								new AlertDialog.Builder(getActivity())
+										.setTitle(R.string.information)
+										.setMessage(R.string.profile_no_services_msg)
+										.setPositiveButton(android.R.string.ok,
+												new DialogInterface.OnClickListener() {
+													public void onClick(DialogInterface dialog,
+															int which) {
+
+													}
+												}).setIcon(android.R.drawable.ic_dialog_info)
+										.show();
 
 								setStateNotActive();
 							}
-						} else {
-							if (MainActivity.getInstance().getHostageService() != null) {
-								MainActivity.getInstance().getHostageService().stopListeners();
-								MainActivity.getInstance().stopAndUnbind();
-							}
-							setStateNotActive();
 						}
+					} else { // switch deactivated
+						if (MainActivity.getInstance().getHostageService() != null) {
+							MainActivity.getInstance().getHostageService().stopListeners();
+							MainActivity.getInstance().stopAndUnbind();
+						}
+						setStateNotActive();
 					}
 				}
 			};

+ 53 - 6
src/de/tudarmstadt/informatik/hostage/ui/fragment/SettingsFragment.java

@@ -5,8 +5,10 @@ import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.TextView;
 import de.tudarmstadt.informatik.hostage.R;
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.system.Device;
 
 /**
@@ -14,13 +16,20 @@ import de.tudarmstadt.informatik.hostage.system.Device;
  * @created 24.02.14 23:37
  */
 public class SettingsFragment extends UpNavigatibleFragment {
+	private TextView mPorthackText;
+	private Button mPorthackInstallButton;
+	private Button mPorthackUninstallButton;
+
 	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 		super.onCreateView(inflater, container, savedInstanceState);
 		getActivity().setTitle(getResources().getString(R.string.drawer_settings));
 		View v = inflater.inflate(R.layout.fragment_settings, container, false);
 
 		TextView rootedText = (TextView) v.findViewById(R.id.settings_device_rooted);
-		TextView porthackText = (TextView) v.findViewById(R.id.settings_porthack_installed);
+		TextView iptablesText = (TextView) v.findViewById(R.id.settings_iptables_available);
+		mPorthackText = (TextView) v.findViewById(R.id.settings_porthack_installed);
+		mPorthackInstallButton = (Button) v.findViewById(R.id.settings_deploy_porthack);
+		mPorthackUninstallButton = (Button) v.findViewById(R.id.settings_uninstall_porthack);
 
 		if (Device.isRooted()) {
 			rootedText.setText(R.string.yes);
@@ -30,17 +39,55 @@ public class SettingsFragment extends UpNavigatibleFragment {
 			rootedText.setTextColor(getResources().getColor(R.color.holo_red));
 		}
 
-		if (Device.isPorthackInstalled()) {
-			porthackText.setText(R.string.yes);
-			porthackText.setTextColor(getResources().getColor(R.color.holo_dark_green));
+		if (Device.isPortRedirectionAvailable()) {
+			iptablesText.setText(R.string.yes);
+			iptablesText.setTextColor(getResources().getColor(R.color.holo_dark_green));
 		} else {
-			porthackText.setText(R.string.no);
-			porthackText.setTextColor(getResources().getColor(R.color.holo_red));
+			iptablesText.setText(R.string.no);
+			iptablesText.setTextColor(getResources().getColor(R.color.holo_red));
 		}
 
+		updatePorthackStatus();
+
+		mPorthackInstallButton.setOnClickListener(new View.OnClickListener() {
+			@Override
+			public void onClick(View v) {
+				Device.deployPorthack();
+				updatePorthackStatus();
+			}
+		});
+		mPorthackUninstallButton.setOnClickListener(new View.OnClickListener() {
+			@Override
+		public void onClick(View v) {
+				Device.uninstallPorthack();
+				updatePorthackStatus();
+			}
+		});
+
 		return v;
 	}
 
+	private void updatePorthackStatus() {
+		Device.checkCapabilities(); // get current situation
+
+		if (Device.isPorthackInstalled()) {
+			mPorthackText.setText(R.string.yes);
+			mPorthackText.setTextColor(getResources().getColor(R.color.holo_dark_green));
+			mPorthackInstallButton.setEnabled(false); // we're only able to deploy if the device is rooted
+			mPorthackInstallButton.setVisibility(View.GONE);
+			mPorthackUninstallButton.setEnabled(true);
+			mPorthackUninstallButton.setVisibility(View.VISIBLE);
+		} else {
+			mPorthackText.setText(R.string.no);
+			mPorthackText.setTextColor(getResources().getColor(R.color.holo_red));
+			// we're only able to deploy if the device is rooted
+			mPorthackInstallButton.setEnabled(Device.isRooted());
+			mPorthackInstallButton.setVisibility(Device.isRooted() ? View.VISIBLE : View.GONE);
+			mPorthackUninstallButton.setEnabled(false);
+			mPorthackUninstallButton.setVisibility(View.GONE);
+		}
+	}
+
 	public void onViewCreated(View view, Bundle savedInstanceState) {
 		super.onViewCreated(view, savedInstanceState);