前言
在现实的攻防中,往往webshell要比主机后门要用得多,因为我们首先要突破的目标是网站嘛,而且waf也往往会更注重webshell的检测。webshell的免杀分为两个,一是静态查杀,二是流量查杀。静态查杀不用多说了,匹配特征码特征值,流量查杀则是根据你webshell的流量特征来判断是否是恶意的行为。
实验环境
JDK1.8,Behinder V4.1
项目构建
老样子先对jar包进行反编译,这里分享一个在线反编译的网站。
Java decompiler online / APK decompiler - Decompiler.com
idea新建一个项目,叫Behinder,jdk建议选择1.8的,因为Behinder是以jdk1.8环境为基础运行的,防止后续的打包出问题。
在Behinder目录下新建一个目录名为lib,把未反编译的jar包拖进去,同时把已经反编译好的jar包解呀到Behinder目录下面。
点击文件 -> 模块 -> 点击依赖 -> 点击加号。
点击加号之后选择JAR或者目录,接着选择我们lib目录下jar包。
记得勾选上。
再来到工件这里,点击左上角的加号。
选择来自具有依赖项的模块。
主类选择后面.ui的,因为你打开一个软件最先显示的肯定是UI设计嘛,所以大多数主类也就是入口点都是xxxx.ui。
项目构建完毕。
流量特征去除
我们先来看看Behinder的原始流量特征,可以看到以下的几个字段都是特征来的。
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Content-type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
我们现在要修改这几个字段的内容,去除特征。直接搜流量的特征值,可以看到这个特征在Constants.java代码里面。
我们找到要修改的Java文件,右键->点击重构->选择复制,要复制到src目录下才行,因为这个目录是开发目录,记得路径要对得上!!!
src目录。
可以看到Accepts头的值和我们上述的流量特征一样,这里还有版本啥的代码。
修改Accepts头,还有版本号也一并修改掉。
点击构建->选择构建工件->所有工件。
然后会在out目录下生成一个jar包。
我们可以运行这个jar包,看看是否修改成功了,可以看到右下角版本变为我们修改的版本了。
Accept头也变了。
继续把剩下的特征也都去除掉,直接搜即可,在ShellService.java中可以找到剩下的特征。可以看到UA头不是写死的,而是通过this.getCurrentUserAgent()方法获取的。这是Behinder的一个特点,就是UA头是从它里面内置的十个中随机获取的。
去除特征修改如下。
重新构建一下,运行起来试试效果,可以看到特征全无了。
静态免杀
不知道是不是这个工具的问题,这个我没有搞成功,但还是记录一下。我们在传输协议这里生成webshell的时候,有多重加密方式可供选择,我们上面的数据包会有一段很长的编码,就是由Behinder内置的算法对webshell加密形成的。
如果我们用Behinder内置的算法的话,别人拿去解密那你不就炸肛了吗,Behinder支持自己导入算法,也就是说我们也可自己写一个算法导入进去。如果你不会写算法(我也不会),你可以叫AI帮你写一个,或者网上找一下。我这里找了一个网上找了一个把数据加密成XML的算法。
//加密
private byte[] Encrypt(byte[] data) throws Exception
{
String xml="<?xml version=\"1.0\"?><user><id>1</id><content>DaYer0</content></user>";
String key = "ffffcmldjt12138s";
String transformation = "AES/ECB/PKCS5Padding";//创建加密对象javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(transformation);//创建加密规则
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES");//加密初始化
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE,secretKeySpec);//调用加密方法byte[] bytes = cipher.doFinal(data);
String encode = java.util.Base64.getEncoder().encodeToString(bytes);xml=xml.replace("DaYer0",encode);
return xml.getBytes();
}
解密
private byte[] Decrypt(byte[] data) throws Exception
{
java.io.ByteArrayOutputStream bos=new java.io.ByteArrayOutputStream();
bos.write(data,46,data.length-63);
String input = new String(bos.toByteArray());
//定义key(16位)
String key = "ffffcmldjt12138s";
String transformation = "AES/ECB/PKCS5Padding";
//创建解密对象
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(transformation);
//创建解密规则
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES");
//解密初始化
cipher.init(javax.crypto.Cipher.DECRYPT_MODE,secretKeySpec);
//调用解密方法
byte[] bytes1 = java.util.Base64.getDecoder().decode(input);
byte[] bytes = cipher.doFinal(bytes1);
return bytes;
}
接着我们新建一个加密方式。
把加密和解密的代码搞上去,如果校验通过则会显示保存成功,就是用你加密代码加密数据,然后再用你的解密代码还原得出来数据,就是校验通过。值得一提的是本地的加解密函数只能Java来写,想要导入其它的代码的加密函数可以选择远程。
保存之后我们点击分享,就会保存成为一个config文件。
在\net\rebeyond\behinder\resource\transprotocol目录下我们可以找到它存放的加密代码,也就是我们要把XML.config放到此目录下才行。
把目录transprotocol移到src目录下面,记得路径不要错,再把我们的XML.config复制进去。
重构项目,运行起来试试,可以看到我们的XML已经写入。
利用XML加密生成一个服务端连接试试,问题就出现了。显示连接失败,右下角显示解密错误,不理解为啥,校验的时候是通过的,而且这个Behinder自带的算法有好几个也是不行的,连接就报错说解密错误。不理解,有无懂的大佬解释一下。
最后就是重新编译一下修改过的代码文件,覆盖掉原来jar包里面的文件即可。
总结
这个冰蝎生成的webshell基本都连不上的,有没有师傅是和我一样的情况,妈的。不知道是这个工具的问题,还是我这里的问题,但是我直接从github下载直接用也是不行,哎。
最后经典语句收尾
以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。