Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
ResourcePoison — Writeup и эксплойт для CVE-2025-22441: повышение привилегий от установленного приложения до процесса SystemUI на Android из-за передачи недоверенного ApplicationInfo в LoadedApk | Kitploit
Инструменты/GitHubGitHub/michalbednarski/resourcepoison
Безопасность AndroidПовышение привилегийАнализ уязвимостейЭксплуатацияМобильная безопасностьСтатьи и Исследования
GitHubmichalbednarski/resourcepoison

ResourcePoison

Writeup и эксплойт для CVE-2025-22441: повышение привилегий от установленного приложения до процесса SystemUI на Android из-за передачи недоверенного ApplicationInfo в LoadedApk

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий
10829630 лет назадПроверено Kitploit

Исправление этой проблемы появилось как CVE-2025-22441: бюллетень патч дополнение

Передача ApplicationInfo между процессами

ApplicationInfo — это структура, содержащая различную информацию об установленном приложении, в первую очередь путь к apk-файлу, из которого загружаются ресурсы и код

Обычно она передаётся от системы к приложениям, однако иногда возникают случаи, когда вызывающий код, не являющийся системным, может предоставить собственную структуру. Например, в прошлом это была уязвимость в методе bindBackupAgent(), где атакующий мог передать в параметре собственный объект ApplicationInfo со значениями uid и sourceDir, которые не проверялись на соответствие реально установленным в системе приложениям, поскольку этот метод предназначался для внутреннего вызова из system_server, но был доступен через adb shell

В этот раз, однако, я внимательно изучил поле ApplicationInfo внутри RemoteViews

RemoteViews — это объект, описывающий представление, которое может прийти из другого процесса. Чаще всего он используется для виджетов главного экрана, где приложение, предоставляющее виджет, создаёт RemoteViews, а затем он "применяется" в процессе главного экрана

Другие места, где используются RemoteViews, — это уведомления (применяются процессом SystemUI) и диалоги автозаполнения (предоставляются сервисом автозаполнения, применяются в system_server)

Поле RemoteViews.mApplication сериализуется через Parcel и поэтому может поступать из удалённых процессов, и всякий раз, когда RemoteViews применяются, оно используется следующим методом (фрагмент исходного кода):```java private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) { if (mApplication != null) { if (context.getUserId() == UserHandle.getUserId(mApplication.uid) && context.getPackageName().equals(mApplication.packageName)) { return context; } try { LoadedApk.checkAndUpdateApkPaths(mApplication); return context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found"); } }

return context;

}

Самое интересное здесь — вызов `LoadedApk.checkAndUpdateApkPaths()`, так как это статический метод, который изменяет некоторое глобальное состояние [(исходный фрагмент)](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/LoadedApk.java;l=2275-2302;drc=5916ee589c4880e2d8a1a9ad6dc852108e4c44c1)```java
public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
    // Get the LoadedApk from the cache
    ActivityThread activityThread = ActivityThread.currentActivityThread();
    if (activityThread == null) {
        Log.e(TAG, "Cannot find activity thread");
        return;
    }
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
}

private static void checkAndUpdateApkPaths(ActivityThread activityThread,
        ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
    String expectedCodePath = expectedAppInfo.getCodePath();
    LoadedApk loadedApk = activityThread.peekPackageInfo(
            expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
    // If there is load apk cached, or if the cache is valid, don't do anything.
    if (loadedApk == null || loadedApk.getApplicationInfo() == null
            || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
        return;
    }
    // Duplicate framework logic
    List<String> oldPaths = new ArrayList<>();
    LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);

    // Force update the LoadedApk instance, which should update the reference in the cache
    loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
}

Давайте обсудим, что происходит в этих методах

Сначала мы вызываем трёхпараметрический checkAndUpdateApkPaths с cacheWithCode, установленным как в true, так и в false. Объект LoadedApk может быть создан в двух режимах: либо с mIncludeCode, равным true, либо false, что на уровне SDK соответствует Context с установленным или не установленным флагом CONTEXT_INCLUDE_CODE

Этот метод сначала вызовет ActivityThread.peekPackageInfo(), который вернёт уже закешированный экземпляр LoadedApk, поэтому если приложение ранее не создавало LoadedApk с соответствующими packageName и includeCode, peekPackageInfo() вернёт null, и checkAndUpdateApkPaths() ничего не сделает

Возвращаясь к RemoteViews.getContextForResourcesEnsuringCorrectCachedApkPaths(), там у нас есть context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED), флаг CONTEXT_INCLUDE_CODE не был указан (то же самое касается контекстов, передаваемых в аргументах этому методу), и поэтому этот метод всегда будет использовать LoadedApk с mIncludeCode=false

Следовательно, для RemoteViews обновление версии с кодом не требуется, так как RemoteViews всегда используют Context без кода. В сообщении коммита просто сказано, что есть два места, где ApplicationInfo может быть закеширован, и я думаю, что удаление обновления версии с кодом не вызовет здесь проблем (так как checkAndUpdateApkPaths() используется только AppWidgetHostView и RemoteViews). Однако контраргументом этому является избежание возможности рассинхронизации различных кешей, и хотя удаление вызова с cacheWithCode=true устраняет наиболее серьёзное влияние этой ошибки, оно не полностью исправляет проблему, так как модификация только ресурсов (вместо кода) всё ещё может быть ценной для злоумышленника

LoadedApk.updateApplicationInfo()

Скачать инструмент