Java agent技术的注入利用与避坑点

什么是Java agent技术?

Java代理(Java
agent)是一种Java技术,它允许开发人员在运行时以某种方式修改或增强Java应用程序的行为。Java代理通过在Java虚拟机(JVM)启动时以"代理"(agent)的形式加载到JVM中,以监视、修改或甚至完全改变目标应用程序的行为。

Java agent 可以做什么?

  1. 安全监控和审计:

    通过Java代理,可以在应用程序中注入代码以监视其行为并记录关键事件。这可以用于安全审计目的,以确保应用程序不受到恶意行为或违规操作的影响。

  2. 安全验证和授权:

    Java代理可以拦截对受保护资源的访问,并执行安全验证和授权操作。通过代理,可以实现访问控制策略,确保只有经过授权的用户或系统可以访问特定资源。

  3. 安全加固:

    通过Java代理,可以对应用程序进行安全加固,例如实时检测和防御攻击,包括代码注入、SQL注入、跨站点脚本攻击等。代理可以拦截请求,并根据安全策略进行处理,从而提高应用程序的安全性。

  4. 加密和解密:

    Java代理可以用于实现端到端的数据加密和解密,保护敏感数据在传输过程中的安全性。代理可以拦截数据流,对数据进行加密或解密操作,以确保数据在传输过程中不会被窃取或篡改。

  5. 安全日志记录:

    Java代理可以用于记录应用程序的安全日志,包括用户操作、异常事件、安全警报等。通过代理,可以将安全日志发送到中央日志服务器进行集中管理和分析,以便及时发现和应对安全威胁。

静态Agent使用

创建Maven项目,写一个类PreMainTraceAgent,使用Maven编译并打成jar包。

package com.example;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class PreMainTraceAgent {

public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("agentArgs : " + agentArgs);
inst.addTransformer(new DefineTransformer(), true);
}

static class DefineTransformer implements ClassFileTransformer {
static int counts=0;
@Override
public byte[] transform(
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer
) throws IllegalClassFormatException {
System.out.println("premain load Class:" + className);
System.out.println("filter "+(counts++)+" class");
return classfileBuffer;
}
}
}

打成jar包之后我们要注意META-INF目录下的MSNIFEST.MF文件,MANIFEST.MF
文件是 Java 归档文件(如 JAR
文件)的一部分,用于描述归档文件的元数据信息和配置。它通常位于归档文件的根目录下。

一些常见的属性我们需要了解

  1. Manifest-Version: 描述了 MANIFEST.MF 文件的版本。

  2. Created-By: 描述了创建该归档文件的工具名称和版本。

  3. Main-Class: 描述了可执行 JAR 文件的入口类(Main类),当您执行 JAR

    文件时,Java虚拟机会自动寻找并执行该类中的main方法。

  4. Class-Path: 描述了归档文件中包含的依赖项 JAR 文件的路径,以便 Java

    虚拟机在运行时能够找到并加载这些依赖项。

在构建和部署 Java 应用程序时,MANIFEST.MF
文件可以帮助指定各种元数据信息,使得应用程序可以更好地被管理和执行。例如,当您创建一个可执行的
JAR 文件时,通过指定 Main-Class 属性,可以告诉 Java 虚拟机该 JAR
文件的入口点是哪个类。

另外创建一个项目,写一个主函数,内容随意,配置虚拟机选项。这里-javaagent:后面跟上上面项目jar包的绝对路径

运行结果如图:

可以看到premain方法中的代码成功的执行在了Main函数之前。这种使用premain方法在Main函数前执行的也被成为静态agent

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

动态Agent使用

首先是被代理部分(单独的项目)

package com.example;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class AgentMain {
public static void agentmain(String agentArgs, Instrumentation
instrumentation) {
instrumentation.addTransformer(new MyTransformer(),true);

}
public static class MyTransformer implements ClassFileTransformer {
static int count = 0;

@Override
public byte[] transform(
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println("hello world");//这里就是我们能看到的输出。
return classfileBuffer;
}
}
}

接下来就是使用Maven打成jar包

默认情况下META-INFMANIFEST.MF文件中有这些内容

Manifest-Version: 1.0

Created-By: Maven JAR Plugin 3.3.0

Build-Jdk-Spec: 11

但是这些是不够的,我们需要指出被代理的类。

Manifest-Version: 1.0

Agent-Class: com.example.AgentMain

Can-Redefine-Classes: true

