diff options
| author | 2015-03-19 02:20:32 -0400 | |
|---|---|---|
| committer | 2015-03-19 02:20:32 -0400 | |
| commit | 96ba0ab422d7f9747e93461524991cf5ceeb48c4 (patch) | |
| tree | cd9504acae257575e0a354e79386da67acd796c6 /src | |
| parent | Added tag v0.10 beta for changeset 68f12fd9afb0 (diff) | |
| download | enigma-fork-96ba0ab422d7f9747e93461524991cf5ceeb48c4.tar.gz enigma-fork-96ba0ab422d7f9747e93461524991cf5ceeb48c4.tar.xz enigma-fork-96ba0ab422d7f9747e93461524991cf5ceeb48c4.zip | |
fix issue with naming method arguments and the local variable tables
Diffstat (limited to 'src')
4 files changed, 82 insertions, 7 deletions
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index ecd7d64..dce4b85 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -233,7 +233,7 @@ public class TranslatingTypeLoader implements ITypeLoader { | |||
| 233 | // do all kinds of deobfuscating transformations on the class | 233 | // do all kinds of deobfuscating transformations on the class |
| 234 | new BridgeMarker(m_jarIndex).markBridges(c); | 234 | new BridgeMarker(m_jarIndex).markBridges(c); |
| 235 | new MethodParameterWriter(m_deobfuscatingTranslator).writeMethodArguments(c); | 235 | new MethodParameterWriter(m_deobfuscatingTranslator).writeMethodArguments(c); |
| 236 | new LocalVariableRenamer().rename(c); | 236 | new LocalVariableRenamer(m_deobfuscatingTranslator).rename(c); |
| 237 | new ClassTranslator(m_deobfuscatingTranslator).translate(c); | 237 | new ClassTranslator(m_deobfuscatingTranslator).translate(c); |
| 238 | 238 | ||
| 239 | return c; | 239 | return c; |
diff --git a/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java b/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java index c87c25b..1179560 100644 --- a/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java +++ b/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java | |||
| @@ -6,9 +6,20 @@ import javassist.bytecode.ByteArray; | |||
| 6 | import javassist.bytecode.CodeAttribute; | 6 | import javassist.bytecode.CodeAttribute; |
| 7 | import javassist.bytecode.ConstPool; | 7 | import javassist.bytecode.ConstPool; |
| 8 | import javassist.bytecode.LocalVariableAttribute; | 8 | import javassist.bytecode.LocalVariableAttribute; |
| 9 | import javassist.bytecode.LocalVariableTypeAttribute; | ||
| 10 | import cuchaz.enigma.mapping.ArgumentEntry; | ||
| 11 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 12 | import cuchaz.enigma.mapping.EntryFactory; | ||
| 13 | import cuchaz.enigma.mapping.Translator; | ||
| 9 | 14 | ||
| 10 | 15 | ||
| 11 | public class LocalVariableRenamer { | 16 | public class LocalVariableRenamer { |
| 17 | |||
| 18 | private Translator m_translator; | ||
| 19 | |||
| 20 | public LocalVariableRenamer(Translator translator) { | ||
| 21 | m_translator = translator; | ||
| 22 | } | ||
| 12 | 23 | ||
| 13 | public void rename(CtClass c) { | 24 | public void rename(CtClass c) { |
| 14 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { | 25 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { |
| @@ -18,18 +29,67 @@ public class LocalVariableRenamer { | |||
| 18 | if (codeAttribute == null) { | 29 | if (codeAttribute == null) { |
| 19 | continue; | 30 | continue; |
| 20 | } | 31 | } |
| 32 | |||
| 33 | BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior); | ||
| 34 | ConstPool constants = c.getClassFile().getConstPool(); | ||
| 35 | |||
| 21 | LocalVariableAttribute table = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag); | 36 | LocalVariableAttribute table = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag); |
| 22 | if (table == null) { | 37 | if (table != null) { |
| 23 | continue; | 38 | renameTable(behaviorEntry, constants, table); |
| 24 | } | 39 | } |
| 25 | 40 | ||
| 26 | ConstPool constants = c.getClassFile().getConstPool(); | 41 | LocalVariableTypeAttribute typeTable = (LocalVariableTypeAttribute)codeAttribute.getAttribute(LocalVariableAttribute.typeTag); |
| 27 | for (int i=0; i<table.tableLength(); i++) { | 42 | if (typeTable != null) { |
| 28 | renameVariable(table, i, constants.addUtf8Info("v" + i)); | 43 | renameTable(behaviorEntry, constants, typeTable); |
| 29 | } | 44 | } |
| 30 | } | 45 | } |
| 31 | } | 46 | } |
| 32 | 47 | ||
| 48 | // DEBUG | ||
| 49 | @SuppressWarnings("unused") | ||
| 50 | private void dumpTable(LocalVariableAttribute table) { | ||
| 51 | for (int i=0; i<table.tableLength(); i++) { | ||
| 52 | System.out.println(String.format("\t%d (%d): %s %s", | ||
| 53 | i, table.index(i), table.variableName(i), table.descriptor(i) | ||
| 54 | )); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | private void renameTable(BehaviorEntry behaviorEntry, ConstPool constants, LocalVariableAttribute table) { | ||
| 59 | |||
| 60 | // skip empty tables | ||
| 61 | if (table.tableLength() <= 0) { | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 65 | // where do we start counting variables? | ||
| 66 | int starti = 0; | ||
| 67 | if (table.variableName(0).equals("this")) { | ||
| 68 | // skip the "this" variable | ||
| 69 | starti = 1; | ||
| 70 | } | ||
| 71 | |||
| 72 | // rename method arguments first | ||
| 73 | int numArgs = 0; | ||
| 74 | if (behaviorEntry.getSignature() != null) { | ||
| 75 | numArgs = behaviorEntry.getSignature().getArgumentTypes().size(); | ||
| 76 | for (int i=starti; i<starti + numArgs && i<table.tableLength(); i++) { | ||
| 77 | int argi = i - starti; | ||
| 78 | String argName = m_translator.translate(new ArgumentEntry(behaviorEntry, argi, "")); | ||
| 79 | if (argName == null) { | ||
| 80 | argName = "a" + (argi + 1); | ||
| 81 | } | ||
| 82 | renameVariable(table, i, constants.addUtf8Info(argName)); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | // then rename the rest of the args, if any | ||
| 87 | for (int i=starti + numArgs; i<table.tableLength(); i++) { | ||
| 88 | int firstIndex = table.index(starti + numArgs); | ||
| 89 | renameVariable(table, i, constants.addUtf8Info("v" + (table.index(i) - firstIndex + 1))); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 33 | private void renameVariable(LocalVariableAttribute table, int i, int stringId) { | 93 | private void renameVariable(LocalVariableAttribute table, int i, int stringId) { |
| 34 | // based off of LocalVariableAttribute.nameIndex() | 94 | // based off of LocalVariableAttribute.nameIndex() |
| 35 | ByteArray.write16bit(stringId, table.get(), i*10 + 6); | 95 | ByteArray.write16bit(stringId, table.get(), i*10 + 6); |
diff --git a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java index f64ca02..87c9196 100644 --- a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java +++ b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java | |||
| @@ -15,6 +15,8 @@ import java.util.List; | |||
| 15 | 15 | ||
| 16 | import javassist.CtBehavior; | 16 | import javassist.CtBehavior; |
| 17 | import javassist.CtClass; | 17 | import javassist.CtClass; |
| 18 | import javassist.bytecode.CodeAttribute; | ||
| 19 | import javassist.bytecode.LocalVariableAttribute; | ||
| 18 | import cuchaz.enigma.mapping.ArgumentEntry; | 20 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 19 | import cuchaz.enigma.mapping.BehaviorEntry; | 21 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 20 | import cuchaz.enigma.mapping.EntryFactory; | 22 | import cuchaz.enigma.mapping.EntryFactory; |
| @@ -33,6 +35,15 @@ public class MethodParameterWriter { | |||
| 33 | 35 | ||
| 34 | // Procyon will read method arguments from the "MethodParameters" attribute, so write those | 36 | // Procyon will read method arguments from the "MethodParameters" attribute, so write those |
| 35 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { | 37 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { |
| 38 | |||
| 39 | // if there's a local variable table here, don't write a MethodParameters attribute | ||
| 40 | // let the local variable writer deal with it instead | ||
| 41 | // procyon starts doing really weird things if we give it both attributes | ||
| 42 | CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute(); | ||
| 43 | if (codeAttribute != null && codeAttribute.getAttribute(LocalVariableAttribute.tag) != null) { | ||
| 44 | continue; | ||
| 45 | } | ||
| 46 | |||
| 36 | BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior); | 47 | BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior); |
| 37 | 48 | ||
| 38 | // get the number of arguments | 49 | // get the number of arguments |
| @@ -53,6 +64,9 @@ public class MethodParameterWriter { | |||
| 53 | } | 64 | } |
| 54 | 65 | ||
| 55 | // save the mappings to the class | 66 | // save the mappings to the class |
| 67 | for (String name : names) { | ||
| 68 | System.out.println("\t" + name); | ||
| 69 | } | ||
| 56 | MethodParametersAttribute.updateClass(behavior.getMethodInfo(), names); | 70 | MethodParametersAttribute.updateClass(behavior.getMethodInfo(), names); |
| 57 | } | 71 | } |
| 58 | } | 72 | } |
diff --git a/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java index bf95956..27f5b9b 100644 --- a/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java +++ b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java | |||
| @@ -27,6 +27,7 @@ public class MethodParametersAttribute extends AttributeInfo { | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | public static void updateClass(MethodInfo info, List<String> names) { | 29 | public static void updateClass(MethodInfo info, List<String> names) { |
| 30 | |||
| 30 | // add the names to the class const pool | 31 | // add the names to the class const pool |
| 31 | ConstPool constPool = info.getConstPool(); | 32 | ConstPool constPool = info.getConstPool(); |
| 32 | List<Integer> parameterNameIndices = new ArrayList<Integer>(); | 33 | List<Integer> parameterNameIndices = new ArrayList<Integer>(); |
| @@ -44,7 +45,7 @@ public class MethodParametersAttribute extends AttributeInfo { | |||
| 44 | 45 | ||
| 45 | private static byte[] writeStruct(List<Integer> parameterNameIndices) { | 46 | private static byte[] writeStruct(List<Integer> parameterNameIndices) { |
| 46 | // JVM 8 Spec says the struct looks like this: | 47 | // JVM 8 Spec says the struct looks like this: |
| 47 | // http://cr.openjdk.java.net/~mr/se/8/java-se-8-fr-spec-01/java-se-8-jvms-fr-diffs.pdf | 48 | // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24 |
| 48 | // uint8 num_params | 49 | // uint8 num_params |
| 49 | // for each param: | 50 | // for each param: |
| 50 | // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry | 51 | // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry |