我正在尝试制作一个安全的 Android 应用程序。我在我的应用程序中启用了 proguard 。但它在反编译时不会隐藏任何 xml 文件或清单。它只会更改 .java 文件。
我尝试使用 apktool 从 Play 商店反编译另一个应用程序的 apk。然后我得到了以下异常
Exception in thread "main" brut.androlib.AndrolibException: brut.directory.Direc
toryException: java.util.zip.ZipException: error in opening zip file
at brut.androlib.ApkDecoder.hasSources(ApkDecoder.java:199)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:83)
at brut.apktool.Main.cmdDecode(Main.java:146)
at brut.apktool.Main.main(Main.java:77)
Caused by: brut.directory.DirectoryException: java.util.zip.ZipException: error
in opening zip file
at brut.directory.ZipRODirectory.<init>(ZipRODirectory.java:55)
at brut.directory.ZipRODirectory.<init>(ZipRODirectory.java:38)
at brut.androlib.res.util.ExtFile.getDirectory(ExtFile.java:55)
at brut.androlib.ApkDecoder.hasSources(ApkDecoder.java:197)
... 3 more
Caused by: java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(Unknown Source)
at java.util.zip.ZipFile.<init>(Unknown Source)
at brut.directory.ZipRODirectory.<init>(ZipRODirectory.java:53)
... 6 more
然后 xml 文件和清单没有被泄露。我也想像这样保护我的应用程序。这怎么可能?
回答你的问题,让你的APK完全安全是不可能的。 XML 文件无需 apktool 即可轻松解析。
我问过 Ben Gruver/JesusFreke(开发 smali 的人),他说不可能完全保护 APK 文件,但你可以让其他人更难反编译。只要 Android 可以读取项目中的资源/代码..那么工具也可以。
您在尝试反编译 Gmail 时看到的异常是因为 Lollipop 需要更新 apktool(正在积极处理)。
@classc_abc的答案是我发现的最好的答案,可以让反编译APK变得更加困难。不幸的是,它包含一个垃圾邮件链接,已被删除,但我认为前 4 个步骤至少有用。
基本上有5种方法可以保护你的APK不被破解/ 反转/重新包装:
- 隔离Java程序
最简单的方法就是让用户无法访问Java Class 程序。这是最基本的方式,它有多种 实现这一目标的具体方法。例如,开发人员可以将 服务器上关键的Java Class,客户端通过访问获取服务 服务器的相关接口而不是访问Class文件 直接地。所以黑客是没有办法反编译Class文件的。 目前,标准和协议服务越来越多 通过接口提供,例如HTTP、Web Service、RPC等。但是 有很多应用程序不适合这种保护。 例如,独立程序中的Java程序无法 隔离。
- 加密类文件
为了防止Class文件被直接反编译,很多开发者 会加密一些关键的Class文件,比如注册号,序列号 号码管理和其他相关类。在使用这些之前 加密的类,程序需要先解密这些类, 然后将这些类加载到 JVM 中。这些类可以通过以下方式解密 硬件,或软件。
开发人员经常通过自定义的方式加载加密类 ClassLoader类(Applet不支持自定义ClassLoader 因为安全)。自定义的类加载器会发现加密的 首先类,然后解密它们。最后加载解密的 类到 JVM。自定义的ClassLoader是这里面非常重要的一个类 保护方法。因为它本身没有加密,所以可能是 黑客的第一个目标。如果有相关的解密密钥和算法 已经被克服了,那么加密的类就可以很容易地被 已解密。
- 转换为本机代码
将程序转换为本机代码也是防止 反编译。因为本机代码通常很难被 反编译。开发者可以将整个应用程序转换为原生应用程序 代码,或者它们也可以仅转换关键模块。如果只是转换密钥 部分模块,Java时需要JNI技术来调用 程序正在使用这些模块。它放弃了Java的跨平台 使用这种方法保护Java程序时的特点。对于不同的 平台上,我们需要维护不同版本的原生代码, 这将增加软件支持和维护工作量。但对于 一些关键模块,有时这种解决方案往往是必要的。为了 以保证这些本机代码不会被修改或替换, 开发人员通常需要对这些代码进行数字签名。使用前 这些本地代码,开发者往往需要对这些本地代码进行认证 代码,以确保这些代码没有被黑客更改。如果 签名检查通过后,开发者就可以调用相关的JNI了 方法。
- 代码混淆
代码混淆就是对Class文件进行重新组织和处理,使得 处理后的代码完成相同的功能(语义) 未经处理的代码。但混淆后的代码很难被破解 反编译,即反编译后的代码很难 理解,因此反编译人员很难理解 真正的语义。理论上,如果黑客有足够的时间, 混淆后的代码仍有可能被破解。甚至有些人正在发育 去混淆工具。但从实际情况来看,自 混淆多元化发展,混淆成熟 理论上,混淆的Java代码可以很好地防止反编译。
[...]