Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] [SmaliVM] visitClassAnnotations() fail on parsing obfuscated member class names #161

Open
fipso opened this issue Jul 26, 2021 · 3 comments

Comments

@fipso
Copy link

fipso commented Jul 26, 2021

Some obfuscators tend to rename member classes to short random strings like "Ab" or "Bc".

.class public final Lde/fipso/test/container/ui/ContainerActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.source "ContainerActivity.kt"

# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Lde/fipso/test/rL;
    }
.end annotation

visitInnerClasses() then fails to parse the inner and outer class name, because we are not using the default class name format with the $ as the separator. (java.lang.ArrayIndexOutOfBoundsException: 1 -> ClassBuilder.java:150);

EDIT:
This could be a baksmali issue.

@CalebFenton
Copy link
Owner

Thanks for the report. I'm also leaning towards this being a dexlib issue. If you can't reproduce with just baksmali, can you share a Dex file which causes the issue?

@fipso
Copy link
Author

fipso commented Jul 27, 2021

classes3.zip

Seems like this is a feature of the Axan Obfuscator, but again this could be a misbehaviour in the smali class name generation by baksmali or dexlib.

I was able to come up with a dirty fix for this problem.
Basically, I am just passing the parents Class name as the outer class name and using the full member class name as the inner class name.

private void visitInnerClasses(String parentClassName, BuilderEncodedValues.BuilderTypeEncodedValue value,
                                   ClassWriter classWriter) {
        // String name, String outerName, String innerName, int access
        String internalName = value.getValue();
        String fullName = stripName(value.getValue());
        String[] parts = fullName.split("\\$", 2);
        String outerName;
        String innerName;
        if (parts.length == 2){
            outerName = parts[0];
            innerName = parts[1];
        }else{
            outerName = parentClassName;
            innerName = fullName;
        }

        System.out.println("visitInnerClasses(): " + outerName + "$" + innerName);

        boolean isAnonymous = innerName.equals("1") || Ints.tryParse(innerName) != null;
        if (isAnonymous) {
            innerName = null;
        }

        int innerAccess = classManager.getVirtualClass(internalName).getClassDef().getAccessFlags();
        classWriter.visitInnerClass(fullName, outerName, innerName, innerAccess);
    }

@CalebFenton
Copy link
Owner

Thanks for the extra detail and the fix. I'll have to read the java specs to see what's technically allowed and see if I can improve what you have here.

Also: I added smali syntax highlighting to github a while back so I changed your original comment to use it. :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants