Skip to content

Commit ab1a122

Browse files
committed
Написание кода v1.0
1 parent 7da50dc commit ab1a122

File tree

5 files changed

+171
-2
lines changed

5 files changed

+171
-2
lines changed

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ tasks.withType(JavaCompile).configureEach {
4444

4545
jar {
4646
manifest {
47-
attributes 'FMLCorePluginContainsFMLMod': 'true'
48-
attributes 'FMLCorePlugin': 'mods.example.LoadingPlugin'
47+
attributes 'FMLCorePluginContainsFMLMod': 'false' // TODO: Not a mod
48+
attributes 'FMLCorePlugin': 'me.theandrey.objectstream.asm.LoadingPlugin'
4949
}
5050
}
5151

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package me.theandrey.objectstream;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.ObjectInputStream;
6+
7+
/**
8+
* Заглушка класса {@link ObjectInputStream}
9+
*/
10+
public final class ObjectInputStreamMock extends ObjectInputStream {
11+
12+
public ObjectInputStreamMock(InputStream in) throws IOException {
13+
throw new SecurityException("Not available due security reasons");
14+
}
15+
16+
public ObjectInputStreamMock() throws IOException, SecurityException {
17+
throw new SecurityException("Not available due security reasons");
18+
}
19+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package me.theandrey.objectstream.asm;
2+
3+
import org.objectweb.asm.ClassReader;
4+
import org.objectweb.asm.ClassWriter;
5+
import org.objectweb.asm.Type;
6+
import org.objectweb.asm.tree.ClassNode;
7+
8+
public final class ASMHelper {
9+
10+
public static ClassNode readClass(byte[] bytes) {
11+
ClassNode node = new ClassNode();
12+
ClassReader reader = new ClassReader(bytes);
13+
reader.accept(node, 0);
14+
return node;
15+
}
16+
17+
public static byte[] writeClass(ClassNode node, int flags) {
18+
ClassWriter writer = new ClassWriter(flags);
19+
node.accept(writer);
20+
return writer.toByteArray();
21+
}
22+
23+
public static Type getObjectType(String name) {
24+
return Type.getType('L' + name.replace('.', '/') + ';');
25+
}
26+
27+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package me.theandrey.objectstream.asm;
2+
3+
import java.util.Map;
4+
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
5+
6+
@IFMLLoadingPlugin.SortingIndex(2000)
7+
@IFMLLoadingPlugin.TransformerExclusions("me.theandrey.objectstream.asm.")
8+
public class LoadingPlugin implements IFMLLoadingPlugin {
9+
10+
@Override
11+
public String[] getASMTransformerClass() {
12+
return new String[]{"me.theandrey.objectstream.asm.ObjectInputStreamTransformer"};
13+
}
14+
15+
@Override
16+
public String getModContainerClass() {
17+
return null;
18+
}
19+
20+
@Override
21+
public String getSetupClass() {
22+
return null;
23+
}
24+
25+
@Override
26+
public void injectData(Map<String, Object> data) {
27+
// NO-OP
28+
}
29+
30+
@Override
31+
public String getAccessTransformerClass() {
32+
return null;
33+
}
34+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package me.theandrey.objectstream.asm;
2+
3+
import java.io.ObjectInputStream;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.ListIterator;
7+
import net.minecraft.launchwrapper.IClassTransformer;
8+
import org.apache.logging.log4j.LogManager;
9+
import org.apache.logging.log4j.Logger;
10+
import org.objectweb.asm.Opcodes;
11+
import org.objectweb.asm.Type;
12+
import org.objectweb.asm.tree.AbstractInsnNode;
13+
import org.objectweb.asm.tree.ClassNode;
14+
import org.objectweb.asm.tree.MethodInsnNode;
15+
import org.objectweb.asm.tree.MethodNode;
16+
import org.objectweb.asm.tree.TypeInsnNode;
17+
18+
/**
19+
* Заменяет использование {@link ObjectInputStream} заглушкой
20+
*/
21+
public class ObjectInputStreamTransformer implements IClassTransformer {
22+
23+
static final Logger LOGGER = LogManager.getLogger();
24+
private final Type findType;
25+
private final Type replaceType;
26+
27+
public ObjectInputStreamTransformer() {
28+
findType = Type.getType(ObjectInputStream.class);
29+
replaceType = ASMHelper.getObjectType("me.theandrey.objectstream.ObjectInputStreamMock");
30+
}
31+
32+
@Override
33+
public byte[] transform(String name, String transformedName, byte[] bytes) {
34+
ClassNode node = ASMHelper.readClass(bytes);
35+
36+
List<MethodNode> unsafeMethods = scanMethods(node);
37+
38+
if (!unsafeMethods.isEmpty()) {
39+
LOGGER.warn("SECURITY ALERT: Detected usage of ObjectInputStream in class '{}'", name);
40+
for (MethodNode method : unsafeMethods) {
41+
LOGGER.warn("Method: {} {}", name, method.name + method.desc);
42+
}
43+
44+
return ASMHelper.writeClass(node, 0);
45+
}
46+
47+
return bytes;
48+
}
49+
50+
/**
51+
* Ищет случаи использования в коде методов и производит замену.
52+
* @return Список методов в которых были найдены случаи использования
53+
*/
54+
private List<MethodNode> scanMethods(ClassNode node) {
55+
List<MethodNode> found = new ArrayList<>();
56+
57+
for (MethodNode method : node.methods) {
58+
ListIterator<AbstractInsnNode> it = method.instructions.iterator();
59+
boolean foundNew = false; // Найден оператор NEW
60+
61+
while (it.hasNext()) {
62+
AbstractInsnNode next = it.next();
63+
64+
if (next.getOpcode() == Opcodes.NEW) {
65+
TypeInsnNode cast = ((TypeInsnNode)next);
66+
67+
if (cast.desc.equals(findType.getInternalName())) { // Инициализация типа
68+
foundNew = true;
69+
cast.desc = replaceType.getInternalName(); // Заглушка
70+
71+
if (!found.contains(method)) {
72+
found.add(method);
73+
}
74+
}
75+
76+
} else if (foundNew && next.getOpcode() == Opcodes.INVOKESPECIAL) { // Вызов конструктора
77+
MethodInsnNode invoke = ((MethodInsnNode)next);
78+
79+
if ("<init>".equals(invoke.name) && invoke.owner.equals(findType.getInternalName())) {
80+
invoke.owner = replaceType.getInternalName(); // Заглушка
81+
foundNew = false; // Завершаем замену блока
82+
}
83+
}
84+
}
85+
}
86+
87+
return found;
88+
}
89+
}

0 commit comments

Comments
 (0)