Can-Retransform-Classes: true

  1. Agent-Class:指定了代理的入口类。这个属性告诉 Java

    虚拟机代理应该从哪个类的 premainagentmain
    方法开始执行。premain 方法用于静态代理(在 JVM
    启动时加载),而 agentmain 方法用于动态代理(在 JVM
    运行时加载)。代理的入口类必须包含其中一个方法。

  2. Can-Redefine-Classes:指定了代理是否可以重新定义类。如果设置为

    true,代理将允许重新定义已经加载的类,这意味着你可以修改已经加载的类的字节码。这对于某些代理操作,如热代码替换,非常有用。

  3. Can-Retransform-Classes:指定了代理是否可以重新转换类。如果设置为

    true,代理将允许重新转换已经加载的类,这意味着你可以多次修改已经加载的类的字节码。这对于一些特定的代理操作也是非常有用的,如
    AOP(面向切面编程)。

因为是动态加载所以我们不需要在虚拟机启动选项中指定jar包的路径。

接下来写主程序的测试类

package org.example;

import com.sun.tools.attach.VirtualMachine;

import java.io.File;
import java.lang.management.ManagementFactory;

public class TestMain {
public static void main(String[] args) {
String agentJarPath =
"C:Users86186DesktopstudyJavauntitledtargetuntitled-1.0-SNAPSHOT.jar";
File agentJarFile = new File(agentJarPath);
if (!agentJarFile.exists()) {
System.err.println("Agent JAR file not found.");
return;
}
String name = ManagementFactory.getRuntimeMXBean().getName();
String pid = name.split("@")[0];

if (pid == null) {
System.err.println("Unable to find process ID.");
return;
}
String targetClassName = "AgentMain";
try {
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(agentJarPath,targetClassName);
vm.detach();
} catch (Exception e) {
e.printStackTrace();
}
}

}

这里在获取进程号的时候会因为版本的不同而出现错误,java9以下默认是正常的,java9以上会出现报错,我们需要在虚拟机启动参数中加上-Djdk.attach.allowAttachSelf=true。

运行结果:

为什么结果中有多个helloworld

这里有讲一下为什么我们在代码中之用了一次sout,但是在结果中却出现了多个helloworld。

MyTransformer类中的transform方法中的输出语句只会在类被加载时执行一次,但是它会对每个类文件调用一次。由于一个类可能会由多个ClassLoader加载,或者同一个ClassLoader可能会加载多次,因此会导致多次输出。

这种情况通常在Java应用程序中使用了多个ClassLoader时发生,例如Web应用程序中的热部署或者OSGi环境中。每次类被加载,transform方法都会被调用一次,因此会看到多次输出。

我们可以修改一下代码做测试,这里我在每个helloworld后添加了被加载类的名字

修改后的输出结果:

实战示例:修改目标虚拟机中执行的程序

第一步

首先我们写出我们正在执行的程序:循环打印helloworld。

package org.example;

import static java.lang.Thread.sleep;

public class Main {
public static void main(String[] args) throws InterruptedException {
while(true) {
hello();
sleep(1500);
}
}
public static void hello(){
System.out.println("Hello World!");
}
}

第二步

准备我们的agentmain和ClassFileTransformer实现类。

package com.example;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;

public class AgentMain {
public static void agentmain(String agentArgs, Instrumentation
instrumentation) throws UnmodifiableClassException {
Class [] classes = instrumentation.getAllLoadedClasses();

//获取目标JVM加载的全部类
for(Class cls : classes){

if (cls.getName().equals("org.example.Main")){

instrumentation.addTransformer(new HackTransform(),true);
instrumentation.retransformClasses(cls);
}
// System.out.println(cls.getName());
}

}

}

package com.example;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class HackTransform implements ClassFileTransformer {

@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if (className.equals("org/example/Main")) {
try {
System.out.println(className);

ClassPool classPool = ClassPool.getDefault();


if (classBeingRedefined != null) {
ClassClassPath ccp = new ClassClassPath(classBeingRedefined);
classPool.insertClassPath(ccp);
}

CtClass ctClass = classPool.get("org.example.Main");
System.out.println(ctClass);


CtMethod ctMethod = ctClass.getDeclaredMethod("hello");

//设置方法体
String body = "{System.out.println("[+]Hacker!");}";
ctMethod.setBody(body);
ctClass.defrost();

return ctClass.toBytecode();

} catch (Exception e) {
e.printStackTrace();
}
}

return null;
}
}

第三步

