修改jar 注入_基于Java Agent实现字节码注入

目录

  1. 探针Java Agent原理概述与示例

  2. 基于Java Agent实现动态修改代码

  3. 基于Java Agent实现字节码注入

  4. 基于Java Agent实现内存Webshell注入

  5. 基于Java Agent实现内存Webshell检测

程序目标

  • 注入自定义Java代码,实现JVM内存和GC监控(搜了下,其实很多APM都会使用字节码注入的方式)

项目代码

使用IDEA新建一个maven项目,项目结构如下:

main程序和agent程序,可以分开成两个工程,这里为了简便就放在一个工程下。

f6928c363357eb740994eb8fe68daaa7.png

main.java

其中main.java是需要被动态修改的源程序,代码如下:

package main;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;public class Main {    public static void main(String[] args) throws InterruptedException {        System.out.println("=====main=====");        while (true) {            Listlist = new ArrayList();            list.add("xxxxx");            list.add("xxxxx");            list.add("xxxxx");            list.add("xxxxx");            list.add("xxxxx");            Thread.sleep(2000);            System.out.println("main running: " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));        }    }}

pom-main.xml

我们使用maven对main.java进行打包,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>    <groupId>org.lynngroupId>    <artifactId>JavaAgent_DynamicChangeartifactId>    <version>1.0-SNAPSHOTversion>    <properties>                <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>                <maven.compiler.source>1.8maven.compiler.source>                <maven.compiler.target>1.8maven.compiler.target>                <maven.compiler.compilerVersion>1.8maven.compiler.compilerVersion>    properties>        <build>        <finalName>mainfinalName>        <plugins>            <plugin>                <groupId>org.apache.maven.pluginsgroupId>                <artifactId>maven-compiler-pluginartifactId>                <version>3.8.1version>                <configuration>                    <source>${maven.compiler.source}source>                    <target>${maven.compiler.target}target>                configuration>            plugin>            <plugin>                <groupId>org.apache.maven.pluginsgroupId>                <artifactId>maven-jar-pluginartifactId>                <version>3.2.0version>                                <configuration>                                        <archive>                                                                        <addMavenDescriptor>falseaddMavenDescriptor>                                                <manifest>                                                        <mainClass>main.MainmainClass>                                                                                                                                        manifest>                    archive>                                        <excludes>                                                <exclude>**/agent/exclude>                    excludes>                configuration>            plugin>        plugins>    build>project>

JVMInfo.java

下面编写获取JVM信息程序,代码如下:

package agent;import java.lang.management.GarbageCollectorMXBean;import java.lang.management.ManagementFactory;import java.lang.management.MemoryMXBean;import java.lang.management.MemoryUsage;import java.util.Arrays;import java.util.List;class JVMInfo {    private static final long MB = 1048576L;    public static void getMemoryInfo() {        MemoryMXBean memory = ManagementFactory.getMemoryMXBean();        MemoryUsage headMemory = memory.getHeapMemoryUsage();        String info = String.format("init: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s",                headMemory.getInit() / MB + "MB",                headMemory.getMax() / MB + "MB", headMemory.getUsed() / MB + "MB",                headMemory.getCommitted() / MB + "MB",                headMemory.getUsed() * 100 / headMemory.getCommitted() + "%"        );        System.out.println("==========================Head Info=========================");        System.out.println(info);        System.out.println("============================================================");        System.out.println();        MemoryUsage nonheadMemory = memory.getNonHeapMemoryUsage();        info = String.format("init: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s",                nonheadMemory.getInit() / MB + "MB",                nonheadMemory.getMax() / MB + "MB", nonheadMemory.getUsed() / MB + "MB",                nonheadMemory.getCommitted() / MB + "MB",                nonheadMemory.getUsed() * 100 / nonheadMemory.getCommitted() + "%"        );        System.out.println("==========================nonHead Info======================");        System.out.println(info);        System.out.println("============================================================");        System.out.println();    }    public static void getGCInfo() {        List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();        for (GarbageCollectorMXBean garbage : garbages) {            String info = String.format("name: %s\t count:%s\t took:%s\t pool name:%s",                    garbage.getName(),                    garbage.getCollectionCount(),                    garbage.getCollectionTime(),                    Arrays.deepToString(garbage.getMemoryPoolNames()));            System.out.println("==========================Garbage Info==========================");            System.out.println(info);            System.out.println("================================================================");            System.out.println();        }    }}

