Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Получение ClassLoader

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
4 Дек 2021
Сообщения
282
Реакции
10
Пишу читуху под Rustex Remake которая работает на загрузке своих классов
Столкнулся с проблемой что эта параша детектит толи загрузку классов толи создания потока толи подключение к класс лоадеру
Какой класс лоадер лучше использовать мой код на данный момент

ByteLoader:
Expand Collapse Copy
package Heroin.base.ClassLoader;

import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class ByteLoader extends Thread {

    public static byte[][] classbyte;
    public static native Class defineClass(ClassLoader loader, byte[] bytecode, int length);
    public static native Class MainAnnotation();
    public static native boolean isKeyDown(int key);
    public static native int getAsyncKeyState(int key);

    public static int startByteLoader(byte[][] classes) {
        try {
            classbyte = classes;
            ByteLoader loader = new ByteLoader();
            loader.start();
        } catch (Exception e) {
            System.out.println("StartLoader: " + e);
        }
        return 0;
    }

    @Override
    public void run() {
        PrintWriter logWriter = null;

        try {
            String logPath = System.getProperty("user.home") + File.separator + "log.txt";
            logWriter = new PrintWriter(logPath, "UTF-8");
            logWriter.println("Starting ByteLoader...");
            logWriter.flush();

            ClassLoader targetLoader = findLoader(logWriter);
            if (targetClassLoader == null) {
                throw new Exception("ClassLoader is null");
            }
            logWriter.println("Found ClassLoader: " + targetClassLoader.getClass().getName());
            logWriter.flush();

            this.setContextClassLoader(targetClassLoader);

            logWriter.println("Loading class");
            List<Class<?>> allClasses = new ArrayList<>();

            for (int i = 0; i < classbyte.length; i++) {
                byte[] classData = classbyte[i];
                if (classData == null) continue;

                try {
                    Class<?> loadedClass = defineClass(null, classData, classData.length);
                    allClasses.add(loadedClass);
                    logWriter.println("  Loaded: " + loadedClass.getName());
                } catch (Throwable e) {
                    logWriter.println("  ERROR: " + e.getMessage());
                    e.printStackTrace(logWriter);
                }
            }

            logWriter.println("Loaded " + allClasses.size() + " classes");
            logWriter.flush();

            Class<?> annotationClass = null;
            for (Class<?> cls : allClasses) {
                if (cls.getName().equals("Heroin.base.Utils.ModInitializer")) {
                    annotationClass = cls;
                    logWriter.println("Found annotation: " + cls.getName());
                    break;
                }
            }

            if (annotationClass == null) {
                logWriter.println("ModInitializer not found!");
                return;
            }

            for (Class<?> cls : allClasses) {
                if (cls != annotationClass && cls.isAnnotationPresent(
                        (Class<? extends java.lang.annotation.Annotation>) annotationClass)) {
                    try {
                        cls.newInstance();
                    } catch (Exception e) {
                        logWriter.println("Error starting " + cls.getName() + ": " + e.getMessage());
                    }
                }
            }

            logWriter.println("success load");
            logWriter.flush();

        } catch (Throwable error) {
            if (logWriter != null) {
                error.printStackTrace(logWriter);
                logWriter.flush();
            }
            error.printStackTrace();
        } finally {
            if (logWriter != null) {
                logWriter.close();
            }
        }
    }

    private ClassLoader findLoader(PrintWriter logWriter) {
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            if (thread == null) continue;
            ClassLoader loader = thread.getContextClassLoader();
            if (loader == null) continue;
            String name = loader.getClass().getName();

            if (logWriter != null) {
                logWriter.println("Thread: " + thread.getName() + " -> " + name);
            }

            if (name.contains("AppClassLoader") ||
                    name.contains("TransformingClassLoader")) {
                return loader;
            }
        }
        return ByteLoader.class.getClassLoader();
    }
}
(Не много гпт фиксил ошибки с загрузкой классов) сейчас работает только AppClassLoader который я так понимаю в детекте чем его можно заменить?
ну или же как лучше дефайнить классы чтоб это не задетектило
Help
 
