千家信息网

怎样浅谈RASP技术的环境配置与代码实现

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章将为大家详细讲解有关怎样浅谈RASP技术的环境配置与代码实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。初始化项目首先我们在IDEA中新建一
千家信息网最后更新 2026年11月01日怎样浅谈RASP技术的环境配置与代码实现

这篇文章将为大家详细讲解有关怎样浅谈RASP技术的环境配置与代码实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

初始化项目

首先我们在IDEA中新建一个maven项目

取名为JavawebAgent

然后当前的目录结构如下:

删除src目录,然后右键新建Module

依然选择Maven项目

然后在ArtifactId处填入agent

然后确定即可

然后再次重复一遍上面的新建Module的操作,将第二小步中的ArtifactId改为test,第三小步中的Module Name 改为test-struts2,如下图所示

这时候的目录结构如下

其中agent目录为我们要实现agent的主要代码区域,test-struts2为测试web代码区域。(注:test-struts2不是必选的)

test-struts2模块基础配置

test-struts2部分的代码这边就不进行复述了,大家可以去本项目的地址中直接下载test-struts2内容。

agent模块基本配置

≡≡ pom.xml包配置

agent这个pom包配置的话有坑,这个以后在说,先看pom.xml内容吧。

                    org.ow2.asm            asm-all            5.1                        agent                                    org.apache.maven.plugins                maven-compiler-plugin                                    1.6                    1.6                                                        org.apache.maven.plugins                maven-jar-plugin                2.3.2                                                            src/main/resources/MANIFEST.MF                                                                            org.apache.maven.plugins                maven-shade-plugin                2.3                                                            package                                                    shade                                                                                                                                                commons-io:commons-io:jar:*                                    org.ow2.asm:asm-all:jar:*                                                                                                                                                                org.apache.maven.plugins                maven-surefire-plugin                2.21.0                                    true                                        

将上述内容复制到agent模块下的pom.xml中

≡≡ 创建MAINFEST.NF文件

在resources目录下创建MAINFEST.NF文件,文件内容如下

Manifest-Version: 1.0Can-Retransform-Classes: trueCan-Redefine-Classes: trueCan-Set-Native-Method-Prefix: true

≡≡ maven自动打包配置

在idea中右上部分找到Add Configurations , 然后点击此按钮

在弹出的窗口中点左上角的+,选择maven

然后点下图①的位置选择工作目录,在②的位置选择agent,在③的位置填入clean install

完成以后如下图所示,然后点击OK保存即可

这时候右上角已经可以看到我们刚刚配置的maven自动打包功能了,agent每改一处都需要重新build,不然无法生效。

≡≡ 创建Agent主要实现代码包

在agent包下面的java文件夹下右键选择新建package,然后填入你的包名,我这边的包名为

cn.org.javaweb.agent

简易版RASP实现

创建入口类

在cn.org.javaweb.agent包下新建一个类。

内容如下:

/* * Copyright sky 2019-04-03 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.agent;import java.lang.instrument.Instrumentation;/** * @author sky */public class Agent {    public static void premain(String agentArgs, Instrumentation inst) {        inst.addTransformer(new AgentTransform());    }}

创建Transform

然后我们再新建一个AgentTransform类,该类需要实现ClassFileTransformer的方法,内容如下:

/* * Copyright sky 2019-04-03 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.agent;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.security.ProtectionDomain;/** * @author sky */public class AgentTransform implements ClassFileTransformer {    /**     * @param loader     * @param className     * @param classBeingRedefined     * @param protectionDomain     * @param classfileBuffer     * @return     * @throws IllegalClassFormatException     */    @Override    public byte[] transform(ClassLoader loader, String className,                            Class classBeingRedefined, ProtectionDomain protectionDomain,                            byte[] classfileBuffer) throws IllegalClassFormatException {        className = className.replace("/", ".");        System.out.println("Load class:" + className);        return classfileBuffer;    }}

build Agent配置

点击右上角的agent[clean,intall]进行build。

由上图可见我们的包的位置为

/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar

将改包的位置记录下来,然后点开tomcat配置(这边没有对idea如何配置tomcat进行讲解,不会的可以自行百度|谷歌)

在VM options处填写以下内容:

-Dfile.encoding=UTF-8-noverify-Xbootclasspath/p:/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar-javaagent:/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar

其中/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar的路径为你在上一步编译出来的agent的路径,注意替换。

这时候我们在启动tomcat,就可以看到我们在AgentTransform中写的打印包名已经生效了,如下图:

上图红框区域为tomcat启动的时候加载的所有类名。然后我们打开浏览器查看web是否正常。

