Skip to content

Commit

Permalink
fix: force rename fields and methods with reserved names (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Oct 24, 2018
1 parent 778b9bb commit 3815d30
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ out/
*.iml
*.ipr
*.iws
.attach_pid*

**/.DS_Store

Expand Down
4 changes: 2 additions & 2 deletions jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public boolean addDefinition(CodeWriter code) {
ai = ai.remove(AccessFlags.ACC_PUBLIC);
}

if (mth.getMethodInfo().isRenamed()) {
if (mth.getMethodInfo().isRenamed() && !ai.isConstructor()) {
code.startLine("/* renamed from: ").add(mth.getName()).add(" */");
}
code.startLineWithNum(mth.getSourceLine());
Expand All @@ -87,7 +87,7 @@ public boolean addDefinition(CodeWriter code) {
if (classGen.addGenericMap(code, mth.getGenericMap())) {
code.add(' ');
}
if (mth.getAccessFlags().isConstructor()) {
if (ai.isConstructor()) {
code.attachDefinition(mth);
code.add(classGen.getClassNode().getShortName()); // constructor
} else {
Expand Down
22 changes: 9 additions & 13 deletions jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private void postProcess() {
for (MethodInfo mth : o.getMethods()) {
if (aliasToUse == null) {
if (mth.isRenamed() && !mth.isAliasFromPreset()) {
mth.setAlias(String.format("mo%d%s", id, makeName(mth.getName())));
mth.setAlias(String.format("mo%d%s", id, prepareNamePart(mth.getName())));
}
aliasToUse = mth.getAlias();
}
Expand Down Expand Up @@ -350,7 +350,7 @@ private String makeClsAlias(ClassNode cls) {

if (alias == null) {
String clsName = classInfo.getShortName();
alias = String.format("C%04d%s", clsIndex++, makeName(clsName));
alias = String.format("C%04d%s", clsIndex++, prepareNamePart(clsName));
}
PackageNode pkg = getPackageNode(classInfo.getPackage(), true);
clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias));
Expand Down Expand Up @@ -426,13 +426,13 @@ private String getMethodAlias(MethodNode mth) {
}

public String makeFieldAlias(FieldNode field) {
String alias = String.format("f%d%s", fldIndex++, makeName(field.getName()));
String alias = String.format("f%d%s", fldIndex++, prepareNamePart(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()));
String alias = String.format("m%d%s", mthIndex++, prepareNamePart(mth.getName()));
mthMap.put(mth.getMethodInfo(), alias);
return alias;
}
Expand All @@ -454,25 +454,21 @@ private void doPkg(PackageNode pkg, String fullName) {

String pkgName = pkg.getName();
if (!pkg.hasAlias() && shouldRename(pkgName)) {
String pkgAlias = String.format("p%03d%s", pkgIndex++, makeName(pkgName));
String pkgAlias = String.format("p%03d%s", pkgIndex++, prepareNamePart(pkgName));
pkg.setAlias(pkgAlias);
}
}

private boolean shouldRename(String s) {
return s.length() > maxLength
|| s.length() < minLength
|| NameMapper.isReserved(s)
|| !NameMapper.isAllCharsPrintable(s);
int len = s.length();
return len < minLength || len > maxLength
|| !NameMapper.isValidIdentifier(s);
}

private String makeName(String name) {
private String prepareNamePart(String name) {
if (name.length() > maxLength) {
return "x" + Integer.toHexString(name.hashCode());
}
if (NameMapper.isReserved(name)) {
return name;
}
if (!NameMapper.isAllCharsPrintable(name)) {
return removeInvalidChars(name);
}
Expand Down
2 changes: 2 additions & 0 deletions jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ public static boolean isReserved(String str) {

public static boolean isValidIdentifier(String str) {
return notEmpty(str)
&& !isReserved(str)
&& VALID_JAVA_IDENTIFIER.matcher(str).matches()
&& isAllCharsPrintable(str);
}

public static boolean isValidFullIdentifier(String str) {
return notEmpty(str)
&& !isReserved(str)
&& VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches()
&& isAllCharsPrintable(str);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jadx.api.JadxArgs;
import jadx.core.Consts;
import jadx.core.deobf.Deobfuscator;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
Expand Down Expand Up @@ -100,7 +101,8 @@ private void checkFields(ClassNode cls) {
Set<String> names = new HashSet<>();
for (FieldNode field : cls.getFields()) {
FieldInfo fieldInfo = field.getFieldInfo();
if (!names.add(fieldInfo.getAlias())) {
String fieldName = fieldInfo.getAlias();
if (!names.add(fieldName) || !NameMapper.isValidIdentifier(fieldName)) {
deobfuscator.renameField(field);
}
}
Expand All @@ -109,11 +111,11 @@ private void checkFields(ClassNode cls) {
private void checkMethods(ClassNode cls) {
Set<String> names = new HashSet<>();
for (MethodNode mth : cls.getMethods()) {
if (mth.contains(AFlag.DONT_GENERATE)) {
if (mth.contains(AFlag.DONT_GENERATE) || mth.getAccessFlags().isConstructor()) {
continue;
}
String signature = mth.getMethodInfo().makeSignature(false);
if (!names.add(signature)) {
if (!names.add(signature) || !NameMapper.isValidIdentifier(mth.getAlias())) {
deobfuscator.renameMethod(mth);
}
}
Expand Down
21 changes: 18 additions & 3 deletions jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.tests.api.compiler.DynamicCompiler;
Expand Down Expand Up @@ -137,20 +138,34 @@ private void insertResources(RootNode root) {
}

protected void decompile(JadxDecompiler jadx, ClassNode cls) {
List<IDexTreeVisitor> passes = Jadx.getPassesList(jadx.getArgs());
List<IDexTreeVisitor> passes = getPassesList(jadx);
ProcessClass.process(cls, passes, new CodeGen());
}

protected void decompileWithoutUnload(JadxDecompiler d, ClassNode cls) {
protected void decompileWithoutUnload(JadxDecompiler jadx, ClassNode cls) {
cls.load();
List<IDexTreeVisitor> passes = Jadx.getPassesList(d.getArgs());
List<IDexTreeVisitor> passes = getPassesList(jadx);
for (IDexTreeVisitor visitor : passes) {
DepthTraversal.visit(visitor, cls);
}
generateClsCode(cls);
// don't unload class
}

private List<IDexTreeVisitor> getPassesList(JadxDecompiler jadx) {
RootNode root = JadxInternalAccess.getRoot(jadx);
List<IDexTreeVisitor> passesList = Jadx.getPassesList(jadx.getArgs());
passesList.forEach(pass -> {
try {
pass.init(root);
} catch (JadxException e) {
e.printStackTrace();
fail(e.getMessage());
}
});
return passesList;
}

protected void generateClsCode(ClassNode cls) {
try {
new CodeGen().visit(cls);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package jadx.tests.integration.names;

import org.junit.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

public class TestReservedNames extends SmaliTest {
/*
public static class TestCls {
public String do; // reserved name
public String 0f; // invalid identifier
public String try() {
return this.do;
}
}
*/

@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("names", "TestReservedNames");
String code = cls.getCode().toString();

assertThat(code, not(containsString("public String do;")));
}
}
32 changes: 32 additions & 0 deletions jadx-core/src/test/smali/names/TestReservedNames.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.class public LTestReservedNames;
.super Ljava/lang/Object;
.source "TestReservedNames.java"


# instance fields
.field public do:Ljava/lang/String; # reserved name
.field public 0f:Ljava/lang/String; # invalid identifier


# direct methods
.method public constructor <init>()V
.registers 1

.prologue
.line 3
invoke-direct {p0}, Ljava/lang/Object;-><init>()V

return-void
.end method


# virtual methods
.method public try()Ljava/lang/String;
.registers 2

.prologue
.line 8
iget-object v0, p0, LTestReservedNames;->do:Ljava/lang/String;

return-object v0
.end method

0 comments on commit 3815d30

Please sign in to comment.