В 2024 году Google внёс значительные изменения в систему защиты целостности своих мобильных устройств, заменив старую инфраструктуру SafetyNet на новую платформу под названием PairIP. Этот шаг вызвал большой интерес среди специалистов по мобильной безопасности и исследователей в области реверс-инжиниринга, ведь новая система существенно изменила подход к проверке целостности, отказавшись от сложной архитектуры с использованием виртуальной машины DroidGuard в пользу более компактного и эффективного решения, базирующегося на собственной VM, работающей внутри нативной библиотеки. До появления PairIP SafetyNet обеспечивал защиту посредством модуля DroidGuard – виртуальной машины, которая выполняла специально разработанный байткод, анализируя ключевые параметры устройства, такие как состояние загрузчика, наличие root-доступа, запуск эмуляторов и различные признаки модификаций. Результатом проверок были два основных параметра: ctsProfileMatch и basicIntegrity. Они показывали, насколько устройство соответствует требованиям безопасности Google, и позволяли приложениям принимать решения о предоставлении доступа к сервисам.
Ответ от SafetyNet сопровождался JSON Web Signature (JWS) токеном, который обеспечивал криптографическую гарантию подлинности и целостности. Однако современные методы обхода систем SafetyNet и потребность в более гибкой и масштабируемой защите заставили Google перейти к PairIP. В отличие от SafetyNet, новая платформа использует нативную библиотеку libpairipcore.so, которая реализует собственную виртуальную машину. Важным отличием стало то, что теперь Java-байткод приложения частично отделён от основной логики и переносится для выполнения в этом VM через метод executeVM().
PairIP отделяет чувствительную логику приложения, преобразуя её в специальный байткод, сохранённый в папке assets внутри APK. Этот байткод, будучи обработанным виртуальной машиной, подвергается множеству проверок целостности и безопасности. Метод executeVM() не является обычной Java-функцией, его реализация загружается и регистрируется динамически через JNI в момент инициализации библиотеки (JNI_OnLoad). Такой подход усложняет анализ и патчинг, ведь функции формируются и запускаются уже во время выполнения, что препятствует статическому анализу. Для успешного реверс-инжиниринга libpairipcore.
so исследователи используют инструменты динамического анализа, такие как Frida, которая позволяет перехватывать вызовы функций, отслеживать ассемблерные инструкции и выводить различную отладочную информацию в реальном времени. Ключевой задачей является нахождение адреса функции executeVM() через перехват и анализ вызова RegisterNatives, а затем дамп библиотеки в памяти во время работы приложения. Структура виртуальной машины, реализованной в libpairipcore.so, соответствует классической модели VM с циклами выборки, декодирования и выполнения (Fetch-Decode-Execute). Внутри присутствует механизм переключения инструкций через большой switch-case, где выбор обработчика формируется динамически на основании текущего opcode.
Каждая инструкция в байткоде сопровождается обязательной проверкой целостности с помощью алгоритма хеширования FNV-1, что значительно повышает защиту от вмешательств и подмены кода. Использование FNV-1 хеширования основано на особенностях вычисления с использованием фиксированного начального значения и простого умножения на константу, что позволяет быстро и эффективно контролировать корректность исполнения инструкций. В случае, если хеш не совпадает с ожидаемым, управление передаётся на альтернативный путь выполнения, фактически предотвращая работу модифицированного байткода. VM работает по стековой модели исполнения, но с определёнными особенностями: отсутствует классический стек в аппаратном смысле, вместо этого память распределяется и используется гибко, при этом операции выполняются с памятью непосредственно, что усложняет анализ и вмешательство. Применение потокобезопасных механизмов (pthread_once, pthread_mutex_lock и другие) обеспечивает корректное выделение и использование памяти в многопоточном окружении, предотвращая гонки и конфликты.
Анализ самих байткодов из assets показывает наличие повторяющихся паттернов, таких как операции XOR с константой 0xffffffff и другие арифметические манипуляции, позволяющие понять структуру и логику работы байткода. Структура байткода и операции, выполняемые виртуальной машиной, формируют эффективный уровень защиты от статического и динамического анализа, так как каждая сборка приложения пересобирает таблицу кодов и меняет конкретные инструкции. Кроме того, код внутри libpairipcore.so подвергается различным обфускациям и анти-дампинговым методам, что заставляет исследователей применять сложные методы динамического анализа, среди которых трейсинг инструкций, анализ регистров процессора и детальный отладочный вывод. Появление PairIP открывает новые вызовы для специалистов по мобильной безопасности, ведь традиционные методы обхода SafetyNet теперь становятся недостаточными, а более глубокое понимание механизмов виртуальной машины и байткода требует значительных усилий и комплексного подхода.
Сообщество активно делится инструментами и наработками, что способствует продвижению в изучении и противодействии PairIP. Несмотря на сложности, разбор PairIP позволяет лучше понять стратегию Google в области защиты мобильных приложений и обеспечивает разработчикам и специалистам по безопасности инструменты для создания более устойчивых продуктов. Важно учитывать, что каждая новая версия этой системы приносит изменения в логику и структуру VM, что требует постоянного обновления знаний и инструментов. Таким образом, PairIP является очередным шагом в развитии систем защиты целостности мобильных устройств, внедряя комплексный VM-базированный подход. Анализ работы executeVM, методов проверки целостности через FNV-1 хеширование и управление памятью в многопоточном режиме открывает перспективы для понимания механизмов, используемых Google для защиты своих платформ.
Это также служит важным ориентиром для разработчиков средств обхода и анализа, предлагая современную точку зрения на развитие мобильной безопасности.