我正在我编写的一个小型 Hello World Android 应用程序上玩smali 和 baksmali 。我的源代码是:
package com.hello;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
然后将其拆解为:
.class public Lcom/hello/Main;
.super Landroid/app/Activity;
.source "Main.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 1
.parameter "savedInstanceState"
.prologue
.line 10
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 11
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/hello/Main;->setContentView(I)V
.line 12
return-void
.end method
我知道这是某种中间表示,但不确定它是什么。据我了解,必须有一些关于如何理解这种表示的规范,但我无法弄清楚如何搜索它。因此,给定一个 apk 文件,有人可以用外行术语解释如何使用Dalvik 操作码规范来获得这种表示吗?我目前的理解是这样的:
- 给定一个 APK,我可以提取二进制 XML 格式的 AndroidManifest.xml 并使用诸如 axml2xml.pl 之类的工具来获取不完整的清单的“文本”版本,或者我可以使用 apktool来获得更具可读性形式。但我仍然不确定他们使用什么规范将二进制 XML 转换为文本。
- 反汇编程序以某种方式利用 Dalvil 操作码规范来读取 dex 文件并将其转换为上述表示形式。
关于上述两个步骤的任何信息(可能带有一些简单的示例)都可以很好地帮助我正确理解这些概念。
更新 1(在 Chris 回复后发布):
所以本质上,我会做以下事情来得到 Dalvik 字节码:
- 获取一个 apk 并将其解压缩以获取 classes.dex 文件。
然后反汇编程序读取 classes.dex 文件并确定 apk 中存在的所有类。你能给我一些关于这是如何完成的信息吗?它是否以十六进制模式解析文件并查找 Dalvik 规范,然后正确解析?还是发生了其他事情?例如,当我在 classes.dex 上使用 hexdump 时,它给了我这样的信息:
64 65 78 0a 30 33 ...
这些现在用于操作码查找吗?
- 假设该工具能够将传入的字节码分成单独的类,然后它会继续扫描 classes.dex 文件中的十六进制代码并使用 Davlik 规范从表中输出适当的操作码名称?
实际上,简而言之,我有兴趣知道所有这些“魔法”是如何完成的。例如,如果我要学习编写这个工具,我应该遵循的高级路线图是什么?