使用javassist修改class文件
javassist jar 修改 方法
javassist jar 修改方法摘要:1.简介2.javassist 是什么3.如何使用javassist 修改jar 包4.修改方法5.总结正文:1.简介在Java 开发中,我们有时需要对jar 包进行一些修改,例如添加、删除或修改类、方法等。
javassist 是一个Java 字节码修改框架,它可以帮助我们轻松地实现这些操作。
2.javassist 是什么Javassist 是一个强大的Java 字节码修改工具,它可以让Java 程序在运行时动态地修改类和字节码。
它支持对类、方法、字段等进行操作,提供了丰富的API 供开发者使用。
3.如何使用javassist 修改jar 包要使用javassist 修改jar 包,首先需要将jar 包转换为Class 文件,然后使用Javassist 的API 对Class 文件进行修改。
接下来,将修改后的Class 文件重新打包成jar 包。
具体步骤如下:a.将jar 包转换为Class 文件使用`jar2class`工具将jar 包转换为Class 文件,例如:`jar2class -x input.jar output`。
b.使用Javassist 修改Class 文件使用Javassist 的API 对Class 文件进行修改,例如:```javaClassPool pool = new ClassPool();pool.appendClassPath(new File("input.jar"));CtClass ctClass = pool.getCtClass("com.example.ClassName");// 修改方法CtMethod method = ctClass.getDeclaredMethod("methodName");method.setBody("{System.out.println("修改后的方法实现");}");// 添加方法CtMethod newMethod = CtMethod.make(Modifier.PUBLIC, ctClass, "newMethodName", new CtClass[]{}, "{}");ctClass.addMethod(newMethod);// 删除字段ctClass.removeField("fieldName");// 修改字段ctClass.getField("fieldName").setModifiers(Modifier.PRIVATE);// 保存修改后的Class 文件ctClass.writeFile("output.class");```c.将修改后的Class 文件重新打包成jar 包使用`jar`命令将修改后的Class 文件打包成jar 包,例如:`jar cvf output.jar output.class`。
java修改class的实例的方法
java修改class的实例的方法在Java中,我们可以使用反射(reflection)和动态代理(dynamic proxy)两种方式来修改类的实例的方法。
这两种方式都可以在运行时动态修改类的行为,但它们的原理和应用场景有所不同。
一、反射(Reflection)反射是Java语言特有的一种机制,可以在运行时动态地调用类的方法、访问和修改类的属性。
通过反射,我们可以获取类的信息,如类名、方法、属性等,然后通过调用相应的方法来修改类的实例的方法。
1.获取类的Class对象在Java中,要使用反射来修改类的方法,首先需要获取类的Class对象。
有三种常用的方法来获取Class对象:- 使用类的.class语法糖来获取Class对象。
例如:Class<?>clazz = MyClass.class;- 使用对象的getClass(方法来获取对象的Class对象。
例如:Class<?> clazz = obj.getClass(;这里需要注意的是,如果要修改的类在运行时还未加载,那么需要用到类的全名(包括包名)。
2.获取并修改方法获取Class对象后,我们可以通过Class类提供的方法来获取类的方法以及相应的调用方式。
对于以前已经存在的方法,我们可以通过反射来修改方法的行为,具体步骤如下:- 使用Class类的getDeclaredMethod(String name, Class<?>... parameterTypes)方法来获取类的指定方法,name为方法名,parameterTypes为方法参数的类型。
例如:Method method =clazz.getDeclaredMethod("methodName", String.class);- 如果方法是私有的,需要调用setAccessible(true)方法来设置访问权限。
例如:method.setAccessible(true);- 使用Method类的invoke(Object obj, Object... args)方法来调用方法,obj为方法所属的对象,args为方法的参数。
javaassist修改方法
javaassist修改方法使用Javaassist修改方法Javaassist是一个强大的Java字节码操作库,可以在运行时修改已经编译好的字节码文件,进而改变程序的行为。
本文将介绍如何使用Javaassist修改方法。
Javaassist的基本概念在开始介绍Javaassist的使用之前,我们先来了解一下Javaassist 的基本概念。
Javaassist是由Javassist Class Pool类、CtClass类、CtMethod类等组成的,其中Class Pool类用于加载字节码文件,CtClass类用于表示一个类,CtMethod类用于表示一个方法。
使用Javaassist修改方法的步骤使用Javaassist修改方法的步骤如下:1. 创建一个ClassPool对象,用于加载字节码文件。
2. 使用ClassPool对象的get方法加载待修改的类。
3. 使用CtClass类的getDeclaredMethod方法获取待修改的方法。
4. 使用CtMethod类的insertBefore或insertAfter方法在方法的前面或后面插入代码。
5. 使用CtMethod类的toBytecode方法将修改后的字节码文件转换为字节数组。
6. 使用CtClass类的writeFile方法将修改后的字节码文件写入磁盘。
下面我们将通过一个示例来演示使用Javaassist修改方法的过程。
示例:修改方法的参数假设我们有一个类Calculator,其中有一个方法add,用于计算两个数的和。
现在我们希望在方法的前面打印出方法的参数和返回值,可以使用Javaassist来实现这个需求。
我们需要在pom.xml文件中添加Javaassist的依赖:```<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.27.0-GA</version></dependency>```然后,我们创建一个类Calculator:```javapublic class Calculator {public int add(int a, int b) {return a + b;}}```接下来,我们使用Javaassist修改add方法的代码:```javaimport javassist.*;public class ModifyMethodExample {public static void main(String[] args) throws Exception {// 创建一个ClassPool对象ClassPool classPool = ClassPool.getDefault();// 使用ClassPool对象的get方法加载待修改的类CtClass ctClass = classPool.get("Calculator");// 使用CtClass类的getDeclaredMethod方法获取待修改的方法CtMethod addMethod = ctClass.getDeclaredMethod("add");// 使用CtMethod类的insertBefore方法在方法的前面插入代码addMethod.insertBefore("{ System.out.println(\"参数a=\" + $1); System.out.println(\"参数b=\" + $2); }");// 使用CtMethod类的insertAfter方法在方法的后面插入代码addMethod.insertAfter("{ System.out.println(\"返回值=\" + $_); }");// 使用CtMethod类的toBytecode方法将修改后的字节码文件转换为字节数组byte[] bytecode = addMethod.toBytecode();// 使用CtClass类的writeFile方法将修改后的字节码文件写入磁盘ctClass.writeFile();}}```运行上述代码后,Javaassist会在add方法的前面插入打印参数的代码,以及在方法的后面插入打印返回值的代码。
javassist使用全解析
javassist使⽤全解析Java 字节码以⼆进制的形式存储在 .class ⽂件中,每⼀个 .class ⽂件包含⼀个 Java 类或接⼝。
Javaassist 就是⼀个⽤来处理 Java 字节码的类库。
它可以在⼀个已经编译好的类中添加新的⽅法,或者是修改已有的⽅法,并且不需要对字节码⽅⾯有深⼊的了解。
同时也可以去⽣成⼀个新的类对象,通过完全⼿动的⽅式。
1. 使⽤ Javassist 创建⼀个 class ⽂件⾸先需要引⼊jar包:<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.25.0-GA</version></dependency>编写创建对象的类:package com.rickiyang.learn.javassist;import javassist.*;/*** @author rickiyang* @date 2019-08-06* @Desc*/public class CreatePerson {/*** 创建⼀个Person 对象** @throws Exception*/public static void createPseson() throws Exception {ClassPool pool = ClassPool.getDefault();// 1. 创建⼀个空类CtClass cc = pool.makeClass("com.rickiyang.learn.javassist.Person");// 2. 新增⼀个字段 private String name;// 字段名为nameCtField param = new CtField(pool.get("ng.String"), "name", cc);// 访问级别是 privateparam.setModifiers(Modifier.PRIVATE);// 初始值是 "xiaoming"cc.addField(param, CtField.Initializer.constant("xiaoming"));// 3. ⽣成 getter、setter ⽅法cc.addMethod(CtNewMethod.setter("setName", param));cc.addMethod(CtNewMethod.getter("getName", param));// 4. 添加⽆参的构造函数CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);cons.setBody("{name = \"xiaohong\";}");cc.addConstructor(cons);// 5. 添加有参的构造函数cons = new CtConstructor(new CtClass[]{pool.get("ng.String")}, cc);// $0=this / $1,$2,$3... 代表⽅法参数cons.setBody("{$ = $1;}");cc.addConstructor(cons);// 6. 创建⼀个名为printName⽅法,⽆参数,⽆返回值,输出name值CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody("{System.out.println(name);}");cc.addMethod(ctMethod);//这⾥会将这个创建的类对象编译为.class⽂件cc.writeFile("/Users/yangyue/workspace/springboot-learn/java-agent/src/main/java/");}public static void main(String[] args) {try {createPseson();} catch (Exception e) {e.printStackTrace();}}}执⾏上⾯的 main 函数之后,会在指定的⽬录内⽣成 Person.class ⽂件://// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.rickiyang.learn.javassist;public class Person {private String name = "xiaoming";public void setName(String var1) { = var1;}public String getName() {return ;}public Person() { = "xiaohong";}public Person(String var1) { = var1;}public void printName() {System.out.println();}}跟咱们预想的⼀样。
java 修改 class方法
java 修改 class方法
在Java中,你不能直接修改已经编译的`.class`文件。
这是因为Java是一种静态类型语言,编译后的`.class`文件包含了完整的类型信息,这些信息在运行时是不可变的。
然而,有几种方法可以间接地"修改"类的方法:
1. 字节码操作库:你可以使用像ASM或Javassist这样的字节码操作库来读取、修改和重新编译类的字节码。
这些库允许你在类加载到JVM之前修改其字节码,从而实现方法的修改。
2. 动态代理:你可以使用Java的动态代理来"修改"类的方法。
动态代理允许你创建一个实现了特定接口的新类,该类在运行时将调用你提供的处理程序。
通过这种方式,你可以拦截方法调用并改变其行为。
3. Aspect Oriented Programming (AOP):AOP是一种编程范式,允许程序员定义跨多个类的横切关注点,如日志、事务管理和安全。
通过使用像Spring AOP这样的框架,你可以定义切面来拦截方法调用,并在调用前后执行特定的代码。
这些方法都有其优点和局限性,并且通常更适用于大型应用程序或框架开发,而不是日常的编码工作。
如果你只是想改变类的方法行为,通常更好的做法是直接修改源代码,然后重新编译和部署它。
javassist使用流程
javassist使用流程Javassist使用流程简介Javassist是一个用于Java字节码操作的开源库,它能够动态地编辑字节码,并且支持在运行时生成、修改和转换Java类文件。
本文将详细介绍Javassist的使用流程,帮助读者快速上手。
安装1.在项目的构建文件中,添加Javassist的依赖。
2.执行构建命令,下载并安装Javassist。
常用功能以下是Javassist的一些常用功能,你可以根据需求选择合适的功能进行使用。
1. 类加载与获取•利用ClassPool类加载目标类文件。
•通过CtClass获取目标类的属性、方法等信息。
•使用ClassPool创建新的类。
2. 类修改与生成•新建ClassPool实例。
•调用makeClass()方法创建一个新的类。
•使用CtClass的相关方法对类进行修改,如添加字段、删除方法等。
3. 代码注入与修改•使用CtClass的addMethod()方法添加新方法。
•通过CtMethod对象获取方法体,使用insertBefore()和insertAfter()方法进行代码注入。
•使用CtMethod的setBody()方法修改方法体。
4. 方法重命名与删除•使用CtMethod的setName()方法对方法进行重命名。
•使用CtClass的removeMethod()方法删除方法。
5. 字段修改与生成•使用CtField类创建新字段,并通过CtClass的addField()方法将其添加到类中。
•调用CtField对象的相关方法对字段进行修改,如修改访问修饰符、修改字段名等。
使用示例以下示例演示了如何使用Javassist对一个类进行修改,在其原有的hello()方法前后注入日志输出代码。
// 导入相关类和方法import ;import ;import ;// 获取目标类ClassPool pool = ();CtClass targetClass = ("");// 获取目标方法CtMethod targetMethod = ("hello");// 在方法前插入代码String beforeCode = "(\"Before method\");"; (beforeCode);// 在方法后插入代码String afterCode = "(\"After method\");"; (afterCode);总结Javassist是一款强大的动态字节码操作库,可以在运行时对Java类进行修改和生成。
javassist jar 修改 方法
javassist jar 修改方法【实用版3篇】目录(篇1)1.Javassist 简介2.Javassist 的功能3.如何使用 Javassist 修改 jar 文件中的方法4.注意事项和局限性正文(篇1)一、Javassist 简介Javassist(Java Class File Processor)是一个开源的 Java 字节码处理工具,它可以对 Java 字节码进行编辑、修改、生成等操作。
使用Javassist,我们可以在保持 Java 代码不变的情况下,修改其行为。
这对于一些需要对已有代码进行定制,但又不想修改原有代码的情况非常有用。
二、Javassist 的功能Javassist 的主要功能有:1.读取和修改 Java 类文件的字节码。
2.生成新的 Java 类文件。
3.动态地创建和修改 Java 类的行为。
4.为 Java 类添加、删除或修改方法、字段等。
三、如何使用 Javassist 修改 jar 文件中的方法下面是一个使用 Javassist 修改 jar 文件中的方法的简单示例:1.首先,需要导入 Javassist 相关的库。
```javaimport javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import javassist.Modifier;import java.io.File;import java.io.FileInputStream;import java.io.IOException;```2.然后,创建一个 ClassPool 实例,用于加载和修改类文件。
```javaClassPool pool = new ClassPool();```3.指定要修改的 jar 文件路径,并加载到 ClassPool 中。
```javaFile jarFile = new File("path/to/your/jarfile.jar"); FileInputStream fis = new FileInputStream(jarFile); pool.open(fis, "jar");```4.通过 ClassPool 实例,获取需要修改的方法所在的类。
javassist jar 修改 方法
javassist jar 修改方法在软件开发过程中,我们经常会遇到需要修改已编译代码的情况。
使用Java编程语言时,有许多方式可以达到这一目的,其中之一是使用javassist jar库。
javassist是一个用于在运行时编辑字节码的Java库。
通过使用javassist,我们可以在不重新编译代码的情况下修改已编译的Java类。
接下来,我将介绍如何使用javassist jar库来修改方法。
首先,确保已经将javassist jar库添加到项目的构建路径中。
你可以从Maven 仓库或其他可靠的源获取该库。
下载并将其添加到项目的classpath中。
接下来,我们需要创建一个简单的Java类,用于演示如何使用javassist来修改方法:```javapublic class MyClass {public static void main(String[] args) {System.out.println("Hello, World!");}public void originalMethod() {System.out.println("This is the original method.");}}```接下来,我们将使用javassist来修改上述类中的方法。
我们将修改`originalMethod`方法,使其输出修改后的消息。
以下是实现此目的的代码示例:```javaimport javassist.*;public class MyClassModifier {public static void main(String[] args) {try {// 获取类池ClassPool classPool = ClassPool.getDefault();// 获取要修改的类CtClass ctClass = classPool.get("MyClass");// 获取要修改的方法CtMethod ctMethod = ctClass.getDeclaredMethod("originalMethod");// 修改方法实现ctMethod.setBody("{ System.out.println(\"This is the modified method.\"); }");// 保存修改后的类ctClass.writeFile();System.out.println("Method Modified Successfully!");} catch (Exception e) {e.printStackTrace();}}}```在上述示例代码中,我们使用了javassist的各种类和方法,以获取要修改的类、方法,并将其实现更改为我们所需的内容。
javassistjar修改方法
javassistjar修改方法要修改一个方法,首先需要获取到对应的类。
可以使用以下代码来获取类:```javaClassPool pool = ClassPool.getDefault(;```一旦我们获得了要修改的类,就可以使用以下代码来获取要修改的方法:```javaCtMethod ctMethod = ctClass.getDeclaredMethod("myMethod");```上述代码中,"myMethod"是要修改的方法的名称。
一旦我们获取到了要修改的方法,我们可以使用以下代码来修改方法的实现:```javactMethod.setBody("{ System.out.println(\"Modifiedmethod\"); }");```上述代码中,我们使用了一个字符串来表示新的方法实现。
可以在字符串中编写任意的Java代码来实现期望的修改。
最后,我们需要将修改后的类保存到磁盘上或加载到内存中。
以下代码演示了如何将修改后的类保存到磁盘上:```javactClass.writeFile(;```上述代码将修改后的类保存到默认的输出目录中。
除了修改方法实现外,我们还可以使用javassist库进行其他类型的修改,如添加新的方法、修改字段、添加注解等。
在使用javassist库时,需要注意以下几点:1. 如果要修改的类在类路径上,则ClassPool.getDefault(方法将返回一个默认的ClassPool实例,该实例将类路径中的类。
如果要修改的类不在类路径上,则需要使用ClassPool对象的insertClassPath(方法设置类路径。
2.进行类的修改后,需要注意可能会破坏类的结构。
因此,在修改类之前,最好先备份原始的类文件,以防修改后无法恢复。
3.在修改类时,需要谨慎操作,确保修改后的类仍然是有效且可用的。
javassist jar 修改 方法
javassist jar 修改方法【原创实用版3篇】目录(篇1)1.Javassist 简介2.Javassist 的功能3.如何使用 Javassist 修改 Java 类4.使用 Javassist 修改方法的实例正文(篇1)一、Javassist 简介Javassist 是一个开源的 Java 字节码操作工具,它可以在运行时修改 Java 类的结构和行为。
通过使用 Javassist,开发者可以在不修改源代码的情况下,对 Java 类的字节码进行操作,实现诸如添加、删除、修改类成员等高级功能。
二、Javassist 的功能Javassist 提供了丰富的 API,可以实现以下功能:1.创建新的 Java 类2.修改现有 Java 类的字节码3.添加或删除类成员4.修改类成员的访问权限5.修改类成员的类型6.添加或删除构造方法7.添加或删除静态方法8.添加或删除实例方法9.修改方法的参数列表10.修改方法的返回值类型三、如何使用 Javassist 修改 Java 类使用 Javassist 修改 Java 类的步骤如下:1.引入 Javassist 依赖2.加载需要修改的 Java 类3.获取类的字节码4.对字节码进行操作5.将修改后的字节码写回类文件下面是一个简单的示例,演示如何使用 Javassist 修改 Java 类的方法:```javaimport javassist.*;public class JavassistDemo {public static void main(String[] args) {try {// 加载需要修改的 Java 类Class<?> clazz =ClassLoader.getSystemClassLoader().loadClass("com.example.MyCla ss");// 获取类的字节码byte[] byteCode =clazz.getProtectionDomain().getCode();// 创建一个方法处理器,用于修改方法MethodHandler methodHandler = new MethodHandler() {@Overridepublic void visit(MethodVisitor mv, int access, String name, String desc, Code code) {// 修改方法的访问权限mv.visit(access, name, desc, code);// 修改方法的返回值类型code.getReturnType().set(Code.Type.INT);}};// 对字节码进行操作CodeTransformer transformer = new CodeTransformer(methodHandler);byte[] modifiedByteCode =transformer.transform(byteCode, clazz);// 将修改后的字节码写回类文件clazz.getProtectionDomain().setCode(modifiedByteCode);// 重新加载修改后的类Class<?> modifiedClazz =ClassLoader.getSystemClassLoader().loadClass("com.example.MyClass");// 创建一个实例,并调用修改后的方法Object instance = modifiedClazz.newInstance();Method method =modifiedClazz.getMethod("myMethod");int result = (Integer) method.invoke(instance);System.out.println("Result: " + result);} catch (Exception e) {e.printStackTrace();}}}```四、使用 Javassist 修改方法的实例在上述示例中,我们使用 Javassist 修改了名为"myMethod"的方法,将其返回类型从原本的 String 修改为 Integer。
使用javassist修改class文件
使用javassist修改class文件Firestorm是一个用JAVA写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强的一个。
Firestorm是一个用JAVA写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强的一个。
你可以在网上下载到最新的2.3试用版本,同时网站会发给你一个试用的license文件。
既然是试用,那么在使用上肯定有一定的限制。
主要限制有3个:1.只能最多生成5张表的DAO;2.有时间限制;3.不能自己定制代码生成;为了能够更好的试用这个软件,我得改改它,去掉这些限制。
将firestorm.jar打开后,可以看到它使用了混淆器进行代码保护,不同于大多数的混淆器生成的文件,它的class和package大部分都是以关键字来命名,所以如果你用JAD之类的工具把它反编译后是不能再把它编译成功,编译器会提示出错误。
反编译后,找到几个有关注册的关键文件,发现它使用的是数字签名技术来做的保护,所以想逆向找出注册码的计算方法是不可行的了,只能通过修改文件的方法来破解。
通常我们是先反编译,然后再修改反编译后生成的原文件,最后再重新编译。
但是由于文件名和包名的关系我们无法进行编译,除非把它的这些‘非法'的文件名和包名全部改成符合java语言规范的名称,由于类,包众多,互相调用也很频繁,所以这种方法几乎不可能的。
另外一种方法就是使用softice之类的调试软件来破解,不过这个脱离JAVA的范畴,这里不做讨论。
还有一种方法可能很少有人用,就是先反编译得到原文件,然后找到关键的方法后修改它的字节码,也就是class文件,这中方法往往需要你知道一些有关CLASS文件格式方面的知识(如果没有也不用担心),有许多的处理字节码的工具可以帮助你,比较流行的这类工具主要有:的BCEL; 的javassist;的asm。
都是出身名门哈。
这3个工具各有特点,这次我选用javassist,因为它修改class文件最方便,甚至不需要懂得字节码和class文件格式。
使用javassist?实现直接修改class文件中的方法
使用javassist 实现直接修改class文件中的方法使用javassist 可以实现直接修改class文件中的方法,javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。
直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
下面是例子:1.要修改的class文件的代码,当然正常情况下你是看不到的package com.ms.xbox.halo.reach;public class For_test {public final boolean output(){return false;}public static void main(String[] args) {// TODO Auto-generated method stubString strAaa="输出结果";System.out.println(strAaa);}}2.随便建一个java工程,引入javassist的jar包,编译环境我用的1.4版本jdk,修改代码如下import javassist.*;public class test {public static void main(String args[]) throws Exception{ClassPool cp = ClassPool.getDefault();//获得类文件名CtClass cc = cp.get("com.ms.xbox.halo.reach.For_test");//获得要修改的方法名CtMethod m = cc.getDeclaredMethod("output");//这里是将返回结果改成truem.insertBefore("return true;");cc.writeFile();}}3.执行java test,用反编译工具(这里用的是jd-gui),再去看看文件夹 com\ms box\halo\reach下的类For_test,方法output已经被修改了package com.ms.xbox.halo.reach;public class For_test {public final boolean output(){return true;return false;}public static void main(String[] args) {// TODO Auto-generated method stubString strAaa="输出结果";System.out.println(strAaa);}}当然javassist 还有很多的功能,可以修改类中方法的属性,新增加方法,修改已有方法的程序体,上面只是一个很简单的例子.感谢能看完全文,javassist jar包的下载地址:/project/jboss/Javassist/3.11.0.GA/javassist-3.11.GA.zip。
java修改class文件
java修改class⽂件最近因为⼯作需要修改class⽂件中⼀个变量的值,特此记录2、找到要修改的变量所在的地址3、创建⼀个java⼯程、并且将jclasslib.jar导⼊、执⾏以下代码即可1package .c;23import java.io.*;4import org.gjt.jclasslib.io.ClassFileWriter;5import org.gjt.jclasslib.structures.CPInfo;6import org.gjt.jclasslib.structures.ClassFile;7import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;89public class Main {10public static void main(String[] args) throws Exception {1112 String filePath = "C:\\Main.class";13 FileInputStream fis = new FileInputStream(filePath);14 DataInput di = new DataInputStream(fis);15 ClassFile cf = new ClassFile();16 cf.read(di);17 CPInfo[] infos = cf.getConstantPool();1819int count = infos.length;20for (int i = 0; i < count; i++) {21if (infos[i] != null) {22 System.out.print(i);23 System.out.print(" = ");24 System.out.print(infos[i].getVerbose());25 System.out.print(" = ");26 System.out.println(infos[i].getTagVerbose());27if (i == 21) {//刚刚找到的是21位置28 ConstantUtf8Info uInfo = (ConstantUtf8Info) infos[i]; //刚刚那⾥是CONSTANT_Utf-8_info所以这⾥要⽤这个29 uInfo.setBytes("baidu".getBytes());30 infos[i] = uInfo;31 }32 }33 }34//这种⽅式也可以,⼀样的35/* if(infos[count] != null) {36 ConstantUtf8Info uInfo = (ConstantUtf8Info) infos[i]; //刚刚那⾥是CONSTANT_Utf-8_info所以这⾥要⽤这个37 uInfo.setBytes("baidu".getBytes());38 infos[count] = uInfo;39 }*/4041 cf.setConstantPool(infos);42 fis.close();43 File f = new File(filePath);44 ClassFileWriter.writeToFile(f, cf);45 }46 }。
Javassist用法详解
Javassist⽤法详解⽬录概述ClassPoolCtClassCtMthodCtFieldCtConstructorClassPathClassLoader⽰例创建Class⽂件调⽤⽣成的类对象修改现有的类对象概述Java字节码以⼆进制的形式存储在.class⽂件中,每⼀个.class⽂件包含⼀个Java类或接⼝。
Javaassist就是⼀个⽤来处理Java字节码的类库。
它可以在⼀个已经编译好的类中添加新的⽅法,或者是修改已有的⽅法,并且不需要对字节码⽅⾯有深⼊的了解。
同时也可以通过完全⼿动的⽅式⽣成⼀个新的类对象。
Maven依赖⽅式:<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.27.0-GA</version></dependency>Gradle依赖⽅式:implementation 'org.javassist:javassist:3.27.0-GA'ClassPoolClassPool是CtClass对象的容器,它按需读取类⽂件来构造CtClass对象,并且保存CtClass对象以便以后使⽤。
从实现的⾓度来看,ClassPool 是⼀个存储 CtClass 的 Hash 表,类的名称作为 Hash 表的 key。
ClassPool 的 get() 函数⽤于从 Hash 表中查找 key 对应的 CtClass 对象。
如果没有找到,get() 函数会创建并返回⼀个新的 CtClass 对象,这个新对象会保存在 Hash 表中。
需要注意的是ClassPool会在内存中维护所有被它创建过的CtClass,当CtClass数量过多时,会占⽤⼤量的内存,API中给出的解决⽅案是重新创建ClassPool 或有意识的调⽤CtClass的detach()⽅法以释放内存。
javassist动态修改类方法
javassist动态修改类方法使用javassist动态修改类方法的功能可以在运行时动态地修改Java 类的方法。
这个功能非常强大,可以实现一些在编译时无法完成的操作,比如在不改变源代码的情况下,添加、删除、修改类的方法。
本文将详细介绍如何使用javassist动态修改类方法的步骤和注意事项。
我们需要在项目中引入javassist库。
可以通过Maven或者手动下载jar包的方式导入。
接下来,我们需要创建一个ClassPool对象,用于加载我们需要修改的类。
ClassPool是javassist库的核心类,负责加载类的字节码。
一般情况下,我们会通过ClassPool的getDefault方法来获取一个默认的ClassPool对象。
然后,我们可以使用ClassPool对象的get方法来加载需要修改的类。
get方法接收一个类的完整名称作为参数,返回一个CtClass对象。
接着,我们可以使用CtClass对象的getMethod方法来获取需要修改的方法。
getMethod方法接收一个方法名和一个描述符作为参数,返回一个CtMethod对象。
如果需要修改的方法是静态方法,可以使用getDeclaredMethod方法。
获取到需要修改的方法后,我们可以使用CtMethod对象的setBody方法来设置新的方法体。
setBody方法接收一个字符串作为参数,这个字符串就是新的方法体的代码。
我们可以在字符串中编写任意的Java代码,来实现我们的需求。
除了直接编写Java代码,我们还可以使用CtMethod对象的insertBefore和insertAfter方法,来在方法的前面或者后面插入一段代码。
这个功能非常便利,可以在不修改原有代码的情况下,添加一些额外的逻辑。
当我们完成了对方法的修改后,别忘了调用writeFile方法将修改后的字节码写入到磁盘。
这样,我们就完成了对类方法的动态修改。
总结一下,使用javassist动态修改类方法的步骤如下:1. 引入javassist库。
javassist使用流程
javassist使用流程javassist是一个开源的Java字节码编辑器库,它提供了一种在运行时修改类文件的方式,可以动态地创建、编辑和修改Java类。
使用javassist可以实现一些在编译时无法完成的操作,比如动态生成类、修改类的行为等。
下面将介绍javassist的使用流程。
1. 引入javassist库首先需要在项目中引入javassist库。
可以通过Maven或手动下载jar包的方式引入。
在引入后,就可以在代码中使用javassist的功能了。
2. 创建ClassPoolClassPool是javassist的核心类,它用于管理被修改的类。
通过ClassPool可以获取要修改的类的CtClass对象,以及创建新的类。
可以通过以下代码创建ClassPool对象:```ClassPool classPool = ClassPool.getDefault();```3. 获取要修改的类通过ClassPool的get方法可以获取要修改的类的CtClass对象。
get方法的参数可以是类的全限定名,也可以是Class对象。
例如,获取ng.String类的CtClass对象可以使用以下代码:```CtClass stringClass = classPool.get("ng.String");```4. 修改类的行为获取到要修改的类的CtClass对象后,就可以对类的行为进行修改了。
可以使用CtClass提供的一系列方法来添加、修改或删除类的成员、方法和字段。
以下是一些常用的示例操作:- 添加方法:```CtMethod newMethod = CtNewMethod.make("public void newMethod() { System.out.println(\"This is a new method.\"); }", ctClass);ctClass.addMethod(newMethod);```- 修改方法:```CtMethod method = ctClass.getDeclaredMethod("methodName");method.insertBefore("{ System.out.println(\"This is insertedbefore the method.\"); }");```- 删除方法:```CtMethod method = ctClass.getDeclaredMethod("methodName");ctClass.removeMethod(method);```- 添加字段:```CtField newField = new CtField(CtClass.intType, "newField", ctClass);ctClass.addField(newField);```- 修改字段:```CtField field = ctClass.getDeclaredField("fieldName");field.setModifiers(Modifier.PRIVATE);```- 删除字段:```CtField field = ctClass.getDeclaredField("fieldName"); ctClass.removeField(field);```5. 生成修改后的类在对类进行修改后,需要将修改后的类写回到磁盘上,或者在内存中动态加载。
javaassist替换类路径
javaassist替换类路径使用Javaassist替换类路径Java是一种广泛使用的编程语言,它具有强大的功能和灵活的特性。
在Java开发过程中,有时我们需要对类进行动态修改或增强。
这时,Javaassist(Java Programming Assistant)就是一个非常有用的工具。
Javaassist是一个开源的Java字节码编辑器库,它提供了一组API,可以在运行时修改或生成Java字节码。
通过使用Javaassist,我们可以实现在运行时动态修改类的行为,而无需修改源代码。
Javaassist的一个常见应用场景是替换类路径。
类路径是指在Java 虚拟机(JVM)上运行Java程序时,用于查找类文件的路径。
在某些情况下,我们可能需要将程序中某个类的类路径替换为另一个类路径,以实现一些特定的需求。
而Javaassist提供了相应的API,可以帮助我们实现这一目标。
下面我们将介绍如何使用Javaassist替换类路径。
我们需要在项目中引入Javaassist的库文件。
可以通过在项目的构建文件(如Maven的pom.xml)中添加相应的依赖项来实现。
引入Javaassist后,我们就可以在代码中使用Javaassist提供的API 了。
下面是替换类路径的示例代码:```import javassist.ClassPool;import javassist.CtClass;import javassist.LoaderClassPath;public class ClassPathReplacer {public static void replaceClassPath(String className, String newClassPath) throws Exception {ClassPool classPool = ClassPool.getDefault();classPool.insertClassPath(newLoaderClassPath(ClassLoader.getSystemClassLoader()));CtClass ctClass = classPool.get(className);ctClass.defrost();ctClass.replaceClassName(className, newClassPath);ctClass.writeFile();}}```在上面的示例代码中,我们首先创建了一个ClassPool对象,它是Javaassist的核心类之一。
借助jclasslib与javassist修改java+class字节码
借助jclasslib与javassist修改java+class字节码有时候,我们在没有java源程序的情况下,想改变.CLASS文件的部分内容输出或者改变跳转流,怎么办呢?介绍2个java hacker的工具javassist 以及jclasslib。
下载javassist-3.1RC2和jclasslib_windows_3_0。
解压后,将2个JAR 加入classpath内。
jclasslib_windows_3_0.exe在JAVA_HOME/lib下安装原文件HelloWorld.javapackage com.unmi;public class HelloWorld{public static void main(String[] args){System.out.println("Hello,gorld!");}}想修改输出的”hello world”,用jclasslib.exe 检测可以看到属于常量池的23。
如下代码就针对23 做调整。
package com.unmi;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import java.io.*;import org.gjt.jclasslib.io.ClassFileWriter;import org.gjt.jclasslib.structures.CPInfo;import org.gjt.jclasslib.structures.ClassFile;importorg.gjt.jclasslib.structures.constants.ConstantStringInfo;importorg.gjt.jclasslib.structures.constants.ConstantUtf8Info;public class JclasslibTest {public static void main(String[] args) throws Exception {{String filePath = "D:\\java_proj\\com\\unmi\\HelloWorld.class";FileInputStream fis = new FileInputStream(filePath);DataInput di = new DataInputStream(fis);ClassFile cf = new ClassFile();cf.read(di);CPInfo[] infos = cf.getConstantPool();int count = infos.length;for (int i = 0; i < count; i++) {if (infos[i] != null) {System.out.print(i);System.out.print(" = ");System.out.print(infos[i].getVerbose());System.out.print(" = ");System.out.println(infos[i].getTagVerbose());if(i == 23){ConstantUtf8Info uInfo = (ConstantUtf8Info)infos[i];uInfo.setString("china alibaba ");}}}cf.setConstantPool(infos);fis.close();File f = new File(filePath + "c");ClassFileWriter.writeToFile(f, cf);}}}D:\java_proj>javac -cp %CLASSPATH%;. com/unmi/JclasslibTest.javaD:\java_proj>java com.unmi.JclasslibT est1 = com/unmi/HelloWorld = CONSTANT_Class_info2 = com/unmi/HelloWorld = CONSTANT_Utf8_info3 = java/lang/Object = CONSTANT_Class_info4 = java/lang/Object = CONSTANT_Utf8_info5 = = CONSTANT_Utf8_info6 = ()V = CONSTANT_Utf8_info7 = Code = CONSTANT_Utf8_info8 = java/lang/Object. = CONSTANT_Methodref_info9 = ()V = CONSTANT_NameAndType_info10 = LineNumberT able = CONSTANT_Utf8_info11 = LocalVariableTable = CONSTANT_Utf8_info12 = this = CONSTANT_Utf8_info13 = Lcom/unmi/HelloWorld; = CONSTANT_Utf8_info14 = main = CONSTANT_Utf8_info15 = ([Ljava/lang/String;)V = CONSTANT_Utf8_info16 = java/lang/System.out = CONSTANT_Fieldref_info17 = java/lang/System = CONSTANT_Class_info18 = java/lang/System = CONSTANT_Utf8_info19 = outLjava/io/PrintStream; = CONSTANT_NameAndType_info20 = out = CONSTANT_Utf8_info21 = Ljava/io/PrintStream; = CONSTANT_Utf8_info22 = Hello,gorld! = CONSTANT_String_info23 = Hello,gorld! = CONSTANT_Utf8_info24 = java/io/PrintStream.println = CONSTANT_Methodref_info25 = java/io/PrintStream = CONSTANT_Class_info26 = java/io/PrintStream = CONSTANT_Utf8_info27 = println(Ljava/lang/String;)V = CONSTANT_NameAndType_info28 = println = CONSTANT_Utf8_info29 = (Ljava/lang/String;)V = CONSTANT_Utf8_info30 = args = CONSTANT_Utf8_info31 = [Ljava/lang/String; = CONSTANT_Utf8_info32 = SourceFile = CONSTANT_Utf8_info33 = HelloWorld.java = CONSTANT_Utf8_info更改生成的HelloWorld.classc 为HelloWorld.class执行输出为D:\java_proj>java com.unmi.HelloWorldchina alibaba 另外,也可以修改if 语句跳转Jclasslib 观测到jvm op code 如下现在想更改>= 为<,怎么办?查询Opcode Mnemonics by Opcode/docs/books/jvms/second_edition/html/ Mnemonics.doc.html 并查到>= 的操作码为0xA1所以只要用Ultraedit 修改0xA1 为0xA2 就可以了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. 指令码 助记符 2. 0x00 nop 说明 什么都不做 将 int 型-1 推送至栈顶 将 int 型 0 推送至栈顶 将 int 型 1 推送至栈顶 将 int 型 2 推送至栈顶 将 int 型 3 推送至栈顶 将 int 型 4 推送至栈顶 将 int 型 5 推送至栈顶 将 long 型 0 推送至栈顶 将 long 型 1 推送至栈顶 将 float 型 0 推送至栈顶 将 float 型 1 推送至栈顶 将 float 型 2 推送至栈顶 将 double 型 0 推送至栈顶 将 double 型 1 推送至栈顶 将单字节的常量值(-128~127)推送至栈顶 将一个短整型常量值(-32768~32767)推送至栈顶 将 int, float 或 String 型常量值从常量池中推送至栈顶 将 int, float 或 String 型常量值从常量池中推送至栈顶(宽索引) 将 long 或 double 型常量值从常量池中推送至栈顶(宽索引) 将指定的 int 型本地变量推送至栈顶 将指定的 long 型本地变量推送至栈顶 将指定的 float 型本地变量推送至栈顶 将指定的 double 型本地变量推送至栈顶 将指定的引用类型本地变量推送至栈顶 将第一个 int 型本地变量推送至栈顶 将第二个 int 型本地变量推送至栈顶 将第三个 int 型本地变量推送至栈顶
byte abyte0[], byte abyte1[]) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.InvalidKeyException, java.security.SignatureException { java.security.Signature java.security.Signature.getInstance("SHA1withDSA", "SUN"); signature.initVerify(publickey); signature.update(abyte0); return signature.verify(abyte1); } 这个方法是对公钥进行检验,修改的思路就是直接让他返回一个 true. signature =
从当前方法返回 int,很明显,63-67 行就是对应
return true; JVM INSTR pop ; return false; 这 5 行对应的 16 进制值是: 0x04,0xAC,0x57,0x03,0xAC,于是, 16 进制编辑器打开, 用 查找 04AC5703AC 的位置,果然不负众望,接下来你知道怎么做了吧,把 0x03 这个位置的值 换成 0x04,那么这个 return false 不就变成 return true 了,呵呵。
本文由beikexiami贡献
doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
使用 javassist 修改 class 文件
Firestorm 是一个用 JAVA 写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强 的一个。 Firestorm 是一个用 JAVA 写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强 的一个。 你可以在网上下载到最新的 2.3 试用版本,同时网站会发给你一个试用的 license 文件。既然是试用, 那么在使用上肯定有一定的限制。主要限制有 3 个: 1.只能最多生成 5 张表的 DAO; 2.有时间限制; 3.不能自己定制代码生成; 为了能够更好的试用这个软件,我得改改它,去掉这些限制。将 firestorm.jar 打开后,可以看到它使用 了 混淆器进行代码保护, 不同于大多数的混淆器生成的文件, 它的 class 和 package 大部分都是以关键字来 命名, 所以如果你用 JAD 之类的工具把它反编译后是不能再把它编译成功,编译器会提示出错误。 反编译后,找到几个有关注册的关键文件,发现它使用的是数字签名技术来做的保护,所以想逆向找出 注册码的计算方法是不可行的了,只能通过修改文件的方法来破解。通常我们是先反编译,然后再修改 反编译后生成的原文件,最后再重新编译。但是由于文件名和包名的关系我们无法进行编译,除非把它的 这些‘非法'的文件名和包名全部改成符合 java 语言规范的名称,由于类,包众多,互相调用也很 频繁,所以这种方法几乎不可能的。 另外一种方法就是使用 softice 之类的调试软件来破解,不过这个脱离 JAVA 的范畴,这里不做讨论。 还有一种方法可能很少有人用,就是先反编译得到原文件,然后找到关键的方法后修改它的字节码, 也就是 class 文件,这中方法往往需要你知道一些有关 CLASS 文件格式方面的知识(如果没有也不用担 心), 有许多的处理字节码的工具可以帮助你,比较流行的这类工具主要有: 的 BCEL; 的 javassist; 的 asm。都是出身名门哈。这 3 个工具各有特点, 这次我选用 javassist,因为它修改 class 文件最方便,甚至不需要懂得字节码和 class 文件格式。 让我们来看看具体步骤:
step4: 将所有的 class 文件重新打包成 firestorm.jar,然后替换 [firestorm 安装路径]/lib/firestorm.jar,再启动 firestorm 即可。
一、直接修改字节码 要查看“return false”对应字节码需要使用 JClassLib 工具,JClassLib 有一个可视 化的界面,方便我们查看类的变量、方法、静态数据等,如下图:
step2: 收到 firestorm.license 文件后不要急着安装,先修改如下: <custom-codegen>no</custom-codegen> 改为 <custom-codegen>yes</custom-codegen> <restriction>5</restriction> 改为 <restriction>none</restriction> <expiry-date>[日期]</expiry-date> 改为 <expiry-date>never</expiry-date> 修改后放到 firestorm 的安装路径的 license 目录。
这个 a 方法(也许实际名称就是 sendsms)的字节码如下: 0 aload_0 1 invokestatic #42 <javax/microedition/io/Connector.open> 4 checkcast #11 <javax/wireless/messaging/MessageConnection> 7 dup 8 astore_2 9 ldc #61 <text> 11 invokeinterface #48 <javax/wireless/messaging/MessageConnection.newMessage> count 2 16 checkcast #12 <javax/wireless/messaging/TextMessage> 19 astore_3 20 aload_2 21 பைடு நூலகம்nvokestatic #29 24 ifne 34 (+10)
step1: 下载并安装 FIRESTORM。 step2: 反编译 jar 文件,阅读代码,找到关键的方法。当然,我这里写出来,你就不用再麻烦了。(其实这步 是最 麻烦的)。 找到 com.codefutures.if.if 文件中的方法 public static boolean a(java.security.PublicKey publickey,
step3: 修改 com.codefutures.if.if 的 class 文件.这里我们需要写一个小程序来完成实现: import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod;
public class Test { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); //设置目标类的路径,确保能够找到需要修改的类,这里我指向 firestorm.jar //解包后的路径
27 aload_3 28 invokestatic #29 31 ifeq 36 (+5) 34 iconst_0 35 ireturn 36 aload_3 37 aload_0 38 invokeinterface #50 <javax/wireless/messaging/TextMessage.setAddress> count 2 43 aload_3 44 aload_1 45 invokeinterface #51 <javax/wireless/messaging/TextMessage.setPayloadText> count 2 50 aload_2 51 aload_3 52 invokeinterface #49 <javax/wireless/messaging/MessageConnection.send> count 2 57 aload_2 58 invokeinterface #47 <javax/wireless/messaging/MessageConnection.close> count 1 63 iconst_1 64 ireturn 65 pop 66 iconst_0 67 ireturn 通过查找 JVM 指令集, 0x03 iconst_0 int 型 1 推送至栈顶 ,0xac ireturn 的 将 int 型 0 推送至栈顶 , 0x04 iconst_1 将