Держать все строки JNI android для защиты от реверс-инжиниринга? - PullRequest
0 голосов
/ 27 января 2020

Вот как я храню строки в JNI

extern "C" JNIEXPORT jstring JNICALL
Java_com_galaxy_mars_moon_MainActivity_getDefaultNegative(JNIEnv* env, jobject)
{
std::string defaultNegative = "Cancel";
return env->NewStringUTF(defaultNegative.c_str());
}

И я вызываю эту встроенную функцию из java класса.

Мои вопросы:

  1. Будет ли возможность декомпилировать человека для идентификации?
  2. Я тоже использую Proguard, Proguard будет делать из него запутанный код?
  3. Будет ли он преобразован в файл .so и будет ли он читаемым для декомпиляции?

Заранее спасибо. Я надеюсь, что кто-то будет проливать больше света на это

1 Ответ

2 голосов
/ 27 января 2020

Вы не можете предотвратить реверс-инжиниринг, но вы можете усложнить его, включив больше работы и дополнительных шагов, на которые не все способны.

Помещение констант в собственную библиотеку предотвращает их появление в декомпилированном java код. Подключение какой строки в скомпилированной библиотеке совпадает с тем, какое значение в конечном приложении не является тривиальным. Обычный метод включает в себя просто экспорт всех строк из собственной библиотеки и сопоставление их по контексту - например, поиск вещей, которые выглядят как ключи API. Если вы зашифруете эти константы и расшифруете их в самом приложении, это добавит еще один шаг к обратному инжинирингу, хотя, поскольку в приложении есть ключи шифрования, злоумышленник, безусловно, может сделать это самостоятельно.

Для быстрого и простого шифрования значений в NDK рассмотрим реализацию basi c salsa20 или chacha20 - для целей запутывания не требуется аутентификация, и ключи могут быть жестко закодированы.

Например, используя этот простой Salsa20 C реализация :

// hard-coded 128-bit key, can be anything
uint8_t k[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };

// hard-coded nonce, can be anything
uint8_t n[8] = { 101, 102, 103, 104, 105, 106, 107, 108 };

// The s20_crypt() function encrypts/decrypts in place.

// During development, do this:
std::string myString = ...;
std::vector<uint8_t> vec(myString.begin(), myString.end());
s20_crypt(k, S20_KEYLEN_128, n, 0, vec.data(), vec.size());
// export the vector bytes somehow - you can run this on your computer and write then to a file or to stdout for example

// After you have the encrypted bytes:

Java_com_galaxy_mars_moon_MainActivity_getDefaultNegative(JNIEnv* env, jobject)
{
  uint8_t[] defaultNegative = [...]; // the encrypted values
  s20_crypt(k, S20_KEYLEN_128, n, 0, defaultNegative, sizeof(defaultNegative));
  std::string decrypted(defaultNegative, defaultNegative+sizeof(defaultNegative));
  return env->NewStringUTF(decrypted.c_str());
}
...