可以看到web也正常启动了。

创建ClassVisitor类

然后我们新建一个TestClassVisitor类,需要继承ClassVisitor类并且实现Opcodes类,代码如下

/* * Copyright sky 2019-04-03 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.agent;import org.objectweb.asm.ClassVisitor;import org.objectweb.asm.MethodVisitor;import org.objectweb.asm.Opcodes;/** * @author sky */public class TestClassVisitor extends ClassVisitor implements Opcodes {    public TestClassVisitor(ClassVisitor cv) {        super(Opcodes.ASM5, cv);    }    @Override    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);        System.out.println(name + "方法的描述符是:" + desc);        return mv;    }}

对ProcessBuilder(命令执行)类进行hook用户执行的命令

≡≡ 使用transform对类名进行过滤

然后回到AgentTransform中,对transform方法的内容进行修改,transform方法代码如下:

public byte[] transform(ClassLoader loader, String className,                            Class classBeingRedefined, ProtectionDomain protectionDomain,                            byte[] classfileBuffer) throws IllegalClassFormatException {        className = className.replace("/", ".");        try {            if (className.contains("ProcessBuilder")) {                System.out.println("Load class: " + className);                ClassReader  classReader  = new ClassReader(classfileBuffer);                ClassWriter  classWriter  = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);                ClassVisitor classVisitor = new TestClassVisitor(classWriter);                classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);                classfileBuffer = classWriter.toByteArray();            }        } catch (Exception e) {            e.printStackTrace();        }        return classfileBuffer;    }

简单介绍一下代码块内容

首先判断类名是否包含ProcessBuilder,如果包含则使用ClassReader对字节码进行读取,然后新建一个ClassWriter进行对ClassReader读取的字节码进行拼接,然后在新建一个我们自定义的ClassVisitor对类的触发事件进行hook,在然后调用classReader的accept方法,最后给classfileBuffer重新赋值修改后的字节码。

可能看起来比较绕,但是如果学会使用以后就比较好理解了。

≡≡ 创建测试环境

我们在tomcat中新建一个jsp,用来调用命令执行,代码如下:

<%@ page import="java.io.InputStream" %><%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%    Process process = Runtime.getRuntime().exec(request.getParameter("cmd"));    InputStream in = process.getInputStream();    int a = 0;    byte[] b = new byte[1024];    while ((a = in.read(b)) != -1) {        out.println(new String(b, 0, a));    }    in.close();%>

可以看到就是一个简单的执行命令的代码;下面我们对就此更改过的内容进行build,看一下会输出点什么。

biuld完成,启动tomcat。

访问

http://localhost:8080/cmd.jsp?cmd=whoami

可以看到已经成功执行命令,我们回到idea里面的控制台看一下输出了什么。

通过上图可以完整的看到一个执行命令所调用的所有调用链。

