OpenRasp Java运行时修改字节码技术

本文介绍了Java运行时如何使用javassist库动态修改字节码,包括插入代码到方法中,以及验证修改位置的正确性。通过实例展示了在`toString()`方法前后插入代码的过程,并探讨了获取和操作类、方法的步骤。
摘要由CSDN通过智能技术生成

Java运行时修改字节码技术

Java运行时动态修改字节码技术,常用的有javassist asm来实现。不过最近在分析openrasp-java这块时,程序使用的javassist来动态插桩关键类,达到监控某些程序的行为,OpenRasp使用这个技术来实现了监控程序的行为。为了分析OpenRasp和理解其使用的技术原理,先做一个java动态修改指令基础知识的补充。

第一个程序

有如下程序

package com.company;

import java.net.URL;
import  java.io.File;
import java.net.URLDecoder;
import java.util.Set;

public class Test1 {
   
    private String aa="heh";

    public Test1(){
   }

    @Override
    public String toString() {
   
        return "Test1{" +
                "aa='" + aa + '\'' +
                '}';
    }
}

正常情况下调用toString()方法,会得到如下

InsertCode:Test1{
   aa='heh'}

如果想要在toString()方法前插入某一个方法块,输出如下内容

方法调用前 ----->>aa
方法调用前 ----->>aaa 
方法调用后 ---->> bbbb
InsertCode:Test1{
   aa='heh'}

可以借用javassist工具类操作对应的字节码。

动态修改字节码–常用javassist类(这里是根据写的样例记录的,不是针对所有情况)

要想在动态修改程序行为,则需要使用javassist内的三个主要类

ClassPool --> 是CtClass的一个容器 要想获得一个类对象,必须
CtClass  -->和java的Class类似
CtMethod -->和java的Method类似
  • ClassPool --> 是CtClass的一个容器 要想获得一个类对象,必须通过这个对象获取
CtClass ctClzz =classPool.get("完整的类名,例如com.test.demn.A");
如果当前的classPool内没有这个类,则会报javassist.NotFoundException: com.company.Test1 后续会提到
#参考
http://javadox.com/org.javassist/javassist/3.18.1-GA/javassist/ClassPool.html
  • CtClass -->和java的Class类似代表了一个类对象,从ClassPool内获取到
参考
http://javadox.com/org.javassist/javassist/3.18.1-GA/javassist/CtClass.html
  • CtMethod -->和java的Method类似代表的一个方法对象,继承自CtBeHavior
参考
http://javadox.com/org.javassist/javassist/3.18.1-GA/javassist/CtMethod.html

在知道了这几个类之后,接着就是动手尝试修改com.company.Test1toString()方法。

插入代码到toString()方法

编写TestInsetOPs类

package com.company;

import javassist.*;
import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;

//测试插入程序
public class TestInsertOps {
   



    private static ClassPool insertCode() {
   

        try {
   

            //todo 两个方式回去ClassPool 1)ClassPool.getDefault(); 内部会自动调用appendSystemPath方法 2)可以直接new,不过要手动 appendSystemPath
            ClassPool pool = new ClassPool();// ClassPool.getDefault();
            pool.appendSystemPath();//如果添加到系统环境中内程序可以执行,否则会javassist.NotFoundException: com.company.Test1
            CtClass clazz = pool.get("com.company.Test1");
            CtMethod method = clazz.getDeclaredMethod("toString");
            method.insertBefore("{ System.out.println(\"方法调用前 ----->>aaa \"); }");
            method.insertAfter("{ System.out.println(\"方法调用后 ---->> bbbb\"); }");

            return pool;
        } catch (NotFoundException e) {
   
// TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CannotCompileException e) {
   
// TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
   
            e.printStackTrace();
        }
        return null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值