Пишу читуху под Rustex Remake которая работает на загрузке своих классов
Столкнулся с проблемой что эта параша детектит толи загрузку классов толи создания потока толи подключение к класс лоадеру
Какой класс лоадер лучше использовать мой код на данный момент

ByteLoader:
Expand Collapse Copy
package Heroin.base.ClassLoader;

import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class ByteLoader extends Thread {

    public static byte[][] classbyte;
    public static native Class defineClass(ClassLoader loader, byte[] bytecode, int length);
    public static native Class MainAnnotation();
    public static native boolean isKeyDown(int key);
    public static native int getAsyncKeyState(int key);

    public static int startByteLoader(byte[][] classes) {
        try {
            classbyte = classes;
            ByteLoader loader = new ByteLoader();
            loader.start();
        } catch (Exception e) {
            System.out.println("StartLoader: " + e);
        }
        return 0;
    }

    @Override
    public void run() {
        PrintWriter logWriter = null;

        try {
            String logPath = System.getProperty("user.home") + File.separator + "log.txt";
            logWriter = new PrintWriter(logPath, "UTF-8");
            logWriter.println("Starting ByteLoader...");
            logWriter.flush();

            ClassLoader targetLoader = findLoader(logWriter);
            if (targetClassLoader == null) {
                throw new Exception("ClassLoader is null");
            }
            logWriter.println("Found ClassLoader: " + targetClassLoader.getClass().getName());
            logWriter.flush();

            this.setContextClassLoader(targetClassLoader);

            logWriter.println("Loading class");
            List<Class<?>> allClasses = new ArrayList<>();

            for (int i = 0; i < classbyte.length; i++) {
                byte[] classData = classbyte[i];
                if (classData == null) continue;

                try {
                    Class<?> loadedClass = defineClass(null, classData, classData.length);
                    allClasses.add(loadedClass);
                    logWriter.println("  Loaded: " + loadedClass.getName());
                } catch (Throwable e) {
                    logWriter.println("  ERROR: " + e.getMessage());
                    e.printStackTrace(logWriter);
                }
            }

            logWriter.println("Loaded " + allClasses.size() + " classes");
            logWriter.flush();

            Class<?> annotationClass = null;
            for (Class<?> cls : allClasses) {
                if (cls.getName().equals("Heroin.base.Utils.ModInitializer")) {
                    annotationClass = cls;
                    logWriter.println("Found annotation: " + cls.getName());
                    break;
                }
            }

            if (annotationClass == null) {
                logWriter.println("ModInitializer not found!");
                return;
            }

            for (Class<?> cls : allClasses) {
                if (cls != annotationClass && cls.isAnnotationPresent(
                        (Class<? extends java.lang.annotation.Annotation>) annotationClass)) {
                    try {
                        cls.newInstance();
                    } catch (Exception e) {
                        logWriter.println("Error starting " + cls.getName() + ": " + e.getMessage());
                    }
                }
            }

            logWriter.println("success load");
            logWriter.flush();

        } catch (Throwable error) {
            if (logWriter != null) {
                error.printStackTrace(logWriter);
                logWriter.flush();
            }
            error.printStackTrace();
        } finally {
            if (logWriter != null) {
                logWriter.close();
            }
        }
    }

    private ClassLoader findLoader(PrintWriter logWriter) {
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            if (thread == null) continue;
            ClassLoader loader = thread.getContextClassLoader();
            if (loader == null) continue;
            String name = loader.getClass().getName();

            if (logWriter != null) {
                logWriter.println("Thread: " + thread.getName() + " -> " + name);
            }

            if (name.contains("AppClassLoader") ||
                    name.contains("TransformingClassLoader")) {
                return loader;
            }
        }
        return ByteLoader.class.getClassLoader();
    }
}
(Не много гпт фиксил ошибки с загрузкой классов) сейчас работает только AppClassLoader который я так понимаю в детекте чем его можно заменить?
ну или же как лучше дефайнить классы чтоб это не задетектило
Help
какая джава у растикса?
 
