> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [mp.weixin.qq.com](https://mp.weixin.qq.com/s/8G0il9gIkubI1w15gOBX6A) 前言 -- As-Exploits,中国蚁剑后渗透模块。**本文将介绍 v1.2 更新内容,并介绍该插件目前已有的功能。**   目前插件的定位是蚁剑的一个**微内核拓展模块**,可以迅速做到 Payload 的工程化,不用过多时间浪费在插件的结构上。目前的 As-Exlpoits 各部分之间基本做到了解耦,新增一个 payload 只需要两步:1. 填写 payload,2. 画一个表单。其余发包,回显处理等事情框架会自动帮你实现。想要自定义的话只需要继承父类然后重写对应方法即可。 其中 Payload 部分很多借鉴了冰蝎跟哥斯拉的实现,向其开发者们表示感谢! 支持列表 ----
模块名称 \ Shell 类型PHPASPXJSP
基本信息
反弹 Shell
内存马

内存马管理

杀软识别
提权辅助
屏幕截图
ShellCode 加载器

Jar 加载器

V1.2 更新主要内容 ----------- ### 1) aspx 增加`屏幕截图`模块 我打我自己 当然实战中需要较高权限。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9EL76pQ0YNWAE0cLhYcp4ZavmO6XOErY0cEr51HMobdrof5senwqrvA/640?wx_fmt=png) 因为在 Jscript 加载 Assembly 踩坑记里面解决了 Jscript 加载 c# 的问题,所以 C# 的 payload 理论上都可以加进去,更多其他的用法就看大家自己发挥了 ### 2) jsp 增加`Jar加载器`模块 打一个 jar 进去通常有两个用处: 一是可以用来上传数据库驱动。 二是把恶意类打入 JVM 中,后续只需要通过反射调用即可。哥斯拉的实现方式就是第一次就把所有的 Payload 打入 jvm 中,后续通过反射调用。所以后续通信的流量包都非常的小,只需要传递参数即可。 冰蝎跟哥斯拉都有类似的功能,研究了一下他们的实现。 冰蝎 冰蝎的加载 jar 功能内嵌于数据库连接部分,仅用于上传数据库驱动。首先把要打入的 jdbc 上传到目标的临时目录,然后再用 URLClassLoader 去加载,这里贴一下代码。 net.rebeyond.behinder.ui.controller.DatabaseViewController#loadDriver ``` private void loadDriver(String scriptType, String databaseType) throws Exception { String driverPath = "net/rebeyond/behinder/resource/driver/"; Platform.runLater(() -> { this.statusLabel.setText("正在上传数据库驱动……"); }); String os = this.currentShellService.shellEntity.getString("os").toLowerCase(); //根据系统型号选择临时目录 String remoteDir = os.indexOf("windows") >= 0 ? "c:/windows/temp/" : "/tmp/"; String libName = null; if (scriptType.equals("jsp")) { //根据类型选择数据库jdbc if (databaseType.equals("sqlserver")) { libName = "sqljdbc41.jar"; } else if (databaseType.equals("mysql")) { libName = "mysql-connector-java-5.1.36.jar"; } else if (databaseType.equals("oracle")) { libName = "ojdbc5.jar"; } } else if (scriptType.equals("aspx")) { if (databaseType.equals("mysql")) { libName = "mysql.data.dll"; } else if (databaseType.equals("oracle")) { libName = "Oracle.ManagedDataAccess.dll"; } } byte[] driverFileContent = Utils.getResourceData(driverPath + libName); String remotePath = remoteDir + libName; //将jar先上传到临时目录 this.currentShellService.uploadFile(remotePath, driverFileContent, true); Platform.runLater(() -> { this.statusLabel.setText("驱动上传成功,正在加载驱动……"); }); //将libPath传递给服务端加载 JSONObject loadRes = this.currentShellService.loadJar(remotePath); if (loadRes.getString("status").equals("fail")) { throw new Exception("驱动加载失败:" + loadRes.getString("msg")); } else { Platform.runLater(() -> { if (scriptType.equals("jsp")) { this.statusLabel.setText("驱动加载成功,请再次点击“连接”。"); } this.statusLabel.setText("驱动加载成功。"); }); } } ``` ``` import java.io.IOException; public class calc { public calc() { try { Runtime.getRuntime().exec("calc"); } catch (IOException var2) { var2.printStackTrace(); } } } ``` WebShell 获取到 libPath 然后用 URLClassLoader 去加载。 net.rebeyond.behinder.payload.java.Loader ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9BoqMiaTPDiblXWN6FwE37FEQHn26xj7uNqcIqYP5zeY0KOlP1eNJlibPg/640?wx_fmt=png) #### 哥斯拉 哥斯拉的操作就比较秀了。因为打入一个 jar 不像打入一个 class 一样,直接有 defineClass 方法去接收一个字节数组。据我的研究,没有直接接收一个 jar 的字节数组的方法。打入 jar 需要使用 **URLClassLoader** 这个类,大概有两种方式,一种是利用 http 协议,远程获取所要加载的 jar。另一种是 file 协议,从本地路径去读取 jar。 每次都额外搭一个 http 当然不方便,并且目标还不一定出网。但是 file 协议的话还需要把 jar 写到磁盘中,文件就会落地,增加了被发现的风险。 但是我们回过头想,既然通过 file 协议加载 jar,肯定会有一个通过路径找到文件,然后把文件读取到内存的过程,如果我们能跳过这个根据路径找文件的过程,直接把文件的内容写到字节数组里不就可以文件不落地了吗? 哥斯拉就是采用的这种做法,利用两个子类分别继承了 URLStreamHandler 跟 URLConnection,然后利用反射模拟了读取文件的过程。 创建了一种新的协议 jarmembuff ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG93lKibh8otlZwoNFMesEbg2uXK6w8AVjhqIEgJGM4QtSvFYIAvxmwx9g/640?wx_fmt=png) 然后把收到的 jar 文件的字节数组给放到变量里。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG99oS09G0rol6WEz7teGCEkrjFrEC7HpbzAgsLKoC6mBuvZeUibSVpr4A/640?wx_fmt=png) 这样就实现了文件不落地,将 jar 打入内存的目的。 本人在 As-Exploits 里也采用了这种做法。 #### 小实验 这里做一个小实验 写一个弹框测试类 ``` <% Class.forName("calc").newInstance(); %> ``` ``` ERROR:// java.lang.NoSuchMethodException: org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext.removeChild(org.apache.catalina.Container) ``` jar -cvf 打包成 jar 开个 web 项目,写一个 test.jsp 如下。去查找 calc 这个类并且实例化。如果实例化成功则会弹出我们的计算器。 ``` <% Class.forName("calc").newInstance(); %> ``` 在第一次访问的时候找不到这个类肯定会报错 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9mKvWcicnX8jQ1VMBiaBhyNAu6msm5oSicrJDWOmugtXm7HKeKb9G2BSRw/640?wx_fmt=png) 然后打开插件,选择要打入的 jar 文件。这里可以点按钮选择,也可以直接在输入框输入绝对路径。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG97D680aDHosXQtQqiasLYvibvAwdibdK2Pp7btsFH5bzErhAJrxN6vRraA/640?wx_fmt=png) exploit! ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9KFVSSeCJvPNoiaP50vrewfGMXicdysYE65xGqWDTVly0ibBWPkhOQRk3w/640?wx_fmt=png) 再去刷新页面,弹出计算器。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG994BYMssic5a3xs3Xian2bcE4Ut05UHNUgRzL5PBu3IexISO7Qu9WYrIg/640?wx_fmt=png) ### 3) 支持返回包加密 选择 reverse 解码器 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9oOic5eeBXCHNMBujOI03hRotDiao63Gn9cJ749r8RX89aibJAoiaVMDaUw/640?wx_fmt=png) 返回包数据 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9nVrXoUx4kelz8qoGvbx7TDI79YBcMWxFZZW2BRQ7tHk1WcPIkE9NIw/640?wx_fmt=png) ### 4) 内存马兼容 Spring 其中 内存马管理 以及 AntSword 类型内存马支持 Tomcat(5-9)、Spring 首先要 Spring 中默认没有 pageContext 的依赖,所以相关的依赖部分都要去除。蚁剑的 jsp 很早就不依赖 pageContext 了,相关文章以前也写过,不知道的同学可以翻一翻我的博客:yzddmr6.tk。 这里有两个细节 #### 关于反射的坑 在研究过程中可以发现哥斯拉中的 Payload 基本都是用反射实现的,这样的好处就是可以不添加任何依赖。这也是为什么哥斯拉只有 8m 的原因。 去除掉所有的 pageContext 后,在 Spring 中获取 servlet 没有问题,但是卸载的时候内存马管理模块报了一个这样的错误: ``` ERROR:// java.lang.NoSuchMethodException: org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext.removeChild(org.apache.catalina.Container) ``` 定位一下问题出在这里 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG92C5rIdkLKBO6pf95CPd4VYkEmXVS7X5ia5czwzs1uWn4Tg0icicaqj3mA/640?wx_fmt=png) 意思就是在 StandardContext 中找不到 **removeChild** 这个方法。 调试一下发现,Spring 中获取到的 StandardContext 示例为其一个子类,叫做 **TomcatEmbeddedContext**。虽然 Spring 中内置了 Tomcat,但这个是 Spring 特有的。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG95l7sprolnolA9JTFWIjId4vyAxHYsuE6dO4ZEBsG93onJ0d5ET6elg/640?wx_fmt=png) TomcatEmbeddedContext 继承了 StandardContext,并且没有对 removeChild 进行改写,如果父类有这个方法应该是可以调用的。 那为什么会找不到方法呢?这里要提一下反射中 getMethods 跟 getDeclaredMethods 的区别: * getMethods 获取所有公有方法(包括父类方法) * getDeclaredMethods 获取本类中的所有方法 (只拿本类中的) 哥斯拉中用的 getDeclaredMethod,也就是只能获取到本类中的方法,自然反射拿不到父类的 removeChild。 所以解决办法要么把 getDeclaredMethod 换成 getMethod,因为 removeChild 本来就是 public 的,要么就直接调用 removeChild 方法,不采用反射。在这里我采用了后者。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9BzN4RPXLKbSkQp31LuW7f2m1QU52SV9lB8e8Ecv5nVU7K4M45W1q4A/640?wx_fmt=png) 在内存马模块同理,这里直接全部改了,不再用反射。 #### addServletMapping 的兼容性问题 要注意的是,在添加 servlet 的过程中,会涉及到 addServletMapping 函数的兼容性问题,并且很多文章中并没有仔细分析具体的版本号。这里贴一下我研究的结果: * tomcat7         只能 addServletMapping * tomcat8         addServletMapping/addServletMappingDecoded 都可以 * tomcat9         只能 addServletMappingDecoded 在这里要么用反射,两种方法都 try 一下。在这里提供一个更好的解决办法,使用 ApplicationServletRegistration 这个类。ApplicationServletRegistration 对 wrapper 做了封装,自动会处理两种方法的兼容性。 #### Spring 下运行截图 获取 Servlet ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9TPgWygiaMspEobLG4KlqfpBG99uNxeXtsm7YGN8gADkz0yaTLiaDeicWg/640?wx_fmt=png) 打入蚁剑内存马 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9dlEc1ia0udnllJEibicQrZgANxjUcbpsH6f1jmAflIsKI1sXibnnt662Qw/640?wx_fmt=png) 再次获取 Servlet,发现已经有了,并且在第一位。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9HNw0mT9JtP5zhl6TW6DT1qwjSxE7SX73ULIwrA5ibUMjgSHhnrjgNwg/640?wx_fmt=png) 连接成功 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG90YDJ6XChjOLoUxicWfBh17dicZFhht6udZiaic4loXj3I43c2zkaicV2nWA/640?wx_fmt=png) 卸载 Servlet ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9plJNv1st0sibux8c0cA6pSqmiakMtHjFnS5TbmcoRDYwiaa9SR870JsUQ/640?wx_fmt=png) 卸载后再次获取 Servlet 列表 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9MTdUeib2pIDVHxicoq3E9ywszmst8PKBZKNQibErxqxFw0W1zgCfkzrGA/640?wx_fmt=png) 虽然我们可以通过 setLoadOnStartup 把 servlet 放在第一位,但是面对需要鉴权的 shiro 等目标打入一个 servlet 内存马还是有不小的局限性。所以目前 filter 内存马依旧是主流。但是蚁剑是支持 listener 类型的,listener 的优先级还在 filter 之上。所以以后可能直接跳过 filter,直接加入 listener 的 payload。 **现有模块介绍** ---------- ### 基本信息 获取当前服务端信息。 支持类型:php/jsp/aspx **php** ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9sZrGwPO9uUTm5G6b7JK2U7Rm0ibdkFf7pID4AJKBxA24nDOoCYWJhnA/640?wx_fmt=png) **jsp** ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9u6Hx9k4fV8UkJxvztso1CAe4ibqOxR92ce5mlSbdF1Qk6IU3tIqgaYw/640?wx_fmt=png) **aspx** ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9YaibYCWaouNJe8txGGWyyp4jxj0n59LK6S4ple4ib1fo7Pic6ia6SECl1w/640?wx_fmt=png) ### 反弹 Shell 跟 MSF 联动 支持类型:php/jsp/aspx **Payload 目前支持以下类型:** * java/meterpreter/reverse_tcp * java/shell/reverse_tcp * java/meterpreter/bind_tcp * java/shell/bind_tcp * php/meterpreter/reverse_tcp * php/shell/reverse_tcp * php/meterpreter/bind_tcp * php/shell/bind_tcp * windows/meterpreter/reverse_tcp * windows/x64/meterpreter/reverse_tcp ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9X0RG9z1fZ8icpROLFlkV9JCFFwcnCAQ0AibkdzREB6djwC8oxWc3WXlQ/640?wx_fmt=png) ### 内存马 一键打入内存 Webshell,由于时间仓促,目前仅支持 Servlet 型内存马。 支持类型:jsp 可打入的内存马种类: * AntSword * Behinder * Godzilla-Base64 * reGerog 组件名称为注册的 Servlet 的名称,可以起一个具有迷惑性的名字来隐藏自己。 其中 AntSword 类型支持 Tomcat(5-9)、Spring。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9TWBGibkDdYbRbGK2MPTowY82uXBlPI6AWicB24hM373OgoVvtxQC4P2A/640?wx_fmt=png) #### 打入哥斯拉内存马 打入 Godzilla-Base64 内存马 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9A5wbmoib4C959ubApPOcoxjTZW9atXPN9UyT48NxzrYo7FqdIebXEJA/640?wx_fmt=png) 在哥斯拉中连接成功 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG99IYibbloSICWIIhXSsLeEfXLBicAsN5IbVGaEXtTMRQgpGbiaonNpweqA/640?wx_fmt=png) ### 杀软识别 > 数据来源是 key 师傅的项目:avList 通过`tasklist /svc`获取当前进程列表,识别出其中的杀软。 支持类型:php/jsp/aspx 目前支持手动跟自动两种获取方式: * 自动获取 自动执行`tasklist /svc`并分析回显数据。 * 手动获取 手动输入`tasklist /svc`的结果。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9g4wyzqnc1T8Dxbfu6kPPcd6hbrbDl9p7MYnrHOic5fibodw3g5LGbDAQ/640?wx_fmt=png) ### 提权辅助 通过`systeminfo`来获取补丁信息,从而给出提权建议。 支持类型:php/jsp/aspx 同样支持手动跟自动两种获取方式。 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9VI1AsgO0gKvAHuOAYkv6N7mvOjT9z2NqOibiaiaCxw9hC3RqHqMNprR7Q/640?wx_fmt=png) ### 屏幕截图 获取目标当前屏幕截图。 支持类型:jsp/aspx ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9UvO6Ps8pUunBmvgsnnyz9lhlfPqvPocTy92LkVogMm3hYYibTgZ8okg/640?wx_fmt=png) ### ShellCode 加载器 加载 shellcode 至内存运行。(shellcode 为 hex 格式,且不能有多余空格或换行) 支持类型:aspx 以 msf 为例:msfvenom 生成 hex 格式的 shellcode ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9uI3RhKUKfWbJVPVcXyvyYg81gMFKRYtWF8KyXMMwN5wrRgOP7y9ib8w/640?wx_fmt=png) 粘贴进输入框,点击`exploit` ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9chyRhCGWuRPL2vCWic4YuCdVL7DpKPPjhTQLcRmeWYib78HXzftBGTSg/640?wx_fmt=png) 收到 Meterpreter 会话 ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9qoo4OxVSuqMLsMOgoXt3D7ibSdSsHZ3EgsoYibadBWrGVfodicrtYgLkw/640?wx_fmt=png) ### Jar 加载器 加载 Jar 到 JVM 内存中。过程中文件不落地,可用于上传数据库驱动等。 支持类型:jsp ![](https://mmbiz.qpic.cn/mmbiz_png/lkcJVly3Wy2iawqL1S4qTmEFElpSDibibG9R5JCswgkAohEUMMZ3Z3UQHSPoZOxzkys2oFlicE0jkKnXiavMk9vLeyA/640?wx_fmt=png) 注意事项 ---- 本插件仅供合法的渗透测试以及爱好者参考学习,请勿用于非法用途,否则自行承担相关责任。 ![](https://mmbiz.qpic.cn/mmbiz_jpg/lkcJVly3Wy3kYxrKTnbxKyJeZhmfzqjkiaA1gWNNFdGMgnpWbicm1mzDFq0Sicfzv5HPHqRlyuDDeUHTE8QJpm9FQ/640?wx_fmt=jpeg) 不如关注一波再走?