gpt4 book ai didi

java - 了解 Dalvik 代码的反汇编?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:54:51 28 4
gpt4 key购买 nike

我正在玩弄 smali and baksmali在我编写的一个小型 Hello World Android 应用程序上。我的源代码是:

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 opcode specification 是如何实现的吗?用于得出这种表示?我目前的理解是这样的:

  • 给定一个 APK,我可以提取二进制 XML 中的 AndroidManifest.xml格式化并使用工具,例如 axml2xml.pl得到一个“文本” list 的版本不是完成或者我可以使用 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 规范从表中输出适当的操作码名称?

实际上,简而言之,我很想知道所有这些“魔法”是如何完成的。因此,例如,如果我要学习编写这个工具,我应该遵循的高级路线图是什么?

最佳答案

您看到的是 davlik 字节码。 Java 代码由 dx 工具翻译成 Dalvik 字节码。 list 是一个单独的问题,我将在一分钟内讨论。实际上,当您编译 Android 应用程序时,dx 工具使用 256 个 dalvik 操作码将您的 Java 代码转换为字节码(对于标准 JVM 应用程序,javac 将 Java 转换为 Java 字节码的方式相同)。

例如,invoke-super 是指示 dvm(dalvik 虚拟机)调用父类(super class)上的方法的操作码。类似地,invoke-interface 指示 dvm 调用接口(interface)方法。

所以你可以看到

super.onCreate(savedInstanceState);

翻译成

invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)

在这种情况下,invoke-super 有两个参数,{p0,p1 组和 Landroid/app/Activity;->onCreate(Landroid/os/Bundle;) 参数是方法规范,必要时用于查找和解析方法。

然后就是构造函数区的invoke-direct调用

invoke-direct {p0}, Landroid/app/Activity;-><init>()V

每个类都有一个init 方法,用于初始化类的数据成员,也称为构造函数。当你构造一个类时,虚拟机也必须调用父类(super class)的构造函数。这解释了为什么您的类的构造函数调用 Activity 构造函数。

关于 list ,会发生什么(如果您查看源代码,这都在 Dalvik 规范中)是编译器(生成 apk 文件)将 list 转换为更压缩的格式(二进制 xml)为了节省空间。 list 与您发布的代码没有任何关系,它更多地指示 dvm 如何处理应用程序是一个关于 ActivitiesServices 的整体,等。您发布的是实际执行的内容。

这是对您问题的高级回答。如果您需要更多,请告诉我,我会尽力而为。

编辑 你基本上是对的。反编译器从 dex 文件中读取二进制数据作为字节流。它了解格式应该是什么,并且能够提取常量、类等信息。关于操作码,这正是它所做的。它了解每个操作码的字节值是什么(或者它在 dex 文件中的表示方式)并且能够将其转换为人类可读的字符串。如果你要实现这个,除了了解编译器的一般基础知识外,我将从深入了解 dex 文件的结构开始。从那里,您需要构建一个表,将操作码值与人类可读的字符串相匹配。使用该信息和一些关于字符串常量等的附加信息,您可以构建已编译类的文本文件表示。这有意义吗?

关于java - 了解 Dalvik 代码的反汇编?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4820285/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com