Skip to content

Commit 0636c86

Browse files
authored
Create asm.md
1 parent 808b16d commit 0636c86

File tree

1 file changed

+347
-0
lines changed

1 file changed

+347
-0
lines changed

java日常/asm.md

+347
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
# asm
2+
3+
## 分析类
4+
5+
分析类的代码
6+
7+
```java
8+
public class Test {
9+
public boolean aBoolean = true;
10+
11+
public void render(){
12+
System.out.println("hello asm");
13+
}
14+
}
15+
```
16+
17+
MyClassVisitors类
18+
19+
```java
20+
import jdk.internal.org.objectweb.asm.ClassVisitor;
21+
import jdk.internal.org.objectweb.asm.FieldVisitor;
22+
import jdk.internal.org.objectweb.asm.MethodVisitor;
23+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
24+
25+
public class MyClassVisitors extends ClassVisitor {
26+
public MyClassVisitors(){
27+
super(ASM5);
28+
}
29+
30+
/**
31+
* 继承关系
32+
* @param version
33+
* @param access
34+
* @param name
35+
* @param signature
36+
* @param superName
37+
* @param interfaces
38+
*/
39+
public void visit(int version,int access,String name,String signature,String superName,String[] interfaces){
40+
System.out.println(name + "extends " + superName + "{");
41+
super.visit(version,access,name,signature,superName,interfaces);
42+
}
43+
44+
/**
45+
* 属性变量
46+
* @param access
47+
* @param name
48+
* @param desc
49+
* @param signature
50+
* @param value
51+
* @return
52+
*/
53+
@Override
54+
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
55+
System.out.println(desc + " " + name);
56+
return super.visitField(access, name, desc, signature, value);
57+
}
58+
59+
/**
60+
* 方法
61+
* @param access
62+
* @param name
63+
* @param desc
64+
* @param signature
65+
* @param exceptions
66+
* @return
67+
*/
68+
@Override
69+
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
70+
System.out.println(name + " " + desc);
71+
return super.visitMethod(access, name, desc, signature, exceptions);
72+
}
73+
74+
@Override
75+
public void visitEnd() {
76+
System.out.println("}");
77+
super.visitEnd();
78+
}
79+
}
80+
```
81+
82+
主程序
83+
84+
```java
85+
import jdk.internal.org.objectweb.asm.ClassReader;
86+
87+
/**
88+
* 通过asm框架分析类
89+
*/
90+
public class AnalysisClass {
91+
public static void main(String[] args)throws Exception {
92+
MyClassVisitors myClassVisitors = new MyClassVisitors();
93+
ClassReader classReader = new ClassReader(Test.class.getName());
94+
classReader.accept(myClassVisitors,0);
95+
}
96+
}
97+
```
98+
99+
![image-20220125122358358](https://user-images.githubusercontent.com/63966847/150936112-ab83838c-4f67-4102-9816-ce2afa734559.png)
100+
101+
102+
![image-20220125122420194](https://user-images.githubusercontent.com/63966847/150936121-914e2c3a-6019-4f01-91ed-38c5453cab39.png)
103+
104+
105+
>该部分也是GI的核心。https://xz.aliyun.com/t/10363
106+
107+
## 生成类
108+
109+
>感觉用于webshell中。
110+
111+
```java
112+
import jdk.internal.org.objectweb.asm.ClassWriter;
113+
import jdk.internal.org.objectweb.asm.MethodVisitor;
114+
import java.io.FileOutputStream;
115+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
116+
117+
public class WriteClass {
118+
public static void main(String[] args) throws Exception {
119+
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
120+
// java1.8 public修饰 路径 签名 父类 接口
121+
classWriter.visit(V1_8, ACC_PUBLIC, "com/firebasky/utils/asm/learn/Learn2Test", null, "java/lang/Object", null);
122+
//public和static修饰 方法名 描述符 签名 异常
123+
MethodVisitor render = classWriter.visitMethod(ACC_PUBLIC + ACC_STATIC, "render", "()V", null, null);
124+
//插入一个字段是方法里面插入 操作码 路径 名字 描述符
125+
render.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
126+
//插入一个ldc
127+
render.visitLdcInsn("Hello asm!");
128+
//插入一个方法 操作码 路径 方法名 参数 是否为接口的方法
129+
render.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
130+
//插入返回值
131+
render.visitInsn(RETURN);
132+
//设置栈和局部变量大小
133+
render.visitMaxs(2, 1);
134+
//结束
135+
render.visitEnd();
136+
classWriter.visitEnd();
137+
//生成文件
138+
byte[] bytes = classWriter.toByteArray();
139+
FileOutputStream outputStream = new FileOutputStream("d://1.class");
140+
outputStream.write(bytes);
141+
outputStream.close();
142+
}
143+
}
144+
```
145+
146+
生成的类
147+
148+
```java
149+
package com.firebasky.utils.asm.learn;
150+
151+
public class Learn2Test {
152+
public static void render() {
153+
System.out.println("Hello asm!");
154+
}
155+
}
156+
157+
```
158+
159+
## 加载或移除类成员
160+
161+
主程序
162+
163+
```java
164+
import jdk.internal.org.objectweb.asm.ClassReader;
165+
import jdk.internal.org.objectweb.asm.ClassWriter;
166+
167+
import java.io.FileOutputStream;
168+
169+
public class Learn3 {
170+
public static void main(String[] args)throws Exception {
171+
ClassReader classReader = new ClassReader(Test.class.getName());
172+
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
173+
MyClassVisitor myClassVisitor = new MyClassVisitor(classWriter);
174+
classReader.accept(myClassVisitor,0);
175+
byte[] bytes = classWriter.toByteArray();
176+
FileOutputStream outputStream = new FileOutputStream("d://1.class");
177+
outputStream.write(bytes);
178+
outputStream.close();
179+
}
180+
}
181+
```
182+
183+
MyClassVisitor类
184+
185+
```java
186+
import jdk.internal.org.objectweb.asm.ClassVisitor;
187+
import jdk.internal.org.objectweb.asm.ClassWriter;
188+
import jdk.internal.org.objectweb.asm.FieldVisitor;
189+
import jdk.internal.org.objectweb.asm.MethodVisitor;
190+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
191+
192+
public class MyClassVisitor extends ClassVisitor {
193+
194+
public MyClassVisitor(ClassWriter classWriter) {
195+
super(ASM5, classWriter);
196+
}
197+
198+
@Override
199+
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
200+
if(name.equals("aBoolean")){
201+
return null;
202+
}
203+
return super.visitField(access, name, desc, signature, value);
204+
}
205+
206+
@Override
207+
public MethodVisitor visitMethod(int access, String name, String desc, String signature,String[] exceptions) {
208+
if(name.equals("render")){
209+
return null;
210+
}
211+
return super.visitMethod(access, name, desc, signature, exceptions);
212+
}
213+
214+
@Override
215+
public void visitEnd() {
216+
super.visitField(ACC_PRIVATE,"name","Ljava/lang/String;",null,null).visitEnd();
217+
super.visitMethod(ACC_PRIVATE,"name","(Ljava/lang/String;)V",null,null).visitEnd();
218+
super.visitEnd();
219+
}
220+
}
221+
```
222+
223+
修改之后的代码
224+
225+
```java
226+
package com.firebasky.utils.asm.learn;
227+
228+
public class Test {
229+
private String name;
230+
231+
public Test() {
232+
this.aBoolean = true;
233+
}
234+
private void name(String var1) {
235+
}
236+
}
237+
238+
```
239+
240+
## 创建对象和数组
241+
242+
```java
243+
import jdk.internal.org.objectweb.asm.ClassWriter;
244+
import jdk.internal.org.objectweb.asm.MethodVisitor;
245+
246+
import java.io.FileOutputStream;
247+
248+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
249+
250+
public class Learn4 {
251+
public static void main(String[] args)throws Exception {
252+
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
253+
MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
254+
methodVisitor.visitTypeInsn(NEW,"java/lang/String");
255+
methodVisitor.visitLdcInsn("xxx");//常量
256+
methodVisitor.visitMethodInsn(INVOKEVIRTUAL,"java/lang/String","<init>","(Ljava/lang/String;)V",false);
257+
//生成文件
258+
byte[] bytes = classWriter.toByteArray();
259+
FileOutputStream outputStream = new FileOutputStream("d://1.class");
260+
outputStream.write(bytes);
261+
outputStream.close();
262+
}
263+
}
264+
```
265+
266+
数组
267+
268+
```java
269+
methodVisitor.visitIntInsn(SIPUSH,2);//数组长度
270+
methodVisitor.visitIntInsn(NEWARRAY,T_BYTE);//类型是byte
271+
methodVisitor.visitInsn(DUP);//
272+
methodVisitor.visitIntInsn(SIPUSH,0);//插入数组0位置
273+
methodVisitor.visitIntInsn(SIPUSH,1);
274+
methodVisitor.visitInsn(AASTORE);//保存
275+
```
276+
277+
## 字符串混淆
278+
279+
就是在写入的时候做一个转换。
280+
281+
```java
282+
import jdk.internal.org.objectweb.asm.ClassReader;
283+
import jdk.internal.org.objectweb.asm.ClassWriter;
284+
285+
import java.io.FileOutputStream;
286+
import java.io.IOException;
287+
288+
public class Learn5 {
289+
public static void main(String[] args) throws IOException {
290+
ClassReader classReader = new ClassReader(Test.class.getName());
291+
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
292+
MyClassVisitor1 myClassVisitor = new MyClassVisitor1(classWriter);
293+
classReader.accept(myClassVisitor,0);
294+
byte[] bytes = classWriter.toByteArray();
295+
FileOutputStream outputStream = new FileOutputStream("d://1.class");
296+
outputStream.write(bytes);
297+
outputStream.close();
298+
}
299+
}
300+
```
301+
302+
MyClassVisitor1
303+
304+
```java
305+
import jdk.internal.org.objectweb.asm.ClassVisitor;
306+
import jdk.internal.org.objectweb.asm.ClassWriter;
307+
import jdk.internal.org.objectweb.asm.MethodVisitor;
308+
import java.nio.charset.StandardCharsets;
309+
310+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
311+
312+
/**
313+
* 拦截字符串修改
314+
*/
315+
public class MyClassVisitor1 extends ClassVisitor {
316+
public MyClassVisitor1(ClassWriter classWriter) {
317+
super(ASM5, classWriter);
318+
}
319+
@Override
320+
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
321+
return new MethodVisitor(api,super.visitMethod(access,name,desc,signature,exceptions)) {
322+
@Override
323+
public void visitLdcInsn(Object cst) {
324+
if(cst instanceof String){
325+
byte[] bytes = ((String) cst).getBytes(StandardCharsets.UTF_8);//转换bytes
326+
mv.visitTypeInsn(NEW,"java/lang/String");
327+
mv.visitInsn(DUP);
328+
mv.visitIntInsn(SIPUSH,bytes.length);
329+
mv.visitIntInsn(NEWARRAY,T_BYTE);
330+
for(int i = 0;i<bytes.length;i++){
331+
mv.visitInsn(DUP);
332+
mv.visitIntInsn(SIPUSH,i);
333+
mv.visitIntInsn(SIPUSH,bytes[i]);
334+
mv.visitInsn(AASTORE);
335+
}
336+
mv.visitLdcInsn("UTF-8");
337+
mv.visitMethodInsn(INVOKEVIRTUAL,"java/lang/String","<init>","([BLjava/lang/String;)V",false);
338+
}else {
339+
super.visitLdcInsn(cst);
340+
}
341+
}
342+
};
343+
}
344+
}
345+
```
346+
347+
将字符串转换成bytes

0 commit comments

Comments
 (0)