feat(deobf): implement a whitelist for deobfuscation (PR #2040)
This commit is contained in:
@@ -131,6 +131,7 @@ options:
|
||||
'auto' - automatically select best name (default)
|
||||
'resources' - use resources names
|
||||
'code' - use R class fields names
|
||||
--deobf-whitelist - list of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
--use-kotlin-methods-for-var-names - use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide, default: apply
|
||||
--rename-flags - fix options (comma-separated list of):
|
||||
'case' - fix case sensitivity issues (according to --fs-case-sensitive option),
|
||||
|
||||
@@ -137,6 +137,10 @@ public class JadxCLIArgs {
|
||||
@Parameter(names = { "--deobf-max" }, description = "max length of name, renamed if longer")
|
||||
protected int deobfuscationMaxLength = 64;
|
||||
|
||||
@Parameter(names = { "--deobf-whitelist}" }, description = "debfucation whitelist")
|
||||
protected String deobfuscationWhitelist =
|
||||
"android.support.v4.*:android.support.v7.*:android.support.v4.os.*:android.support.annotation.Px:androidx.core.os.*:androidx.annotation.Px";
|
||||
|
||||
@Parameter(
|
||||
names = { "--deobf-cfg-file" },
|
||||
description = "deobfuscation mappings file used for JADX auto-generated names (in the JOBF file format),"
|
||||
@@ -316,6 +320,7 @@ public class JadxCLIArgs {
|
||||
args.setGeneratedRenamesMappingFileMode(generatedRenamesMappingFileMode);
|
||||
args.setDeobfuscationMinLength(deobfuscationMinLength);
|
||||
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
|
||||
args.setDeobfuscationWhitelist(deobfuscationWhitelist);
|
||||
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
|
||||
args.setUseKotlinMethodsForVarNames(useKotlinMethodsForVarNames);
|
||||
args.setResourceNameSource(resourceNameSource);
|
||||
@@ -443,6 +448,10 @@ public class JadxCLIArgs {
|
||||
return deobfuscationMaxLength;
|
||||
}
|
||||
|
||||
public String getDeobfuscationWhitelist() {
|
||||
return deobfuscationWhitelist;
|
||||
}
|
||||
|
||||
public String getGeneratedRenamesMappingFile() {
|
||||
return generatedRenamesMappingFile;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,8 @@ public class JadxArgs implements Closeable {
|
||||
private int deobfuscationMinLength = 0;
|
||||
private int deobfuscationMaxLength = Integer.MAX_VALUE;
|
||||
|
||||
private String deobfuscationWhitelist = "";
|
||||
|
||||
/**
|
||||
* Nodes alias provider for deobfuscator and rename visitor
|
||||
*/
|
||||
@@ -434,6 +436,14 @@ public class JadxArgs implements Closeable {
|
||||
this.deobfuscationMaxLength = deobfuscationMaxLength;
|
||||
}
|
||||
|
||||
public String getDeobfuscationWhitelist() {
|
||||
return this.deobfuscationWhitelist;
|
||||
}
|
||||
|
||||
public void setDeobfuscationWhitelist(String deobfuscationWhitelist) {
|
||||
this.deobfuscationWhitelist = deobfuscationWhitelist;
|
||||
}
|
||||
|
||||
public File getGeneratedRenamesMappingFile() {
|
||||
return generatedRenamesMappingFile;
|
||||
}
|
||||
@@ -714,6 +724,7 @@ public class JadxArgs implements Closeable {
|
||||
+ ", extractFinally=" + extractFinally
|
||||
+ ", deobfuscationMinLength=" + deobfuscationMinLength
|
||||
+ ", deobfuscationMaxLength=" + deobfuscationMaxLength
|
||||
+ ", deobfuscationWhitelist=" + deobfuscationWhitelist
|
||||
+ ", escapeUnicode=" + escapeUnicode
|
||||
+ ", replaceConsts=" + replaceConsts
|
||||
+ ", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package jadx.core.deobf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.deobf.IRenameCondition;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.PackageNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
|
||||
public class DeobfWhitelist implements IRenameCondition {
|
||||
|
||||
private static DeobfWhitelist whitelist = null;
|
||||
|
||||
private final List<String> packages = new ArrayList<>();
|
||||
|
||||
private final List<String> classes = new ArrayList<>();
|
||||
|
||||
public static DeobfWhitelist getWhitelist() {
|
||||
if (whitelist == null) {
|
||||
whitelist = new DeobfWhitelist();
|
||||
}
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(RootNode root) {
|
||||
packages.clear();
|
||||
classes.clear();
|
||||
JadxArgs args = root.getArgs();
|
||||
String whitelistStr = args.getDeobfuscationWhitelist();
|
||||
String[] whitelisteItems = whitelistStr.split(":");
|
||||
for (String whitelistItem : whitelisteItems) {
|
||||
if (!whitelistItem.isEmpty()) {
|
||||
if (whitelistItem.endsWith(".*")) {
|
||||
packages.add(whitelistItem.substring(0, whitelistItem.length() - 2));
|
||||
} else {
|
||||
classes.add(whitelistItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRename(PackageNode pkg) {
|
||||
String fullname = pkg.getPkgInfo().getFullName();
|
||||
for (String p : packages) {
|
||||
if (fullname.equals(p)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRename(ClassNode cls) {
|
||||
String fullname = cls.getFullName();
|
||||
for (String c : classes) {
|
||||
if (fullname.equals(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRename(FieldNode fld) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRename(MethodNode mth) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ public class DeobfuscatorVisitor extends AbstractVisitor {
|
||||
if (!args.isDeobfuscationOn()) {
|
||||
return;
|
||||
}
|
||||
DeobfWhitelist whitelist = DeobfWhitelist.getWhitelist();
|
||||
whitelist.init(root);
|
||||
DeobfPresets mapping = DeobfPresets.build(root);
|
||||
if (args.getGeneratedRenamesMappingFileMode().shouldRead()) {
|
||||
if (mapping.load()) {
|
||||
@@ -32,9 +34,11 @@ public class DeobfuscatorVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
public static void process(RootNode root, IRenameCondition renameCondition, IAliasProvider aliasProvider) {
|
||||
DeobfWhitelist whitelist = DeobfWhitelist.getWhitelist();
|
||||
|
||||
boolean pkgUpdated = false;
|
||||
for (PackageNode pkg : root.getPackages()) {
|
||||
if (renameCondition.shouldRename(pkg)) {
|
||||
if (whitelist.shouldRename(pkg) && renameCondition.shouldRename(pkg)) {
|
||||
String alias = aliasProvider.forPackage(pkg);
|
||||
if (alias != null) {
|
||||
pkg.rename(alias, false);
|
||||
|
||||
@@ -236,12 +236,29 @@ public class JadxSettingsWindow extends JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
JButton editWhitelistedEntities = new JButton(NLS.str("preferences.excludedPackages.button"));
|
||||
editWhitelistedEntities.addActionListener(event -> {
|
||||
|
||||
String oldEWhitelistedEntities = settings.getDeobfuscationWhitelist();
|
||||
String result = JOptionPane.showInputDialog(this, NLS.str("preferences.deobfuscation_whitelist.editDialog"),
|
||||
settings.getDeobfuscationWhitelist());
|
||||
if (result != null) {
|
||||
settings.setExcludedPackages(result);
|
||||
if (!oldEWhitelistedEntities.equals(result)) {
|
||||
needReload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SettingsGroup deobfGroup = new SettingsGroup(NLS.str("preferences.deobfuscation"));
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_on"), deobfOn);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_min_len"), minLenSpinner);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_max_len"), maxLenSpinner);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_res_name_source"), resNamesSource);
|
||||
deobfGroup.addRow(NLS.str("preferences.generated_renames_mapping_file_mode"), generatedRenamesMappingFileModeCB);
|
||||
deobfGroup.addRow(NLS.str("preferences.deobfuscation_whitelist"),
|
||||
NLS.str("preferences.deobfuscation_whitelist.tooltip"), editWhitelistedEntities);
|
||||
|
||||
deobfGroup.end();
|
||||
|
||||
Collection<JComponent> connectedComponents = Arrays.asList(minLenSpinner, maxLenSpinner);
|
||||
|
||||
@@ -215,6 +215,9 @@ 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_res_name_source=Better resources name source
|
||||
preferences.deobfuscation_whitelist=Pakete und Klassen von Deobfuskierung ausschließen
|
||||
preferences.deobfuscation_whitelist.editDialog=Whitelist für Deobfuskierung
|
||||
preferences.deobfuscation_whitelist.tooltip=Liste der durch ':' getrennten Pakete (Suffix '.*') und Klassenamen, die nicht deobfuskiert werden sollen
|
||||
preferences.save=Speichern
|
||||
preferences.cancel=Abbrechen
|
||||
preferences.reset=Zurücksetzen
|
||||
|
||||
@@ -215,6 +215,9 @@ 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_res_name_source=Better resources name source
|
||||
preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=Save
|
||||
preferences.cancel=Cancel
|
||||
preferences.reset=Reset
|
||||
|
||||
@@ -215,6 +215,9 @@ 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_res_name_source=Better resources name source
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=Guardar
|
||||
preferences.cancel=Cancelar
|
||||
preferences.reset=Reestablecer
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=Panjang nama minimum
|
||||
preferences.deobfuscation_max_len=Panjang nama maksimum
|
||||
preferences.deobfuscation_source_alias=Gunakan nama berkas sumber sebagai alias nama kelas
|
||||
preferences.deobfuscation_res_name_source=Sumber nama sumber daya yang lebih baik
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=Simpan
|
||||
preferences.cancel=Batal
|
||||
preferences.reset=Reset
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=최소 이름 길이
|
||||
preferences.deobfuscation_max_len=최대 이름 길이
|
||||
preferences.deobfuscation_source_alias=소스 파일 이름을 클래스 이름 별칭으로 사용
|
||||
preferences.deobfuscation_res_name_source=더 나은 리소스 이름 소스
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=저장
|
||||
preferences.cancel=취소
|
||||
preferences.reset=재설정
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=Tamanho mínimo do nome
|
||||
preferences.deobfuscation_max_len=Tamanho máximo do nome
|
||||
preferences.deobfuscation_source_alias=Utilizar nome do arquivo como apelido da classe
|
||||
preferences.deobfuscation_res_name_source=Melhora nome da fonte dos recursos
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=Salvar
|
||||
preferences.cancel=Cancelar
|
||||
preferences.reset=Redefinir
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=Минимальная длина имени
|
||||
preferences.deobfuscation_max_len=Максимальная длина имени
|
||||
preferences.deobfuscation_source_alias=Иcпользовать атрибут SOURCE
|
||||
preferences.deobfuscation_res_name_source=Расшифровка имен ресурсов
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=Сохранить
|
||||
preferences.cancel=Отмена
|
||||
preferences.reset=Сброс
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=最小命名长度
|
||||
preferences.deobfuscation_max_len=最大命名长度
|
||||
preferences.deobfuscation_source_alias=使用资源名作为类的别名
|
||||
preferences.deobfuscation_res_name_source=更好的资源名称来源
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=保存
|
||||
preferences.cancel=取消
|
||||
preferences.reset=重置
|
||||
|
||||
@@ -215,6 +215,9 @@ preferences.deobfuscation_min_len=最小名稱長度
|
||||
preferences.deobfuscation_max_len=最大名稱長度
|
||||
preferences.deobfuscation_source_alias=將原始檔案名稱作為類別別名
|
||||
preferences.deobfuscation_res_name_source=較佳的資源名稱來源
|
||||
#preferences.deobfuscation_whitelist=Exclude packages and classes from deobfuscation
|
||||
#preferences.deobfuscation_whitelist.editDialog=Whitelist for deobfuscation
|
||||
#preferences.deobfuscation_whitelist.tooltip=List of ':' separated packages (suffix '.*') and class names that will not be deobfuscated
|
||||
preferences.save=儲存
|
||||
preferences.cancel=取消
|
||||
preferences.reset=重設
|
||||
|
||||
Reference in New Issue
Block a user