Skip to content

Commit d628fed

Browse files
author
xuanyh
committed
方法插入代码 test
1 parent 715a566 commit d628fed

File tree

1 file changed

+42
-26
lines changed
  • src/main/java/com/threedr3am/bug/asm

1 file changed

+42
-26
lines changed

src/main/java/com/threedr3am/bug/asm/Test.java

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package com.threedr3am.bug.asm;
22

33
import com.google.common.reflect.ClassPath;
4+
import com.sun.org.apache.bcel.internal.Constants;
45
import java.io.IOException;
56
import java.io.InputStream;
7+
import java.lang.reflect.Method;
8+
import org.mozilla.javascript.GeneratedClassLoader;
69
import org.objectweb.asm.AnnotationVisitor;
710
import org.objectweb.asm.Attribute;
811
import org.objectweb.asm.ClassReader;
912
import org.objectweb.asm.ClassVisitor;
13+
import org.objectweb.asm.ClassWriter;
1014
import org.objectweb.asm.FieldVisitor;
1115
import org.objectweb.asm.Handle;
1216
import org.objectweb.asm.Label;
@@ -18,6 +22,7 @@
1822

1923
/**
2024
* 学习asm字节码操作,fuzz基础
25+
*
2126
* @author xuanyh
2227
*/
2328
public class Test {
@@ -45,34 +50,48 @@ public static void main(String[] args) {
4550
try (InputStream in = Thread.currentThread().getContextClassLoader()
4651
.getResourceAsStream("com.threedr3am.bug.asm.Test".replace(".", "/") + ".class")) {
4752
ClassReader cr = new ClassReader(in);
53+
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
4854
try {
49-
MethodCallDiscoveryClassVisitor visitor = new MethodCallDiscoveryClassVisitor(
50-
Opcodes.ASM6);
55+
MyClassVisitorAdapter visitor = new MyClassVisitorAdapter(
56+
Opcodes.ASM6, cw);
5157
cr.accept(visitor, ClassReader.EXPAND_FRAMES);
58+
GeneratorClassLoader classLoader = new GeneratorClassLoader();
59+
classLoader.defineClassFromClassFile("com.threedr3am.bug.asm.Test", cw.toByteArray());
60+
Class c = classLoader.loadClass("com.threedr3am.bug.asm.Test");
61+
Object o = c.newInstance();
62+
Method method = c.getDeclaredMethod("test", new Class[]{String.class});
63+
method.invoke(o, "输入参数");
5264
} catch (Exception e) {
5365
e.printStackTrace();
5466
}
5567
}
5668
} catch (IOException e) {
5769
e.printStackTrace();
5870
}
71+
}
5972

60-
new Test().test();
73+
public void test(String str) {
74+
System.out.println("call Test.test(" + str + ")");
6175
}
6276

63-
public void test() {
64-
System.out.println("call Test.test()");
77+
public static class GeneratorClassLoader extends ClassLoader {
78+
79+
public Class defineClassFromClassFile(String className, byte[] classFile)
80+
throws ClassFormatError {
81+
return defineClass(className, classFile, 0, classFile.length);
82+
}
6583
}
6684

6785
/**
6886
* ClassVisitor 基于观察者模式的class asm操作
6987
*
70-
* visit -> visitSource -> visitInnerClass -> visitInnerClass -> visitMethod -> visitMethod -> visitMethod -> visitEnd
88+
* visit -> visitSource -> visitInnerClass -> visitInnerClass -> visitMethod -> visitMethod ->
89+
* visitMethod -> visitEnd
7190
*/
72-
private static class MethodCallDiscoveryClassVisitor extends ClassVisitor {
91+
private static class MyClassVisitorAdapter extends ClassVisitor {
7392

74-
public MethodCallDiscoveryClassVisitor(int api) {
75-
super(api);
93+
public MyClassVisitorAdapter(int api, ClassVisitor cv) {
94+
super(api, cv);
7695
}
7796

7897
@Override
@@ -140,11 +159,8 @@ public FieldVisitor visitField(int access, String name, String descriptor, Strin
140159
private String name = null;
141160

142161
/**
143-
*
144162
* @param version 字节码版本
145-
* @param access
146163
* @param name 类全限定名
147-
* @param signature
148164
* @param superName 继承的基类
149165
* @param interfaces 实现的接口
150166
*/
@@ -167,13 +183,10 @@ public void visit(int version, int access, String name, String signature,
167183
}
168184

169185
/**
170-
*
171-
* @param access
172186
* @param name 方法名
173187
* @param desc 方法参数和返回值
174188
* @param signature 方法签名
175189
* @param exceptions 方法抛出的异常数组
176-
* @return
177190
*/
178191
@Override
179192
public MethodVisitor visitMethod(int access, String name, String desc,
@@ -186,31 +199,28 @@ public MethodVisitor visitMethod(int access, String name, String desc,
186199
// System.out.println("desc: " + desc);
187200
// System.out.println("signature: " + signature);
188201
// System.out.println("exceptions: " + Arrays.toString(exceptions));
189-
MethodCallDiscoveryMethodVisitor modelGeneratorMethodVisitor = new MethodCallDiscoveryMethodVisitor(
190-
api, mv, this.name, name, desc);
191202

192203
//适配器封装MethodVisitor,进行asm操作方法字节码
193-
return new JSRInlinerAdapter(modelGeneratorMethodVisitor, access, name, desc, signature,
194-
exceptions);
204+
return new MethodVisitorAdapter(api, mv, this.name, name, desc);
195205
}
196206

197207
@Override
198208
public void visitEnd() {
199-
System.out.printf("visitEnd -> ");
209+
System.out.printf("visitEnd\n");
200210
super.visitEnd();
201211
}
202212
}
203213

204214
/**
205215
* MethodVisitor 基于观察者模式的method asm操作
206216
*/
207-
private static class MethodCallDiscoveryMethodVisitor extends MethodVisitor {
217+
private static class MethodVisitorAdapter extends MethodVisitor {
208218

209219
private String owner = null;
210220
private MethodVisitor mv = null;
211221
private String name = null;
212222

213-
public MethodCallDiscoveryMethodVisitor(final int api, final MethodVisitor mv,
223+
public MethodVisitorAdapter(final int api, final MethodVisitor mv,
214224
final String owner, String name, String desc) {
215225
super(api, mv);
216226
this.owner = owner;
@@ -255,9 +265,18 @@ public void visitAttribute(Attribute attribute) {
255265
super.visitAttribute(attribute);
256266
}
257267

268+
/**
269+
* 进入方法代码执行时会先执行该方法
270+
*/
258271
@Override
259272
public void visitCode() {
260273
super.visitCode();
274+
if (name.equals("test")) {
275+
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
276+
mv.visitLdcInsn("插入代码调用,输出字符串");
277+
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
278+
"(Ljava/lang/String;)V", false);
279+
}
261280
}
262281

263282
@Override
@@ -383,14 +402,11 @@ public void visitEnd() {
383402
}
384403

385404
/**
405+
* TODO this.name base call method(调用方法) TODO this.owner base call class(调用类)
386406
*
387-
* TODO this.name base call method(调用方法)
388-
* TODO this.owner base call class(调用类)
389-
* @param opcode
390407
* @param owner target class(被调用类)
391408
* @param name target method(被调用方法)
392409
* @param desc 方法参数和返回值描述
393-
* @param itf
394410
*/
395411
@Override
396412
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {

0 commit comments

Comments
 (0)