From 13247d891f8b5fccf3078a84ab5b618868c5c9a0 Mon Sep 17 00:00:00 2001 From: nitram84 Date: Wed, 1 Nov 2023 22:35:51 +0100 Subject: [PATCH] Implement a whitelist for deobfuscation --- README.md | 1 + .../src/main/java/jadx/cli/JadxCLIArgs.java | 9 +++ .../src/main/java/jadx/api/JadxArgs.java | 11 +++ .../java/jadx/core/deobf/DeobfWhitelist.java | 78 +++++++++++++++++++ .../jadx/core/deobf/DeobfuscatorVisitor.java | 6 +- .../gui/settings/ui/JadxSettingsWindow.java | 17 ++++ .../resources/i18n/Messages_de_DE.properties | 3 + .../resources/i18n/Messages_en_US.properties | 3 + .../resources/i18n/Messages_es_ES.properties | 3 + .../resources/i18n/Messages_id_ID.properties | 3 + .../resources/i18n/Messages_ko_KR.properties | 3 + .../resources/i18n/Messages_pt_BR.properties | 3 + .../resources/i18n/Messages_ru_RU.properties | 3 + .../resources/i18n/Messages_zh_CN.properties | 3 + .../resources/i18n/Messages_zh_TW.properties | 3 + 15 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 jadx-core/src/main/java/jadx/core/deobf/DeobfWhitelist.java diff --git a/README.md b/README.md index 1e4ee74c942..67570f5445c 100644 --- a/README.md +++ b/README.md @@ -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), diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index b98c4e840be..b8c4fdc4cd8 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -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 JadxArgs toJadxArgs() { 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 int getDeobfuscationMaxLength() { return deobfuscationMaxLength; } + public String getDeobfuscationWhitelist() { + return deobfuscationWhitelist; + } + public String getGeneratedRenamesMappingFile() { return generatedRenamesMappingFile; } diff --git a/jadx-core/src/main/java/jadx/api/JadxArgs.java b/jadx-core/src/main/java/jadx/api/JadxArgs.java index e478c4dcaf4..d14674cb04f 100644 --- a/jadx-core/src/main/java/jadx/api/JadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/JadxArgs.java @@ -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 void setDeobfuscationMaxLength(int deobfuscationMaxLength) { 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 String toString() { + ", extractFinally=" + extractFinally + ", deobfuscationMinLength=" + deobfuscationMinLength + ", deobfuscationMaxLength=" + deobfuscationMaxLength + + ", deobfuscationWhitelist=" + deobfuscationWhitelist + ", escapeUnicode=" + escapeUnicode + ", replaceConsts=" + replaceConsts + ", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers diff --git a/jadx-core/src/main/java/jadx/core/deobf/DeobfWhitelist.java b/jadx-core/src/main/java/jadx/core/deobf/DeobfWhitelist.java new file mode 100644 index 00000000000..de94556234c --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/deobf/DeobfWhitelist.java @@ -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 packages = new ArrayList<>(); + + private final List 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; + } +} diff --git a/jadx-core/src/main/java/jadx/core/deobf/DeobfuscatorVisitor.java b/jadx-core/src/main/java/jadx/core/deobf/DeobfuscatorVisitor.java index 7366779e2b2..0f189c56522 100644 --- a/jadx-core/src/main/java/jadx/core/deobf/DeobfuscatorVisitor.java +++ b/jadx-core/src/main/java/jadx/core/deobf/DeobfuscatorVisitor.java @@ -19,6 +19,8 @@ public void init(RootNode root) throws JadxException { 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 void init(RootNode root) throws JadxException { } 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); diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java index 2644f07e9c8..6aa8a8b14b8 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java @@ -236,12 +236,29 @@ private SettingsGroup makeDeobfuscationGroup() { } }); + 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 connectedComponents = Arrays.asList(minLenSpinner, maxLenSpinner); diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index be297759ed0..fd078261b02 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -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 diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 48355561c0f..fa6bd94890a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -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 diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index c30126c008c..766e8417c5a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -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 diff --git a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties index 5311de078f5..890b10c45e4 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties @@ -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 diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index 3beda69b4b7..f9795e611d5 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -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=재설정 diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index 7888a63329b..da7ae5ecc49 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -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 diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index 0bca7b3fa40..f19454b7fc9 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -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=Сброс diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index 7e9819f876b..ba7b5518a7f 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -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=重置 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index dd78117aff6..8ed0d7dbdc1 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -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=重設