Commit 14ed0c3a authored by Skylot's avatar Skylot

core: rename classes with unicode characters or reserved names

parent 229d78f1
...@@ -28,8 +28,8 @@ public class Deobfuscator { ...@@ -28,8 +28,8 @@ public class Deobfuscator {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private static final String MAP_FILE_CHARSET = "UTF-8"; private static final String MAP_FILE_CHARSET = "UTF-8";
private static final String classNameSeparator = "."; private static final String CLASS_NAME_SEPARATOR = ".";
private static final String innerClassSeparator = "$"; private static final String INNER_CLASS_SEPARATOR = "$";
private final Map<ClassInfo, DeobfClsInfo> clsMap = new HashMap<ClassInfo, DeobfClsInfo>(); private final Map<ClassInfo, DeobfClsInfo> clsMap = new HashMap<ClassInfo, DeobfClsInfo>();
private final IJadxArgs args; private final IJadxArgs args;
...@@ -43,6 +43,7 @@ public class Deobfuscator { ...@@ -43,6 +43,7 @@ public class Deobfuscator {
private int clsIndex = 0; private int clsIndex = 0;
private final PackageNode rootPackage = new PackageNode(""); private final PackageNode rootPackage = new PackageNode("");
private final Set<String> pkgSet = new TreeSet<String>();
private Map<String, String> preLoadClsMap = Collections.emptyMap(); private Map<String, String> preLoadClsMap = Collections.emptyMap();
public Deobfuscator(IJadxArgs args, @NotNull List<DexNode> dexNodes, File deobfMapFile) { public Deobfuscator(IJadxArgs args, @NotNull List<DexNode> dexNodes, File deobfMapFile) {
...@@ -106,14 +107,14 @@ public class Deobfuscator { ...@@ -106,14 +107,14 @@ public class Deobfuscator {
* @return package node object or {@code null} if no package found and <b>create</b> set to {@code false} * @return package node object or {@code null} if no package found and <b>create</b> set to {@code false}
*/ */
private PackageNode getPackageNode(String fullPkgName, boolean create) { private PackageNode getPackageNode(String fullPkgName, boolean create) {
if (fullPkgName.isEmpty() || fullPkgName.equals(classNameSeparator)) { if (fullPkgName.isEmpty() || fullPkgName.equals(CLASS_NAME_SEPARATOR)) {
return rootPackage; return rootPackage;
} }
PackageNode result = rootPackage; PackageNode result = rootPackage;
PackageNode parentNode; PackageNode parentNode;
do { do {
String pkgName; String pkgName;
int idx = fullPkgName.indexOf(classNameSeparator); int idx = fullPkgName.indexOf(CLASS_NAME_SEPARATOR);
if (idx > -1) { if (idx > -1) {
pkgName = fullPkgName.substring(0, idx); pkgName = fullPkgName.substring(0, idx);
...@@ -154,7 +155,7 @@ public class Deobfuscator { ...@@ -154,7 +155,7 @@ public class Deobfuscator {
} else { } else {
prefix = getNameWithoutPackage(parentClass.getClassInfo()); prefix = getNameWithoutPackage(parentClass.getClassInfo());
} }
prefix += innerClassSeparator; prefix += INNER_CLASS_SEPARATOR;
} else { } else {
prefix = ""; prefix = "";
} }
...@@ -163,7 +164,7 @@ public class Deobfuscator { ...@@ -163,7 +164,7 @@ public class Deobfuscator {
} }
public String getFullName() { public String getFullName() {
return pkg.getFullAlias() + classNameSeparator + makeNameWithoutPkg(); return pkg.getFullAlias() + CLASS_NAME_SEPARATOR + makeNameWithoutPkg();
} }
} }
...@@ -177,7 +178,7 @@ public class Deobfuscator { ...@@ -177,7 +178,7 @@ public class Deobfuscator {
} else { } else {
prefix = getNameWithoutPackage(parentClsInfo); prefix = getNameWithoutPackage(parentClsInfo);
} }
prefix += innerClassSeparator; prefix += INNER_CLASS_SEPARATOR;
} else { } else {
prefix = ""; prefix = "";
} }
...@@ -220,18 +221,9 @@ public class Deobfuscator { ...@@ -220,18 +221,9 @@ public class Deobfuscator {
} }
} }
String clsName = cls.getClassInfo().getShortName(); String clsName = cls.getClassInfo().getShortName();
return String.format("C%04d%s", clsIndex++, short4LongName(clsName)); return String.format("C%04d%s", clsIndex++, makeName(clsName));
} }
private String short4LongName(String name) {
if (name.length() > maxLength) {
return "x" + Integer.toHexString(name.hashCode());
}
return name;
}
private final Set<String> pkgSet = new TreeSet<String>();
private void doPkg(PackageNode pkg, String fullName) { private void doPkg(PackageNode pkg, String fullName) {
if (pkgSet.contains(fullName)) { if (pkgSet.contains(fullName)) {
return; return;
...@@ -248,8 +240,8 @@ public class Deobfuscator { ...@@ -248,8 +240,8 @@ public class Deobfuscator {
} }
final String pkgName = pkg.getName(); final String pkgName = pkg.getName();
if (shouldRename(pkgName) && !pkg.hasAlias()) { if (!pkg.hasAlias() && shouldRename(pkgName)) {
final String pkgAlias = String.format("p%03d%s", pkgIndex++, short4LongName(pkgName)); final String pkgAlias = String.format("p%03d%s", pkgIndex++, makeName(pkgName));
pkg.setAlias(pkgAlias); pkg.setAlias(pkgAlias);
} }
} }
...@@ -263,7 +255,34 @@ public class Deobfuscator { ...@@ -263,7 +255,34 @@ public class Deobfuscator {
} }
private boolean shouldRename(String s) { private boolean shouldRename(String s) {
return s.length() > maxLength || s.length() < minLength || NameMapper.isReserved(s); return s.length() > maxLength
|| s.length() < minLength
|| NameMapper.isReserved(s)
|| !NameMapper.isAllCharsPrintable(s);
}
private String makeName(String name) {
if (name.length() > maxLength) {
return "x" + Integer.toHexString(name.hashCode());
}
if (NameMapper.isReserved(name)) {
return name;
}
if (!NameMapper.isAllCharsPrintable(name)) {
return removeInvalidChars(name);
}
return name;
}
private String removeInvalidChars(String name) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
int ch = name.charAt(i);
if (NameMapper.isPrintableChar(ch)) {
sb.append((char) ch);
}
}
return sb.toString();
} }
private void dumpClassAlias(ClassNode cls) { private void dumpClassAlias(ClassNode cls) {
...@@ -300,13 +319,13 @@ public class Deobfuscator { ...@@ -300,13 +319,13 @@ public class Deobfuscator {
for (String l : lines) { for (String l : lines) {
l = l.trim(); l = l.trim();
if (l.startsWith("p ")) { if (l.startsWith("p ")) {
String va[] = splitAndTrim(l); String[] va = splitAndTrim(l);
if (va.length == 2) { if (va.length == 2) {
PackageNode pkg = getPackageNode(va[0], true); PackageNode pkg = getPackageNode(va[0], true);
pkg.setAlias(va[1]); pkg.setAlias(va[1]);
} }
} else if (l.startsWith("c ")) { } else if (l.startsWith("c ")) {
String va[] = splitAndTrim(l); String[] va = splitAndTrim(l);
if (va.length == 2) { if (va.length == 2) {
if (preLoadClsMap.isEmpty()) { if (preLoadClsMap.isEmpty()) {
preLoadClsMap = new HashMap<String, String>(); preLoadClsMap = new HashMap<String, String>();
...@@ -385,6 +404,6 @@ public class Deobfuscator { ...@@ -385,6 +404,6 @@ public class Deobfuscator {
if (deobfClsInfo != null) { if (deobfClsInfo != null) {
return deobfClsInfo.getFullName(); return deobfClsInfo.getFullName();
} }
return getPackageName(clsInfo.getPackage()) + classNameSeparator + getClassName(clsInfo); return getPackageName(clsInfo.getPackage()) + CLASS_NAME_SEPARATOR + getClassName(clsInfo);
} }
} }
...@@ -76,10 +76,23 @@ public class NameMapper { ...@@ -76,10 +76,23 @@ public class NameMapper {
} }
public static boolean isValidIdentifier(String str) { public static boolean isValidIdentifier(String str) {
return VALID_JAVA_IDENTIFIER.matcher(str).matches(); return VALID_JAVA_IDENTIFIER.matcher(str).matches() && isAllCharsPrintable(str);
} }
public static boolean isValidFullIdentifier(String str) { public static boolean isValidFullIdentifier(String str) {
return VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches(); return VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches() && isAllCharsPrintable(str);
}
public static boolean isPrintableChar(int c) {
return 32 <= c && c <= 126;
}
public static boolean isAllCharsPrintable(String str) {
for (int i = 0; i < str.length(); i++) {
if (!isPrintableChar(str.charAt(i))) {
return false;
}
}
return true;
} }
} }
package jadx.core.dex.info; package jadx.core.dex.info;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
...@@ -103,9 +102,6 @@ public final class ClassInfo { ...@@ -103,9 +102,6 @@ public final class ClassInfo {
} else if (firstChar == '$') { } else if (firstChar == '$') {
clsName = "_" + clsName; clsName = "_" + clsName;
} }
if (NameMapper.isReserved(clsName)) {
clsName += "_";
}
this.name = clsName; this.name = clsName;
if (parentClass != null) { if (parentClass != null) {
this.fullName = parentClass.fullName + "." + clsName; this.fullName = parentClass.fullName + "." + clsName;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment