摘要
我对RASP技术充满热情,大学毕业设计做了Python的RASP,现在又开始了Java的探索。OpenR… 让我感到无限可能。
正文
- 0 从零开始的Java RASP完成(一)
- 1 javaagent
- 1.1 Main方式 运行前
- 定义详细介绍:
- 怎么使用
- 建立agent
- 建立main
- 1.2 JVM运行后
- attach体制
- 运行一个长期运作的jvm
- 装包一个agentmain代理商jar
- 应用attach
- 1.1 Main方式 运行前
- 参照
0 从零开始的Java RASP完成(一)
大学本科毕业设计做了Python的RASP以后,对此项技术性很有兴趣爱好,那时候OpenRASP逐渐发生,而且Java的完成十分贴近真真正正的运作时防御力的定义。一直没有时间和充足的驱动力学习培训Java,近期一口气学了许多Java有关的物品,提前准备从反序列化和RASP2个方位再次深层次学一下Java。这里手记关键也是纪录全部学习过程,总体目标是模仿OpenRASP的java完成,进行一个Java的RASP。
1 javaagent
1.1 Main方式 运行前
定义详细介绍:
javaagent是java指令给予的一个主要参数,这一主要参数能够特定一个jar包,在真真正正的程序流程沒有运作以前先运作特定的jar包。而且对jar包有两个规定:
- jar包的MANIFEST.MF文档务必特定Premain-Class
- Premain-Class特定的类务必完成premain()方式 。
这一premain方式 会在javacmd特定的main函数以前运作。
在java指令主要参数种,还能够见到其他主要参数,比如
-agentlib:<libname>[=<选择项>]
载入该设备代理商库 <libname>, 比如 -agentlib:hprof
另客户程序 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选择项>]
按详细路径名载入该设备代理商库
-javaagent:<jarpath>[=<选择项>]
载入 Java 计算机语言代理商, 客户程序 java.lang.instrument
javaagent能够特定许多个,jvm会先后实行不一样的jar。前边提及的premain方式 有二种界定方法
public static void premain(String agentArgs, Instrumentation inst)
public static void premain(String agentArgs)
依据sun.instrument.InstrumentationImpl 的源码,能够了解,会优先选择启用第一种书写。这类方式 能够在JDK1.5及以后的版本号应用
怎么使用
应用javaagent必须好多个流程:
- 界定一个MANIFEST.MF文档,务必包括Premain-Class选择项,也必须添加Can-Redefine-Classes和Can-Retransform-Classes选择项,后边2个选择项看名称就了解含意
- 建立Premain-Class特定的类,类中包括premain方式 ,该方式 能够进一步载入RASP完成基本原理
- 将MANIFEST.MF和写好的各种各样类装包成jar
- 运行java时,加上-javaagent:xx.jar,就可以让java先全自动实行写好的premain方式
在premain方式 实行时,获得的Instrumentation目标还会继续载入绝大多数类,包含后边main方式 实行时必须载入的各种各样类,可是抓不上系统软件类。换句话说,在这个部位在main方式 实行前,就可以阻拦或是调用类,融合ASM、javassist、cglib方法就可以完成对类的改变或是插桩。
建立agent
如今来完成一下,文件目录构造以下
-java-agent
----src
----|----main
----|----------java
----|--------------com
----|-------------------bitterz
----|----------------------PreMain
----|pom.xml
pom.xml应用idea建立maven新项目内置的pom.xml就可以,随后添加以下配备
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Premain-Class>com.bitterz.PreMain</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
改动里边的premain就可以,那样配备以后,立即应用idea的maven->package就可以装包成一个能够应用的agent.jar。
com.bitterz.PreMain以下:
package com.bitterz;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class PreMain {
public static void premain(String agentArgs, Instrumentation inst){
System.out.println("agentArgs:" agentArgs);
inst.addTransformer(new DefineTransformer(), true);
}
static class DefineTransformer implements ClassFileTransformer{
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println("premain load Class: " className); // 留意这儿的輸出
return classfileBuffer;
}
}
}
建立main
随后再建立一个要实行的main
package com.bitterz;
public class Main {
public static void main(String[] args) {
System.out.println("Main.main() in test project");
}
}
一样改动pom.xml配备,只必须再<manifestEntries>
标识下加上一个<Main-Class>
就可以用idea的maven装包成一个jar,而且特定了main类。
2个新项目用maven装包后,在cmd实行一下
能够见到premain先輸出了载入的各种各样类,包含com.bitterz.Main,随后才算是真真正正的main实行,最终完毕时,premain还载入了一些完毕时必须的类。到此,在运行main方式 前,完成对事后类的载入或进一步改动实际操作,早已拥有原型
1.2 JVM运行后
前边的方式 必须在main函数运行前,实行agent,但有一些情况下,jvm早已运行了,并且服务项目不可以随便中止,但这个时候或是想对jvm中的类做一些改动应当怎么办呢?
attach体制
这就需要引进attch体制了,jdk1.6以后在Instrumentation中加上了一种agentmain的代理商方式 ,能够在main函数实行以后再运行。和premain函数一样,开发人员能够撰写一个包括agentmain函数的Java类,它也是有二种书写:
public static void agentmain (String agentArgs, Instrumentation inst)
public static void agentmain (String agentArgs)
一样的,含有Instrumentation的方式 会被优先选择启用,开发人员务必再MANIFEST.MF文档中设定Agent-Class
来特定包括agentmain函数的类。
这类attach体制的实际完成在com.sun.tools.attach
中,有以下2个类:
-
VirtualMachine
字面上实际意义表明一个Java vm虚拟机,也就是程序流程必须监管的总体目标vm虚拟机,给予了获得系统信息(例如获得运行内存dump、进程dump,类信息内容统计分析(例如已载入的类及其案例数量等), loadAgent,Attach 和 Detach (Attach 姿势的反过来个人行为,从 JVM 上边消除一个代理商)等方式 ,能够完成的作用可以说十分之强劲 。此类容许大家根据给attach方式 传到一个jvm的pid(过程id),远程桌面连接到jvm上代理商类引入实际操作仅仅它诸多作用中的一个,根据
loadAgent
方式 向jvm申请注册一个代理商程序流程agent,在该agent的代理商程序流程中会获得一个Instrumentation案例,该案例能够 在class载入前更改class的字节码,还可以在class载入后重新加载。在启用Instrumentation案例的方式 时,这种方式 会应用ClassFileTransformer插口中给予的方式 开展解决。 -
VirtualMachineDescriptor
则是一个叙述vm虚拟机的容器类,相互配合 VirtualMachine 类进行各种各样作用
实际完成全过程:根据VirtualMachine类的attach(pid)
方式 ,便能够attach到一个运作中的java过程上,以后便能够根据loadAgent(agentJarPath)
来将agent的jar包引入到相匹配的过程,随后相匹配的过程会启用agentmain方式 。
从jdk网站根目录的lib/tools.jar源代码一路追踪了一下VirtualMachine.attach方式 ,发觉传到一个pid以后,在Windows下能根据WindowsVirtualMachine
这一类的构造方法,启用native方式 ,完成对jvm过程的attach
运行一个长期运作的jvm
最底层方式 还得靠c/c 来完成(搞笑),掌握这一体制以后,返回前边的agentmain的完成步骤。最先运行一个一直运作的jvm
package com.bitterz;
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("Main.main() in test project start!!");
Thread.sleep(300000000);
System.out.println("Main.main() in test project end!!");
}
}
装包一个agentmain代理商jar
运行以后,把再写一个agentmain,而且还需要写好MANIFEST.MF文档配备,编码和pom.xml以下:
package com.bitterz;
import java.lang.instrument.Instrumentation;
public class AgentMain {
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
System.out.println("agentmain start!");
System.out.println(instrumentation.toString());
}
}
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Agent-Class>com.bitterz.AgentMain</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
应用maven package装包成一个jar文件就可以
应用attach
再开运行另一个java程序流程,应用过程号attach到前边一直运作的jvm,并应用loadAgent给这一jvm加上代理商jar:
package com.bitterz.attach;
import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import java.io.IOException;
public class AttachTest {
public static void main(String[] args) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
VirtualMachine attach = VirtualMachine.attach("12244"); // cmd寻找这一jvm的过程号
attach.loadAgent("C:\\Users\\helloworld\\Desktop\\java learn\\java-attach\\target\\java-attach-1.0-SNAPSHOT.jar");
attach.detach();
}
}
运作这一java文件,会见到前边一直sleep运作的jvm会輸出agentmain里边给出的輸出!
这儿也就表明,根据attach体制,我们可以对特定运作中的jvm加上agent,而在premain方式 中获得到Instrumentation目标,根据对Instrumentation目标加上transformer类,能够完成类变换(Class Transform),也就是在transform涵数中融合改动字节码的方式 (ASM、Javassist、cglib等)能够进一步完成RASP!
事后的文章内容可能写一写怎样完成这种对特定类方法的Hook,及其怎样运作时对最底层涵数的主要参数开展过虑。
参照
https://www.cnblogs.com/rickiyang/p/11368932.html
https://www.cnblogs.com/kendoziyu/p/maven-auto-build-javaagent-jar.html
Java最底层安全防护 – OpenRASP关键源代码浅谈
创作者:bitterz
假如您感觉这篇博闻对您有一定的获得,请点一下右下方的 [强烈推荐],感谢!
关注不迷路
扫码下方二维码,关注宇凡盒子公众号,免费获取最新技术内幕!
评论0