文章目录
注:
本文还没完成,后面有空再完成吧。
其实吧,关键的东西都在代码实现里了:
https://github.com/fa1c0n1/JavaInstrument
Java Instrument简介
我们只要拥有一个web容器进程执行用户的权限,理论上就可以完全控制该进程的地址空间(更确切的说是地址空间中的非Kernel部分),包括地址空间内的数据和代码。OS层进程注入的方法有很多,不过具体到Java环境,我们不需要使用操作系统层面的进程注入方法。Java为我们提供了更方便的接口,Java Instrumentation。
java.lang.Instrument包是在JDK5引入的,开发者通过修改方法的字节码实现动态修改类代码。利用Instrument,开发者可以开发单独的代理Agent,实现对JVM进程的运行时监控,分析JVM进程运行时内存状态,甚至可以很方便地修改内存中类的字节码,修改或者扩展已有的功能。
Java Agent 开发
Java agent的使用方式有两种:
- 实现
premain
方法,在JVM启动前加载; - 实现
agentmain
方法,在JVM启动后加载。
premain和agentmain函数声明如下,拥有Instrumentation inst参数的方法优先级更高:
public static void agentmain(String agentArgs, Instrumentation inst) {
...
}
public static void agentmain(String agentArgs) {
...
}
public static void premain(String agentArgs, Instrumentation inst) {
...
}
public static void premain(String agentArgs) {
...
}
第一个参数String agentArgs
就是Java agent的参数。
第二个参数 Instrumentaion inst
相当重要,后面会提到。
由于内存马的使用场景,一般是注入正在运行的JVM进程,所以下面只介绍 agentmain 方式的使用。
agentmain() 方法
VirtualMachine
Agent内存马实现:Tomcat环境
演示:Tomcat环境
演示,SpringMVC 5.2.0 + Tomcat 8.5.39:
启动Tomcat环境后,注入我们的Agent内存马。
这里要注意,由于是自己的测试环境,所以刚启动Tomcat,需要自己访问一下Tomcat服务的随便一个url,否则Tomcat里的一些类没有加载进内存,比如注入Agent内存马时要找的目标类
org.apache.catalina.core.ApplicationFilterChain
。没有加载到内存中,从而找不到这个类,所以注入内存马失败。而线上环境的话由于早就被访问过无数次了,所以Tomcat的这些类肯定都已被加载到内存中了,所以就不存在这个问题,直接注入Agent内存马即可。
然后做以下操作:
- 访问已存在的路由url
(1) 指定非webshell的参数时,原有业务不受影响:
(2) 指定webshell参数时,将执行我们注入的webshell代码:
- 访问不存在的路由url
(1) 指定非webshell的参数时,显示404页面:
(2) 指定webshell参数时,将执行我们注入的webshell代码:
agent内存马持久化:Tomcat重启后被自动注入agent内存马
agent内存马注入Tomcat进程后,原来路径下的两个jar被agent删除了,然后当Tomcat进程关闭前,两个jar会写入到Tomcat的临时目录,并开启AgentTomcatMemShellInject 进程。
当Tomcat再次启动后,AgentTomcatMemShellInject检测到Tomcat进程后,将agent内存马注入进去,然后AgentTomcatMemShellInject进程便结束了。
此时再次访问agent内存马,发现依旧生效。自此,便实现了agent内存马在Tomcat环境下的持久化,会随着Tomcat进程的重启而自动复活。(如果不想让它自动复活,则在Tomcat关闭后,kill掉AgentTomcatMemShellInject的进程即可)
演示:Springboot环境
Springboot环境下,目前笔者无法做到自动复活。因为在Agent注入到Springboot的进程后,尝试了各种办法都无法在agentmain()
方法中获取到上下文context对象,从而无法进一步获取Tomcat端口号。
Instrument内存马的特点
- 优点:不会生成新的Servlet,Filter,Listener对象,因此隐蔽性更强。
- 缺点:需要生成Agent文件落地,有可能会被IDS文件检测检测到Agent。
针对缺点的改进,参考学习[3][4]
相关代码已传github:
https://github.com/fa1c0n1/JavaInstrument
参考
[1] https://mp.weixin.qq.com/s/cbF2cdV9mnbGZWDwHuUoNA
[2] https://www.cnblogs.com/rebeyond/p/9686213.html
[3] https://mp.weixin.qq.com/s/JIjBjULjFnKDjEhzVAtxhw
[4] https://mp.weixin.qq.com/s/ulINOH4BnwfR7MBc6r5YHQ
[5] https://mp.weixin.qq.com/s/sV_mUnI6GshehMiLgCSn7Q
[6] https://mp.weixin.qq.com/s/YVwqD6SwUq_jkEe_9afBCg
[7] https://mp.weixin.qq.com/s/gmKSmW5SIME8lWKj8bvhWw