agent.java

下面编写我们的Java Agent程序,我们使用一个ScheduleExecutor来定时获取JVM的内存和GC信息,代码如下:

package agent;import java.lang.instrument.Instrumentation;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class Agent {    public static void premain(String args, Instrumentation instrumentation) {        System.out.println("======agent premain=====");        // 创建并执行并结束一个runnable在延迟指定initialDelay时间        // 然后,每隔initialDelay+period*n时间执行一次        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {            JVMInfo.getMemoryInfo();            JVMInfo.getGCInfo();        }, 0, 5, TimeUnit.SECONDS);    }}

pom-agent.xml

使用maven对agent.java进行打包,使用maven-shade-plugin来将其打包成一个jar文件,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>    <groupId>org.lynngroupId>    <artifactId>JavaAgent_DynamicChangeartifactId>    <version>1.0-SNAPSHOTversion>    <properties>                <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>                <maven.compiler.source>1.8maven.compiler.source>                <maven.compiler.target>1.8maven.compiler.target>                <maven.compiler.compilerVersion>1.8maven.compiler.compilerVersion>        <premain.class>agent.Agentpremain.class>        <can.redefine.classes>truecan.redefine.classes>        <can.retransform.classes>truecan.retransform.classes>    properties>        <build>        <finalName>agentfinalName>        <plugins>                        <plugin>                <groupId>org.apache.maven.pluginsgroupId>                <artifactId>maven-shade-pluginartifactId>                <version>3.2.4version>                <executions>                    <execution>                        <phase>packagephase>                        <goals>                            <goal>shadegoal>                        goals>                        <configuration>                            <createSourcesJar>falsecreateSourcesJar>                            <shadeSourcesContent>falseshadeSourcesContent>                            <shadedArtifactAttached>falseshadedArtifactAttached>                            <createDependencyReducedPom>falsecreateDependencyReducedPom>                            <transformers>                                <transformer                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">                                    <manifestEntries>                                        <Premain-Class>${premain.class}Premain-Class>                                        <Can-Redefine-Classes>${can.redefine.classes}Can-Redefine-Classes>                                        <Can-Retransform-Classes>${can.retransform.classes}Can-Retransform-Classes>                                    manifestEntries>                                transformer>                            transformers>                            <filters>                                <filter>                                    <artifact>net.bytebuddy:byte-buddyartifact>                                    <excludes>                                        <exclude>META-INF/versions/9/module-info.classexclude>                                    excludes>                                filter>                                <filter>                                    <artifact>*:*artifact>                                    <excludes>                                        <exclude>main/**exclude>                                        <exclude>**/maven/exclude>                                    excludes>                                filter>                            filters>                        configuration>                    execution>                executions>            plugin>        plugins>    build>project>

运行示例

运行我们的示例,可以看到执行了监控的代码,不定时的输出JVM信息。

main running: 2020-07-31 12:53:00main running: 2020-07-31 12:53:02==========================Head Info=========================init: 256MB      max: 3614MB     used: 10MB      committed: 245MB        use rate: 4%======================================================================================nonHead Info======================init: 2MB        max: 0MB        used: 7MB       committed: 8MB  use rate: 92%======================================================================================Garbage Info==========================name: PS Scavenge        count:0         took:0  pool name:[PS Eden Space, PS Survivor Space]==========================================================================================Garbage Info==========================name: PS MarkSweep       count:0         took:0  pool name:[PS Eden Space, PS Survivor Space, PS Old Gen]================================================================main running: 2020-07-31 12:53:04
下一节,我们开始探讨下针对SpringBoot的内存马注入。
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值