Java Agent到内存马(二)
原文请关注公众号:
https://mp.weixin.qq.com/s/DwgKs1jM7g-VwNoECZg1jQ
前言
接着上一篇继续分析内存马实现原理。
Instrumentation
Instrumentation
是JVMTIAgent
(JVM Tool Interface Agent)的一部分。Java agent通过这个类和目标JVM进行交互,从而达到修改数据的效果。
以下是这个类的一些方法:
也可以参考官方文档:https://docs.oracle.com/javase/9/docs/api/java/lang/instrument/package-summary.html
接下来测试一下getAllLoadedClasses
和isModifiableClasses
两个类:
getAllLoadedClasses
:获取所有已经加载的类。isModifiableClasses
:判断某个类是否能被修改。
修改AgentMain:
重新attach之后,看到/tmp/classesInfo输出哪些类被加载,哪些类能被修改:
然后我们可以通过addTransformer()
和retransformClasses()
来篡改Class的字节码:
addTransformer
这个方法中的ClassFileTransformer参数可以完成字节码修改工作。
ClassFileTransformer是一个接口,并且提供了transformer方法。
使用addTransformer
方法可以注册一个我们自定义的Transformer到Java Agent,当有新的类被JVM加载时JVM会自动回调用我们自定义的Transformer类的transform方法,传入该类的transform信息(类名、类加载器、类字节码等),我们可以根据传入的类信息决定是否需要修改类字节码,修改完字节码后我们将新的类字节码返回JVM,JVM会验证类和相应的修改是否合法,如果符合类加载要求JVM会加载我们修改后的类字节码。
Javassist
简介
Javassist (JAVA programming ASSISTant) 是在 Java 中编辑字节码的类库;它使 Java 程序能够在运行时定义一个新类, 并在 JVM 加载时修改类文件。
我们常用到的动态特性主要是反射,在运行时查找对象属性、方法,修改作用域,通过方法名称调用方法等。在线的应用不会频繁使用反射,因为反射的性能开销较大。其实还有一种和反射一样强大的特性,但是开销却很低,它就是Javassit。
与其他类似的字节码编辑器不同, Javassist 提供了两个级别的 API: 源级别和字节码级别。 如果用户使用源级 API, 他们可以编辑类文件, 而不知道 Java 字节码的规格。 整个 API 只用 Java 语言的词汇来设计。 您甚至可以以源文本的形式指定插入的字节码; Javassist 在运行中编译它。 另一方面, 字节码级 API 允许用户直接编辑类文件作为其他编辑器。
ClassPool
ClassPool
是CtClass
对象的容器。CtClass
对象必须从该对象获得。如果get()
在此对象上调用,则它将搜索表示的各种源ClassPath
以查找类文件,然后创建一个CtClass
表示该类文件的对象。创建的对象将返回给调用者。
ClassPool是一个存放CtClass对象的容器。
获得方法: ClassPool cp = ClassPool.getDefault();
。通过 ClassPool.getDefault()
获取的 ClassPool
使用 JVM 的类搜索路径。如果程序运行在 JBoss 或者 Tomcat 等 Web 服务器上,ClassPool 可能无法找到用户的类,因为 Web 服务器使用多个类加载器作为系统类加载器。在这种情况下,ClassPool 必须添加额外的类搜索路径。
CtClass
可以把它理解成加强版的Class
对象,需要从ClassPool
中获得。
获得方法:CtClass cc = cp.get(ClassName)
。
CtMethod
同理,可以理解成加强版的Method
对象。
获得方法:CtMethod m = cc.getDeclaredMethod(MethodName)
。
这个类提供了一些方法,使我们可以便捷的修改方法体:
在输入之前使用的java agent
使用Javassist案例
这个例子参考木头师傅
编写 AgentMain.java
DefineTransformer.java
弹出计算器
创建 jar 文件清单 agentmain.mf
使用javac分别编译java文件后,打包成jar文件
(在另外一个demo中,用maven打包再测试不成功,可以采用上述方式)
此时jar包编写完成后,编写测试类:
运行后调用了agent.jar:
当然我们由于 tools.jar 并不会在 JVM 启动的时候默认加载,所以这里也可以利用 URLClassloader 来加载我们的 tools.jar
实现内存马注入
以springboot为例,首先要找到hook的方法,需满足:
- 该方法一定会被执行
- 不会影响正常的业务逻辑
之前学习java web时了解到filter肯定在servlet之前,所有ApplicationFilterChain#doFilter是肯定会被调用的,并且还封装了用户请求的 request 和 response,可以直接获取返回。
这边参考木头师傅案例,也搭建了一个反序列化漏洞环境,模拟在springboot环境下打入内存马
漏洞环境
搭建一个cc11反序列化环境:
Pom.xml
编译agent.jar
AgentMain.java
DefineTransformer.java
这里利用 insertBefore ,将其插入到前面,从而减少对原程序的功能破坏
可以使用mvn assembly:assembly命令打包,也可以直接在idea中package打包
反序列化打入内存马
通过反序列化加载字节码,并加载编译好的jar包:
此处是用的木头师傅修改后的yso:
https://github.com/KpLi0rn/ysoserial
打入成功
思考
- agent 内存马打入之前需要将agent.jar传到目标上
- 关于agent内存马查杀:https://mp.weixin.qq.com/s/Whta6akjaZamc3nOY1Tvxg
参考
https://xz.aliyun.com/t/9450#toc-3
http://wjlshare.com/archives/1582
__EOF__

本文链接:https://www.cnblogs.com/N0r4h/p/16780190.html
关于博主:一个废物到自闭的人
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析