隐藏模糊代码中的字符串

2022-08-31 16:14:53

我只是使用proguard对我的Android代码进行了模糊处理,然后对其进行了反编译。有一些字符串我真的很想隐藏起来免受窥探。当我反编译我的代码时,字符串就在那里供所有人查看......和改变。其中一个字符串是指向我的许可服务器的 URL,它们实际上可以将 url 更改为指向假服务器(因为我将向公众发布服务器代码)。隐藏此类信息的最佳方法是什么?

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

敌人示例明白了:new SimpleCursorAdapter(localActivity, 2130903058, localCursor, arrayOfString, arrayOfInt);

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


答案 1

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

要实现此目的,您需要自己对字符串进行编码或加密,您使用的方法取决于您试图防御的内容,如果您只是试图隐藏明显的检查,那么编码可能就足够了(请参阅android.util.Base64,http://developer.android.com/reference/android/util/Base64.html)。请注意,编码绝不安全,它所做的只是删除对您网站的明显引用。

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

为了更清楚地说明这一点,基本步骤是:

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

以前:

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

    ...
}

成为:

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

    ...
}

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


答案 2

大家好。

  1. 让它成为您要隐藏的文本secret

  2. 查找 debug/release.keystore 的键哈希。让我们成为这个钥匙。k1

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

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

    encrypted = encode (secret, k1)

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

  1. 在你的安卓Java代码写下.当你需要解码版本(这是原始的)写入encryptedencryptedsecret

original = decode(encrypted, get_my_keyhash_programmatically() )

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

注: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) {

}

推荐