在混淆代码中隐藏字符串

jax*_*jax 57 java android proguard

我只是使用proguard对我的Android代码进行了模糊处理,然后对其进行了反编译.有许多字符串我真的想隐藏在窥探之中.当我反编译我的代码时,每个人都可以看到字符串......并进行更改.其中一个字符串是我的许可服务器的URL,它们实际上可以将URL更改为指向虚假服务器(因为我将向公众发布服务器代码).隐藏此类信息的最佳方式是什么?

另外,我注意到R类字符串都是随机数,但我在反编译代码中找不到R类.它在哪里?

敌人的例子我看到:new SimpleCursorAdapter(localActivity, 2130903058, localCursor, arrayOfString, arrayOfInt);

2130903058是一个布局文件,但它引用了什么?除非它指向某种地址,否则该数字没有任何意义.

Mar*_*erd 33

假设你对晦涩而不安全感到满意,你可以使用许多机制,但像proguard这样的混淆器无法帮助你.

要实现这一点,你需要自己对字符串进行编码或加密,你使用的方法取决于你想要防范的内容,如果它只是试图隐藏明显的检查,那么编码可能就足够了(请参阅android .util.Base64,http://developer.android.com/reference/android/util/Base64.html).请注意,编码是在NO WAY SECURE中完成的,它将删除对您站点的明显引用.

如果你试图防范更多内容,那么你可以转向实际加密字符串,为此你可以使用像AES那样的对称密码来通过javax.crypto.Cipher,http: //www.androidsnippets.org/snippets/ 39/index.html提供了一个不错的用法示例.再次,这对于黑客来说更加烦人,因为你需要将密钥存储在jar中的某个位置,从而否定任何加密安全性.

为了更清楚,基本步骤是:

  1. 使用已知密钥手动创建加密字符串.
  2. 转换您的代码以使用此字符串的解密版本,例如:

之前:

public class Foo {
    private String mySecret = "http://example.com";

    ...
}
Run Code Online (Sandbox Code Playgroud)

变为:

public class Foo {
    private String encrypted = "<manually created encrypted string>";
    private String key = "<key used for encryption";
    private String mySecret = MyDecryptUtil.decrypt(encrypted, key);

    ...
}
Run Code Online (Sandbox Code Playgroud)

所有这一切的(好)替代方案是考虑使用第三方drm解决方案,例如许可服务器google提供http://android-developers.blogspot.com/2010/07/licensing-service-for-android.html.这可能比你自己的东西更安全,但是受到与我上面描述的非常相似的限制.

  • 您可以添加多个图层,但最终,您无法阻止确定的黑客.在某些时候,你最好把时间花在产品的其余部分上,使它足够好(阅读足够有价值),人们不会想要偷它. (21认同)
  • "最终,你无法阻止一个坚定的黑客" - >这是这个长线程中最好的词.马克说得对,我们能做的最好的事情就是放慢攻击者的速度. (3认同)
  • 也许我遗漏了一些东西,但加密 URL 似乎并不安全,因为您仍然必须在代码中包含用于解密值的密钥。有决心的黑客仍然可以反编译 APK,获取密钥,然后手动解密秘密。 (2认同)

cib*_*en1 21

大家好.

  1. 我们secret是你要隐藏的文本

  2. 找到debug/release.keystore的keyhash.让k1这个关键.

(使用的工具密钥工具+ OpenSSL的:keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64 )

  1. 使用的工具(外部Android的代码)来加密secretk1

    encrypted = encode (secret, k1)

(例如:https://jwt.io,for java:https://github.com/jwtk/jjwt).

  1. 在你的android java代码中写下来encrypted.当你需要解码版本encrypted(这是原始的secret)写入

original = decode(encrypted, get_my_keyhash_programmatically() )

就这样.这是有效的,因为原始secret代码不会显示在java源代码上,也不会k1解码它.并且,如果黑客想要打印已解码的秘密,他必须更改代码并重新编译,使用自己的密钥库签署他的.apk而不是你的密钥库,因此无法获得正确的原件 secret.("唯一"一点是,是否k1可以从原始.apk中找出).

注意:get_my_keyhash_programmatically():

try {
    PackageInfo info = getPackageManager().getPackageInfo(
            "el nombre de su paquete por ejemplo com.tarea.u8",
            PackageManager.GET_SIGNATURES);
    for (Signature signature : info.signatures) {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(signature.toByteArray());
        Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
    }
} catch (PackageManager.NameNotFoundException e) {

} catch (NoSuchAlgorithmException e) {

}
Run Code Online (Sandbox Code Playgroud)

  • 经验丰富的黑客应该在5分钟内反转java函数encode(),他可以发现应用程序的cert散列非常容易编码.使用像XPosed这样的挂钩框架,他可以在运行时提取应用程序的证书哈希值.从那时起,他使用该哈希来解码所有字符串. (4认同)
  • 这不会在开发过程中产生问题吗?我认为 Android Studio 使用自动生成的证书对调试版本进行签名,该证书对于所有开发人员来说都是不同的,并且易于使用。 (4认同)

Som*_*ere 8

我所做的是在我的全局实用程序类中创建一长串静态字符串.在长字符串列表中的某个地方,我把我的密钥放在多个块中.

使用我的代码很容易看出真正的密码是什么 - 但是一旦混淆器开始工作,所有的静态都会有A,B,C等名称,并且不再容易发现.

  • 嗨,山姆,只需创建一个公共类,其中包含一大堆`public static String variable1 ="fake data";`当我说"整群"时,我的意思就像那些字符串中的一百个.使用excel创建这样的文件很容易.然后,在所有那些"假"行中隐藏一些重要数据.一旦混淆器开始工作,所有这些数据看起来就像一团糟.如果要使用数据,请组合几个单独的字符串以重新创建要隐藏的内容.你可以通过某种方式进一步编码那些文本行,使它看起来更像一团糟. (2认同)
  • 需要注意的是,您必须在某处使用代码,因为编译器/混淆器可能会删除未使用的代码,即不要只是转储一堆未使用的字符串变量。 (2认同)
  • 至于组合字符串..取决于你如何做,proguard 可能会用字符串生成器将它们全部放在一起。基本上你应该检查反编译的输出 (2认同)