diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java index 6aa174140..518a12d6d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java @@ -21,12 +21,13 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Helper; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.regex.Pattern; @@ -104,26 +105,27 @@ public class IdentifiersDeobfuscation { return false; } - private String fooString(boolean as3, HashMap deobfuscated, String orig, boolean firstUppercase, int rndSize) { + private String fooString(boolean as3, HashMap deobfuscated, String orig, boolean firstUppercase, int rndSize) { boolean exists; String ret; loopfoo: do { exists = false; int len = 3 + rnd.nextInt(rndSize - 3); - ret = ""; + StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++) { - String c = ""; + char c; if ((i % 2) == 0) { - c = "" + FOO_CHARACTERS.charAt(rnd.nextInt(FOO_CHARACTERS.length())); + c = FOO_CHARACTERS.charAt(rnd.nextInt(FOO_CHARACTERS.length())); } else { - c = "" + FOO_JOIN_CHARACTERS.charAt(rnd.nextInt(FOO_JOIN_CHARACTERS.length())); + c = FOO_JOIN_CHARACTERS.charAt(rnd.nextInt(FOO_JOIN_CHARACTERS.length())); } if (i == 0 && firstUppercase) { - c = c.toUpperCase(Locale.ENGLISH); + c = Character.toUpperCase(c); } - ret += c; + sb.append(c); } + ret = sb.toString(); if (allVariableNamesStr.contains(ret)) { exists = true; rndSize += 1; @@ -134,7 +136,7 @@ public class IdentifiersDeobfuscation { rndSize += 1; continue; } - if (deobfuscated.containsValue(ret)) { + if (deobfuscated.containsValue(DottedChain.parse(ret))) { exists = true; rndSize += 1; continue; @@ -143,7 +145,7 @@ public class IdentifiersDeobfuscation { return ret; } - public void deobfuscateInstanceNames(boolean as3, HashMap namesMap, RenameType renameType, List tags, Map selected) { + public void deobfuscateInstanceNames(boolean as3, HashMap namesMap, RenameType renameType, List tags, Map selected) { for (Tag t : tags) { if (t instanceof DefineSpriteTag) { deobfuscateInstanceNames(as3, namesMap, renameType, ((DefineSpriteTag) t).subTags, selected); @@ -170,50 +172,38 @@ public class IdentifiersDeobfuscation { } } - public String deobfuscatePackage(boolean as3, String pkg, HashMap namesMap, RenameType renameType, Map selected) { + public DottedChain deobfuscatePackage(boolean as3, DottedChain pkg, HashMap namesMap, RenameType renameType, Map selected) { if (namesMap.containsKey(pkg)) { return namesMap.get(pkg); } - String[] parts = null; - if (pkg.contains(".")) { - parts = pkg.split("\\."); - } else { - parts = new String[]{pkg}; - } - StringBuilder ret = new StringBuilder(); + List ret = new ArrayList<>(pkg.size()); boolean isChanged = false; - for (int p = 0; p < parts.length; p++) { - if (p > 0) { - ret.append("."); - } - String partChanged = deobfuscateName(as3, parts[p], false, "package", namesMap, renameType, selected); + for (int p = 0; p < pkg.size(); p++) { + String part = pkg.get(p); + String partChanged = deobfuscateName(as3, part, false, "package", namesMap, renameType, selected); if (partChanged != null) { - ret.append(partChanged); + ret.add(partChanged); isChanged = true; } else { - ret.append(parts[p]); + ret.add(part); } } if (isChanged) { - String retStr = ret.toString(); - namesMap.put(pkg, retStr); - return retStr; + DottedChain chain = new DottedChain(ret); + namesMap.put(pkg, chain); + return chain; } return null; } - public String deobfuscateNameWithPackage(boolean as3, String n, HashMap namesMap, RenameType renameType, Map selected) { - String pkg = null; - String name = ""; - if (n.contains(".")) { - pkg = n.substring(0, n.lastIndexOf('.')); - name = n.substring(n.lastIndexOf('.') + 1); - } else { - name = n; - } + public String deobfuscateNameWithPackage(boolean as3, String n, HashMap namesMap, RenameType renameType, Map selected) { + DottedChain nChain = DottedChain.parse(n); + DottedChain pkg = nChain.getWithoutLast(); + String name = nChain.getLast(); + boolean changed = false; if ((pkg != null) && (!pkg.isEmpty())) { - String changedPkg = deobfuscatePackage(as3, pkg, namesMap, renameType, selected); + DottedChain changedPkg = deobfuscatePackage(as3, pkg, namesMap, renameType, selected); if (changedPkg != null) { changed = true; pkg = changedPkg; @@ -258,22 +248,23 @@ public class IdentifiersDeobfuscation { return false; } - public String deobfuscateName(boolean as3, String s, boolean firstUppercase, String usageType, HashMap namesMap, RenameType renameType, Map selected) { + public String deobfuscateName(boolean as3, String s, boolean firstUppercase, String usageType, HashMap namesMap, RenameType renameType, Map selected) { boolean isValid = true; if (usageType == null) { usageType = "name"; } + DottedChain sChain = DottedChain.parse(s); if (selected != null) { - if (selected.containsKey(s)) { - return selected.get(s); + if (selected.containsKey(sChain)) { + return selected.get(sChain).toRawString(); } } isValid = isValidName(as3, s); if (!isValid) { - if (namesMap.containsKey(s)) { - return namesMap.get(s); + if (namesMap.containsKey(sChain)) { + return namesMap.get(sChain).toRawString(); } else { Integer cnt = typeCounts.get(usageType); if (cnt == null) { @@ -294,7 +285,7 @@ public class IdentifiersDeobfuscation { } else if (renameType == RenameType.RANDOMWORD) { ret = fooString(as3, namesMap, s, firstUppercase, DEFAULT_FOO_SIZE); } - namesMap.put(s, ret); + namesMap.put(DottedChain.parse(s), DottedChain.parse(ret)); return ret; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index a3d23cac2..1ab01d567 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -125,6 +125,7 @@ import com.jpexs.decompiler.flash.types.filters.BlendComposite; import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.decompiler.flash.xfl.FLAVersion; import com.jpexs.decompiler.flash.xfl.XFLConverter; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemContainer; @@ -284,7 +285,7 @@ public final class SWF implements SWFContainerItem, Timelined { public DefineBinaryDataTag binaryData; @Internal - private final HashMap deobfuscated = new HashMap<>(); + private final HashMap deobfuscated = new HashMap<>(); @Internal private final IdentifiersDeobfuscation deobfuscation = new IdentifiersDeobfuscation(); @@ -1886,8 +1887,8 @@ public final class SWF implements SWFContainerItem, Timelined { } public void renameAS2Identifier(String identifier, String newname) throws InterruptedException { - Map selected = new HashMap<>(); - selected.put(identifier, newname); + Map selected = new HashMap<>(); + selected.put(DottedChain.parse(identifier), DottedChain.parse(newname)); renameAS2Identifiers(null, selected); } @@ -1895,7 +1896,7 @@ public final class SWF implements SWFContainerItem, Timelined { return renameAS2Identifiers(renameType, null); } - private int renameAS2Identifiers(RenameType renameType, Map selected) throws InterruptedException { + private int renameAS2Identifiers(RenameType renameType, Map selected) throws InterruptedException { HashMap actionsMap = new HashMap<>(); List allFunctions = new ArrayList<>(); List> allVariableNames = new ArrayList<>(); @@ -1959,7 +1960,7 @@ public final class SWF implements SWFContainerItem, Timelined { String fname = dvf.toStringNoH(null); String changed = deobfuscation.deobfuscateName(false, fname, false, "method", deobfuscated, renameType, selected); if (changed != null) { - deobfuscated.put(fname, changed); + deobfuscated.put(DottedChain.parse(fname), DottedChain.parse(changed)); } } } @@ -1978,7 +1979,7 @@ public final class SWF implements SWFContainerItem, Timelined { String vname = dvf.toStringNoH(null); String changed = deobfuscation.deobfuscateName(false, vname, false, "attribute", deobfuscated, renameType, selected); if (changed != null) { - deobfuscated.put(vname, changed); + deobfuscated.put(DottedChain.parse(vname), DottedChain.parse(changed)); } } } @@ -2014,7 +2015,7 @@ public final class SWF implements SWFContainerItem, Timelined { changedNameStr = changedNameStr2; } ret++; - deobfuscated.put(nameStr, changedNameStr); + deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); pos++; } name = mem.object; @@ -2038,7 +2039,7 @@ public final class SWF implements SWFContainerItem, Timelined { changedNameStr = changedNameStr2; } ret++; - deobfuscated.put(nameStr, changedNameStr); + deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); pos++; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index c57d15399..81a82284e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -282,7 +282,7 @@ public class ABC { } } - public void deobfuscateIdentifiers(HashMap namesMap, RenameType renameType, boolean classesOnly) { + public void deobfuscateIdentifiers(HashMap namesMap, RenameType renameType, boolean classesOnly) { Set stringUsages = getStringUsages(); Set namespaceUsages = getNsStringUsages(); Map stringUsageTypes = new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java index 467b9ecce..3a93c56b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java @@ -30,13 +30,13 @@ public class ClassPath { public final String className; public ClassPath(DottedChain packageStr, String className) { - this.packageStr = packageStr; + this.packageStr = packageStr == null ? DottedChain.EMPTY : packageStr; this.className = className; } @Override public String toString() { - return (packageStr == null || packageStr.isEmpty()) ? className : packageStr.toPrintableString(true) + "." + className; + return packageStr.isEmpty() ? className : packageStr.toPrintableString(true) + "." + className; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java index 642c4b5f2..17384cd43 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java @@ -421,12 +421,7 @@ public class AVM2ConstantPool { String str = getString(index); DottedChain chain = dottedChainCache.get(str); if (chain == null) { - if (str.isEmpty()) { - chain = DottedChain.EMPTY; - } else { - chain = new DottedChain(str.split("\\.")); - } - + chain = DottedChain.parse(str); dottedChainCache.put(str, chain); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java index 2589e03dc..69b9a9bf9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java @@ -18,8 +18,9 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.graph.DottedChain; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Locale; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; @@ -109,7 +110,7 @@ public class AVM2Deobfuscation { return null; } - private String fooString(HashMap deobfuscated, String orig, boolean firstUppercase, int rndSize, String usageType, RenameType renameType) { + private String fooString(HashMap deobfuscated, String orig, boolean firstUppercase, int rndSize, String usageType, RenameType renameType) { boolean exists; String ret; int pos = 0; @@ -131,18 +132,21 @@ public class AVM2Deobfuscation { } else if (renameType == RenameType.RANDOMWORD) { int len = 3 + rnd.nextInt(rndSize - 3); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < len; i++) { - String c = ""; + char c; if ((i % 2) == 0) { - c = "" + FOO_CHARACTERS.charAt(rnd.nextInt(FOO_CHARACTERS.length())); + c = FOO_CHARACTERS.charAt(rnd.nextInt(FOO_CHARACTERS.length())); } else { - c = "" + FOO_JOIN_CHARACTERS.charAt(rnd.nextInt(FOO_JOIN_CHARACTERS.length())); + c = FOO_JOIN_CHARACTERS.charAt(rnd.nextInt(FOO_JOIN_CHARACTERS.length())); } if (i == 0 && firstUppercase) { - c = c.toUpperCase(Locale.ENGLISH); + c = Character.toUpperCase(c); } - ret += c; + sb.append(c); } + + ret = sb.toString(); } for (int i = 1; i < constants.getStringCount(); i++) { if (constants.getString(i).equals(ret)) { @@ -156,18 +160,18 @@ public class AVM2Deobfuscation { rndSize += 1; continue; } - if (deobfuscated.containsValue(ret)) { + if (deobfuscated.containsValue(DottedChain.parse(ret))) { exists = true; rndSize += 1; continue; } } while (exists); usageTypesCount.put(usageType, pos); - deobfuscated.put(orig, ret); + deobfuscated.put(DottedChain.parse(orig), DottedChain.parse(ret)); return ret; } - public int deobfuscatePackageName(Map stringUsageTypes, Set stringUsages, HashMap namesMap, int strIndex, RenameType renameType) { + public int deobfuscatePackageName(Map stringUsageTypes, Set stringUsages, HashMap namesMap, int strIndex, RenameType renameType) { if (strIndex <= 0) { return strIndex; } @@ -177,41 +181,35 @@ public class AVM2Deobfuscation { } boolean isValid = isValidNSPart(s); if (!isValid) { - String newName; - if (namesMap.containsKey(s)) { - newName = constants.setString(strIndex, namesMap.get(s)); + DottedChain sChain = DottedChain.parse(s); + DottedChain newName; + if (namesMap.containsKey(sChain)) { + newName = namesMap.get(sChain); + constants.setString(strIndex, newName.toRawString()); } else { - String[] parts = null; - if (s.contains(".")) { - parts = s.split("\\."); - } else { - parts = new String[]{s}; - } - StringBuilder ret = new StringBuilder(); - for (int p = 0; p < parts.length; p++) { - if (p > 0) { - ret.append("."); - } - if (!isValidNSPart(parts[p])) { - ret.append(fooString(namesMap, parts[p], false, DEFAULT_FOO_SIZE, "package", renameType)); + List ret = new ArrayList<>(); + for (int p = 0; p < sChain.size(); p++) { + String part = sChain.get(p); + if (!isValidNSPart(part)) { + ret.add(fooString(namesMap, part, false, DEFAULT_FOO_SIZE, "package", renameType)); } else { - ret.append(parts[p]); + ret.add(part); } } - newName = ret.toString(); - namesMap.put(s, newName); + newName = new DottedChain(ret); + namesMap.put(sChain, newName); } if (stringUsages.contains(strIndex)) { - strIndex = constants.addString(newName); + strIndex = constants.addString(newName.toRawString()); } else { - constants.setString(strIndex, newName); + constants.setString(strIndex, newName.toRawString()); } } return strIndex; } - public int deobfuscateName(Map stringUsageTypes, Set stringUsages, Set namespaceUsages, HashMap namesMap, int strIndex, boolean firstUppercase, RenameType renameType) { + public int deobfuscateName(Map stringUsageTypes, Set stringUsages, Set namespaceUsages, HashMap namesMap, int strIndex, boolean firstUppercase, RenameType renameType) { if (strIndex <= 0) { return strIndex; } @@ -238,18 +236,20 @@ public class AVM2Deobfuscation { } if (!isValid) { - String newname; - if (namesMap.containsKey(s)) { - newname = namesMap.get(s); + DottedChain newname; + DottedChain sChain = DottedChain.parse(s); + if (namesMap.containsKey(sChain)) { + newname = namesMap.get(sChain); } else { - newname = fooString(namesMap, constants.getString(strIndex), firstUppercase, DEFAULT_FOO_SIZE, stringUsageTypes.get(strIndex), renameType); + String str = fooString(namesMap, constants.getString(strIndex), firstUppercase, DEFAULT_FOO_SIZE, stringUsageTypes.get(strIndex), renameType); + newname = DottedChain.parse(str); } if (stringUsages.contains(strIndex) || namespaceUsages.contains(strIndex)) { // this name is already referenced as String strIndex = constants.addString(s); // add new index } - constants.setString(strIndex, newname); - if (!namesMap.containsKey(s)) { - namesMap.put(s, constants.getString(strIndex)); + constants.setString(strIndex, newname.toRawString()); + if (!namesMap.containsKey(sChain)) { + namesMap.put(sChain, DottedChain.parse(constants.getString(strIndex))); } } return strIndex; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index ed5542257..25ab403c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -294,7 +294,7 @@ public class Multiname { return isAttribute() ? "@*" : "*"; } else { String name = constants.getString(name_index); - if (fullyQualifiedNames != null && fullyQualifiedNames.contains(name)) { + if (fullyQualifiedNames != null && fullyQualifiedNames.contains(DottedChain.parse(name))) { DottedChain dc = getNameWithNamespace(constants); return raw ? dc.toRawString() : dc.toPrintableString(true); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 870966d97..29e2c5af1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -381,8 +381,7 @@ public class TraitClass extends Trait implements TraitWithSlot { for (ScriptInfo si : tag.getABC().script_info) { for (Trait t : si.traits.traits) { ClassPath classPath = t.getPath(tag.getABC()); - DottedChain pkg = classPath.packageStr == null ? DottedChain.EMPTY : classPath.packageStr; - if (pkg.equals(packageName)) { + if (classPath.packageStr.equals(packageName)) { namesInThisPackage.add(classPath.className); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java index 3fbff38b9..204e3cad4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -66,6 +66,14 @@ public class DottedChain implements Serializable { private final int hash; + public static final DottedChain parse(String name) { + if (name == null || name.isEmpty()) { + return DottedChain.EMPTY; + } else { + return new DottedChain(name.split("\\.")); + } + } + public DottedChain(List parts) { length = parts.size(); this.parts = parts.toArray(new String[length]);