Load class: java.lang.ProcessBuilder方法的描述符是:(Ljava/util/List;)V方法的描述符是:([Ljava/lang/String;)Vcommand方法的描述符是:(Ljava/util/List;)Ljava/lang/ProcessBuilder;command方法的描述符是:([Ljava/lang/String;)Ljava/lang/ProcessBuilder;command方法的描述符是:()Ljava/util/List;environment方法的描述符是:()Ljava/util/Map;environment方法的描述符是:([Ljava/lang/String;)Ljava/lang/ProcessBuilder;directory方法的描述符是:()Ljava/io/File;directory方法的描述符是:(Ljava/io/File;)Ljava/lang/ProcessBuilder;redirects方法的描述符是:()[Ljava/lang/ProcessBuilder$Redirect;redirectInput方法的描述符是:(Ljava/lang/ProcessBuilder$Redirect;)Ljava/lang/ProcessBuilder;redirectOutput方法的描述符是:(Ljava/lang/ProcessBuilder$Redirect;)Ljava/lang/ProcessBuilder;redirectError方法的描述符是:(Ljava/lang/ProcessBuilder$Redirect;)Ljava/lang/ProcessBuilder;redirectInput方法的描述符是:(Ljava/io/File;)Ljava/lang/ProcessBuilder;redirectOutput方法的描述符是:(Ljava/io/File;)Ljava/lang/ProcessBuilder;redirectError方法的描述符是:(Ljava/io/File;)Ljava/lang/ProcessBuilder;redirectInput方法的描述符是:()Ljava/lang/ProcessBuilder$Redirect;redirectOutput方法的描述符是:()Ljava/lang/ProcessBuilder$Redirect;redirectError方法的描述符是:()Ljava/lang/ProcessBuilder$Redirect;inheritIO方法的描述符是:()Ljava/lang/ProcessBuilder;redirectErrorStream方法的描述符是:()ZredirectErrorStream方法的描述符是:(Z)Ljava/lang/ProcessBuilder;start方法的描述符是:()Ljava/lang/Process;方法的描述符是:()VLoad class: java.lang.ProcessBuilder$NullInputStream方法的描述符是:()Vread方法的描述符是:()Iavailable方法的描述符是:()I方法的描述符是:()VLoad class: java.lang.ProcessBuilder$NullOutputStream方法的描述符是:()Vwrite方法的描述符是:(I)V方法的描述符是:()V

≡≡ 拿到用户所执行的命令

接下来我们看看尝试一下能否拿到所执行的命令

新建一个名为ProcessBuilderHook的类,然后在类中新建一个名字为start的静态方法,完整代码如下:

/* * Copyright sky 2019-04-04 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.agent;import java.util.Arrays;import java.util.List;/** * @author sky */public class ProcessBuilderHook {    public static void start(List commands) {        String[] commandArr = commands.toArray(new String[commands.size()]);        System.out.println(Arrays.toString(commandArr));    }}

这个方法干啥用的我们一会在说,先看下面。

≡≡ 复写visitMethod方法

打开TestClassVisitor,对visitMethod方法进行更改。具体代码如下:

@Override    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);        if ("start".equals(name) && "()Ljava/lang/Process;".equals(desc)) {            System.out.println(name + "方法的描述符是:" + desc);            return new AdviceAdapter(Opcodes.ASM5, mv, access, name, desc) {                @Override                public void visitCode() {                    mv.visitVarInsn(ALOAD, 0);                    mv.visitFieldInsn(GETFIELD, "java/lang/ProcessBuilder", "command", "Ljava/util/List;");                    mv.visitMethodInsn(INVOKESTATIC, "cn/org/javaweb/agent/ProcessBuilderHook", "start", "(Ljava/util/List;)V", false);                    super.visitCode();                }            };        }        return mv;    }

给大家解释下新增加的代码,从if判断开始

判断传入进来的方法名是否为start以及方法描述符是否为()Ljava/lang/Process;,如果是的话就新建一个AdviceAdapter方法,并且复写visitCode方法,对其字节码进行修改,

mv.visitVarInsn(ALOAD, 0);

拿到栈顶上的this

mv.visitFieldInsn(GETFIELD, "java/lang/ProcessBuilder", "command", "Ljava/util/List;");

拿到this里面的command

mv.visitMethodInsn(INVOKESTATIC, "cn/org/javaweb/agent/ProcessBuilderHook", "start", "(Ljava/util/List;)V", false);

然后调用我们上面新建的ProcessBuilderHook类中的start方法,将上面拿到的this.command压入我们方法。

ProcessBuilderHook类的作用就是让这部分进行调用,然后转移就可以转入到我们的逻辑代码了。

我们再次编译一下,然后启动tomcat,访问cmd.jsp看看.

≡≡ 测试hook用户执行的命令参数是否拿到

访问

http://localhost:8080/cmd.jsp?cmd=ls%20-la

可以看到已经将当前目录下的内容打印了出来。

我们到idea中看看控制台输出了什么。

可以看到我们输入的命令

[whoami]

已经输出出来了,到此为止,我们拿到了要执行的命令.

关于怎样浅谈RASP技术的环境配置与代码实现就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

方法 代码 内容 配置 命令 目录 位置 选择 字节 文件 输出 环境 上图 区域 模块 用户 类名 项目 中新 测试 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 天津市摩尔互联网科技 高科技互联网 科技和互联网公司 科技类互联网 善班互联网科技 广州宏创互联网科技 互联网科技视频素材 上海亿帐通互联网科技 联恩商钥互联网科技有限公司 南平创想时代互联网科技有限公司 乌苏新华互联网科技做什么的 科技大学互联网 特约风豹互联网科技为什么扣费 烟台灵鸽互联网科技有限公司 上海钢联属于互联网科技股吗 广州梦谷互联网科技有限公司领导 广西泛欧互联网科技有限公司 上海互联网科技园景观 知域互联网科技有限公司官网 广州全民伙伴互联网科技有限公司 美国互联网科技 杭州互联网科技公司 互联网科技实习生岗位职责 链环科技传统企业怎么转型互联网 互联网风格科技公司名称 西安有哪些互联网高科技企业 全球科技与互联网公司市值变化 众联互联网络科技 保山浩联互联网科技有限公司 互联网领先科技成果宣传视频
0