Android 逆向工程工具如何提取 Android 应用程序中存在的包/包层次结构?

逆向工程 拆卸 反编译 静态分析 安卓
2021-06-19 10:39:57

我参与过使用baksmali和 dexpler反汇编 Android 应用程序每当我反汇编一个应用程序时,我都会发现包和包层次结构(在开发场景中本来可以使用)完好无损。例如,当我反汇编一个任务管理器应用程序(MD5:3377f8527479ab4e72bf9fa5eec62abe)时,我得到如下图所示的包层次结构。在此处输入图片说明.

在这种情况下,我有以下问题,

  1. 在构建应用程序时,这种 Java 包的层次结构是否会被保留和保留。当然,当我们开发应用程序时,我们会使用许多包,并在构建应用程序时将它们放在一个层次结构中。但是,开发人员编写的所有代码都将转换为单个 classes.dex 文件。包和包层次结构信息是否会保留在这个 classes.dex 文件或 apk 文件的任何其他部分(如 META-INF)中?
  2. 如果 .dex 中没有此信息,那么此信息从何而来?每个反汇编/反编译工具如何设法提取这个包层次结构?
  3. 在应用程序构建过程中,在哪里可以找到与包和包层次结构相关的文档/文献?我尝试浏览 Android 文档是徒劳的。
2个回答

是的,包层次结构保留在 dex 文件中。更准确地说,如果一个类在源代码中被命名为 foo.bar.baz.foo.Myclass,那么它在 .dex 中的名称也将是 foo.bar.baz.foo.Myclass。任何“包层次结构”都将从这些类名派生。

如果您想了解更多关于 .dex 文件格式的信息,Dalvik Executable Format Reference应该包含您需要的一切。

快速的答案是在 Java 中,类的完全限定名称与其包连接的类实际名称。对于类加载器,com.foo.Annamalai是它将在运行时加载的名称。这也是为什么不能在同一个包中拥有两个同名类的原因

这将是一个(半)人为的实例,但让我们假设您的应用程序有两个不同的日志框架,并且您需要同时支持这两个框架。

import java.util.logging.Logger;
import org.apache.log4j.Logger;

如果你尝试这样做,你的编译器应该会报错,抱怨你有两个同名的类。嗯,这个版本可以工作:

org.apache.log4j.Logger logger4j = org.apache.log4j.Logger.getLogger(DeleteMe.class);
java.util.logging.Logger loggingLogger = java.util.logging.Logger.getLogger(DeleteMe.class.getName());

由于这种包/类命名约定,为了逆向工程目的提取应用程序的文件结构是微不足道的,因为在 java 中,包名称被指定为与文件结构相关联。

在您询问不使用包的评论中,好吧,如果您这样做了,那么您将永远无法使用两个同名的类——编译器永远不会允许它。

上面的例子会变成这样:

Logger logger4j = Logger.getLogger(DeleteMe.class.getName());
Logger loggingLogger = Logger.getLogger(DeleteMe.class.getName());

Logger如果类路径中有两个没有包名,编译器会选择哪个