问题描述
我在smali github上问了这个问题,但这可能是再次询问的更好的地方。
我观察了两个我想询问的奇怪的代码反编译情况。在Windows 10上使用apktool 2.4.1将代码反编译为apk,这两个问题都与弄清楚这在smali语言中是否合法以及如何在逻辑上和编程上(使用解析器)进行处理有关。
- 第一个问题是在单个smali类中具有多个相同的字段定义。我有以下情况:
.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”。它们也有不同的类型。最初,我以为可能是在超类中隐藏成员的情况,但是该类的超类是普通对象。
这将如何解释?
- 第二个问题是方法名称中的字符“-”作为第一个字符。有问题的代码是这样的:
...
# 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,该脚本将函数名称设置为始终以字母开头,并且对此字符失败。
如果任何人都可以对这两个特殊的情况以及如何正确处理它们的解析有所了解,我将不胜感激。
解决方法
-
dex文件有一个表,该表包含了dex文件中引用的每个字段,然后对任何给定字段的任何引用都通过该表中的索引进行。 field_id_item结构是该表中的一个条目,其中包含一个字段引用。如您所见,所有
field_id_items
都包含所引用字段的名称 AND 类型。因此,在同一个类中具有相同名称,但具有不同类型的多个字段是非常繁琐的。由于字段引用始终包含名称和类型,因此在引用哪个字段方面没有任何歧义。 -
以here定义了dex格式的成员名称的允许语法。这个定义比Java所允许的范围更广,因此完全有可能拥有一个有效的dex成员名称,而该成员名称在Java中是一个无效名称。
-deprecated_javaName
是一个完美的dex成员名称:)