未验证 提交 a9bbadd6 编写于 作者: S Skylot

feat: add option for deobfuscation map file handle mode (#1351)

上级 2c570681
......@@ -96,7 +96,12 @@ options:
--deobf-min - min length of name, renamed if shorter, default: 3
--deobf-max - max length of name, renamed if longer, default: 64
--deobf-cfg-file - deobfuscation map file, default: same dir and name as input file with '.jobf' extension
--deobf-rewrite-cfg - force to ignore and overwrite deobfuscation map file
--deobf-cfg-file-mode - set mode for handle deobfuscation map file:
'read' - read if found, don't save (default)
'read-or-save' - read if found, save otherwise (don't overwrite)
'overwrite' - don't read, always save
'ignore' - don't read and don't save
--deobf-rewrite-cfg - set '--deobf-cfg-file-mode' to 'overwrite' (deprecated)
--deobf-use-sourcename - use source file name as class name alias
--deobf-parse-kotlin-metadata - parse kotlin metadata to class and package names
--use-kotlin-methods-for-var-names - use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide, default: apply
......
......@@ -94,7 +94,7 @@ public class JCommanderWrapper<T> {
opt.append("- ").append(description);
}
String defaultValue = getDefaultValue(args, f, opt);
if (defaultValue != null) {
if (defaultValue != null && !description.contains("(default)")) {
opt.append(", default: ").append(defaultValue);
}
out.println(opt);
......
......@@ -16,6 +16,7 @@ import jadx.api.JadxArgs;
import jadx.api.JadxArgs.RenameEnum;
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
import jadx.api.JadxDecompiler;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.FileUtils;
......@@ -93,7 +94,18 @@ public class JadxCLIArgs {
)
protected String deobfuscationMapFile;
@Parameter(names = { "--deobf-rewrite-cfg" }, description = "force to ignore and overwrite deobfuscation map file")
@Parameter(
names = { "--deobf-cfg-file-mode" },
description = "set mode for handle deobfuscation map file:"
+ "\n 'read' - read if found, don't save (default)"
+ "\n 'read-or-save' - read if found, save otherwise (don't overwrite)"
+ "\n 'overwrite' - don't read, always save"
+ "\n 'ignore' - don't read and don't save",
converter = DeobfuscationMapFileModeConverter.class
)
protected DeobfuscationMapFileMode deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
@Parameter(names = { "--deobf-rewrite-cfg" }, description = "set '--deobf-cfg-file-mode' to 'overwrite' (deprecated)")
protected boolean deobfuscationForceSave = false;
@Parameter(names = { "--deobf-use-sourcename" }, description = "use source file name as class name alias")
......@@ -226,7 +238,11 @@ public class JadxCLIArgs {
args.setReplaceConsts(replaceConsts);
args.setDeobfuscationOn(deobfuscationOn);
args.setDeobfuscationMapFile(FileUtils.toFile(deobfuscationMapFile));
args.setDeobfuscationForceSave(deobfuscationForceSave);
if (deobfuscationForceSave) {
args.setDeobfuscationMapFileMode(DeobfuscationMapFileMode.OVERWRITE);
} else {
args.setDeobfuscationMapFileMode(deobfuscationMapFileMode);
}
args.setDeobfuscationMinLength(deobfuscationMinLength);
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
......@@ -323,6 +339,10 @@ public class JadxCLIArgs {
return deobfuscationMapFile;
}
public DeobfuscationMapFileMode getDeobfuscationMapFileMode() {
return deobfuscationMapFileMode;
}
public boolean isDeobfuscationForceSave() {
return deobfuscationForceSave;
}
......@@ -438,6 +458,19 @@ public class JadxCLIArgs {
}
}
public static class DeobfuscationMapFileModeConverter implements IStringConverter<DeobfuscationMapFileMode> {
@Override
public DeobfuscationMapFileMode convert(String value) {
try {
return DeobfuscationMapFileMode.valueOf(value.toUpperCase());
} catch (Exception e) {
throw new IllegalArgumentException(
'\'' + value + "' is unknown, possible values are: "
+ JadxCLIArgs.enumValuesString(DeobfuscationMapFileMode.values()));
}
}
}
public static String enumValuesString(Enum<?>[] values) {
return Stream.of(values)
.map(v -> v.name().replace('_', '-').toLowerCase(Locale.ROOT))
......
......@@ -9,6 +9,7 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.data.ICodeData;
import jadx.api.impl.AnnotatedCodeWriter;
import jadx.api.impl.InMemoryCodeCache;
......@@ -54,11 +55,12 @@ public class JadxArgs {
private Predicate<String> classFilter = null;
private boolean deobfuscationOn = false;
private boolean deobfuscationForceSave = false;
private boolean useSourceNameAsClassAlias = false;
private boolean parseKotlinMetadata = false;
private File deobfuscationMapFile = null;
private DeobfuscationMapFileMode deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
private int deobfuscationMinLength = 0;
private int deobfuscationMaxLength = Integer.MAX_VALUE;
......@@ -264,12 +266,24 @@ public class JadxArgs {
this.deobfuscationOn = deobfuscationOn;
}
@Deprecated
public boolean isDeobfuscationForceSave() {
return deobfuscationForceSave;
return deobfuscationMapFileMode == DeobfuscationMapFileMode.OVERWRITE;
}
@Deprecated
public void setDeobfuscationForceSave(boolean deobfuscationForceSave) {
this.deobfuscationForceSave = deobfuscationForceSave;
if (deobfuscationForceSave) {
this.deobfuscationMapFileMode = DeobfuscationMapFileMode.OVERWRITE;
}
}
public DeobfuscationMapFileMode getDeobfuscationMapFileMode() {
return deobfuscationMapFileMode;
}
public void setDeobfuscationMapFileMode(DeobfuscationMapFileMode deobfuscationMapFileMode) {
this.deobfuscationMapFileMode = deobfuscationMapFileMode;
}
public boolean isUseSourceNameAsClassAlias() {
......@@ -476,7 +490,7 @@ public class JadxArgs {
+ ", skipSources=" + skipSources
+ ", deobfuscationOn=" + deobfuscationOn
+ ", deobfuscationMapFile=" + deobfuscationMapFile
+ ", deobfuscationForceSave=" + deobfuscationForceSave
+ ", deobfuscationMapFileMode=" + deobfuscationMapFileMode
+ ", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias
+ ", parseKotlinMetadata=" + parseKotlinMetadata
+ ", useKotlinMethodsForVarNames=" + useKotlinMethodsForVarNames
......
package jadx.api.args;
public enum DeobfuscationMapFileMode {
/**
* Load if found, don't save (default)
*/
READ,
/**
* Load if found, save only if new (don't overwrite)
*/
READ_OR_SAVE,
/**
* Don't load, always save
*/
OVERWRITE,
/**
* Don't load and don't save
*/
IGNORE;
public boolean shouldRead() {
return this == READ || this == READ_OR_SAVE;
}
public boolean shouldWrite() {
return this == READ_OR_SAVE || this == OVERWRITE;
}
}
......@@ -17,6 +17,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.JadxArgs;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
......@@ -50,6 +51,9 @@ public class DeobfPresets {
@Nullable
private static Path getPathDeobfMapPath(RootNode root) {
JadxArgs jadxArgs = root.getArgs();
if (jadxArgs.getDeobfuscationMapFileMode() == DeobfuscationMapFileMode.IGNORE) {
return null;
}
File deobfMapFile = jadxArgs.getDeobfuscationMapFile();
if (deobfMapFile != null) {
return deobfMapFile.toPath();
......@@ -70,9 +74,9 @@ public class DeobfPresets {
/**
* Loads deobfuscator presets
*/
public void load() {
public boolean load() {
if (!Files.exists(deobfMapFile)) {
return;
return false;
}
LOG.info("Loading obfuscation map from: {}", deobfMapFile.toAbsolutePath());
try {
......@@ -106,8 +110,10 @@ public class DeobfPresets {
break;
}
}
return true;
} catch (Exception e) {
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
return false;
}
}
......@@ -142,9 +148,7 @@ public class DeobfPresets {
}
Files.write(deobfMapFile, list, MAP_FILE_CHARSET,
StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
if (LOG.isDebugEnabled()) {
LOG.debug("Deobfuscation map file saved as: {}", deobfMapFile);
}
LOG.info("Deobfuscation map file saved as: {}", deobfMapFile);
}
public String getForCls(ClassInfo cls) {
......
......@@ -16,6 +16,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.JadxArgs;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
import jadx.core.dex.attributes.AFlag;
......@@ -76,22 +77,25 @@ public class Deobfuscator {
}
public void execute() {
if (!args.isDeobfuscationForceSave()) {
deobfPresets.load();
for (Map.Entry<String, String> pkgEntry : deobfPresets.getPkgPresetMap().entrySet()) {
addPackagePreset(pkgEntry.getKey(), pkgEntry.getValue());
if (args.getDeobfuscationMapFileMode().shouldRead()) {
if (deobfPresets.load()) {
for (Map.Entry<String, String> pkgEntry : deobfPresets.getPkgPresetMap().entrySet()) {
addPackagePreset(pkgEntry.getKey(), pkgEntry.getValue());
}
deobfPresets.getPkgPresetMap().clear(); // not needed anymore
initIndexes();
}
deobfPresets.getPkgPresetMap().clear(); // not needed anymore
initIndexes();
}
process();
}
public void savePresets() {
DeobfuscationMapFileMode mode = args.getDeobfuscationMapFileMode();
if (!mode.shouldWrite()) {
return;
}
Path deobfMapFile = deobfPresets.getDeobfMapFile();
if (Files.exists(deobfMapFile) && !args.isDeobfuscationForceSave()) {
LOG.info("Deobfuscation map file '{}' exists. Use command line option '--deobf-rewrite-cfg' to rewrite it",
deobfMapFile.toAbsolutePath());
if (mode == DeobfuscationMapFileMode.READ_OR_SAVE && Files.exists(deobfMapFile)) {
return;
}
try {
......
......@@ -210,7 +210,10 @@ public class JadxProject {
private void upgrade() {
int fromVersion = data.getProjectVersion();
LOG.debug("upgrade settings from version: {} to {}", fromVersion, CURRENT_PROJECT_VERSION);
if (fromVersion == CURRENT_PROJECT_VERSION) {
return;
}
LOG.debug("upgrade project settings from version: {} to {}", fromVersion, CURRENT_PROJECT_VERSION);
if (fromVersion == 0) {
fromVersion++;
}
......
......@@ -28,6 +28,7 @@ import com.beust.jcommander.Parameter;
import jadx.api.CommentsLevel;
import jadx.api.JadxArgs;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.cli.JadxCLIArgs;
import jadx.cli.LogHelper;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -43,7 +44,7 @@ public class JadxSettings extends JadxCLIArgs {
private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));
private static final int RECENT_PROJECTS_COUNT = 15;
private static final int CURRENT_SETTINGS_VERSION = 15;
private static final int CURRENT_SETTINGS_VERSION = 16;
private static final Font DEFAULT_FONT = new RSyntaxTextArea().getFont();
......@@ -326,8 +327,8 @@ public class JadxSettings extends JadxCLIArgs {
this.deobfuscationMaxLength = deobfuscationMaxLength;
}
public void setDeobfuscationForceSave(boolean deobfuscationForceSave) {
this.deobfuscationForceSave = deobfuscationForceSave;
public void setDeobfuscationMapFileMode(DeobfuscationMapFileMode mode) {
this.deobfuscationMapFileMode = mode;
}
public void setDeobfuscationUseSourceNameAsAlias(boolean deobfuscationUseSourceNameAsAlias) {
......@@ -588,7 +589,7 @@ public class JadxSettings extends JadxCLIArgs {
setDeobfuscationMaxLength(64);
setDeobfuscationUseSourceNameAsAlias(true);
setDeobfuscationParseKotlinMetadata(true);
setDeobfuscationForceSave(false);
setDeobfuscationMapFileMode(DeobfuscationMapFileMode.READ);
setThreadsCount(JadxArgs.DEFAULT_THREADS_COUNT);
setReplaceConsts(true);
setSkipResources(false);
......@@ -659,6 +660,14 @@ public class JadxSettings extends JadxCLIArgs {
useKotlinMethodsForVarNames = JadxArgs.UseKotlinMethodsForVarNames.APPLY;
fromVersion++;
}
if (fromVersion == 15) {
if (deobfuscationForceSave) {
deobfuscationMapFileMode = DeobfuscationMapFileMode.OVERWRITE;
} else {
deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
}
fromVersion++;
}
if (fromVersion != CURRENT_SETTINGS_VERSION) {
throw new JadxRuntimeException("Incorrect settings upgrade");
}
......
......@@ -61,6 +61,7 @@ import say.swing.JFontChooser;
import jadx.api.CommentsLevel;
import jadx.api.JadxArgs;
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.codearea.EditorTheme;
import jadx.gui.utils.FontUtils;
......@@ -232,13 +233,6 @@ public class JadxSettingsWindow extends JDialog {
needReload();
});
JCheckBox deobfForce = new JCheckBox();
deobfForce.setSelected(settings.isDeobfuscationForceSave());
deobfForce.addItemListener(e -> {
settings.setDeobfuscationForceSave(e.getStateChange() == ItemEvent.SELECTED);
needReload();
});
SpinnerNumberModel minLenModel = new SpinnerNumberModel(settings.getDeobfuscationMinLength(), 0, Integer.MAX_VALUE, 1);
JSpinner minLenSpinner = new JSpinner(minLenModel);
minLenSpinner.addChangeListener(e -> {
......@@ -267,17 +261,27 @@ public class JadxSettingsWindow extends JDialog {
needReload();
});
JComboBox<DeobfuscationMapFileMode> deobfMapFileModeCB = new JComboBox<>(DeobfuscationMapFileMode.values());
deobfMapFileModeCB.setSelectedItem(settings.getDeobfuscationMapFileMode());
deobfMapFileModeCB.addActionListener(e -> {
DeobfuscationMapFileMode newValue = (DeobfuscationMapFileMode) deobfMapFileModeCB.getSelectedItem();
if (newValue != settings.getDeobfuscationMapFileMode()) {
settings.setDeobfuscationMapFileMode(newValue);
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.addRow(NLS.str("preferences.deobfuscation_map_file_mode"), deobfMapFileModeCB);
deobfGroup.end();
Collection<JComponent> connectedComponents =
Arrays.asList(deobfForce, minLenSpinner, maxLenSpinner, deobfSourceAlias, deobfKotlinMetadata);
Arrays.asList(minLenSpinner, maxLenSpinner, deobfSourceAlias, deobfKotlinMetadata);
deobfOn.addItemListener(e -> enableComponentList(connectedComponents, e.getStateChange() == ItemEvent.SELECTED));
enableComponentList(connectedComponents, settings.isDeobfuscationOn());
return deobfGroup;
......
......@@ -9,7 +9,7 @@ import jadx.api.data.impl.JadxCodeData;
public class ProjectData {
private int projectVersion;
private int projectVersion = 1;
private List<Path> files;
private List<String[]> treeExpansions = new ArrayList<>();
private JadxCodeData codeData = new JadxCodeData();
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=Autom. Hintergrunddekompilierung starten
preferences.select_font=Ändern
preferences.select_smali_font=Ändern
preferences.deobfuscation_on=Deobfuskierung aktivieren
preferences.deobfuscation_force=Überschreiben der Deobfuskierungs-Map-Datei erzwingen
#preferences.deobfuscation_map_file_mode=Map file handle mode
preferences.deobfuscation_min_len=Minimale Namenlänge
preferences.deobfuscation_max_len=Maximale Namenlänge
preferences.deobfuscation_source_alias=Quelldateiname als Klassennamen-Alias verwenden
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=Auto start background decompilation
preferences.select_font=Change
preferences.select_smali_font=Change
preferences.deobfuscation_on=Enable deobfuscation
preferences.deobfuscation_force=Force rewrite deobfuscation map file
preferences.deobfuscation_map_file_mode=Map file handle mode
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
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=Inicio autom. descompilación de fondo
preferences.select_font=Seleccionar
#preferences.select_smali_font=
preferences.deobfuscation_on=Activar desobfuscación
preferences.deobfuscation_force=Forzar reescritura del fichero de ofuscación
#preferences.deobfuscation_map_file_mode=Map file handle mode
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
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=백그라운드에서 디컴파일 자동 시작
preferences.select_font=변경
preferences.select_smali_font=변경
preferences.deobfuscation_on=난독 해제 활성화
preferences.deobfuscation_force=난독 해제 맵 파일 다시 쓰기
#preferences.deobfuscation_map_file_mode=Map file handle mode
preferences.deobfuscation_min_len=최소 이름 길이
preferences.deobfuscation_max_len=최대 이름 길이
preferences.deobfuscation_source_alias=소스 파일 이름을 클래스 이름 별칭으로 사용
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=自动进行后台反编译
preferences.select_font=修改
preferences.select_smali_font=修改
preferences.deobfuscation_on=启用反混淆
preferences.deobfuscation_force=强制覆盖反混淆映射文件
#preferences.deobfuscation_map_file_mode=Map file handle mode
preferences.deobfuscation_min_len=最小命名长度
preferences.deobfuscation_max_len=最大命名长度
preferences.deobfuscation_source_alias=使用资源名作为类的别名
......
......@@ -153,7 +153,7 @@ preferences.start_jobs=自動開始背景反編譯
preferences.select_font=變更
preferences.select_smali_font=變更
preferences.deobfuscation_on=啟用去模糊化
preferences.deobfuscation_force=強制覆寫去模糊化對應檔
#preferences.deobfuscation_map_file_mode=Map file handle mode
preferences.deobfuscation_min_len=最小名稱長度
preferences.deobfuscation_max_len=最大名稱長度
preferences.deobfuscation_source_alias=將原始檔案名稱作為類別別名
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册