core: added deobfuscation feature (basic functionality)

This commit is contained in:
NeoSpb 2015-02-10 20:37:12 +03:00
parent 883429fa47
commit 30138f7a38
16 changed files with 794 additions and 13 deletions

View File

@ -50,6 +50,18 @@ public final class JadxCLIArgs implements IJadxArgs {
@Parameter(names = {"-v", "--verbose"}, description = "verbose output")
protected boolean verbose = false;
@Parameter(names = {"--deobf"}, description = "activate deobfuscation")
protected boolean deobfuscationOn = false;
@Parameter(names = {"--deobf-min"}, description = "min length of name")
protected int deobfuscationMinLength = 2;
@Parameter(names = {"--deobf-max"}, description = "max length of name")
protected int deobfuscationMaxLength = 40;
@Parameter(names = {"--deobf-rewrite-cfg"}, description = "force to save deobfuscation map")
protected boolean deobfuscationForceSave = false;
@Parameter(names = {"-h", "--help"}, description = "print this help", help = true)
protected boolean printHelp = false;
@ -209,4 +221,24 @@ public final class JadxCLIArgs implements IJadxArgs {
public boolean isVerbose() {
return verbose;
}
@Override
public boolean isDeobfuscationOn() {
return deobfuscationOn;
}
@Override
public int getDeobfuscationMinLength() {
return deobfuscationMinLength;
}
@Override
public int getDeobfuscationMaxLength() {
return deobfuscationMaxLength;
}
@Override
public boolean isDeobfuscationForceSave() {
return deobfuscationForceSave;
}
}

View File

@ -6,6 +6,7 @@ dependencies {
runtime files(jadxClasspath)
compile files('lib/dx-1.10.jar')
compile 'commons-io:commons-io:2.4'
compile 'org.ow2.asm:asm:5.0.3'
compile 'com.intellij:annotations:12.0'

View File

@ -48,4 +48,24 @@ public class DefaultJadxArgs implements IJadxArgs {
public boolean isSkipSources() {
return false;
}
@Override
public boolean isDeobfuscationOn() {
return false;
}
@Override
public int getDeobfuscationMinLength() {
return Integer.MIN_VALUE+1;
}
@Override
public int getDeobfuscationMaxLength() {
return Integer.MAX_VALUE-1;
}
@Override
public boolean isDeobfuscationForceSave() {
return false;
}
}

View File

@ -20,4 +20,12 @@ public interface IJadxArgs {
boolean isSkipResources();
boolean isSkipSources();
boolean isDeobfuscationOn();
int getDeobfuscationMinLength();
int getDeobfuscationMaxLength();
boolean isDeobfuscationForceSave();
}

View File

@ -3,6 +3,8 @@ package jadx.api;
import jadx.core.Jadx;
import jadx.core.ProcessClass;
import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.DefaultDeobfuscator;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
@ -253,6 +255,51 @@ public final class JadxDecompiler {
root = new RootNode();
LOG.info("loading ...");
root.load(inputFiles);
if (args.isDeobfuscationOn()) {
final String firstInputFileName = inputFiles.get(0).getFile().getAbsolutePath();
final String inputPath = org.apache.commons.io.FilenameUtils.getFullPathNoEndSeparator(
firstInputFileName);
final String inputName = org.apache.commons.io.FilenameUtils.getBaseName(firstInputFileName);
final File deobfuscationMapFile = new File(inputPath, inputName + ".jobf");
DefaultDeobfuscator deobfuscator = new DefaultDeobfuscator();
if (deobfuscationMapFile.exists()) {
try {
deobfuscator.load(deobfuscationMapFile);
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'",
deobfuscationMapFile.getAbsolutePath());
}
}
deobfuscator.setInputData(root.getDexNodes());
deobfuscator.setMinNameLength(args.getDeobfuscationMinLength());
deobfuscator.setMaxNameLength(args.getDeobfuscationMaxLength());
deobfuscator.process();
try {
if (deobfuscationMapFile.exists()) {
if (args.isDeobfuscationForceSave()) {
deobfuscator.save(deobfuscationMapFile);
} else {
LOG.warn("Deobfuscation map file '{}' exists. Use command line option '--deobf=rewrite-cfg'" +
" to rewrite it", deobfuscationMapFile.getAbsolutePath());
}
} else {
deobfuscator.save(deobfuscationMapFile);
}
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'",
deobfuscationMapFile.getAbsolutePath());
}
Deobfuscator.setDeobfuscator(deobfuscator);
}
root.loadResources(getResources());
root.initAppResClass();
}