Пишу читуху под Rustex Remake которая работает на загрузке своих классов
Столкнулся с проблемой что эта параша детектит толи загрузку классов толи создания потока толи подключение к класс лоадеру
Какой класс лоадер лучше использовать мой код на данный момент

ByteLoader:
Expand Collapse Copy
package Heroin.base.ClassLoader;

import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class ByteLoader extends Thread {

    public static byte[][] classbyte;
    public static native Class defineClass(ClassLoader loader, byte[] bytecode, int length);
    public static native Class MainAnnotation();
    public static native boolean isKeyDown(int key);
    public static native int getAsyncKeyState(int key);

    public static int startByteLoader(byte[][] classes) {
        try {
            classbyte = classes;
            ByteLoader loader = new ByteLoader();
            loader.start();
        } catch (Exception e) {
            System.out.println("StartLoader: " + e);
        }
        return 0;
    }

    @Override
    public void run() {
        PrintWriter logWriter = null;

        try {
            String logPath = System.getProperty("user.home") + File.separator + "log.txt";
            logWriter = new PrintWriter(logPath, "UTF-8");
            logWriter.println("Starting ByteLoader...");
            logWriter.flush();

            ClassLoader targetLoader = findLoader(logWriter);
            if (targetClassLoader == null) {
                throw new Exception("ClassLoader is null");
            }
            logWriter.println("Found ClassLoader: " + targetClassLoader.getClass().getName());
            logWriter.flush();

            this.setContextClassLoader(targetClassLoader);

            logWriter.println("Loading class");
            List<Class<?>> allClasses = new ArrayList<>();

            for (int i = 0; i < classbyte.length; i++) {
                byte[] classData = classbyte[i];
                if (classData == null) continue;

                try {
                    Class<?> loadedClass = defineClass(null, classData, classData.length);
                    allClasses.add(loadedClass);
                    logWriter.println("  Loaded: " + loadedClass.getName());
                } catch (Throwable e) {
                    logWriter.println("  ERROR: " + e.getMessage());
                    e.printStackTrace(logWriter);
                }
            }

            logWriter.println("Loaded " + allClasses.size() + " classes");
            logWriter.flush();

            Class<?> annotationClass = null;
            for (Class<?> cls : allClasses) {
                if (cls.getName().equals("Heroin.base.Utils.ModInitializer")) {
                    annotationClass = cls;
                    logWriter.println("Found annotation: " + cls.getName());
                    break;
                }
            }

            if (annotationClass == null) {
                logWriter.println("ModInitializer not found!");
                return;
            }

            for (Class<?> cls : allClasses) {
                if (cls != annotationClass && cls.isAnnotationPresent(
                        (Class<? extends java.lang.annotation.Annotation>) annotationClass)) {
                    try {
                        cls.newInstance();
                    } catch (Exception e) {
                        logWriter.println("Error starting " + cls.getName() + ": " + e.getMessage());
                    }
                }
            }

            logWriter.println("success load");
            logWriter.flush();

        } catch (Throwable error) {
            if (logWriter != null) {
                error.printStackTrace(logWriter);
                logWriter.flush();
            }
            error.printStackTrace();
        } finally {
            if (logWriter != null) {
                logWriter.close();
            }
        }
    }

    private ClassLoader findLoader(PrintWriter logWriter) {
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            if (thread == null) continue;
            ClassLoader loader = thread.getContextClassLoader();
            if (loader == null) continue;
            String name = loader.getClass().getName();

            if (logWriter != null) {
                logWriter.println("Thread: " + thread.getName() + " -> " + name);
            }

            if (name.contains("AppClassLoader") ||
                    name.contains("TransformingClassLoader")) {
                return loader;
            }
        }
        return ByteLoader.class.getClassLoader();
    }
}
(Не много гпт фиксил ошибки с загрузкой классов) сейчас работает только AppClassLoader который я так понимаю в детекте чем его можно заменить?
ну или же как лучше дефайнить классы чтоб это не задетектило
Help
попробуй такое

