@@ -85,6 +85,9 @@ public class JadxCLIArgs {
|
||||
@Parameter(names = { "--deobf-use-sourcename" }, description = "use source file name as class name alias")
|
||||
protected boolean deobfuscationUseSourceNameAsAlias = false;
|
||||
|
||||
@Parameter(names = { "--deobf-parse-kotlin-metadata" }, description = "parse kotlin metadata to class and package names")
|
||||
protected boolean deobfuscationParseKotlinMetadata = false;
|
||||
|
||||
@Parameter(
|
||||
names = { "--rename-flags" },
|
||||
description = "what to rename, comma-separated,"
|
||||
@@ -194,6 +197,7 @@ public class JadxCLIArgs {
|
||||
args.setDeobfuscationMinLength(deobfuscationMinLength);
|
||||
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
|
||||
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
|
||||
args.setParseKotlinMetadata(deobfuscationParseKotlinMetadata);
|
||||
args.setEscapeUnicode(escapeUnicode);
|
||||
args.setRespectBytecodeAccModifiers(respectBytecodeAccessModifiers);
|
||||
args.setExportAsGradleProject(exportAsGradleProject);
|
||||
@@ -275,6 +279,10 @@ public class JadxCLIArgs {
|
||||
return deobfuscationUseSourceNameAsAlias;
|
||||
}
|
||||
|
||||
public boolean isDeobfuscationParseKotlinMetadata() {
|
||||
return deobfuscationParseKotlinMetadata;
|
||||
}
|
||||
|
||||
public boolean isEscapeUnicode() {
|
||||
return escapeUnicode;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public class JadxArgs {
|
||||
private boolean deobfuscationOn = false;
|
||||
private boolean deobfuscationForceSave = false;
|
||||
private boolean useSourceNameAsClassAlias = false;
|
||||
private boolean parseKotlinMetadata = false;
|
||||
|
||||
private int deobfuscationMinLength = 0;
|
||||
private int deobfuscationMaxLength = Integer.MAX_VALUE;
|
||||
@@ -230,6 +231,14 @@ public class JadxArgs {
|
||||
this.useSourceNameAsClassAlias = useSourceNameAsClassAlias;
|
||||
}
|
||||
|
||||
public boolean isParseKotlinMetadata() {
|
||||
return parseKotlinMetadata;
|
||||
}
|
||||
|
||||
public void setParseKotlinMetadata(boolean parseKotlinMetadata) {
|
||||
this.parseKotlinMetadata = parseKotlinMetadata;
|
||||
}
|
||||
|
||||
public int getDeobfuscationMinLength() {
|
||||
return deobfuscationMinLength;
|
||||
}
|
||||
@@ -355,6 +364,7 @@ public class JadxArgs {
|
||||
+ ", deobfuscationOn=" + deobfuscationOn
|
||||
+ ", deobfuscationForceSave=" + deobfuscationForceSave
|
||||
+ ", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias
|
||||
+ ", parseKotlinMetadata=" + parseKotlinMetadata
|
||||
+ ", deobfuscationMinLength=" + deobfuscationMinLength
|
||||
+ ", deobfuscationMaxLength=" + deobfuscationMaxLength
|
||||
+ ", escapeUnicode=" + escapeUnicode
|
||||
|
||||
@@ -37,6 +37,9 @@ public class Deobfuscator {
|
||||
|
||||
public static final String CLASS_NAME_SEPARATOR = ".";
|
||||
public static final String INNER_CLASS_SEPARATOR = "$";
|
||||
public static final String KOTLIN_METADATA_ANNOTATION = "kotlin.Metadata";
|
||||
public static final String KOTLIN_METADATA_D2_PARAMETER = "d2";
|
||||
public static final String KOTLIN_METADATA_CLASSNAME_REGEX = "(L.*;)";
|
||||
|
||||
private final JadxArgs args;
|
||||
@NotNull
|
||||
@@ -57,6 +60,7 @@ public class Deobfuscator {
|
||||
private final int maxLength;
|
||||
private final int minLength;
|
||||
private final boolean useSourceNameAsAlias;
|
||||
private final boolean parseKotlinMetadata;
|
||||
|
||||
private int pkgIndex = 0;
|
||||
private int clsIndex = 0;
|
||||
@@ -70,6 +74,7 @@ public class Deobfuscator {
|
||||
this.minLength = args.getDeobfuscationMinLength();
|
||||
this.maxLength = args.getDeobfuscationMaxLength();
|
||||
this.useSourceNameAsAlias = args.isUseSourceNameAsClassAlias();
|
||||
this.parseKotlinMetadata = args.isParseKotlinMetadata();
|
||||
|
||||
this.deobfPresets = new DeobfPresets(this, deobfMapFile);
|
||||
}
|
||||
@@ -392,6 +397,18 @@ public class Deobfuscator {
|
||||
|
||||
private String makeClsAlias(ClassNode cls) {
|
||||
ClassInfo classInfo = cls.getClassInfo();
|
||||
|
||||
String metadataClassName = "";
|
||||
String metadataPackageName = "";
|
||||
if (this.parseKotlinMetadata) {
|
||||
String rawClassName = getRawClassNameFromMetadata(cls);
|
||||
if (rawClassName != null) {
|
||||
metadataClassName = rawClassName.substring(rawClassName.lastIndexOf(".") + 1, rawClassName.length() - 1);
|
||||
if (rawClassName.lastIndexOf(".") != -1) {
|
||||
metadataPackageName = rawClassName.substring(1, rawClassName.lastIndexOf("."));
|
||||
}
|
||||
}
|
||||
}
|
||||
String alias = null;
|
||||
|
||||
if (this.useSourceNameAsAlias) {
|
||||
@@ -399,14 +416,40 @@ public class Deobfuscator {
|
||||
}
|
||||
|
||||
if (alias == null) {
|
||||
String clsName = classInfo.getShortName();
|
||||
alias = String.format("C%04d%s", clsIndex++, prepareNamePart(clsName));
|
||||
if (metadataClassName.isEmpty()) {
|
||||
String clsName = classInfo.getShortName();
|
||||
alias = String.format("C%04d%s", clsIndex++, prepareNamePart(clsName));
|
||||
} else {
|
||||
alias = metadataClassName;
|
||||
}
|
||||
}
|
||||
PackageNode pkg;
|
||||
if (metadataPackageName.isEmpty()) {
|
||||
pkg = getPackageNode(classInfo.getPackage(), true);
|
||||
} else {
|
||||
pkg = getPackageNode(metadataPackageName, true);
|
||||
}
|
||||
PackageNode pkg = getPackageNode(classInfo.getPackage(), true);
|
||||
clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias));
|
||||
return alias;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getRawClassNameFromMetadata(ClassNode cls) {
|
||||
if (cls.getAnnotation(KOTLIN_METADATA_ANNOTATION) != null
|
||||
&& cls.getAnnotation(KOTLIN_METADATA_ANNOTATION).getValues().get(KOTLIN_METADATA_D2_PARAMETER) != null
|
||||
&& cls.getAnnotation(KOTLIN_METADATA_ANNOTATION).getValues().get(KOTLIN_METADATA_D2_PARAMETER) instanceof List) {
|
||||
Object rawClassNameObject =
|
||||
((List) cls.getAnnotation(KOTLIN_METADATA_ANNOTATION).getValues().get(KOTLIN_METADATA_D2_PARAMETER)).get(0);
|
||||
if (rawClassNameObject instanceof String) {
|
||||
String rawClassName = ((String) rawClassNameObject).trim().replace("/", ".");
|
||||
if (rawClassName.length() > 1 && rawClassName.matches(KOTLIN_METADATA_CLASSNAME_REGEX)) {
|
||||
return rawClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getAliasFromSourceFile(ClassNode cls) {
|
||||
SourceFileAttr sourceFileAttr = cls.get(AType.SOURCE_FILE);
|
||||
|
||||
@@ -279,6 +279,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
this.deobfuscationUseSourceNameAsAlias = deobfuscationUseSourceNameAsAlias;
|
||||
}
|
||||
|
||||
public void setDeobfuscationParseKotlinMetadata(boolean deobfuscationParseKotlinMetadata) {
|
||||
this.deobfuscationParseKotlinMetadata = deobfuscationParseKotlinMetadata;
|
||||
}
|
||||
|
||||
public void updateRenameFlag(JadxArgs.RenameEnum flag, boolean enabled) {
|
||||
if (enabled) {
|
||||
renameFlags.add(flag);
|
||||
@@ -387,6 +391,7 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
if (fromVersion == 0) {
|
||||
setDeobfuscationMinLength(3);
|
||||
setDeobfuscationUseSourceNameAsAlias(true);
|
||||
setDeobfuscationParseKotlinMetadata(true);
|
||||
setDeobfuscationForceSave(true);
|
||||
setThreadsCount(1);
|
||||
setReplaceConsts(true);
|
||||
|
||||
@@ -167,15 +167,24 @@ public class JadxSettingsWindow extends JDialog {
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox deobfKotlinMetadata = new JCheckBox();
|
||||
deobfKotlinMetadata.setSelected(settings.isDeobfuscationParseKotlinMetadata());
|
||||
deobfKotlinMetadata.addItemListener(e -> {
|
||||
settings.setDeobfuscationParseKotlinMetadata(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
SettingsGroup deobfGroup = new SettingsGroup(NLS.str("preferences.deobfuscation"));
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_on"), deobfOn);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_force"), deobfForce);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_min_len"), minLenSpinner);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_max_len"), maxLenSpinner);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_source_alias"), deobfSourceAlias);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_kotlin_metadata"), deobfKotlinMetadata);
|
||||
deobfGroup.end();
|
||||
|
||||
Collection<JComponent> connectedComponents = Arrays.asList(deobfForce, minLenSpinner, maxLenSpinner, deobfSourceAlias);
|
||||
Collection<JComponent> connectedComponents =
|
||||
Arrays.asList(deobfForce, minLenSpinner, maxLenSpinner, deobfSourceAlias, deobfKotlinMetadata);
|
||||
deobfOn.addItemListener(e -> enableComponentList(connectedComponents, e.getStateChange() == ItemEvent.SELECTED));
|
||||
enableComponentList(connectedComponents, settings.isDeobfuscationOn());
|
||||
return deobfGroup;
|
||||
|
||||
@@ -118,6 +118,7 @@ preferences.deobfuscation_force=Deobfuscationskartendatei umschreiben erzwingen
|
||||
preferences.deobfuscation_min_len=Minimale Namenlänge
|
||||
preferences.deobfuscation_max_len=Maximale Namenlänge
|
||||
preferences.deobfuscation_source_alias=Quelldateiname als Klassennamen-Alias verwenden
|
||||
preferences.deobfuscation_kotlin_metadata=Analysieren Sie Kotlin-Metadaten nach Klassen- und Paketnamen
|
||||
preferences.save=Speichern
|
||||
preferences.cancel=Abbrechen
|
||||
preferences.reset=Zurücksetzen
|
||||
|
||||
@@ -118,6 +118,7 @@ preferences.deobfuscation_force=Force rewrite deobfuscation map file
|
||||
preferences.deobfuscation_min_len=Minimum name length
|
||||
preferences.deobfuscation_max_len=Maximum name length
|
||||
preferences.deobfuscation_source_alias=Use source file name as class name alias
|
||||
preferences.deobfuscation_kotlin_metadata=Parse Kotlin metadata for class and package names
|
||||
preferences.save=Save
|
||||
preferences.cancel=Cancel
|
||||
preferences.reset=Reset
|
||||
|
||||
@@ -118,6 +118,7 @@ preferences.deobfuscation_force=Forzar reescritura del fichero de ofuscación
|
||||
preferences.deobfuscation_min_len=Longitud mínima del nombre
|
||||
preferences.deobfuscation_max_len=Longitud máxima del nombre
|
||||
preferences.deobfuscation_source_alias=Usar el nombre del source como alias para la clase
|
||||
preferences.deobfuscation_kotlin_metadata=Parse Kotlin metadatos para nombres de clase y paquete
|
||||
preferences.save=Guardar
|
||||
preferences.cancel=Cancelar
|
||||
preferences.reset=Reestablecer
|
||||
|
||||
@@ -118,6 +118,7 @@ preferences.deobfuscation_force=强制覆盖反混淆映射文件
|
||||
preferences.deobfuscation_min_len=最小命名长度
|
||||
preferences.deobfuscation_max_len=最大命名长度
|
||||
preferences.deobfuscation_source_alias=使用资源名作为类的别名
|
||||
preferences.deobfuscation_kotlin_metadata=解析Kotlin元数据以获得类和包名
|
||||
preferences.save=保存
|
||||
preferences.cancel=取消
|
||||
preferences.reset=重置
|
||||
|
||||
Reference in New Issue
Block a user