草庐IT

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

coder 2023-12-07 原文

我正在玩弄 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/

有关java - 了解 Dalvik 代码的反汇编?的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