把第二步中的两个类打成jar包。并修改其中MANIFEST.MF中的内容。

MANIFEST.MF中的内容

Manifest-Version: 1.0Agent-Class:
com.example.AgentMainCan-Redefine-Classes: trueCan-Retransform-Classes:
true

第四步

写我们的注入代码

package org.example;

import com.sun.tools.attach.*;

import java.io.IOException;
import java.util.List;

public class inject {

public static void main(String[] args) throws IOException,
AttachNotSupportedException, AgentLoadException,
AgentInitializationException {
//调用VirtualMachine.list()获取正在运行的JVM列表
List<VirtualMachineDescriptor> list = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : list) {
System.out.println(vmd.displayName());

if (vmd.displayName().equals("org.example.Main")) {

//连接指定JVM
VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());
String agentJarPath =
"C:Users86186DesktopstudyJavauntitledtargetuntitled-1.0-SNAPSHOT.jar";
//加载Agent
virtualMachine.loadAgent(agentJarPath,"com.example.AgentMain");
//断开JVM连接
virtualMachine.detach();
}

}

}
}

第五步

执行即可(先运行主java程序,后运行注入程序)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/435572.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis(十七)分布式锁

文章目录 面试题分布式锁锁的种类分布式锁需要具备的条件和刚需分布式锁 案例nginx分布式微服务部署&#xff0c;单机锁问题分布式锁注意事项lock/unlocklua脚本自研版的redis分布式锁搞定lua脚本 可重入锁可重入锁种类可重入锁hset实现&#xff0c;对比setnx&#xff08;重要&…

react高阶组件:如何同时兼容class类组件和函数式组件。

场景&#xff1a; 每个页面都要实现分享功能&#xff0c;但是页面有些是用class类&#xff0c;有些又直接是函数式。 方案1&#xff1a; 写2套方法。各自引用。&#xff08;维护不太好&#xff0c;改要改2遍&#xff09; 方案2&#xff1a; 可以封一个 jsx的组件&#xff0c…

NLP:spacy库安装与zh_core_web_sm配置

到公司来第一个项目竟然是偏文本信息抽取与结构化的&#xff0c;&#xff08;也太高看我了┭┮﹏┭┮&#xff09; 反正给机会了就上吧&#xff0c;我就一臭实习的&#xff0c;怕个啥。配置了两天的环境&#xff0c;也踩了不少坑&#xff0c;我把我的经历给大家分享一下&#…

HarmonyOS NEXT应用开发案例集

概述 随着应用代码的复杂度提升&#xff0c;为了使应用有更好的可维护性和可扩展性&#xff0c;良好的应用架构设计变得尤为重要。本篇文章将介绍一个应用通用架构的设计思路&#xff0c;以减少模块间的耦合、提升团队开发效率&#xff0c;为开发者呈现一个清晰且结构化的开发…

【Tauri】(4):整合Tauri和actix-web做本地大模型应用开发,可以实现session 登陆接口,完成页面展示,进入聊天界面

1&#xff0c;视频地址 https://www.bilibili.com/video/BV1GJ4m1Y7Aj/ 【Tauri】&#xff08;4&#xff09;&#xff1a;整合Tauri和actix-web做本地大模型应用开发&#xff0c;可以实现session 登陆接口&#xff0c;完成页面展示&#xff0c;进入聊天界面 使用国内代理进行加…

【HTML】HTML基础7.3(自定义列表)

目录 标签 效果 代码 注意 标签 <dl> <dt>自定义标题</dt><dd>内容1</dd><dd>内容2</dd><dd>内容3</dd> 。。。。。。 </dl> 效果 代码 <dl><dt>蜘蛛侠系列</dt><dd>蜘蛛侠1</dd…

PyCharm Community Edition 2023.3.3,UI界面设置成旧版

File->Settings->Appearance & Behavior->New UI->Enable new UI(取消勾选)->重启PyCharm 旧版UI: 新版UI&#xff1a;

基于决策树实现葡萄酒分类

基于决策树实现葡萄酒分类 将葡萄酒数据集拆分成训练集和测试集&#xff0c;搭建tree_1和tree_2两个决策树模型&#xff0c;tree_1使用信息增益作为特征选择指标&#xff0c;B树使用基尼指数作为特征选择指标&#xff0c;各自对训练集进行训练&#xff0c;然后分别对训练集和测…

【ETCD】简介安装常用操作---图文并茂详细讲解

