Поддельное Android-приложение имеет оригинальную подпись

Что у меня есть

У меня есть приложение для Android с некоторыми конфиденциальными данными. Я хочу убедиться, что клиентское приложение вызывает сервер только в том случае, если оно не было каким-либо образом изменено. По сути, я хочу проверить целостность приложения для Android.

Что я сделал

Для этого я реализовал метод, который может проверить, совпадает ли подпись с подписью, которой я подписал APK. Вот пример кода,

fun isApkSignatureBroken(): Boolean {
        val packageInfo = context.packageManager.getPackageInfo(context.packageName, GET_SIGNATURES)

        val signatures = packageInfo.signatures
        if (signatures == null || signatures.isEmpty()) {
            return true
        }

        return signatures
                .map { it.toByteArray() }
                .map { hash.getSha1(it) }
                .none { it.equals(getRealAppSignature(), true) }
    }

Здесь getRealAppSignature() возвращает мою фактическую подпись, которой я подписал приложение.

Наблюдения

  • Я видел, что этот метод иногда работает хорошо. Всякий раз, когда обнаруживается поддельное приложение, этот метод возвращает значение true, и пользователь блокируется от использования приложения, и я уведомляюсь о событии. Я обнаружил, что многие пользователи были заблокированы таким образом.

  • Я видел много других случаев, о которых сообщалось на форумах и других сайтах социальных сетей, когда люди используют мое приложение, даже если у них есть поддельные приложения. Я заметил, что многие из моих приложений имеют искаженные имена версий и имена приложений, используемые многими пользователями. Например, если моя исходная версия приложения 2.2, то они создадут искаженную версию 2.2-TERMINATOR.

Анализ

Я провел некоторый анализ приложений и нашел некоторые поддельные приложения на некоторых форумах. Это явно модифицированные приложения с неверными версиями и именами приложений. Некоторые даже имеют незначительные изменения пользовательского интерфейса. Я пытался установить эти приложения, но они не могут быть установлены с сообщением «Пакет поврежден».

Я попытался запустить keytool в этих приложениях, чтобы проверить их подпись, вот так:

keytool -list -printcert -jarfile TAMPERED_APP.apk

но я всегда получал,

keytool error: java.lang.SecurityException: SHA1 digest error for classes.dex

Наконец-то я рутировал свое устройство, установил Xposed Framework и отключил «Проверку подписи приложения», а затем смог установить эти приложения. Я обнаружил, что приложение не блокировалось, поскольку мой метод проверки подписи всегда возвращал «ложь». Это означает, что он всегда находил оригинальную подпись внутри apk.

Дополнительный анализ

Я потратил еще немного времени и смог распаковать APK с помощью ApkTool. Внутри папки META-INF я обнаружил, что CERT.RSA содержит только мою оригинальную подпись и никакой другой подписи. Я открыл файл MANIFEST.MF и обнаружил, что все записи имеют другой SHA1, чем исходный файл манифеста APK.

Это явно означает, что приложение было изменено и подписано другой подписью (отсюда и изменение в MANIFEST.MF), но у моего CERTIFICATE.RSA была только моя исходная подпись, из-за которой мое приложение всегда получало оригинальный SHA от PackageManager.

Вопросы

  • Как приложение переподписывается, но новая подпись не сохраняется в CERTIFICATE.RSA?

  • Почему мой исходный сертификат все еще присутствует в CERTIFICATE.RSA?

  • Если приложение было уволено, то должны присутствовать несколько подписей? Но это верно здесь.

  • Как в этой ситуации определить, что приложение было взломано? Есть ли способ, которым я могу вычислить SHA приложения самостоятельно, вместо того, чтобы запрашивать PackageManager?

РЕДАКТИРОВАНИЕ №1: весь код запутан с помощью DexGuard. Таким образом, вероятность того, что логика обнаружения несанкционированного доступа испортится, значительно меньше.


person Aritra Roy    schedule 19.03.2018    source источник
comment
Связано: stackoverflow.com/questions /9865162/ и stackoverflow.com/questions/8611960/   -  person Morrison Chang    schedule 19.03.2018
comment
как определить, что приложение было подделано? -- если они могут вмешиваться в ваше приложение, они могут вмешиваться в любой код обнаружения несанкционированного доступа, который может быть в вашем приложении.   -  person CommonsWare    schedule 19.03.2018
comment
@CommonsWare Да, согласен. Но вся эта логика обнаружения запутывается с помощью DexGuard. Им очень сложно напрямую вмешиваться в логику. Есть ли другой способ проверить целостность приложения?   -  person Aritra Roy    schedule 20.03.2018
comment
Даже очень сильно запутанные приложения могут быть достаточно легко подделаны — я видел довольно мало приложений, которые специальный взломщик не смог бы взломать.   -  person Akhil Kedia    schedule 01.04.2018
comment
@AritraRoy, ты нашел ответ на свои вопросы или какой-то способ продвинуться вперед?   -  person Sharp Edge    schedule 22.02.2021