提交 3314de8d 编写于 作者: S Skylot

core: rename fields and methods in deobfuscation pass.

上级 8dab9b83
......@@ -16,12 +16,12 @@ public final class JavaField implements JavaNode {
@Override
public String getName() {
return field.getName();
return field.getAlias();
}
@Override
public String getFullName() {
return parent.getFullName() + "." + field.getName();
return parent.getFullName() + "." + getName();
}
@Override
......
......@@ -17,7 +17,7 @@ public final class JavaMethod implements JavaNode {
@Override
public String getName() {
return mth.getName();
return mth.getAlias();
}
@Override
......
......@@ -108,9 +108,7 @@ public class Jadx {
passes.add(new DependencyCollector());
if (args.isDeobfuscationOn()) {
passes.add(new RenameVisitor());
}
passes.add(new RenameVisitor());
}
return passes;
}
......
......@@ -53,10 +53,6 @@ public final class ProcessClass {
static void processDependencies(ClassNode cls, List<IDexTreeVisitor> passes) {
for (ClassNode depCls : cls.getDependencies()) {
if (cls.getTopParentClass() == cls) {
// ignore inner classes of this class
continue;
}
process(depCls, passes, null);
}
}
......
......@@ -337,7 +337,7 @@ public class ClassGen {
code.startLine(f.getAccessFlags().makeString());
useType(code, f.getType());
code.add(' ');
code.add(f.getName());
code.add(f.getAlias());
FieldValueAttr fv = f.get(AType.FIELD_VALUE);
if (fv != null) {
code.add(" = ");
......
......@@ -157,7 +157,7 @@ public class InsnGen {
if (fieldNode != null) {
code.attachAnnotation(fieldNode);
}
code.add(field.getName());
code.add(field.getAlias());
}
public static void makeStaticFieldAccess(CodeWriter code, FieldInfo field, ClassGen clsGen) {
......@@ -179,7 +179,7 @@ public class InsnGen {
if (fieldNode != null) {
code.attachAnnotation(fieldNode);
}
code.add(field.getName());
code.add(field.getAlias());
}
protected void staticField(CodeWriter code, FieldInfo field) {
......@@ -612,7 +612,7 @@ public class InsnGen {
if (callMthNode != null) {
code.attachAnnotation(callMthNode);
}
code.add(callMth.getName());
code.add(callMth.getAlias());
generateMethodArguments(code, insn, k, callMthNode);
}
......
......@@ -90,7 +90,7 @@ public class MethodGen {
} else {
classGen.useType(code, mth.getReturnType());
code.add(' ');
code.add(mth.getName());
code.add(mth.getAlias());
}
code.add('(');
......
......@@ -245,7 +245,7 @@ public class RegionGen extends InsnGen {
if (k instanceof FieldNode) {
FieldNode fn = (FieldNode) k;
if (fn.getParentClass().isEnum()) {
code.add(fn.getName());
code.add(fn.getAlias());
} else {
staticField(code, fn.getFieldInfo());
// print original value, sometimes replace with incorrect field
......
package jadx.core.deobf;
import jadx.core.dex.nodes.ClassNode;
class DeobfClsInfo {
private final Deobfuscator deobfuscator;
private final ClassNode cls;
private final PackageNode pkg;
private final String alias;
public DeobfClsInfo(Deobfuscator deobfuscator, ClassNode cls, PackageNode pkg, String alias) {
this.deobfuscator = deobfuscator;
this.cls = cls;
this.pkg = pkg;
this.alias = alias;
}
public String makeNameWithoutPkg() {
String prefix;
ClassNode parentClass = cls.getParentClass();
if (parentClass != cls) {
DeobfClsInfo parentDeobfClsInfo = deobfuscator.getClsMap().get(parentClass.getClassInfo());
if (parentDeobfClsInfo != null) {
prefix = parentDeobfClsInfo.makeNameWithoutPkg();
} else {
prefix = deobfuscator.getNameWithoutPackage(parentClass.getClassInfo());
}
prefix += Deobfuscator.INNER_CLASS_SEPARATOR;
} else {
prefix = "";
}
return prefix + (this.alias != null ? this.alias : this.cls.getShortName());
}
public String getFullName() {
return pkg.getFullAlias() + Deobfuscator.CLASS_NAME_SEPARATOR + makeNameWithoutPkg();
}
public ClassNode getCls() {
return cls;
}
public PackageNode getPkg() {
return pkg;
}
public String getAlias() {
return alias;
}
}
package jadx.core.deobf;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
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 org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class DeobfPresets {
private static final Logger LOG = LoggerFactory.getLogger(DeobfPresets.class);
private static final String MAP_FILE_CHARSET = "UTF-8";
private final Deobfuscator deobfuscator;
private final File deobfMapFile;
private final Map<String, String> clsPresetMap = new HashMap<String, String>();
private final Map<String, String> fldPresetMap = new HashMap<String, String>();
private final Map<String, String> mthPresetMap = new HashMap<String, String>();
public DeobfPresets(Deobfuscator deobfuscator, File deobfMapFile) {
this.deobfuscator = deobfuscator;
this.deobfMapFile = deobfMapFile;
}
/**
* Loads deobfuscator presets
*/
public void load() {
if (!deobfMapFile.exists()) {
return;
}
LOG.info("Loading obfuscation map from: {}", deobfMapFile.getAbsoluteFile());
try {
List<String> lines = FileUtils.readLines(deobfMapFile, MAP_FILE_CHARSET);
for (String l : lines) {
l = l.trim();
if (l.isEmpty() || l.startsWith("#")) {
continue;
}
String[] va = splitAndTrim(l);
if (va.length != 2) {
continue;
}
String origName = va[0];
String alias = va[1];
if (l.startsWith("p ")) {
deobfuscator.addPackagePreset(origName, alias);
} else if (l.startsWith("c ")) {
clsPresetMap.put(origName, alias);
} else if (l.startsWith("f ")) {
fldPresetMap.put(origName, alias);
} else if (l.startsWith("m ")) {
mthPresetMap.put(origName, alias);
}
}
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.getAbsolutePath(), e);
}
}
private static String[] splitAndTrim(String str) {
String[] v = str.substring(2).split("=");
for (int i = 0; i < v.length; i++) {
v[i] = v[i].trim();
}
return v;
}
public void save(boolean forceSave) {
try {
if (deobfMapFile.exists()) {
if (forceSave) {
dumpMapping();
} else {
LOG.warn("Deobfuscation map file '{}' exists. Use command line option '--deobf-rewrite-cfg' to rewrite it",
deobfMapFile.getAbsolutePath());
}
} else {
dumpMapping();
}
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.getAbsolutePath(), e);
}
}
/**
* Saves DefaultDeobfuscator presets
*/
private void dumpMapping() throws IOException {
List<String> list = new ArrayList<String>();
// packages
for (PackageNode p : deobfuscator.getRootPackage().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 (DeobfClsInfo deobfClsInfo : deobfuscator.getClsMap().values()) {
if (deobfClsInfo.getAlias() != null) {
list.add(String.format("c %s = %s",
deobfClsInfo.getCls().getClassInfo().getFullName(), deobfClsInfo.getAlias()));
}
}
for (FieldInfo fld : deobfuscator.getFldMap().keySet()) {
list.add(String.format("f %s = %s", fld.getFullId(), fld.getAlias()));
}
for (MethodInfo mth : deobfuscator.getMthMap().keySet()) {
list.add(String.format("m %s = %s", mth.getFullId(), mth.getAlias()));
}
Collections.sort(list);
FileUtils.writeLines(deobfMapFile, MAP_FILE_CHARSET, list);
list.clear();
}
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()));
}
}
public String getForCls(ClassInfo cls) {
return clsPresetMap.get(cls.getFullName());
}
public String getForFld(FieldInfo fld) {
return fldPresetMap.get(fld.getFullId());
}
public String getForMth(MethodInfo mth) {
return mthPresetMap.get(mth.getFullId());
}
public void clear() {
clsPresetMap.clear();
fldPresetMap.clear();
mthPresetMap.clear();
}
public Map<String, String> getClsPresetMap() {
return clsPresetMap;
}
public Map<String, String> getFldPresetMap() {
return fldPresetMap;
}
public Map<String, String> getMthPresetMap() {
return mthPresetMap;
}
}
......@@ -4,21 +4,22 @@ import jadx.api.IJadxArgs;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.SourceFileAttr;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
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.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -27,56 +28,60 @@ public class Deobfuscator {
private static final boolean DEBUG = false;
private static final String MAP_FILE_CHARSET = "UTF-8";
private static final String CLASS_NAME_SEPARATOR = ".";
private static final String INNER_CLASS_SEPARATOR = "$";
public static final String CLASS_NAME_SEPARATOR = ".";
public static final String INNER_CLASS_SEPARATOR = "$";
private final Map<ClassInfo, DeobfClsInfo> clsMap = new HashMap<ClassInfo, DeobfClsInfo>();
private final IJadxArgs args;
private final File deobfMapFile;
@NotNull
private final List<DexNode> dexNodes;
private final DeobfPresets deobfPresets;
private final Map<ClassInfo, DeobfClsInfo> clsMap = new HashMap<ClassInfo, DeobfClsInfo>();
private final Map<FieldInfo, String> fldMap = new HashMap<FieldInfo, String>();
private final Map<MethodInfo, String> mthMap = new HashMap<MethodInfo, String>();
private final PackageNode rootPackage = new PackageNode("");
private final Set<String> pkgSet = new TreeSet<String>();
private final int maxLength;
private final int minLength;
private int pkgIndex = 0;
private int clsIndex = 0;
private final PackageNode rootPackage = new PackageNode("");
private final Set<String> pkgSet = new TreeSet<String>();
private Map<String, String> preLoadClsMap = Collections.emptyMap();
private int fldIndex = 0;
private int mthIndex = 0;
public Deobfuscator(IJadxArgs args, @NotNull List<DexNode> dexNodes, File deobfMapFile) {
this.args = args;
this.dexNodes = dexNodes;
this.deobfMapFile = deobfMapFile;
this.minLength = args.getDeobfuscationMinLength();
this.maxLength = args.getDeobfuscationMaxLength();
this.deobfPresets = new DeobfPresets(this, deobfMapFile);
}
public void execute() {
if (deobfMapFile.exists() && !args.isDeobfuscationForceSave()) {
try {
load();
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.getAbsolutePath(), e);
}
if (!args.isDeobfuscationForceSave()) {
deobfPresets.load();
initIndexes();
}
process();
try {
if (deobfMapFile.exists()) {
if (args.isDeobfuscationForceSave()) {
save();
} else {
LOG.warn("Deobfuscation map file '{}' exists. Use command line option '--deobf-rewrite-cfg' to rewrite it",
deobfMapFile.getAbsolutePath());
}
} else {
save();
deobfPresets.save(args.isDeobfuscationForceSave());
clear();
}
private void initIndexes() {
pkgIndex = pkgSet.size();
clsIndex = deobfPresets.getClsPresetMap().size();
fldIndex = deobfPresets.getFldPresetMap().size();
mthIndex = deobfPresets.getMthPresetMap().size();
}
private void preProcess() {
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
doClass(cls);
}
} catch (IOException e) {
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.getAbsolutePath(), e);
}
}
......@@ -85,20 +90,47 @@ public class Deobfuscator {
if (DEBUG) {
dumpAlias();
}
preLoadClsMap.clear();
preLoadClsMap = Collections.emptyMap();
for (DexNode dexNode : dexNodes) {
for (ClassNode classNode : dexNode.getClasses()) {
ClassInfo clsInfo = classNode.getClassInfo();
String fullName = getClassFullName(clsInfo);
if (!fullName.equals(clsInfo.getFullName())) {
clsInfo.rename(dexNode, fullName);
}
for (ClassNode cls : dexNode.getClasses()) {
processClass(dexNode, cls);
}
}
}
void clear() {
deobfPresets.clear();
clsMap.clear();
fldMap.clear();
mthMap.clear();
}
private void processClass(DexNode dex, ClassNode cls) {
ClassInfo clsInfo = cls.getClassInfo();
String fullName = getClassFullName(clsInfo);
if (!fullName.equals(clsInfo.getFullName())) {
clsInfo.rename(dex, fullName);
}
for (FieldNode field : cls.getFields()) {
FieldInfo fieldInfo = field.getFieldInfo();
String alias = getFieldAlias(field);
if (alias != null) {
fieldInfo.setAlias(alias);
}
}
for (MethodNode mth : cls.getMethods()) {
MethodInfo methodInfo = mth.getMethodInfo();
String alias = getMethodAlias(mth);
if (alias != null) {
methodInfo.setAlias(alias);
}
}
}
public void addPackagePreset(String origPkgName, String pkgAlias) {
PackageNode pkg = getPackageNode(origPkgName, true);
pkg.setAlias(pkgAlias);
}
/**
* Gets package node for full package name
*
......@@ -134,41 +166,7 @@ public class Deobfuscator {
return result;
}
private final class DeobfClsInfo {
public final ClassNode cls;
public final PackageNode pkg;
public final String alias;
public DeobfClsInfo(ClassNode cls, PackageNode pkg, String alias) {
this.cls = cls;
this.pkg = pkg;
this.alias = alias;
}
public String makeNameWithoutPkg() {
String prefix;
ClassNode parentClass = cls.getParentClass();
if (parentClass != cls) {
DeobfClsInfo parentDeobfClsInfo = clsMap.get(parentClass.getClassInfo());
if (parentDeobfClsInfo != null) {
prefix = parentDeobfClsInfo.makeNameWithoutPkg();
} else {
prefix = getNameWithoutPackage(parentClass.getClassInfo());
}
prefix += INNER_CLASS_SEPARATOR;
} else {
prefix = "";
}
return prefix + (this.alias != null ? this.alias : this.cls.getShortName());
}
public String getFullName() {
return pkg.getFullAlias() + CLASS_NAME_SEPARATOR + makeNameWithoutPkg();
}
}
private String getNameWithoutPackage(ClassInfo clsInfo) {
String getNameWithoutPackage(ClassInfo clsInfo) {
String prefix;
ClassInfo parentClsInfo = clsInfo.getParentClass();
if (parentClsInfo != null) {
......@@ -191,18 +189,17 @@ public class Deobfuscator {
PackageNode pkg = getPackageNode(pkgFullName, true);
doPkg(pkg, pkgFullName);
String fullName = classInfo.getFullName();
if (preLoadClsMap.containsKey(fullName)) {
String alias = preLoadClsMap.get(fullName);
clsMap.put(classInfo, new DeobfClsInfo(cls, pkg, alias));
String alias = deobfPresets.getForCls(classInfo);
if (alias != null) {
clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias));
return;
}
if (clsMap.containsKey(classInfo)) {
return;
}
if (shouldRename(classInfo.getShortName())) {
String alias = makeClsAlias(cls);
clsMap.put(classInfo, new DeobfClsInfo(cls, pkg, alias));
alias = makeClsAlias(cls);
clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias));
}
}
......@@ -224,6 +221,54 @@ public class Deobfuscator {
return String.format("C%04d%s", clsIndex++, makeName(clsName));
}
@Nullable
public String getFieldAlias(FieldNode field) {
FieldInfo fieldInfo = field.getFieldInfo();
String alias = fldMap.get(fieldInfo);
if (alias != null) {
return alias;
}
alias = deobfPresets.getForFld(fieldInfo);
if (alias != null) {
fldMap.put(fieldInfo, alias);
return alias;
}
if (shouldRename(field.getName())) {
return makeFieldAlias(field);
}
return null;
}
@Nullable
public String getMethodAlias(MethodNode mth) {
MethodInfo methodInfo = mth.getMethodInfo();
String alias = mthMap.get(methodInfo);
if (alias != null) {
return alias;
}
alias = deobfPresets.getForMth(methodInfo);
if (alias != null) {
mthMap.put(methodInfo, alias);
return alias;
}
if (shouldRename(mth.getName())) {
return makeMethodAlias(mth);
}
return null;
}
public String makeFieldAlias(FieldNode field) {
String alias = String.format("f%d%s", fldIndex++, makeName(field.getName()));
fldMap.put(field.getFieldInfo(), alias);
return alias;
}
public String makeMethodAlias(MethodNode mth) {
String alias = String.format("m%d%s", mthIndex++, makeName(mth.getName()));
mthMap.put(mth.getMethodInfo(), alias);
return alias;
}
private void doPkg(PackageNode pkg, String fullName) {
if (pkgSet.contains(fullName)) {
return;
......@@ -246,14 +291,6 @@ public class Deobfuscator {
}
}
private void preProcess() {
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
doClass(cls);
}
}
}
private boolean shouldRename(String s) {
return s.length() > maxLength
|| s.length() < minLength
......@@ -305,80 +342,6 @@ public class Deobfuscator {
}
}
/**
* Loads deobfuscator presets
*
* @throws IOException
*/
private void load() throws IOException {
if (!deobfMapFile.exists()) {
return;
}
LOG.info("Loading obfuscation map from: {}", deobfMapFile.getAbsoluteFile());
List<String> lines = FileUtils.readLines(deobfMapFile, MAP_FILE_CHARSET);
for (String l : lines) {
l = l.trim();
if (l.startsWith("p ")) {
String[] va = splitAndTrim(l);
if (va.length == 2) {
PackageNode pkg = getPackageNode(va[0], true);
pkg.setAlias(va[1]);
}
} else if (l.startsWith("c ")) {
String[] va = splitAndTrim(l);
if (va.length == 2) {
if (preLoadClsMap.isEmpty()) {
preLoadClsMap = new HashMap<String, String>();
}
preLoadClsMap.put(va[0], va[1]);
}
}
}
}
private static String[] splitAndTrim(String str) {
String[] v = str.substring(2).split("=");
for (int i = 0; i < v.length; i++) {
v[i] = v[i].trim();
}
return v;
}
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
*/
private void save() 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 (DeobfClsInfo deobfClsInfo : clsMap.values()) {
if (deobfClsInfo.alias != null) {
list.add(String.format("c %s=%s",
deobfClsInfo.cls.getClassInfo().getFullName(), deobfClsInfo.alias));
}
}
Collections.sort(list);
FileUtils.writeLines(deobfMapFile, MAP_FILE_CHARSET, list);
list.clear();
}
private String getPackageName(String packageName) {
final PackageNode pkg = getPackageNode(packageName, false);
if (pkg != null) {
......@@ -406,4 +369,20 @@ public class Deobfuscator {
}
return getPackageName(clsInfo.getPackage()) + CLASS_NAME_SEPARATOR + getClassName(clsInfo);
}
public Map<ClassInfo, DeobfClsInfo> getClsMap() {
return clsMap;
}
public Map<FieldInfo, String> getFldMap() {
return fldMap;
}
public Map<MethodInfo, String> getMthMap() {
return mthMap;
}
public PackageNode getRootPackage() {
return rootPackage;
}
}
......@@ -88,10 +88,11 @@ public class NameMapper {
}
public static boolean isAllCharsPrintable(String str) {
for (int i = 0; i < str.length(); i++) {
if (!isPrintableChar(str.charAt(i))) {
return false;
}
int len = str.length();
for (int i = 0; i < len; i++) {
if (!isPrintableChar(str.charAt(i))) {
return false;
}
}
return true;
}
......
......@@ -7,11 +7,11 @@ import java.util.Stack;
public class PackageNode {
private static final char SEPARATOR_CHAR = '.';
private PackageNode parentPackage;
private List<PackageNode> innerPackages = Collections.emptyList();
private static final char separatorChar = '.';
private final String packageName;
private String packageAlias;
......@@ -34,7 +34,7 @@ public class PackageNode {
StringBuilder result = new StringBuilder();
result.append(pp.pop().getName());
while (pp.size() > 0) {
result.append(separatorChar);
result.append(SEPARATOR_CHAR);
result.append(pp.pop().getName());
}
cachedPackageFullName = result.toString();
......@@ -63,7 +63,7 @@ public class PackageNode {
StringBuilder result = new StringBuilder();
result.append(pp.pop().getAlias());
while (pp.size() > 0) {
result.append(separatorChar);
result.append(SEPARATOR_CHAR);
result.append(pp.pop().getAlias());
}
cachedPackageFullAlias = result.toString();
......
package jadx.core.dex.info;
import jadx.core.codegen.TypeGen;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.DexNode;
......@@ -10,11 +11,13 @@ public final class FieldInfo {
private final ClassInfo declClass;
private final String name;
private final ArgType type;
private String alias;
private FieldInfo(ClassInfo declClass, String name, ArgType type) {
this.declClass = declClass;
this.name = name;
this.type = type;
this.alias = name;
}
public static FieldInfo from(DexNode dex, ClassInfo declClass, String name, ArgType type) {
......@@ -42,6 +45,22 @@ public final class FieldInfo {
return declClass;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getFullId() {
return declClass.getFullName() + "." + name + ":" + TypeGen.signature(type);
}
public boolean isRenamed() {
return !name.equals(alias);
}
@Override
public boolean equals(Object o) {
if (this == o) {
......
......@@ -17,10 +17,12 @@ public final class MethodInfo {
private final List<ArgType> args;
private final ClassInfo declClass;
private final String shortId;
private String alias;
private MethodInfo(DexNode dex, int mthIndex) {
MethodId mthId = dex.getMethodId(mthIndex);
name = dex.getString(mthId.getNameIndex());
alias = name;
declClass = ClassInfo.fromDex(dex, mthId.getDeclaringClassIndex());
ProtoId proto = dex.getProtoId(mthId.getProtoIndex());
......@@ -91,6 +93,18 @@ public final class MethodInfo {
return name.equals("<clinit>");
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public boolean isRenamed() {
return !name.equals(alias);
}
@Override
public int hashCode() {
int result = declClass.hashCode();
......
......@@ -42,6 +42,10 @@ public class FieldNode extends LineAttrNode {
return fieldInfo.getName();
}
public String getAlias() {
return fieldInfo.getAlias();
}
public ArgType getType() {
return type;
}
......
......@@ -369,6 +369,10 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return mthInfo.getName();
}
public String getAlias() {
return mthInfo.getAlias();
}
public ClassNode getParentClass() {
return parentClass;
}
......
......@@ -2,6 +2,9 @@ package jadx.core.dex.visitors;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InvokeNode;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
......@@ -73,6 +76,21 @@ public class DependencyCollector extends AbstractVisitor {
addDep(dex, depList, arg.getType());
}
}
processCustomInsn(dex, depList, insnNode);
}
private static void processCustomInsn(DexNode dex, Set<ClassNode> depList, InsnNode insn) {
if (insn instanceof IndexInsnNode) {
Object index = ((IndexInsnNode) insn).getIndex();
if (index instanceof FieldInfo) {
addDep(dex, depList, ((FieldInfo) index).getDeclClass());
} else if (index instanceof ArgType) {
addDep(dex, depList, (ArgType) index);
}
} else if (insn instanceof InvokeNode) {
ClassInfo declClass = ((InvokeNode) insn).getCallMth().getDeclClass();
addDep(dex, depList, declClass);
}
}
private static void addDep(DexNode dex, Set<ClassNode> depList, ArgType type) {
......@@ -94,15 +112,14 @@ public class DependencyCollector extends AbstractVisitor {
private static void addDep(DexNode dex, Set<ClassNode> depList, ClassInfo clsInfo) {
if (clsInfo != null) {
ClassNode node = dex.resolveClass(clsInfo);
if (node != null) {
depList.add(node);
}
addDep(dex, depList, node);
}
}
private static void addDep(DexNode dex, Set<ClassNode> depList, ClassNode clsNode) {
if (clsNode != null) {
depList.add(clsNode);
// add only top classes
depList.add(clsNode.getTopParentClass());
}
}
}
package jadx.core.dex.visitors;
import jadx.api.IJadxArgs;
import jadx.core.codegen.TypeGen;
import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
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.RootNode;
import jadx.core.utils.exceptions.JadxException;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.NotNull;
public class RenameVisitor extends AbstractVisitor {
@NotNull
private Deobfuscator deobfuscator;
@Override
public void init(RootNode root) {
String firstInputFileName = root.getDexNodes().get(0).getInputFile().getFile().getAbsolutePath();
String inputPath = FilenameUtils.getFullPathNoEndSeparator(firstInputFileName);
String inputName = FilenameUtils.getBaseName(firstInputFileName);
File deobfMapFile = new File(inputPath, inputName + ".jobf");
deobfuscator = new Deobfuscator(root.getArgs(), root.getDexNodes(), deobfMapFile);
// TODO: check classes for case sensitive names (issue #24)
// TODO: sometimes can be used source file name from 'SourceFileAttr'
deobfuscator.execute();
IJadxArgs args = root.getArgs();
File deobfMapFile = new File(args.getOutDir(), "deobf_map.jobf");
deobfuscator = new Deobfuscator(args, root.getDexNodes(), deobfMapFile);
if (args.isDeobfuscationOn()) {
// TODO: check classes for case sensitive names (issue #24)
deobfuscator.execute();
}
}
@Override
public boolean visit(ClassNode cls) throws JadxException {
// TODO: rename fields and methods
checkFields(cls);
checkMethods(cls);
for (ClassNode inner : cls.getInnerClasses()) {
visit(inner);
}
return false;
}
private void checkFields(ClassNode cls) {
Set<String> names = new HashSet<String>();
for (FieldNode field : cls.getFields()) {
FieldInfo fieldInfo = field.getFieldInfo();
if (!names.add(fieldInfo.getAlias())) {
fieldInfo.setAlias(deobfuscator.makeFieldAlias(field));
}
}
}
private void checkMethods(ClassNode cls) {
Set<String> names = new HashSet<String>();
for (MethodNode mth : cls.getMethods()) {
if (mth.contains(AFlag.DONT_GENERATE)) {
continue;
}
MethodInfo methodInfo = mth.getMethodInfo();
String signature = makeMethodSignature(methodInfo);
if (!names.add(signature)) {
methodInfo.setAlias(deobfuscator.makeMethodAlias(mth));
}
}
}
private static String makeMethodSignature(MethodInfo methodInfo) {
StringBuilder signature = new StringBuilder();
signature.append(methodInfo.getAlias());
signature.append('(');
for (ArgType arg : methodInfo.getArgumentsTypes()) {
signature.append(TypeGen.signature(arg));
}
signature.append(')');
return signature.toString();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册