我曾参与使用baksmali和dexpler拆卸Android应用程序。每当我拆解一个应用程序时,我都会发现程序包和程序包层次结构(在开发场景中可以使用)完好无损。例如,当我分解一个任务管理器应用程序(MD5:3377f8527479ab4e72bf9fa5eec62abe)时,我得到的包层次结构如下图所示。

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


在构建应用程序时将保留并保留此Java包层次结构。当然,在开发应用程序时,我们会使用许多软件包,并在构建应用程序时将它们放在层次结构中。但是,开发人员编写的所有代码都将转换为单个classes.dex文件。软件包和软件包层次结构信息会保留在此classes.dex文件或apk文件的任何其他部分(如META-INF)中吗?
如果.dex无法提供此信息,请问该信息来自何处?每个反汇编/反编译工具如何管理以提取此软​​件包层次结构?我试图徒劳地浏览Android文档。


#1 楼

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

评论


感谢您的链接和答案。在dex文档中,我碰巧看到“ FullClassName是完全合格的类名,包括一个可选的包说明符和一个必需的名称”。似乎包括软件包名称不是强制性的吗?

– Annamalai N
2014年5月12日14:42



此外,在该文档中提到,完全限定的类名以字符“ L”开头。假设这就是为什么我们引用的实际类是android / support / v4 / widget时,在.smali文件中看到“ Landroid / support / v4 / widget”的正确性吗?

– Annamalai N
2014年5月12日14:44

#2 楼

快速的答案是,在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中,软件包名称是指定为与文件结构相关的。

在评论中,您询问不使用软件包,如果这样做,您将永远无法使用两个同名的类-编译器将永远不允许使用它。

上面的示例将变成这样:名字?

评论


感谢您的解释。我现在清楚地了解了观点。提取应用程序的文件结构以进行反向工程是很简单的,因为在Java中指定了包名称以与文件结构相关联-在反转Android应用程序(即使它们包含本机代码)时也是如此?如果我错了,请纠正我。

– Annamalai N
14年5月12日在16:41



是的,Google仍然必须遵循JLS,否则Oracle将起诉他们。

–avgvstvs
2014年5月12日17:04

我没有注意到的另一件事是,不将所有内容放在“默认”包中的最大原因(这意味着没有包名)是因为它可能导致意外地编写与另一个类具有相同名称的类库代码。这意味着您将获得怪异的异常,并且无需反转每个库,因此可能无法弄清原因,因此包名称为您提供了很多实用程序。

–avgvstvs
2014年5月13日在12:26