forked from openrs2/openrs2
parent
fef902c176
commit
bf55b0d901
@ -0,0 +1,30 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<parent> |
||||
<groupId>dev.openrs2</groupId> |
||||
<artifactId>openrs2</artifactId> |
||||
<version>1.0.0-SNAPSHOT</version> |
||||
</parent> |
||||
|
||||
<artifactId>openrs2-deob-ast</artifactId> |
||||
<packaging>jar</packaging> |
||||
|
||||
<name>OpenRS2 AST Deobfuscator</name> |
||||
|
||||
<properties> |
||||
<openrs2.root>${project.parent.basedir}</openrs2.root> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>ch.qos.logback</groupId> |
||||
<artifactId>logback-classic</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.github.javaparser</groupId> |
||||
<artifactId>javaparser-symbol-solver-core</artifactId> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,80 @@ |
||||
package dev.openrs2.deob.ast; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.nio.file.Paths; |
||||
|
||||
import com.github.javaparser.ParserConfiguration; |
||||
import com.github.javaparser.printer.PrettyPrinter; |
||||
import com.github.javaparser.printer.PrettyPrinterConfiguration; |
||||
import com.github.javaparser.symbolsolver.JavaSymbolSolver; |
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; |
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; |
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; |
||||
import com.github.javaparser.utils.SourceRoot; |
||||
import com.google.common.collect.ImmutableList; |
||||
import dev.openrs2.deob.ast.transform.AddSubTransformer; |
||||
import dev.openrs2.deob.ast.transform.ComplementTransformer; |
||||
import dev.openrs2.deob.ast.transform.Transformer; |
||||
|
||||
public final class AstDeobfuscator { |
||||
private static final ImmutableList<Transformer> TRANSFORMERS = ImmutableList.of( |
||||
new AddSubTransformer(), |
||||
new ComplementTransformer() |
||||
); |
||||
|
||||
public static void main(String[] args) { |
||||
var deobfuscator = new AstDeobfuscator(ImmutableList.of( |
||||
Paths.get("nonfree/client/src/main/java"), |
||||
Paths.get("nonfree/gl/src/main/java"), |
||||
Paths.get("nonfree/gl-dri/src/main/java"), |
||||
Paths.get("nonfree/loader/src/main/java"), |
||||
Paths.get("nonfree/signlink/src/main/java"), |
||||
Paths.get("nonfree/unpack/src/main/java"), |
||||
Paths.get("nonfree/unpacker/src/main/java") |
||||
)); |
||||
deobfuscator.run(); |
||||
} |
||||
|
||||
private final ImmutableList<Path> modules; |
||||
|
||||
public AstDeobfuscator(ImmutableList<Path> modules) { |
||||
this.modules = modules; |
||||
} |
||||
|
||||
public void run() { |
||||
var solver = new CombinedTypeSolver(new ReflectionTypeSolver(true)); |
||||
for (var module : modules) { |
||||
solver.add(new JavaParserTypeSolver(module)); |
||||
} |
||||
|
||||
var config = new ParserConfiguration() |
||||
.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_8) |
||||
.setSymbolResolver(new JavaSymbolSolver(solver)); |
||||
|
||||
var printerConfig = new PrettyPrinterConfiguration() |
||||
.setIndentType(PrettyPrinterConfiguration.IndentType.TABS_WITH_SPACE_ALIGN) |
||||
.setIndentSize(1); |
||||
|
||||
var printer = new PrettyPrinter(printerConfig); |
||||
|
||||
for (var module : modules) { |
||||
var root = new SourceRoot(module, config); |
||||
|
||||
var results = root.tryToParseParallelized(); |
||||
for (var result : results) { |
||||
if (!result.isSuccessful()) { |
||||
throw new IllegalArgumentException(result.toString()); |
||||
} |
||||
} |
||||
|
||||
root.getCompilationUnits().forEach(unit -> { |
||||
TRANSFORMERS.forEach(transformer -> { |
||||
transformer.transform(unit); |
||||
}); |
||||
}); |
||||
|
||||
root.setPrinter(printer::print); |
||||
root.saveAll(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
package dev.openrs2.deob.ast.transform; |
||||
|
||||
import com.github.javaparser.ast.CompilationUnit; |
||||
import com.github.javaparser.ast.expr.Expression; |
||||
import com.github.javaparser.ast.expr.IntegerLiteralExpr; |
||||
import com.github.javaparser.ast.expr.UnaryExpr; |
||||
import dev.openrs2.deob.ast.util.ExprUtils; |
||||
|
||||
public final class AddSubTransformer extends Transformer { |
||||
private static Expression negate(Expression expr) { |
||||
if (expr.isIntegerLiteralExpr()) { |
||||
return new IntegerLiteralExpr(-expr.asIntegerLiteralExpr().asInt()); |
||||
} else if (expr.isLongLiteralExpr()) { |
||||
return ExprUtils.createLong(-expr.asLongLiteralExpr().asLong()); |
||||
} else { |
||||
throw new IllegalArgumentException(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void transform(CompilationUnit unit) { |
||||
unit.findAll(UnaryExpr.class).forEach(expr -> { |
||||
var operand = expr.getExpression(); |
||||
if (!ExprUtils.isIntegerOrLongLiteral(operand)) { |
||||
return; |
||||
} |
||||
|
||||
var op = expr.getOperator(); |
||||
if (op == UnaryExpr.Operator.PLUS) { |
||||
expr.replace(operand); |
||||
} else if (op == UnaryExpr.Operator.MINUS) { |
||||
expr.replace(negate(operand)); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
package dev.openrs2.deob.ast.transform; |
||||
|
||||
import java.util.Optional; |
||||
|
||||
import com.github.javaparser.ast.CompilationUnit; |
||||
import com.github.javaparser.ast.expr.BinaryExpr; |
||||
import com.github.javaparser.ast.expr.Expression; |
||||
import com.github.javaparser.ast.expr.IntegerLiteralExpr; |
||||
import com.github.javaparser.ast.expr.UnaryExpr; |
||||
import dev.openrs2.deob.ast.util.ExprUtils; |
||||
|
||||
public final class ComplementTransformer extends Transformer { |
||||
private static boolean isComplement(Expression expr) { |
||||
return expr.isUnaryExpr() && expr.asUnaryExpr().getOperator() == UnaryExpr.Operator.BITWISE_COMPLEMENT; |
||||
} |
||||
|
||||
private static boolean isComplementOrLiteral(Expression expr) { |
||||
return isComplement(expr) || ExprUtils.isIntegerOrLongLiteral(expr); |
||||
} |
||||
|
||||
private static Optional<BinaryExpr.Operator> complement(BinaryExpr.Operator op) { |
||||
switch (op) { |
||||
case EQUALS: |
||||
case NOT_EQUALS: |
||||
return Optional.of(op); |
||||
case GREATER: |
||||
return Optional.of(BinaryExpr.Operator.LESS); |
||||
case GREATER_EQUALS: |
||||
return Optional.of(BinaryExpr.Operator.LESS_EQUALS); |
||||
case LESS: |
||||
return Optional.of(BinaryExpr.Operator.GREATER); |
||||
case LESS_EQUALS: |
||||
return Optional.of(BinaryExpr.Operator.GREATER_EQUALS); |
||||
default: |
||||
return Optional.empty(); |
||||
} |
||||
} |
||||
|
||||
private static Expression complement(Expression expr) { |
||||
if (expr.isUnaryExpr()) { |
||||
return expr.asUnaryExpr().getExpression(); |
||||
} else if (expr.isIntegerLiteralExpr()) { |
||||
return new IntegerLiteralExpr(~expr.asIntegerLiteralExpr().asInt()); |
||||
} else if (expr.isLongLiteralExpr()) { |
||||
return ExprUtils.createLong(~expr.asLongLiteralExpr().asLong()); |
||||
} else { |
||||
throw new IllegalArgumentException(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void transform(CompilationUnit unit) { |
||||
unit.findAll(BinaryExpr.class).forEach(expr -> { |
||||
complement(expr.getOperator()).ifPresent(op -> { |
||||
var left = expr.getLeft(); |
||||
var right = expr.getRight(); |
||||
|
||||
if (isComplementOrLiteral(left) && isComplementOrLiteral(right) && !(ExprUtils.isIntegerOrLongLiteral(left) && ExprUtils.isIntegerOrLongLiteral(right))) { |
||||
expr.setOperator(op); |
||||
expr.setLeft(complement(left)); |
||||
expr.setRight(complement(right)); |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,7 @@ |
||||
package dev.openrs2.deob.ast.transform; |
||||
|
||||
import com.github.javaparser.ast.CompilationUnit; |
||||
|
||||
public abstract class Transformer { |
||||
public abstract void transform(CompilationUnit unit); |
||||
} |
@ -0,0 +1,18 @@ |
||||
package dev.openrs2.deob.ast.util; |
||||
|
||||
import com.github.javaparser.ast.expr.Expression; |
||||
import com.github.javaparser.ast.expr.LongLiteralExpr; |
||||
|
||||
public final class ExprUtils { |
||||
public static boolean isIntegerOrLongLiteral(Expression expr) { |
||||
return expr.isIntegerLiteralExpr() || expr.isLongLiteralExpr(); |
||||
} |
||||
|
||||
public static LongLiteralExpr createLong(long value) { |
||||
return new LongLiteralExpr(Long.toString(value).concat("L")); |
||||
} |
||||
|
||||
private ExprUtils() { |
||||
/* empty */ |
||||
} |
||||
} |
Loading…
Reference in new issue