Java:
Expand Collapse Copy
private ClassLoader findLoader() {
    try {
        Class<?> mcClass = Class.forName("net.minecraft.client.Minecraft");
        return mcClass.getClassLoader();
    } catch (ClassNotFoundException e) {
        return Thread.currentThread().getContextClassLoader();
    }
    
    
    
}
 
какая джава у растикса?
какая джава у растикса?
обычная java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)
попробуй такое

Java:
Expand Collapse Copy
private ClassLoader findLoader() {
    try {
        Class<?> mcClass = Class.forName("net.minecraft.client.Minecraft");
        return mcClass.getClassLoader();
    } catch (ClassNotFoundException e) {
        return Thread.currentThread().getContextClassLoader();
    }
   
   
   
}
Спасиб попробую
 
н
какая джава у растикса?
ну у них проверки там типо в отдельной дллки которая при запуске майна и там есть чет связаное с jni если хочешь могу кинуть джарку и дллку эту почекаешь
 
н

ну у них проверки там типо в отдельной дллки которая при запуске майна и там есть чет связаное с jni если хочешь могу кинуть джарку и дллку эту почекаешь
У них детект загрузки классов, а также в дллке происходит расшифровка классов из .jar игры.
 
У них детект загрузки классов, а также в дллке происходит расшифровка классов из .jar игры.
это я знаю что декрипт в дллке но как именно или где загрузку классов детектит в той же дллки? или гдет в коде игры
 
У них детект загрузки классов, а также в дллке происходит расшифровка классов из .jar игры.
вот че нейронка ответила

Если у них хук на defineClass на Java уровне, то обход через нативный JNI — самый чистый путь.

Схема:

Rustex скорее всего хукает ClassLoader.defineClass через java.lang.instrument или патчит байткод самого метода. Нативный вызов через JNI_DefineClass обходит это полностью.

В твоей DLL добавь:

#include &lt;jni.h&gt;<br><br>extern "C" JNIEXPORT jclass JNICALL<br>Java_Heroin_base_ClassLoader_ByteLoader_defineClass(<br> JNIEnv* env, jclass, jobject loader, jbyteArray bytecode, jint length) {<br> <br> jbyte* buf = env-&gt;GetByteArrayElements(bytecode, nullptr);<br> jclass result = env-&gt;DefineClass(nullptr, loader, buf, length);<br> env-&gt;ReleaseByteArrayElements(bytecode, buf, JNI_ABORT);<br> return result;<br>}<br>
env-&gt;DefineClass идёт напрямую через JVM без прохода через Java ClassLoader.defineClass — хуки на Java уровне не срабатывают.


Про обнаружение потока:

Переименуй тред и замаскируй под системный:

public static int startByteLoader(byte[][] classes) {<br> ByteLoader loader = new ByteLoader();<br> loader.setName("AWT-EventQueue-0");<br> loader.setDaemon(true);<br> loader.setPriority(Thread.MIN_PRIORITY);<br> loader.start();<br> return 0;<br>}<br>

Про findLoader:

Вместо перебора тредов — достань лоадер через уже загруженный класс самого Rustex:

private ClassLoader findLoader() {<br> try {<br> return Class.forName("net.minecraft.client.main.Main",<br> false, null).getClassLoader();<br> } catch (Throwable e) {<br> return ClassLoader.getSystemClassLoader();<br> }<br>}<br>
Class.forName с initialize=false не триггерит статические блоки и менее заметен.


Если детект именно на Thread.getAllStackTraces() — убери его полностью, он виден через ThreadMXBeanкоторый античиты мониторят.

Какая версия Java у Rustex? Если 8/11 — можно ещё Unsafe.defineAnonymousClass добавить как фоллбэк.
 
8 простая джава там мои соо на проверку модеров югейма юлетают почемуто xD
Rustex скорее всего хукает ClassLoader.defineClass через java.lang.instrument или патчит байткод самого метода.
Это врядли скорей всего в дллке их
 
Назад
Сверху Снизу