目录 一 简介 1.1 etcd是什么 1.2. 特点 1.3. 使用场景 1.4 关键字 1.5 工作原理 二 安装 2.1 etcd安装前介绍 2.2 安装 2.3 启动 2.4 创建一个etcd服务 三 常用操作 一 简介 1.1 etcd是什么 etcd是CoreOS团队于2013年6月发起的开源项目&#xff0c;它的目标是构建…

git 如何将多个提交点合并为一个提交点 commit

文章目录 核心命令详细使用模式总结示例 核心命令 git merge branch2 是将分支branch2的提交点合并到本地当前分支。 而在执行这条命令的时候&#xff0c;加一个选项--squash就表示在合并的时候将多个提交点合并为一个提交点。 git merge --squash branch2 先看squash单词的意…

探索c++——了解c++的魅力

前言&#xff1a;c是一门既面向对象又面向过程的语言。 不同于java纯粹的面向对象和c纯粹的面向过程。 造成c该特性的原因是c是由本贾尼大佬在c的基础上增添语法创建出来的一门新的语言。 它既兼容了c&#xff0c; 身具面向过程的特性。 又有本身的面向对象的特性。 面向对象和…

SpringBoot集成ElasticSearch(ES)

ElasticSearch环境搭建 采用docker-compose搭建&#xff0c;具体配置如下&#xff1a; version: 3# 网桥es -> 方便相互通讯 networks:es:services:elasticsearch:image: registry.cn-hangzhou.aliyuncs.com/zhengqing/elasticsearch:7.14.1 # 原镜像elasticsearch:7.…

Unity 整体界面淡入淡出效果

在Unity中&#xff0c;如果我们要实现控制多个组件同时淡出&#xff0c;同时淡入的效果&#xff0c;可以使用DOTween插件实现。 如图&#xff0c;一个页面中带有背景&#xff0c;一张图片&#xff0c;一个文本&#xff0c;一个滑动条。 要实现以上界面的整体淡入淡出&#xff…

机器学习-启航

文章目录 原理分析机器学习的两种典型任务机器学习分类总结数据机器学习分类解读简单复杂 原理分析 马克思主义哲学-规律篇 规律客观存在&#xff0c;万事万物皆有规律。 机器学习则是多维角度拆解分析复杂事实数据&#xff0c;发现复杂事实背后的规律&#xff0c;然后将规律用…

C#,回文分割问题(Palindrome Partitioning Problem)算法与源代码

1 回文串 “回文串”是一个正读和反读都一样的字符串&#xff0c;初始化标志flagtrue&#xff0c;比如“level”或者“noon”等等就是回文串。 2 回文分割问题 给定一个字符串&#xff0c;如果该字符串的每个子字符串都是回文的&#xff0c;那么该字符串的分区就是回文分区。…

VS code下载与使用方法(包含远程调试)

Visual Studio Code(简称 VSCode)是由微软开发的一款免费、开源、跨平台的现代化轻量级代码编辑器。它具有丰富的功能和强大的扩展性,适用于多种编程语言和开发环境。以下是 VSCode 的一些主要特点和功能: 跨平台支持: 可在 Windows、macOS 和 Linux 等多种操作系…

基于ACM32 MCU的两轮车充电桩方案,打造高效安全的电池管理

随着城市化进程的加快、人们生活水平的提高和节能环保理念的普及&#xff0c;越来越多的人选择了电动车作为代步工具&#xff0c;而两轮电动车的出行半径较短&#xff0c;需要频繁充电&#xff0c;因此在城市中设置两轮车充电桩就非常有必要了。城市中的充电桩不仅能解决两轮车…

Flink:Temporal Table 的两种实现方式 Temporal Table DDL 和 Temporal Table Function

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

近地面无人机植被定量遥感与生理参数反演技术应用

李老师&#xff08;副教授&#xff09;&#xff0c;长期从事无人机近地面植被遥感&#xff0c;植被生理参数&#xff0c;多角度遥感&#xff0c;RGB/多光谱/高光谱数据处理&#xff0c;LiDAR点云处理等领域研究工作&#xff0c;具有资深的技术底蕴和专业背景。 专题一、近十年…

java 获取项目内的资源/配置文件

【getResourceAsStream】是java中用于获取项目内资源的常用方法&#xff0c;能够返回一个数据流&#xff0c;从而允许我们读取指定路径下的资源文件。这个方法可以用来读取各种类型的资源文件&#xff0c;包括但不限于文本文件、图像文件、配置文件等。 要使用getResourceAsStr…