refactor(deobf): split deobfuscation conditions (#2040)

This commit is contained in:
Skylot
2023-11-05 20:00:22 +00:00
parent f7002c7fad
commit a989fa7e64
22 changed files with 482 additions and 246 deletions
+1 -1
View File
@@ -120,6 +120,7 @@ options:
--deobf - activate deobfuscation
--deobf-min - min length of name, renamed if shorter, default: 3
--deobf-max - max length of name, renamed if longer, default: 64
--deobf-whitelist - space separated list of classes (full name) and packages (ends with '.*') to exclude from deobfuscation, default: android.support.v4.* android.support.v7.* android.support.v4.os.* android.support.annotation.Px androidx.core.os.* androidx.annotation.Px
--deobf-cfg-file - deobfuscation mappings file used for JADX auto-generated names (in the JOBF file format), default: same dir and name as input file with '.jobf' extension
--deobf-cfg-file-mode - set mode for handling the JADX auto-generated names' deobfuscation map file:
'read' - read if found, don't save (default)
@@ -131,7 +132,6 @@ 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),
@@ -2,6 +2,7 @@ package jadx.cli;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
@@ -27,6 +28,7 @@ import jadx.api.args.GeneratedRenamesMappingFileMode;
import jadx.api.args.IntegerFormat;
import jadx.api.args.ResourceNameSource;
import jadx.api.args.UserRenamesMappingsMode;
import jadx.core.deobf.conditions.DeobfWhitelist;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.FileUtils;
@@ -137,9 +139,11 @@ 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-whitelist" },
description = "space separated list of classes (full name) and packages (ends with '.*') to exclude from deobfuscation"
)
protected String deobfuscationWhitelistStr = DeobfWhitelist.DEFAULT_STR;
@Parameter(
names = { "--deobf-cfg-file" },
@@ -320,7 +324,7 @@ public class JadxCLIArgs {
args.setGeneratedRenamesMappingFileMode(generatedRenamesMappingFileMode);
args.setDeobfuscationMinLength(deobfuscationMinLength);
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
args.setDeobfuscationWhitelist(deobfuscationWhitelist);
args.setDeobfuscationWhitelist(Arrays.asList(deobfuscationWhitelistStr.split(" ")));
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
args.setUseKotlinMethodsForVarNames(useKotlinMethodsForVarNames);
args.setResourceNameSource(resourceNameSource);
@@ -448,8 +452,8 @@ public class JadxCLIArgs {
return deobfuscationMaxLength;
}
public String getDeobfuscationWhitelist() {
return deobfuscationWhitelist;
public String getDeobfuscationWhitelistStr() {
return deobfuscationWhitelistStr;
}
public String getGeneratedRenamesMappingFile() {
+10 -6
View File
@@ -32,7 +32,8 @@ import jadx.api.plugins.loader.JadxPluginLoader;
import jadx.api.usage.IUsageInfoCache;
import jadx.api.usage.impl.InMemoryUsageInfoCache;
import jadx.core.deobf.DeobfAliasProvider;
import jadx.core.deobf.DeobfCondition;
import jadx.core.deobf.conditions.DeobfWhitelist;
import jadx.core.deobf.conditions.JadxRenameConditions;
import jadx.core.plugins.PluginContext;
import jadx.core.utils.files.FileUtils;
@@ -103,7 +104,10 @@ public class JadxArgs implements Closeable {
private int deobfuscationMinLength = 0;
private int deobfuscationMaxLength = Integer.MAX_VALUE;
private String deobfuscationWhitelist = "";
/**
* List of classes and packages (ends with '.*') to exclude from deobfuscation
*/
private List<String> deobfuscationWhitelist = DeobfWhitelist.DEFAULT_LIST;
/**
* Nodes alias provider for deobfuscator and rename visitor
@@ -113,7 +117,7 @@ public class JadxArgs implements Closeable {
/**
* Condition to rename node in deobfuscator
*/
private IRenameCondition renameCondition = new DeobfCondition();
private IRenameCondition renameCondition = JadxRenameConditions.buildDefault();
private boolean escapeUnicode = false;
private boolean replaceConsts = true;
@@ -436,11 +440,11 @@ public class JadxArgs implements Closeable {
this.deobfuscationMaxLength = deobfuscationMaxLength;
}
public String getDeobfuscationWhitelist() {
public List<String> getDeobfuscationWhitelist() {
return this.deobfuscationWhitelist;
}
public void setDeobfuscationWhitelist(String deobfuscationWhitelist) {
public void setDeobfuscationWhitelist(List<String> deobfuscationWhitelist) {
this.deobfuscationWhitelist = deobfuscationWhitelist;
}
@@ -678,7 +682,7 @@ public class JadxArgs implements Closeable {
public String makeCodeArgsHash(@Nullable JadxDecompiler decompiler) {
String argStr = "args:" + decompilationMode + useImports + showInconsistentCode
+ inlineAnonymousClasses + inlineMethods + moveInnerClasses + allowInlineKotlinLambda
+ deobfuscationOn + deobfuscationMinLength + deobfuscationMaxLength
+ deobfuscationOn + deobfuscationMinLength + deobfuscationMaxLength + deobfuscationWhitelist
+ resourceNameSource
+ useKotlinMethodsForVarNames
+ insertDebugLines + extractFinally
@@ -0,0 +1,31 @@
package jadx.api.deobf;
import jadx.api.deobf.impl.CombineDeobfConditions;
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;
/**
* Utility interface to simplify merging several rename conditions to build {@link IRenameCondition}
* instance with {@link CombineDeobfConditions#combine(IDeobfCondition...)}.
*/
public interface IDeobfCondition {
enum Action {
NO_ACTION,
FORCE_RENAME,
FORBID_RENAME,
}
void init(RootNode root);
Action check(PackageNode pkg);
Action check(ClassNode cls);
Action check(FieldNode fld);
Action check(MethodNode mth);
}
@@ -0,0 +1,73 @@
package jadx.api.deobf.impl;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import jadx.api.deobf.IDeobfCondition;
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 CombineDeobfConditions implements IRenameCondition {
public static IRenameCondition combine(List<IDeobfCondition> conditions) {
return new CombineDeobfConditions(conditions);
}
public static IRenameCondition combine(IDeobfCondition... conditions) {
return new CombineDeobfConditions(Arrays.asList(conditions));
}
private final List<IDeobfCondition> conditions;
private CombineDeobfConditions(List<IDeobfCondition> conditions) {
if (conditions == null || conditions.isEmpty()) {
throw new IllegalArgumentException("Conditions list can't be empty");
}
this.conditions = conditions;
}
private boolean combineFunc(Function<IDeobfCondition, IDeobfCondition.Action> check) {
for (IDeobfCondition c : conditions) {
switch (check.apply(c)) {
case NO_ACTION:
// ignore
break;
case FORCE_RENAME:
return true;
case FORBID_RENAME:
return false;
}
}
return false;
}
@Override
public void init(RootNode root) {
conditions.forEach(c -> c.init(root));
}
@Override
public boolean shouldRename(PackageNode pkg) {
return combineFunc(c -> c.check(pkg));
}
@Override
public boolean shouldRename(ClassNode cls) {
return combineFunc(c -> c.check(cls));
}
@Override
public boolean shouldRename(FieldNode fld) {
return combineFunc(c -> c.check(fld));
}
@Override
public boolean shouldRename(MethodNode mth) {
return combineFunc(c -> c.check(mth));
}
}
@@ -1,103 +0,0 @@
package jadx.core.deobf;
import java.util.HashSet;
import java.util.Set;
import jadx.api.JadxArgs;
import jadx.api.deobf.IRenameCondition;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.args.ArgType;
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 DeobfCondition implements IRenameCondition {
private int minLength;
private int maxLength;
private final Set<String> avoidClsNames = new HashSet<>();
@Override
public void init(RootNode root) {
JadxArgs args = root.getArgs();
this.minLength = args.getDeobfuscationMinLength();
this.maxLength = args.getDeobfuscationMaxLength();
for (PackageNode pkg : root.getPackages()) {
avoidClsNames.add(pkg.getPkgInfo().getName());
}
}
@Override
public boolean shouldRename(PackageNode pkg) {
String name = pkg.getAliasPkgInfo().getName();
return shouldRename(name)
&& !pkg.hasAlias()
&& !TldHelper.contains(name);
}
@Override
public boolean shouldRename(ClassNode cls) {
if (cls.contains(AFlag.DONT_RENAME)
|| cls.getClassInfo().hasAlias()
|| isR(cls.getTopParentClass())) {
return false;
}
String name = cls.getAlias();
if (avoidClsNames.contains(name)) {
return true;
}
return shouldRename(name);
}
@Override
public boolean shouldRename(FieldNode fld) {
return shouldRename(fld.getAlias())
&& !fld.contains(AFlag.DONT_RENAME)
&& !fld.getFieldInfo().hasAlias()
&& !isR(fld.getTopParentClass());
}
@Override
public boolean shouldRename(MethodNode mth) {
return shouldRename(mth.getAlias())
&& !mth.contains(AFlag.DONT_RENAME)
&& !mth.getMethodInfo().hasAlias()
&& !mth.isConstructor();
}
private boolean shouldRename(String s) {
int len = s.length();
return len < minLength || len > maxLength;
}
private static boolean isR(ClassNode cls) {
if (cls.contains(AFlag.ANDROID_R_CLASS)) {
return true;
}
if (!cls.getClassInfo().getShortName().equals("R")) {
return false;
}
if (!cls.getMethods().isEmpty() || !cls.getFields().isEmpty()) {
return false;
}
for (ClassNode inner : cls.getInnerClasses()) {
for (MethodNode m : inner.getMethods()) {
if (!m.getMethodInfo().isConstructor() && !m.getMethodInfo().isClassInit()) {
return false;
}
}
for (FieldNode field : cls.getFields()) {
ArgType type = field.getType();
if (type != ArgType.INT && (!type.isArray() || type.getArrayElement() != ArgType.INT)) {
return false;
}
}
}
cls.add(AFlag.ANDROID_R_CLASS);
return true;
}
}
@@ -1,78 +0,0 @@
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,8 +19,6 @@ 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()) {
@@ -34,11 +32,9 @@ 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 (whitelist.shouldRename(pkg) && renameCondition.shouldRename(pkg)) {
if (renameCondition.shouldRename(pkg)) {
String alias = aliasProvider.forPackage(pkg);
if (alias != null) {
pkg.rename(alias, false);
@@ -1,37 +0,0 @@
package jadx.core.deobf;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import jadx.core.utils.exceptions.JadxRuntimeException;
/**
* Provides a list of all top level domains with 3 characters and less,
* so we can exclude them from deobfuscation.
*/
public class TldHelper {
private static final Set<String> TLD_SET = loadTldFile();
private static Set<String> loadTldFile() {
Set<String> tldNames = new HashSet<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(TldHelper.class.getResourceAsStream("tld_3.txt")))) {
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (!line.startsWith("#") && !line.isEmpty()) {
tldNames.add(line);
}
}
return tldNames;
} catch (Exception e) {
throw new JadxRuntimeException("Failed to load top level domain list tld_3.txt", e);
}
}
public static boolean contains(String name) {
return TLD_SET.contains(name);
}
}
@@ -0,0 +1,35 @@
package jadx.core.deobf.conditions;
import jadx.api.deobf.IDeobfCondition;
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 abstract class AbstractDeobfCondition implements IDeobfCondition {
@Override
public void init(RootNode root) {
}
@Override
public Action check(PackageNode pkg) {
return Action.NO_ACTION;
}
@Override
public Action check(ClassNode cls) {
return Action.NO_ACTION;
}
@Override
public Action check(FieldNode fld) {
return Action.NO_ACTION;
}
@Override
public Action check(MethodNode mth) {
return Action.NO_ACTION;
}
}
@@ -0,0 +1,29 @@
package jadx.core.deobf.conditions;
import java.util.HashSet;
import java.util.Set;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.PackageNode;
import jadx.core.dex.nodes.RootNode;
public class AvoidClsAndPkgNamesCollision extends AbstractDeobfCondition {
private final Set<String> avoidClsNames = new HashSet<>();
@Override
public void init(RootNode root) {
avoidClsNames.clear();
for (PackageNode pkg : root.getPackages()) {
avoidClsNames.add(pkg.getName());
}
}
@Override
public Action check(ClassNode cls) {
if (avoidClsNames.contains(cls.getAlias())) {
return Action.FORCE_RENAME;
}
return Action.NO_ACTION;
}
}
@@ -0,0 +1,49 @@
package jadx.core.deobf.conditions;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.PackageNode;
/**
* Disable deobfuscation for nodes:
* - with 'DONT_RENAME' flag
* - already renamed
*/
public class BaseDeobfCondition extends AbstractDeobfCondition {
@Override
public Action check(PackageNode pkg) {
if (pkg.contains(AFlag.DONT_RENAME) || pkg.hasAlias()) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
@Override
public Action check(ClassNode cls) {
if (cls.contains(AFlag.DONT_RENAME) || cls.getClassInfo().hasAlias()) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
@Override
public Action check(MethodNode mth) {
if (mth.contains(AFlag.DONT_RENAME)
|| mth.getMethodInfo().hasAlias()
|| mth.isConstructor()) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
@Override
public Action check(FieldNode fld) {
if (fld.contains(AFlag.DONT_RENAME) || fld.getFieldInfo().hasAlias()) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
}
@@ -0,0 +1,50 @@
package jadx.core.deobf.conditions;
import jadx.api.JadxArgs;
import jadx.api.deobf.IDeobfCondition;
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 DeobfLengthCondition implements IDeobfCondition {
private int minLength;
private int maxLength;
@Override
public void init(RootNode root) {
JadxArgs args = root.getArgs();
this.minLength = args.getDeobfuscationMinLength();
this.maxLength = args.getDeobfuscationMaxLength();
}
private Action checkName(String s) {
int len = s.length();
if (len < minLength || len > maxLength) {
return Action.FORCE_RENAME;
}
return Action.NO_ACTION;
}
@Override
public Action check(PackageNode pkg) {
return checkName(pkg.getName());
}
@Override
public Action check(ClassNode cls) {
return checkName(cls.getName());
}
@Override
public Action check(FieldNode fld) {
return checkName(fld.getName());
}
@Override
public Action check(MethodNode mth) {
return checkName(mth.getName());
}
}
@@ -0,0 +1,58 @@
package jadx.core.deobf.conditions;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.PackageNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.Utils;
public class DeobfWhitelist extends AbstractDeobfCondition {
public static final List<String> DEFAULT_LIST = Arrays.asList(
"android.support.v4.*",
"android.support.v7.*",
"android.support.v4.os.*",
"android.support.annotation.Px",
"androidx.core.os.*",
"androidx.annotation.Px");
public static final String DEFAULT_STR = Utils.listToString(DEFAULT_LIST, " ");
private final Set<String> packages = new HashSet<>();
private final Set<String> classes = new HashSet<>();
@Override
public void init(RootNode root) {
packages.clear();
classes.clear();
for (String whitelistItem : root.getArgs().getDeobfuscationWhitelist()) {
if (!whitelistItem.isEmpty()) {
if (whitelistItem.endsWith(".*")) {
packages.add(whitelistItem.substring(0, whitelistItem.length() - 2));
} else {
classes.add(whitelistItem);
}
}
}
}
@Override
public Action check(PackageNode pkg) {
if (packages.contains(pkg.getPkgInfo().getFullName())) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
@Override
public Action check(ClassNode cls) {
if (classes.contains(cls.getClassInfo().getFullName())) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
}
@@ -0,0 +1,45 @@
package jadx.core.deobf.conditions;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
public class ExcludeAndroidRClass extends AbstractDeobfCondition {
@Override
public Action check(ClassNode cls) {
if (isR(cls.getTopParentClass())) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
private static boolean isR(ClassNode cls) {
if (cls.contains(AFlag.ANDROID_R_CLASS)) {
return true;
}
if (!cls.getClassInfo().getShortName().equals("R")) {
return false;
}
if (!cls.getMethods().isEmpty() || !cls.getFields().isEmpty()) {
return false;
}
for (ClassNode inner : cls.getInnerClasses()) {
for (MethodNode m : inner.getMethods()) {
if (!m.getMethodInfo().isConstructor() && !m.getMethodInfo().isClassInit()) {
return false;
}
}
for (FieldNode field : cls.getFields()) {
ArgType type = field.getType();
if (type != ArgType.INT && (!type.isArray() || type.getArrayElement() != ArgType.INT)) {
return false;
}
}
}
cls.add(AFlag.ANDROID_R_CLASS);
return true;
}
}
@@ -0,0 +1,42 @@
package jadx.core.deobf.conditions;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.stream.Collectors;
import jadx.core.dex.nodes.PackageNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
/**
* Provides a list of all top level domains with 3 characters and less,
* so we can exclude them from deobfuscation.
*/
public class ExcludePackageWithTLDNames extends AbstractDeobfCondition {
/**
* Lazy load TLD set
*/
private static class TldHolder {
private static final Set<String> TLD_SET = loadTldFile();
}
private static Set<String> loadTldFile() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(TldHolder.class.getResourceAsStream("tld_3.txt")))) {
return reader.lines()
.map(String::trim)
.filter(line -> !line.startsWith("#") && !line.isEmpty())
.collect(Collectors.toSet());
} catch (Exception e) {
throw new JadxRuntimeException("Failed to load top level domain list file: tld_3.txt", e);
}
}
@Override
public Action check(PackageNode pkg) {
if (TldHolder.TLD_SET.contains(pkg.getName())) {
return Action.FORBID_RENAME;
}
return Action.NO_ACTION;
}
}
@@ -0,0 +1,30 @@
package jadx.core.deobf.conditions;
import java.util.ArrayList;
import java.util.List;
import jadx.api.deobf.IDeobfCondition;
import jadx.api.deobf.IRenameCondition;
import jadx.api.deobf.impl.CombineDeobfConditions;
public class JadxRenameConditions {
/**
* This method provides a mutable list of default deobfuscation conditions used by jadx.
* To build {@link IRenameCondition} use {@link CombineDeobfConditions#combine(List)} method.
*/
public static List<IDeobfCondition> buildDefaultDeobfConditions() {
List<IDeobfCondition> list = new ArrayList<>();
list.add(new BaseDeobfCondition());
list.add(new DeobfWhitelist());
list.add(new ExcludePackageWithTLDNames());
list.add(new ExcludeAndroidRClass());
list.add(new AvoidClsAndPkgNamesCollision());
list.add(new DeobfLengthCondition());
return list;
}
public static IRenameCondition buildDefault() {
return CombineDeobfConditions.combine(buildDefaultDeobfConditions());
}
}
@@ -130,6 +130,14 @@ public class PackageNode extends LineAttrNode
}
}
public String getName() {
return pkgInfo.getName();
}
public String getFullName() {
return pkgInfo.getFullName();
}
public PackageInfo getPkgInfo() {
return pkgInfo;
}
@@ -9,7 +9,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.deobf.NameMapper;
import jadx.core.deobf.TldHelper;
public class BetterName {
private static final Logger LOG = LoggerFactory.getLogger(BetterName.class);
@@ -43,9 +42,6 @@ public class BetterName {
if (NameMapper.isValidIdentifier(str)) {
rating += 50;
}
if (TldHelper.contains(str)) {
rating += 20;
}
if (str.contains("_")) {
// rare in obfuscated names
rating += 100;
@@ -369,6 +369,10 @@ public class JadxSettings extends JadxCLIArgs {
this.deobfuscationMaxLength = deobfuscationMaxLength;
}
public void setDeobfuscationWhitelistStr(String value) {
this.deobfuscationWhitelistStr = value;
}
public void setGeneratedRenamesMappingFileMode(GeneratedRenamesMappingFileMode mode) {
this.generatedRenamesMappingFileMode = mode;
}
@@ -238,13 +238,13 @@ 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());
String prevWhitelistedEntities = settings.getDeobfuscationWhitelistStr();
String result = JOptionPane.showInputDialog(this,
NLS.str("preferences.deobfuscation_whitelist.editDialog"),
prevWhitelistedEntities);
if (result != null) {
settings.setExcludedPackages(result);
if (!oldEWhitelistedEntities.equals(result)) {
settings.setDeobfuscationWhitelistStr(result);
if (!prevWhitelistedEntities.equals(result)) {
needReload();
}
}