Skip to content

Commit

Permalink
getCommonSuperClass - move away from custom classloader and use Inher…
Browse files Browse the repository at this point in the history
…itanceGraph

this should resolve issues with libraries which were compiled against a newer java version than the obfuscator was running.
Other changes:
- Update cafedude, use fork of SSVM to be able to update cafedude
- Use SLF4J bridge
- Make Classpath immutable
- More uses for cafedude
  • Loading branch information
EpicPlayerA10 committed Oct 9, 2024
1 parent e5bb812 commit fe861df
Show file tree
Hide file tree
Showing 20 changed files with 1,243 additions and 211 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[*]
[*.java]
charset = utf-8
end_of_line = lf
indent_style = space
Expand Down
36 changes: 15 additions & 21 deletions deobfuscator-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@

<log4j.version>2.23.1</log4j.version>
<slf4j.version>2.0.13</slf4j.version>
<kafedjud.version>1.10.2</kafedjud.version>
<ssvm.version>d559ea90bb</ssvm.version>
<cafedude.version>83ea274ff8</cafedude.version>
<ssvm.version>4d3f2bc142</ssvm.version>
<jlinker.version>205d8eaa1f</jlinker.version>
</properties>

Expand All @@ -51,88 +51,82 @@
<version>${jlinker.version}</version>
</dependency>

<!-- SSVM -->
<dependency>
<groupId>com.github.xxDark.SSVM</groupId>
<groupId>com.github.EpicPlayerA10.SSVM</groupId>
<artifactId>mirrors</artifactId>
<version>${ssvm.version}</version>
</dependency>

<dependency>
<groupId>com.github.xxDark.SSVM</groupId>
<groupId>com.github.EpicPlayerA10.SSVM</groupId>
<artifactId>ssvm-core</artifactId>
<version>${ssvm.version}</version>
</dependency>

<dependency>
<groupId>com.github.xxDark.SSVM</groupId>
<groupId>com.github.EpicPlayerA10.SSVM</groupId>
<artifactId>ssvm-invoke</artifactId>
<version>${ssvm.version}</version>
</dependency>

<dependency>
<groupId>com.github.xxDark.SSVM</groupId>
<groupId>com.github.EpicPlayerA10.SSVM</groupId>
<artifactId>ssvm-io</artifactId>
<version>${ssvm.version}</version>
</dependency>

<!-- ASM -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>${asm.version}</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>${asm.version}</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
<version>${asm.version}</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-analysis</artifactId>
<version>${asm.version}</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>

<!-- SLF4J Bridge -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<version>2.0.16</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j.version}</version>
</dependency>

<dependency>
<groupId>com.github.Col-E</groupId>
<artifactId>CAFED00D</artifactId>
<version>${kafedjud.version}</version>
<version>${cafedude.version}</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import uwu.narumi.deobfuscator.api.context.Context;
import uwu.narumi.deobfuscator.api.helper.ClassHelper;
import uwu.narumi.deobfuscator.api.classpath.ClasspathClassWriter;
import uwu.narumi.deobfuscator.api.classpath.InheritanceClassWriter;
import uwu.narumi.deobfuscator.api.inheritance.InheritanceGraph;

