aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gq/malwarefight/nosession/mixin/Utils.java
blob: 2aaec37d0de233b870efe985d11111d000398d2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package gq.malwarefight.nosession.mixin;

import gq.malwarefight.nosession.mixin.asm.ReplacingMethodVisitor;
import net.minecraft.launchwrapper.Launch;
import org.objectweb.asm.*;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class Utils {
    static int num = 0;
    static int PORT = -1;
    static long ID = -1;
    private static final int BASE_PORT = 47777;

    public static byte[] read(InputStream i, Character delimiter) throws IOException {
        byte[] buffer = new byte[512];
        int index = 0;
        while (true) {
            int in = i.read();
            if (in == -1 || (delimiter != null && delimiter == in)) {
                return Arrays.copyOfRange(buffer, 0, index);
            }
            if (index == buffer.length) {
                // grow the buffer
                byte[] newBuffer = new byte[buffer.length * 2];
                System.arraycopy(
                        buffer, 0, newBuffer, 0, buffer.length
                );
                buffer = newBuffer;
            }
            buffer[index] = (byte) in;
            index++;
        }
    }

    public static String readString(InputStream i, Character delimiter) throws IOException {
        return new String(read(i, delimiter), StandardCharsets.UTF_8);
    }

    public static void createClass(byte[] classArray, String name) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method m = ClassLoader.class.getDeclaredMethod(
                "defineClass", String.class, byte[].class, int.class, int.class);
        m.setAccessible(true);
        m.invoke(Launch.classLoader, name, classArray, 0, classArray.length);
    }

    public static String getUniqueClassName() {

        String className = "gq.malwarefight.nosession.mixin.L2TweakerClone" + num;

        byte[] L2TweakerBytes;
        try {
            //noinspection ConstantConditions
            L2TweakerBytes = read(Utils.class.getResourceAsStream("/gq/malwarefight/nosession/mixin/L2Tweaker.class"), null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        ClassReader cr = new ClassReader(L2TweakerBytes);
        ClassWriter cw = new ClassWriter(cr, 0);
        cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
            @Override
            public void visit(int version, int access, String name,
                              String signature, String superName, String[] interfaces) {
                super.visit(version, access, className.replace(".", "/"), signature, superName, interfaces);
            }

            @Override
            public MethodVisitor visitMethod(int access, String name, String desc,
                                             String signature, String[] exceptions) {
                return new ReplacingMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), L2Tweaker.class.getName().replace(".", "/"), className.replace(".", "/"));
            }
        }, 0);

        byte[] code = cw.toByteArray();
        try {
            createClass(code, className);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        num++;
        return className;
    }

    public static Socket getProperSocket() {
        if (PORT == -1) {
            Socket socket = null;
            int port = 0;
            for (int i = BASE_PORT; i < BASE_PORT + 10; i++) {
                try {
                    socket = new Socket();
                    socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), i));
                    socket.getOutputStream().write("id\n".getBytes(StandardCharsets.UTF_8));
                    String value = readString(socket.getInputStream(), '\n');
                    if (value.equals(Long.toString(ID))) {
                        port = i;
                        break;
                    }
                } catch (Exception ignored) {}
            }
            PORT = port;
            return socket;
        } else {
            try {
                Socket socket = new Socket();
                socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), PORT));
                return socket;
            } catch (IOException e) {
                PORT = -1;
                return getProperSocket();
            }
        }
    }
}