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

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

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

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

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

Категории

Все категории
Loading categories
AndroidKernelVulnerability — Запуск и анализ уязвимости ядра Android CVE-2019-2215 | Kitploit
Инструменты/GitHubGitHub/sharif-dev/androidkernelvulnerability
Безопасность AndroidПовышение привилегийСтатический анализДинамический анализ (песочница)ЭксплуатацияОбучение и ОбразованиеЭксплуатация Бинарных ФайловЛаборатории и Практика

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
GitHub
sharif-dev/androidkernelvulnerability

AndroidKernelVulnerability

Запуск и анализ уязвимости ядра Android CVE-2019-2215

Репозиторий
7219144 лет назадПроверено Kitploit

Android Kernel Vulnerability

Обзор

В ноябре 2017 года системой syzkaller была обнаружена use-after-free ошибка в ядре linux. В феврале 2018 года она была исправлена в некоторых ядрах linux и версиях Android.

Это исправление никогда не включалось в ежемесячные бюллетени безопасности Android, поэтому оно не было исправлено на многих новых устройствах, таких как Pixel и Pixel2.

В сентябре 2019 года компания Project Zero уведомила Android о последствиях этой ошибки для безопасности. Затем Android присвоил этой уязвимости идентификатор CVE-2019-2215, чтобы сделать её более формальной и известной.

CVE-2019-2215 — это use-after-free в файле binder.c, который позволяет повышение привилегий (получение root-доступа) из приложения Android. Для эксплуатации этой уязвимости не требуется взаимодействия с пользователем. Требуется лишь установка вредоносного локального приложения.

Здесь мы более подробно рассмотрим эту уязвимость ядра Android и используем её для получения root-доступа (повышения привилегий) ко всему устройству Android.

Мы будем использовать это Proof of Concept (PoC):

https://github.com/cloudfuzz/android-kernel-exploitation

Запуск уязвимости

Сначала мы покажем, как запустить эту уязвимость на эмуляторе Android и вызвать крах ядра. Затем, чтобы увидеть, насколько это может быть опасно, мы продолжим использовать PoC для получения root-доступа на эмулированном устройстве Android. После этого мы проанализируем код ядра, чтобы понять причину (статический и динамический анализ).

После анализа мы увидим, как мы получили root-доступ. В конце мы рассмотрим, как эта уязвимость смягчается с помощью патчей.