public class ClassWrapper implements Cloneable {

Expand All @@ -27,7 +27,7 @@ public class ClassWrapper implements Cloneable {
private final ConstantPool constantPool;
private final int classWriterFlags;

public ClassWrapper(String pathInJar, ClassReader classReader, int classReaderFlags, int classWriterFlags) throws Exception {
public ClassWrapper(String pathInJar, ClassReader classReader, int classReaderFlags, int classWriterFlags) {
this.pathInJar = pathInJar;
this.classNode = new ClassNode();
this.constantPool = new ConstantPool(classReader);
Expand Down Expand Up @@ -129,9 +129,9 @@ public String canonicalName() {
/**
* Compiles class to bytes.
*/
public byte[] compileToBytes(Context context) {
public byte[] compileToBytes(InheritanceGraph inheritanceGraph) {
try {
ClassWriter classWriter = new ClasspathClassWriter(this.classWriterFlags, context.getClasspath());
ClassWriter classWriter = new InheritanceClassWriter(this.classWriterFlags, inheritanceGraph);
this.classNode.accept(classWriter);

return classWriter.toByteArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,114 @@

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import uwu.narumi.deobfuscator.api.context.DeobfuscatorOptions;
import uwu.narumi.deobfuscator.api.helper.ClassHelper;
import uwu.narumi.deobfuscator.api.helper.FileHelper;

/**
* All sources for deobfuscated jar
* Immutable classpath
*
* @param classesInfo Class nodes that hold only the class information, not code
*/
public class Classpath {
public record Classpath(
Map<String, byte[]> rawClasses,
Map<String, byte[]> files,
Map<String, ClassNode> classesInfo
) {

public static Builder builder() {
return new Builder();
}

private static final Logger LOGGER = LogManager.getLogger(Classpath.class);
public static class Builder {
private static final Logger LOGGER = LogManager.getLogger();

private final Map<String, byte[]> files = new ConcurrentHashMap<>();
private final Map<String, byte[]> classes = new ConcurrentHashMap<>();
private final Map<String, byte[]> rawClasses = new HashMap<>();
private final Map<String, byte[]> files = new HashMap<>();

private final int classWriterFlags;
private final Map<String, ClassNode> classesInfo = new HashMap<>();

public Classpath(int classWriterFlags) {
this.classWriterFlags = classWriterFlags;
}
private Builder() {
}

/**
* Adds jar to classpath
*
* @param jarPath Jar path
*/
public void addJar(@NotNull Path jarPath) {
int prevSize = classes.size();

FileHelper.loadFilesFromZip(
jarPath,
(classPath, bytes) -> {
if (!ClassHelper.isClass(classPath, bytes)) {
files.putIfAbsent(classPath, bytes);
return;
}

try {
String className = ClassHelper.loadClass(
classPath,
bytes,
ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG,
classWriterFlags
).name();

classes.putIfAbsent(className, bytes);
} catch (Exception e) {
LOGGER.error("Could not load {} class from {} library", classPath, jarPath, e);
}
});

LOGGER.info("Loaded {} classes from {}", classes.size() - prevSize, jarPath.getFileName());
}
/**
* Adds jar to classpath
*
* @param jarPath Jar path
*/
@Contract("_ -> this")
public Builder addJar(@NotNull Path jarPath) {
FileHelper.loadFilesFromZip(jarPath, (classPath, bytes) -> {
if (!ClassHelper.isClass(classPath, bytes)) {
files.putIfAbsent(classPath, bytes);
return;
}

try {
ClassNode classNode = ClassHelper.loadUnknownClassInfo(bytes);
String className = classNode.name;

rawClasses.putIfAbsent(className, bytes);
classesInfo.putIfAbsent(className, classNode);
} catch (Exception e) {
LOGGER.error("Could not load {} class from {} library", classPath, jarPath, e);
}
});

return this;
}

/**
* Adds {@link DeobfuscatorOptions.ExternalClass} to classpath
*
* @param externalClass External class
*/
@Contract("_ -> this")
public Builder addExternalClass(DeobfuscatorOptions.ExternalClass externalClass) {
try {
byte[] classBytes = Files.readAllBytes(externalClass.path());

ClassNode classNode = ClassHelper.loadUnknownClassInfo(classBytes);

/**
* Adds {@link DeobfuscatorOptions.ExternalClass} to classpath
*
* @param externalClass External class
*/
public void addExternalClass(DeobfuscatorOptions.ExternalClass externalClass) {
try {
byte[] classBytes = Files.readAllBytes(externalClass.path());
String className = ClassHelper.loadClass(
externalClass.pathInJar(),
classBytes,
ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG,
classWriterFlags
).name();

// Add class to classpath
classes.putIfAbsent(className, classBytes);
} catch (Exception e) {
throw new RuntimeException(e);
String className = classNode.name;

// Add class to classpath
rawClasses.putIfAbsent(className, classBytes);
classesInfo.putIfAbsent(className, classNode);
} catch (Exception e) {
throw new RuntimeException(e);
}

return this;
}
}

public Map<String, byte[]> getFiles() {
return this.files;
}
/**
* Adds another classpath to this classpath
*/
@Contract("_ -> this")
public Builder addClasspath(Classpath classpath) {
this.rawClasses.putAll(classpath.rawClasses);
this.files.putAll(classpath.files);
this.classesInfo.putAll(classpath.classesInfo);

public Map<String, byte[]> getClasses() {
return this.classes;
return this;
}

public Classpath build() {
return new Classpath(
Collections.unmodifiableMap(rawClasses),
Collections.unmodifiableMap(files),
Collections.unmodifiableMap(classesInfo)
);
}
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit fe861df

Please sign in to comment.