保护字符串常量免受逆向工程

Posted

技术标签:

【中文标题】保护字符串常量免受逆向工程【英文标题】:Protect string constant against reverse-engineering 【发布时间】:2011-11-18 03:45:06 【问题描述】:

我有一个具有硬编码(静态字符串常量)凭据(用户/密码)的 android 应用程序,用于通过 SMTP 发送电子邮件。

问题是 .apk 中的 .dex 文件很容易被逆向工程,每个人都可以看到我的密码。

有没有办法保护这些凭据,同时我仍然可以在我的课程中使用它们?

【问题讨论】:

为什么不散列它们? @Richard H,我认为如果他必须重用凭据,散列是不可能的? 如果他对它们进行哈希处理,他如何取消哈希登录/传递以将其发送到 SMTP 服务器?如果它是双向功能,它将很容易解密。如果它是需要盐/密钥的哈希,他也需要对其进行哈希处理。 THERE 甚至关于将 DEX 反编译为源代码的线程。 @Y.A.P - 是的,对不起,我不明白需要双向加密。 【参考方案1】:

我们可以使用“jni 模块”在应用程序中保留“敏感硬编码字符串”。当我们尝试对 APK 文件进行逆向工程时,我们会在各自的进程文件夹中获得 lib 文件夹和 .so 文件。无法解密。

【讨论】:

我仍然可以在 .so 文件中看到字符串。【参考方案2】:

您可以保存被 AES 混淆的字符串。

在许可验证库中,您可以找到AESObfuscator。在 LVL 中,它用于混淆读取的缓存许可信息,而不是要求 Android Market 找出应用程序是否获得许可。 LVL 可以作为 SDK 的组件下载。

【讨论】:

【参考方案3】:

我想您可以尝试使用代码混淆器,但实际上这不会使您的密码 100% 安全,而且我不知道它与 android 编译器的配合情况如何。为什么不使用像 Google 这样的安全网络身份验证?

【讨论】:

我认为混淆器不会更改字符串的内容(凭据)。内容需要首先加密。但正如你所说,更好的网络身份验证。 ProGuard(Android SDK 默认提供的混淆工具)不加密也不混淆字符串。 DexGuard 确实会加密字符串,但它有点贵。【参考方案4】:
    散列是不可能的,因为它不是两种方式。 AES、DES、blowfish、etch 等任何加密都不是可行的解决方案,因为您必须在应用程序中包含解密部分,并且可以使用 apktool、dex2jar 和 JD(java 反编译器)的组合进行反编译,即反编译任何 apk 时非常强大的组合。 即使是代码混淆器也无济于事,只会让反编译人员的生活变得更加困难,无论如何他们最终都会得到它。

我认为在一定程度上可行的唯一方法是将凭据托管在服务器上,只有您的应用程序才能通过某种单独的身份验证通过 Web 服务调用访问该凭据——类似于 FB 的哈希密钥。如果它对他们有用,它应该对我们有用。

【讨论】:

...这带来了一个问题,如果服务器将如何区分“仅您的应用程序”访问与黑客的访问。 对,你又被卡住了——这样。 @EugeneMayevski'EldoSCorp 有什么改善吗?【参考方案5】:

我正在研究一个类似的问题,并遇到了这个有用的线程: http://www.dreamincode.net/forums/topic/208159-protect-plain-string-from-decompilers/

我对 Android 开发不太熟悉,但应该适用相同的想法。

【讨论】:

伟大的lnik!这是一个非常有趣的想法【参考方案6】:

这样做会很有用:

1- 您可以加密它们并混淆加密算法。任何加密以及混淆(Adnroid 中的 progaurd)都是有用的。

2- 您最好在代码中将字符串硬编码为字节数组。许多逆向工程应用程序可以获取硬编码字符串的列表并猜测它们是什么。但是当它们以字节数组的形式出现时,它们是不可读的。但再次Proguard是必要的。 (它只隐藏在 RAM 字符串常量搜索中,它们仍然可以从 .class 文件中搜索)

3- 如果您在硬编码之前对其进行加密并使用 C++ 代码对其进行解密,那么使用 C++ 代码来托管您的常量并不是一个坏主意。

这里也有一篇很棒的文章:

https://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/

【讨论】:

【参考方案7】:

如果您无法进行网络授权,则需要在您的应用程序中包含第三方解密。

这是你可以尝试的 1) 编写一个独立程序,仅用于创建一次密码哈希。 (此程序不应成为您应用程序的一部分)。记下生成的哈希。 http://www.mindrot.org/projects/jBCrypt/

 // Hash a password for the first time.
    String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));

2) 将此密码哈希作为字符串常量存储在您的 APK 中。

3) 然后每次需要检查密码时,与哈希后的密码进行比较,使用 bcrypt。

// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
    System.out.println("It matches");
else
    System.out.println("It does not match");

jBCrypt 是一个单独的 java 文件,它可以直接包含在您的应用程序中。它被认为是最强大的密码加密算法之一。 即使您的 APK 中存在解密算法,尝试破解它也是非常耗时的,详情请参阅下面的文章。

阅读本文了解 bcrypt 的详细信息和安全性。http://codahale.com/how-to-safely-store-a-password/

同样,仅当您无法进行基于 Web 的身份验证时才使用此功能。

【讨论】:

但他似乎需要原始密码而不是散列密码来进行 smtp 身份验证。我们怎样才能扭转这种局面? candidate 字符串呢?或者我遗漏了什么,或者这个答案没用。【参考方案8】:

使用某种只有您(和您的代码)才能理解的简单加密或密码。反转字符串,将其存储为整数数组,您需要在其中获取 217 的 mod 或一些愚蠢的东西才能找到真正的密码。

【讨论】:

【参考方案9】:

一种可以 100% 保护硬编码字符串的方法。 首先不要使用 pro-guard 使用 allatori 链接:http://www.allatori.com/

其次,不要在任何变量中使用硬编码字符串,只需像这样使用该字符串:

if(var=="abc")

"abc" 是硬编码字符串示例。

Allatori 完全混淆了上述代码中使用的所有字符串。

希望对您有所帮助。

【讨论】:

以上是关于保护字符串常量免受逆向工程的主要内容,如果未能解决你的问题,请参考以下文章

Go语言逆向技术:常量字符串

签名以保护 JAR 免受逆向工程

保护 Android 应用免受逆向工程

如何保护 Android 代码免受逆向工程? [复制]

Apk 保护免受逆向工程 - 使用包名称? [复制]

无法在eclipse中保护代码免受逆向工程