Чтобы вызвать крах ядра путём запуска этой уязвимости, выполните следующие шаги:

  1. Прежде всего, вам потребуется ОС linux с установленными 'gdb' и 'python'.
  2. Клонируйте репозиторий PoC. (https://github.com/cloudfuzz/android-kernel-exploitation)
  3. Установите эмулятор Android и Android NDK (установив Android Studio).
  4. Клонируйте исходный код ядра Android. (Будет использоваться ветка 'q-goldfish-android-goldfish-4.14-dev')
  5. Это ядро уже пропатчено, мы изменим его, чтобы заново внести уязвимость в этот код ядра.
  6. Теперь мы должны собрать ядро из исходного кода. Мы собираем ядро с KASan.
  7. Мы загружаем собранное ядро и запускаем наш эмулятор с ним.
  8. Затем, используя 'trigger.cpp' из репозитория PoC, мы вызываем крах (с помощью команды 'adb').
  9. Мы будем использовать 'root-me.py' из PoC и команду 'gdb', чтобы получить root-доступ на эмулированном устройстве.

Посмотрите следующее видео:

[video]

Статический анализ

В этом (и следующем) разделе мы собираемся понять, почему происходит крах, используя статический и динамический анализ.

Здесь мы проанализируем код ядра (статический анализ), чтобы понять проблему. В crash_report.txt есть отчёт от KASan, который говорит, что это ошибка use-after-free. Это означает, что объект был выделен в куче (и у нас есть ссылка на него), затем мы освободили объект из кучи, и после этого ошибочно обратились к нему по ссылке. В этом отчёте напечатан стек вызовов для этих трёх этапов.

Если вы помните из предыдущего, мы использовали 'trigger.cpp' из PoC.

Вот основной код trigger.cpp:``` int main() { //1 int fd, epfd; //2 struct epoll_event event = {.events = EPOLLIN}; //3 fd = open("/dev/binder", O_RDONLY); //4 epfd = epoll_create(1000); //5 epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); //6 ioctl(fd, BINDER_THREAD_EXIT, NULL); }

Давайте посмотрим, что делает `trigger.cpp`.

В Android (как и в других Unix-подобных операционных системах) существуют процессы. Каждая запущенная программа создаёт один (или более) процесс, и эти процессы управляются ОС. ОС может переключаться между ними (многозадачность) или завершать процесс и т.д. По соображениям безопасности процессы по умолчанию изолированы друг от друга.

В некоторых случаях одному процессу может потребоваться обменяться данными с другим процессом. Это называется межпроцессным взаимодействием (IPC). В Linux существует несколько способов взаимодействия процессов. Android представил собственный механизм IPC, называемый **'Binder'**. Binder — это драйвер ядра, обеспечивающий межпроцессное взаимодействие.

В Android IPC может осуществляться прямым вызовом некоторых методов ядра (большинство из них находится в drivers/binder.c) или с помощью высокоуровневых реализаций (например, на Java).

![alt_text](https://raw.githubusercontent.com/sharif-dev/AndroidKernelVulnerability/master/images/binder.jpg)

Для использования **binder** необходимо открыть модуль ядра binder. Это делается в строке 3 файла trigger.cpp. После этого у нас есть указатель на файловый дескриптор. С помощью этого fd можно идентифицировать инициатора и получателя IPC.

Все взаимодействия с драйвером осуществляются через небольшой набор команд **'ioctl'** (BINDER_THREAD_EXIT, BINDER_WRITE_READ, ...).

Подробнее о binder: [ссылка1](https://www.nds.ruhr-uni-bochum.de/media/attachments/files/2012/03/binder.pdf), [ссылка2](http://rts.lab.asu.edu/web_438/project_final/CSE_598_Android_Architecture_Binder.pdf)

В Linux существует понятие **'event polling'**. API **'epoll'** используется, когда необходимо отслеживать несколько файловых дескрипторов (файловые дескрипторы — это то, что мы получаем при открытии драйвера или работе с вводом/выводом и т.д.).

**epoll** — это структура ядра, имеющая два важных поля:

*   interest list = список файловых дескрипторов, которые мы хотим отслеживать.
*   ready list = список файловых дескрипторов, готовых к вводу/выводу.

Чтобы использовать event polling, мы сначала создаём epoll (строка 4), затем добавляем или удаляем (EPOLL_CTL_ADD) событие (&event), связанное с файловым дескриптором (**fd**), в наш созданный epoll (**epfd**) с помощью вызова метода ядра **epoll_ctl**.

=> `epoll_event event` — это событие, которое срабатывает, когда связанный файл (fd) становится доступен для операции чтения.

Теперь мы понимаем, что делает **trigger.cpp** (нет необходимости углубляться!). Он открывает модуль **binder**, создаёт **epoll** для прослушивания, когда binder будет готов. Затем, в строке 6, мы выходим из binder, который запустили в строке 3.


#### Выделение:

При вызове open() фактически вызывается **open_binder()** (реализация open() в binder.c). В open_binder() создаётся новая структура **'binder_proc'** и:

   ` fd->pricate_data = binder_proc`

При вызове **epoll_create()** создаётся новая структура epoll и добавляется в очередь.

![alt_text](https://raw.githubusercontent.com/sharif-dev/AndroidKernelVulnerability/master/images/event_poll.jpg)

При вызове **epoll_ctrl(epdf, ADD, fd, event)** создаётся новый **ep_item**, который связывается с **fd** (прослушиваемым файловым дескриптором), и вставляется в **красное чёрное дерево** event_poll (структура данных в ep для хранения ep_items). Также вызывается **ep_item_poll()**, который обрабатывает привязку функции обратного вызова к ep_item.

Создаётся новая структура **binder_thread** (**здесь происходит выделение памяти**), которая связывается с **binder_proc** (созданным выше). Затем создаётся структура **epoll_entry**, содержащая два списка: **epoll_entry->wait** и **epoll_entry->whead**. Оба списка содержат указатель на **binder_thread**, созданный ранее.

Затем **epoll_entry** связывается с ep_item (**ep_item->pwqlist** — это список, содержащий данный epoll_entry).
Скачать инструмент