关于使用 apktool 从 apk 反转的特殊 smali 类 的两个问题

Two questions regarding peculiar smali classes reversed from an apk using apktool

我在 smali github 上问过这个问题,但这可能是一个更好的地方再问一次。

观察到两起奇怪的代码反编译案例,想请教一下。该代码是在 Windows 10 上使用 apktool 2.4.1 反编译的 apk,这两个问题都与确定这在 smali 语言中是否合法以及如何以逻辑和编程方式(使用解析器)处理此问题有关。

  1. 第一个问题是在单个 smali 中有多个相同的字段定义 class。我有以下情况:
.class public final Likev2/network/sdk/network/tools/VpnBuilderHelper;
.super Ljava/lang/Object;


# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Likev2/network/sdk/network/tools/VpnBuilderHelper$a;
    }
.end annotation


# instance fields
.field public a:Landroid/net/VpnService$Builder;

.field public final a:Landroid/net/VpnService;

.field public a:Likev2/network/sdk/network/tools/VpnBuilderHelper$a;

.field public b:Likev2/network/sdk/network/tools/VpnBuilderHelper$a;


# direct methods
.method public constructor <init>(Landroid/net/VpnService;)V
    .locals 0

    if-eqz p1, :cond_0

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

如果您观察前三个实例字段,所有三个都具有相同的名称 'a'。它们也有不同的类型。最初,我在想这可能是对 superclasses 隐藏成员的情况,但是这个的 superclass 是普通的 Object.

这将如何解释?

  1. 第二个问题是将字符“-”作为方法名称中的第一个字符。有问题的代码是这个:
...
# virtual methods
.method public final -deprecated_javaName()Ljava/lang/String;
    .locals 1

    .line 1
    iget-object v0, p0, Lb0/m0;->javaName:Ljava/lang/String;

    return-object v0
.end method
...

这里提到的方法名称是“-deprecated_javaName”。考虑到“-”字符,这是合法名称吗?我在 Google 上搜索过,只发现一个地方提到了这个名字,这是在下面的代码中:https://jar-download.com/artifacts/com.squareup.okhttp3/okhttp/4.2.2/source-code/okhttp3/CipherSuite.kt

如果您看一下,这似乎已被弃用并重命名为 Kotlin 函数:

...
@JvmName("-deprecated_javaName")
  @Deprecated(
      message = "moved to val",
      replaceWith = ReplaceWith(expression = "javaName"),
      level = DeprecationLevel.ERROR)
  fun javaName(): String = javaName
...

我正在使用自定义 antlr 脚本解析 smali,该脚本将函数名称设置为始终以字母开头并在该字符上失败。

如果有人能阐明这两个 smali 的特点以及如何正确处理它们的解析,我将不胜感激。

  1. 一个 dex 文件在 dex 文件中引用的每个字段都有一个 table,然后对任何给定字段的任何引用都是通过索引到 table. field_id_item 结构是 table 中的一个条目,它包含一个字段引用。如您所见,所有 field_id_items 都包含所引用字段的名称 类型。因此,在同一个 class 中具有相同名称但具有不同类型的多个字段是完美的。由于字段引用始终包括名称和类型,因此对于引用哪个字段没有歧义。

  2. 定义了 dex 格式成员名称允许的语法 here。这个定义比 java 允许的范围更广,所以完全有可能有一个有效的 dex 成员名称是 java 中的一个无效名称。 -deprecated_javaName 是一个完美的 cromulent dex 成员名称:)