View File

@ -1,6 +1,7 @@
package jadx.api;
import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.info.AccessInfo;
@ -150,16 +151,16 @@ public final class JavaClass implements JavaNode {
@Override
public String getName() {
return cls.getShortName();
return Deobfuscator.instance().getClassShortName(cls);
}
@Override
public String getFullName() {
return cls.getFullName();
return Deobfuscator.instance().getClassFullName(cls);
}
public String getPackage() {
return cls.getPackage();
return Deobfuscator.instance().getPackageName(cls.getPackage());
}
@Override
@ -202,6 +203,6 @@ public final class JavaClass implements JavaNode {
@Override
public String toString() {
return getFullName();
return cls.getFullName() + "[ " + getFullName() + " ]";
}
}

View File

@ -1,5 +1,7 @@
package jadx.api;
import jadx.core.deobf.Deobfuscator;
import java.util.List;
import org.jetbrains.annotations.NotNull;
@ -9,7 +11,7 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
private final List<JavaClass> classes;
JavaPackage(String name, List<JavaClass> classes) {
this.name = name;
this.name = Deobfuscator.instance().getPackageName(name);
this.classes = classes;
}

View File

@ -2,6 +2,7 @@ package jadx.core.codegen;
import jadx.api.IJadxArgs;
import jadx.core.Consts;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.AttrNode;
@ -80,14 +81,14 @@ public class ClassGen {
CodeWriter clsCode = new CodeWriter();
if (!"".equals(cls.getPackage())) {
clsCode.add("package ").add(cls.getPackage()).add(';');
clsCode.add("package ").add(Deobfuscator.instance().getPackageName(cls.getPackage())).add(';');
clsCode.newLine();
}
int importsCount = imports.size();
if (importsCount != 0) {
List<String> sortImports = new ArrayList<String>(importsCount);
for (ClassInfo ic : imports) {
sortImports.add(ic.getFullName());
sortImports.add(Deobfuscator.instance().getClassFullName(ic));
}
Collections.sort(sortImports);
@ -142,7 +143,7 @@ public class ClassGen {
} else {
clsCode.add("class ");
}
clsCode.add(cls.getShortName());
clsCode.add(Deobfuscator.instance().getClassShortName(cls));
addGenericMap(clsCode, cls.getGenericMap());
clsCode.add(' ');
@ -453,7 +454,8 @@ public class ClassGen {
if (fallback) {
return fullName;
}
String shortName = classInfo.getShortName();
fullName = Deobfuscator.instance().getClassFullName(classInfo);
String shortName = Deobfuscator.instance().getClassShortName(classInfo);
if (classInfo.getPackage().equals("java.lang") && classInfo.getParentClass() == null) {
return shortName;
} else {
@ -474,7 +476,7 @@ public class ClassGen {
return fullName;
}
if (classInfo.getPackage().equals(useCls.getPackage())) {
fullName = classInfo.getNameWithoutPackage();
fullName = Deobfuscator.instance().getClassName(classInfo);
}
for (ClassInfo importCls : getImports()) {
if (!importCls.equals(classInfo)

View File

@ -1,5 +1,6 @@
package jadx.core.codegen;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.annotations.MethodParameters;
@ -85,7 +86,7 @@ public class MethodGen {
code.add(' ');
}
if (mth.getAccessFlags().isConstructor()) {
code.add(classGen.getClassNode().getShortName()); // constructor
code.add(Deobfuscator.instance().getClassShortName(classGen.getClassNode())); // constructor
} else {
classGen.useType(code, mth.getReturnType());
code.add(' ');

View File

@ -0,0 +1,415 @@
package jadx.core.deobf;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultDeobfuscator implements IDeobfuscator {
private static final Logger LOG = LoggerFactory.getLogger(DefaultDeobfuscator.class);
private static final boolean DEBUG = false;
public static final char classNameSepearator = '.';
private int maxLength = 40;
private int minLength = 2;
private int pkgIndex = 0;
private int clsIndex = 0;
private List<DexNode> dexNodes;
private static PackageNode rootPackage = new PackageNode("");
private static final String MAP_FILE_CHARSET = "UTF-8";
/**
* Gets package node for full package name
*
* @param fullPkgName full package name
* @param _creat if {@code true} then will create all absent objects
*
* @return package node object or {@code null} if no package found and <b>_creat</b> set to {@code false}
*/
public static PackageNode getPackageNode(String fullPkgName, boolean _creat) {
if (fullPkgName.isEmpty() || fullPkgName.equals(classNameSepearator)) {
return rootPackage;
}
PackageNode result = rootPackage;
PackageNode parentNode;
do {
String pkgName;
int idx = fullPkgName.indexOf(classNameSepearator);
if (idx > -1) {
pkgName = fullPkgName.substring(0, idx);
fullPkgName = fullPkgName.substring(idx+1);
} else {
pkgName = fullPkgName;
fullPkgName = "";
}
parentNode = result;
result = result.getInnerPackageByName(pkgName);
if ((result == null) && (_creat)) {
result = new PackageNode(pkgName);
parentNode.addInnerPackage(result);
}
} while (!fullPkgName.isEmpty() && (result != null));
return result;
}
private class DefaultDeobfuscatorClassInfo {
public ClassNode cls;
public PackageNode pkg;
public String alias;
public DefaultDeobfuscatorClassInfo(ClassNode cls, PackageNode pkg) {
this.cls = cls;
this.pkg = pkg;
}
public String getNameWithoutPackage(DefaultDeobfuscatorClassInfo deobfClsInfo) {
final ClassNode clsNode = deobfClsInfo.cls;
String prefix;
ClassNode parentClass = clsNode.getParentClass();
if (parentClass != clsNode) {
DefaultDeobfuscatorClassInfo parentDeobfClassInfo = DefaultDeobfuscator.clsMap.get(parentClass.getClassInfo());
if (parentDeobfClassInfo != null) {
prefix = getNameWithoutPackage(parentDeobfClassInfo) + DefaultDeobfuscator.classNameSepearator;
} else {
prefix = DefaultDeobfuscator.getNameWithoutPackage(parentClass.getClassInfo()) + DefaultDeobfuscator.classNameSepearator;
}
} else {
prefix = "";
}
return prefix + ((deobfClsInfo.alias != null) ? deobfClsInfo.alias : deobfClsInfo.cls.getShortName());
}
public String getFullName() {
return pkg.getFullAlias() + DefaultDeobfuscator.classNameSepearator + getNameWithoutPackage(this);
}
}
private Map<String, String> preloadClsMap = Collections.emptyMap();
private static Map<ClassInfo, DefaultDeobfuscatorClassInfo> clsMap = new HashMap<ClassInfo, DefaultDeobfuscatorClassInfo>();
public static String getNameWithoutPackage(ClassInfo clsInfo) {
String prefix;
ClassInfo parentClsInfo = clsInfo.getParentClass();
if (parentClsInfo != null) {
DefaultDeobfuscatorClassInfo parentDeobfClsInfo = DefaultDeobfuscator.clsMap.get(parentClsInfo);
if (parentDeobfClsInfo != null) {
prefix = parentDeobfClsInfo.getNameWithoutPackage(parentDeobfClsInfo) + DefaultDeobfuscator.classNameSepearator;
} else {
prefix = getNameWithoutPackage(parentClsInfo) + DefaultDeobfuscator.classNameSepearator;
}
} else {
prefix = "";
}
return prefix + clsInfo.getShortName();
}
private void doClass(ClassNode cls) {
final String pkgFullName = cls.getPackage();
PackageNode pkg = getPackageNode(pkgFullName, true);
doPkg(pkg, pkgFullName);
if (preloadClsMap.containsKey(cls.getFullName())) {
DefaultDeobfuscatorClassInfo clsInfo = new DefaultDeobfuscatorClassInfo(cls, pkg);
clsInfo.alias = preloadClsMap.get(cls.getFullName());
clsMap.put(cls.getClassInfo(), clsInfo);
return;
}
if (clsMap.containsKey(cls)) {
return;
}
final String className = cls.getShortName();
if (shouldRename(className)) {
DefaultDeobfuscatorClassInfo clsInfo = new DefaultDeobfuscatorClassInfo(cls, pkg);
clsInfo.alias = String.format("C%04d%s", clsIndex++, short4LongName(className));
clsMap.put(cls.getClassInfo(), clsInfo);
}
}
private String short4LongName(String name) {
if (name.length() > maxLength) {
return "x" + Integer.toHexString(name.hashCode());
} else {
return name;
}
}
private Set<String> pkgSet = new TreeSet<String>();
private void doPkg(PackageNode pkg, String fullName) {
if (pkgSet.contains(fullName)) {
return;
}
pkgSet.add(fullName);
// doPkg for all parent packages except root that not hasAlisas
PackageNode parentPkg = pkg.getParentPackage();
while (!parentPkg.getName().isEmpty()) {
if (!parentPkg.hasAlias()) {
doPkg(parentPkg, parentPkg.getFullName());
}
parentPkg = parentPkg.getParentPackage();
}
final String pkgName = pkg.getName();
if (shouldRename(pkgName) && !pkg.hasAlias()) {
final String pkgAlias = String.format("p%03d%s", pkgIndex++, short4LongName(pkgName));
pkg.setAlias(pkgAlias);
}
}
private void preprocess() {
if (dexNodes != null) {
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
doClass(cls);
}
}
}
}
private boolean shouldRename(String s) {
return s.length() > maxLength || s.length() < minLength || NameMapper.isReserved(s);
}
private void dumpClassAlias(ClassNode cls) {
PackageNode pkg = getPackageNode(cls.getPackage(), false);
if (pkg != null) {
if (!cls.getFullName().equals(getClassFullName(cls))) {
LOG.info("Alias name for class '{}' is '{}'", cls.getFullName(), getClassFullName(cls));
}
} else {
LOG.error("Can't find package node for '{}'", cls.getPackage());
}
}
private void dumpAlias() {
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
dumpClassAlias(cls);
}
}
}
/**
* Sets input data for processing
*
* @param nodes
*
* @return @{code this}
*/
public DefaultDeobfuscator setInputData(List<DexNode> nodes) {
this.dexNodes = nodes;
return this;
}
/**
* Sets minimum name length, if name length lesser than value,
* DefaultDeobfuscator will work
*
* @param value
*
* @return @{code this}
*/
public DefaultDeobfuscator setMinNameLength(int value) {
this.minLength = value;
return this;
}
/**
* Sets maximum name length, if name length greater than value,
* DefaultDeobfuscator will work
*
* @param value
*
* @return @{code this}
*/
public DefaultDeobfuscator setMaxNameLength(int value) {
this.maxLength = value;
return this;
}
/**
* Loads DefaultDeobfuscator presets
*
* @param config
* @throws IOException
*/
public void load(File mapFile) throws IOException {
if (mapFile.exists()) {
List<String> lines = FileUtils.readLines(mapFile, MAP_FILE_CHARSET);
for (String l : lines) {
if (l.startsWith("p ")) {
final String rule = l.substring(2);
final String va[] = rule.split("=");
if (va.length == 2) {
PackageNode pkg = getPackageNode(va[0], true);
pkg.setAlias(va[1]);
}
} else if (l.startsWith("c ")) {
final String rule = l.substring(2);
final String va[] = rule.split("=");
if (va.length == 2) {
if (preloadClsMap.isEmpty()) {
preloadClsMap = new HashMap<String, String>();
}
preloadClsMap.put(va[0], va[1]);
}
}
}
}
}
public void process() {
preprocess();
if (DEBUG) {
dumpAlias();
}
preloadClsMap.clear();
preloadClsMap = Collections.emptyMap();
}
private static void dfsPackageName(List<String> list, String prefix, PackageNode node) {
for (PackageNode pp : node.getInnerPackages()) {
dfsPackageName(list, prefix + '.' + node.getName(), pp);
}
if (node.hasAlias()) {
list.add(String.format("p %s.%s=%s", prefix, node.getName(), node.getAlias()));
}
}
/**
* Saves DefaultDeobfuscator presets
*
* @param mapFile
* @throws IOException
*/
public void save(File mapFile) throws IOException {
List<String> list = new ArrayList<String>();
// packages
for (PackageNode p : rootPackage.getInnerPackages()) {
for (PackageNode pp : p.getInnerPackages()) {
dfsPackageName(list, p.getName(), pp);
}
if (p.hasAlias()) {
list.add(String.format("p %s=%s", p.getName(), p.getAlias()));
}
}
// classes
for (DefaultDeobfuscatorClassInfo deobfClsInfo : clsMap.values()) {
if (deobfClsInfo.alias != null) {
list.add(String.format("c %s=%s", deobfClsInfo.cls.getFullName(), deobfClsInfo.alias));
}
}
FileUtils.writeLines(mapFile, MAP_FILE_CHARSET, list);
list.clear();
}
@Override
public String getPackageName(String packageName) {
final PackageNode pkg = getPackageNode(packageName, false);
if (pkg != null) {
return pkg.getFullAlias();
}
return packageName;
}
@Override
public String getClassShortName(ClassNode cls) {
return getClassShortName(cls.getClassInfo());
}
@Override
public String getClassShortName(ClassInfo clsInfo) {
final DefaultDeobfuscatorClassInfo deobfClsInfo = clsMap.get(clsInfo);
if (deobfClsInfo != null) {
return (deobfClsInfo.alias != null) ? deobfClsInfo.alias : clsInfo.getShortName();
}
return clsInfo.getShortName();
}
@Override
public String getClassName(ClassNode cls) {
return getClassName(cls.getClassInfo());
}
@Override
public String getClassName(ClassInfo clsInfo) {
final DefaultDeobfuscatorClassInfo deobfClsInfo = clsMap.get(clsInfo);
if (deobfClsInfo != null) {
return deobfClsInfo.getNameWithoutPackage(deobfClsInfo);
}
return getNameWithoutPackage(clsInfo);
}
@Override
public String getClassFullName(ClassNode cls) {
return getClassFullName(cls.getClassInfo());
}
@Override
public String getClassFullName(ClassInfo clsInfo) {
final DefaultDeobfuscatorClassInfo deobfClsInfo = clsMap.get(clsInfo);
if (deobfClsInfo != null) {
return deobfClsInfo.getFullName();
}
return getPackageName(clsInfo.getPackage()) + DefaultDeobfuscator.classNameSepearator + getClassName(clsInfo);
}
@Override
public String getClassFullPath(ClassInfo clsInfo) {
final DefaultDeobfuscatorClassInfo deobfClsInfo = clsMap.get(clsInfo);
if (deobfClsInfo != null) {
return deobfClsInfo.pkg.getFullAlias().replace(DefaultDeobfuscator.classNameSepearator, File.separatorChar)
+ File.separatorChar
+ deobfClsInfo.getNameWithoutPackage(deobfClsInfo).replace(DefaultDeobfuscator.classNameSepearator, '_');
}
return getPackageName(clsInfo.getPackage()).replace('.', File.separatorChar)
+ File.separatorChar
+ clsInfo.getNameWithoutPackage().replace('.', '_');
}
}

View File

@ -0,0 +1,37 @@
package jadx.core.deobf;
public class Deobfuscator {
private static final StubDeobfuscator stubDeobfuscator;
private static IDeobfuscator deobfuscatorInstance;
static {
stubDeobfuscator = new StubDeobfuscator();
deobfuscatorInstance = stubDeobfuscator;
}
/**
* Gets instance of active deobfuscator
*
* @return deobfuscator instance
*/
public static IDeobfuscator instance() {
return deobfuscatorInstance;
}
/**
* Sets active deobfuscator
*
* @param deobfuscator object that makes deobfuscation or {@code null}
* to set stub deobfuscator
*
*/
public static void setDeobfuscator(IDeobfuscator deobfuscator) {
if (deobfuscator != null) {
deobfuscatorInstance = deobfuscator;
} else {
deobfuscatorInstance = stubDeobfuscator;
}
}
}

View File

@ -0,0 +1,18 @@
package jadx.core.deobf;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
public interface IDeobfuscator {
public String getPackageName(String packageName);
public String getClassShortName(ClassNode cls);
public String getClassShortName(ClassInfo clsInfo);
public String getClassName(ClassNode cls);
public String getClassName(ClassInfo clsInfo);
public String getClassFullName(ClassNode cls);
public String getClassFullName(ClassInfo clsInfo);
public String getClassFullPath(ClassInfo clsInfo);
}

View File

@ -0,0 +1,147 @@
package jadx.core.deobf;
import jadx.core.dex.nodes.ClassNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
public class PackageNode {
private PackageNode parentPackage;
private List<ClassNode> innerClasses = Collections.emptyList();
private List<PackageNode> innerPackages = Collections.emptyList();
public static final char separatorChar = '.';
private String packageName;
private String packageAlias;
private String cachedPackageFullName;
private String cachedPackageFullAlias;
public PackageNode(String packageName) {
this.packageName = packageName;
this.parentPackage = this;
}
public String getName() {
return packageName;
}
public String getFullName() {
if (cachedPackageFullName == null) {
Stack<PackageNode> pp = getParentPackages();
StringBuilder result = new StringBuilder();
result.append(pp.pop().getName());
while (pp.size() > 0) {
result.append(separatorChar);
result.append(pp.pop().getName());
}
cachedPackageFullName = result.toString();
}
return cachedPackageFullName;
}
public String getAlias() {
if (packageAlias != null) {
return packageAlias;
}
return packageName;
}
public void setAlias(String alias) {
packageAlias = alias;
}
public boolean hasAlias() {
return (packageAlias != null);
}
public String getFullAlias() {
if (cachedPackageFullAlias == null) {
Stack<PackageNode> pp = getParentPackages();
StringBuilder result = new StringBuilder();
result.append(pp.pop().getAlias());
while (pp.size() > 0) {
result.append(separatorChar);
result.append(pp.pop().getAlias());
}
cachedPackageFullAlias = result.toString();
}
return cachedPackageFullAlias;
}
public PackageNode getParentPackage() {
return parentPackage;
}
public List<PackageNode> getInnerPackages() {
return innerPackages;
}
public List<ClassNode> getInnerClasses() {
return innerClasses;
}
public void addInnerClass(ClassNode cls) {
if (innerClasses.isEmpty()) {
innerClasses = new ArrayList<ClassNode>();
}
innerClasses.add(cls);
}
public void addInnerPackage(PackageNode pkg) {
if (innerPackages.isEmpty()) {
innerPackages = new ArrayList<PackageNode>();
}
innerPackages.add(pkg);
pkg.parentPackage = this;
}
/**
* Gets inner package node by name
*
* @param name inner package name
*
* @return package node or {@code null}
*/
public PackageNode getInnerPackageByName(String name) {
PackageNode result = null;
for (PackageNode p : innerPackages) {
if (p.getName().equals(name)) {
result = p;
break;
}
}
return result;
}
/**
* Fills stack with parent packages exclude root node
*
* @return stack with parent packages
*/
private Stack<PackageNode> getParentPackages() {
Stack<PackageNode> pp = new Stack<PackageNode>();
PackageNode currentP = this;
PackageNode parentP = currentP.getParentPackage();
while (currentP != parentP) {
pp.push(currentP);
currentP = parentP;
parentP = currentP.getParentPackage();
}
return pp;
}
}

View File

@ -0,0 +1,48 @@
package jadx.core.deobf;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
public class StubDeobfuscator implements IDeobfuscator {
@Override
public String getPackageName(String packageName) {
return packageName;
}
@Override
public String getClassShortName(ClassNode cls) {
return cls.getShortName();
}
@Override
public String getClassShortName(ClassInfo clsInfo) {
return clsInfo.getShortName();
}
@Override
public String getClassName(ClassNode cls) {
return cls.getClassInfo().getNameWithoutPackage();
}
@Override
public String getClassName(ClassInfo clsInfo) {
return clsInfo.getNameWithoutPackage();
}
@Override
public String getClassFullName(ClassNode cls) {
return cls.getFullName();
}
@Override
public String getClassFullName(ClassInfo clsInfo) {
return clsInfo.getFullName();
}
@Override
public String getClassFullPath(ClassInfo clsInfo) {
return clsInfo.getFullPath();
}
}

View File

@ -2,6 +2,7 @@ package jadx.core.dex.visitors;
import jadx.core.codegen.CodeWriter;
import jadx.core.codegen.MethodGen;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.InsnType;
@ -104,7 +105,7 @@ public class DotGraphVisitor extends AbstractVisitor {
+ (useRegions ? ".regions" : "")
+ (rawInsn ? ".raw" : "")
+ ".dot";
dot.save(dir, mth.getParentClass().getClassInfo().getFullPath() + "_graphs", fileName);
dot.save(dir, Deobfuscator.instance().getClassFullPath(mth.getParentClass().getClassInfo()) + "_graphs", fileName);
}
private void processMethodRegion(MethodNode mth) {

View File

@ -2,6 +2,7 @@ package jadx.core.dex.visitors;
import jadx.api.IJadxArgs;
import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.utils.exceptions.CodegenException;
@ -24,7 +25,7 @@ public class SaveCode extends AbstractVisitor {
public static void save(File dir, IJadxArgs args, ClassNode cls) {
CodeWriter clsCode = cls.getCode();
String fileName = cls.getClassInfo().getFullPath() + ".java";
String fileName = Deobfuscator.instance().getClassFullPath(cls.getClassInfo()) + ".java";
if (args.isFallbackMode()) {
fileName += ".jadx";
}