
Это эксплойт для CVE-2017-7047, работает на версиях 10.3.2 и ниже.
triple_fetch — ianbeer [https://bugs.chromium.org/p/project-zero/issues/detail?id=1247]
Это эксплойт для CVE-2017-7047, логической ошибки в libxpc, которая позволяла вредоносным отправителям сообщений отправлять объекты xpc_data, основанные на разделяемой памяти. Потребители xpc-сообщений, по-видимому, не ожидали, что буферы, подлежащие объектам xpc_data, могут изменяться отправителем во время обработки получателем.
Этот проект использует CVE-2017-7047 для создания доказательства концепции удалённого сервера отладки lldb debugserver, способного подключаться и разрешать удалённую отладку всех пользовательских процессов на iOS.
Это высокоуровневый обзор эксплойта; более глубокое описание может быть опубликовано позже. А пока подробности смотрите в коде :)
Часть I
Эксплойт нацелен на NSXPC — реализацию Objective-C удалённого вызова процедур, используемую многими службами iOS (1). Сообщение NSXPC состоит из объекта, сериализованного в bplist16, внутри сериализованного xpc-объекта xpc_data внутри mach-сообщения.
Помимо прочего, объект bplist16 содержит строку кодировки типов Objective-C (2), которая будет разобрана функцией ___NSMS1 в CoreFoundation. Эта функция не ожидает, что содержимое разбираемой строки изменится, и данный эксплойт использует это для создания примитива переполнения кучи, эксплуатируя тот факт, что определённая часть строки будет извлекаться из памяти три раза. Переключаясь между тремя различными, тщательно выбранными значениями, мы можем переполнить выбранный размер выделения кучи произвольными байтами.
minibplist16.c содержит минимальную реализацию сериализации bplist и обсуждение того, как это работает.
Внешнее xpc-сообщение содержит подготовку кучи. Оно использует собственную реализацию протокола сериализации XPC для подготовки кучи путём создания xpc-словарей с конфликтующими ключами для создания примитивов выделения и освобождения. Внешнее xpc-сообщение также содержит распыление кучи (с использованием нескольких копий объекта разделяемой памяти для снижения использования памяти) и распыление имён прав отправки mach-порта.
Переполнение указывает указатель класса isa объекта Objective-C на поддельный объект, созданный путём распыления кучи, так что при вызове метода на этом поддельном объекте стек переключается на небольшой ROP-стек. ROP-стек методом перебора проходит через распылённые имена прав отправки mach-порта, пытаясь отправить право отправки цели на её собственный task port каждому из кандидатов распылённых имён прав отправки. Эксплойт прослушивает все распылённые порты, и если эксплойт успешен, он получает право отправки на task port цели, что даёт полный контроль над целевой задачей.
Интерлюдия
Эксплойт нацелен на службу com.apple.CoreAuthentication.daemon, размещённую демоном coreauthd, работающим от root. Эта служба доступна из песочницы приложений. Немного экспериментов после первоначальной работы эксплойта показали, что из контекста coreauthd API processor_set_tasks может получать права отправки на task port для всех пользовательских процессов, запущенных на устройстве. Это было общеизвестно как минимум с 2012 года, и история подробно освещена известным исследователем внутреннего устройства iOS Джонатаном Левином на его сайте (3). Код, загруженный Левином в 2015 году, работает до сих пор — для него не требуется джейлбрейк, достаточно root на стоковом устройстве.
Часть II
Основная цель отладчика, который я хотел построить с помощью этого эксплойта, — возможность подключаться к произвольному процессу, устанавливать точки останова, а также проверять и изменять состояние регистров и памяти при их срабатывании. Вместо реализации протокола gdb или lldb с нуля я решил внести необходимые изменения в проект lldb debugserver, а затем использовать эксплойт для его запуска.
Вместо программных точек останова, которые требуют отключения или обхода подписи кода, debugserver патчится для исключительного использования аппаратных точек останова. ARM64 имеет 16 аппаратных регистров точек останова, что означает максимум 16 активных точек останова.
Прототипная поддержка аппаратных точек останова ARM существовала в коде lldb debugserver, но потребовала некоторой доработки для работы. Например, мне пришлось добавить код, который патчит указатель функции pthread_introspection_hook в отлаживаемом процессе так, чтобы он всегда падал, чтобы я мог обнаружить создание новых потоков, распространить состояние аппаратных точек останова на вновь созданные потоки и продолжить выполнение, как если бы сбоя не было.
Я также пропатчил код подключения и продолжения так, чтобы он напрямую приостанавливал и возобновлял задачу через task port вместо использования ptrace и сигналов.
Советы по сборке
Всё должно работать на всех iOS-устройствах с версиями iOS 10.0–10.3.2 включительно. Я тестировал на:
iPhone 7 + 10.3.2 iPod Touch + 10.1.1 iPad Mini 2 + 10.2
Я включил предварительно собранный бинарник debugserver, который рекомендую использовать, но патч для lldb debugserver также включён в debugserver.diff.
Собрать debugserver не слишком сложно. Я работал со следующими ревизиями git: lldb: 0db640c4cd1ec4e4c2580336fa5f53be029c5bc7 llvm: ec48fd127774a4b67c72ea7c3057b5c964375e77 clang: b6e778e0bfa2fc32f8821c6b33762f5cb6724659
Примените приложенный debugserver.diff.
Для сборки вам понадобятся (свежие) cmake и ninja; их можно получить из исходников или бинарников из вашего любимого менеджера пакетов для Mac.
(4) содержит руководство по настройке обычной сборки llvm на MacOS, которое может быть полезным.
Вам нужно будет создать символические ссылки на набор заголовочных файлов в вашем iOS SDK, как минимум:
xpc/ launchd.h libproc.h sys/proc_info.h sys/kern_control.h net/route.h mach/mach_vm.h mach/shared_region.h sys/ptrace.h crt_externs.h
Следующая cmake-команда должна дать вам все необходимые подсказки:
cmake -G "Ninja" -DCMAKE_OSX_ARCHITECTURES="armv7;armv7s;arm64" -DCMAKE_TOOLCHAIN_FILE=../cmake/platforms/iOS.cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_BUILD_RUNTIME=Off -DLLVM_INCLUDE_TESTS=Off -DLLVM_INCLUDE_EXAMPLES=Off -DLLVM_ENABLE_BACKTRACES=Off ../
ninja debugserver
Затем вам нужно подписать или подделать подпись бинарника debugserver и заменить его в прилагаемом xcode-проекте.
Подпись кода
По умолчанию проект эксплойта устанавливает улучшенную версию хука amfid из mach_portal (на этот раз с работающей поддержкой fat-файлов и без жёстко заданных смещений :) )
Если вы просто хотите отлаживать, вы должны иметь возможность подписать бинарник debugserver своим собственным сертификатом и отключить хук amfid.
Если вы всё же используете хук amfid, имейте в виду, что приложение, в котором он работает, по-прежнему подчиняется ограничениям на выполнение кода в фоне. Приложение запрашивает дополнительное время через beginBackgroundTaskWithName.
Использование:
Подключите ваш хост и целевое iDevice к одной беспроводной сети и запишите IP-адрес iDevice.
Соберите и запустите приложение эксплойта. Я рекомендую делать это в Xcode, но оно будет работать и отдельно.
Подождите немного. Если через пару минут ничего не произойдёт, сделайте жёсткую перезагрузку устройства, подождите немного и попробуйте снова.
Если всё сработает, должно вывестись «patched debugserver listening on port 1234»
Если вы нажмёте кнопку «get process listing», вы увидите вывод ps
(проще увидеть вывод, если вы используете Xcode, но эксплойт также показывает вывод)
Найдите целевой процесс, который вы хотите отлаживать, и запишите его pid.
На хосте запустите lldb из командной строки: $ lldb (lldb)
установите платформу remote-ios: (lldb) platform select remote-ios
подключитесь к заглушке debugserver: (lldb) process connect connect://192.168.0.172:1234
(где 192.168.0.172 — IP-адрес iDevice)
подключитесь к интересующему процессу: (lldb) attach 55
...подождите немного, debugserver работает в подробном режиме...
Process 55 stopped
Executable module set to "/usr/libexec/backboardd".
вы подключены :)
установите точку останова: (lldb) break set --name malloc Breakpoint 1: 4 locations.
продолжите:
(lldb) c Process 55 resuming Process 55 stopped
malloc libsystem_malloc.dylibmalloc:
-> 0x1936161e0 <+0>: stp x20, x19, [sp, #-0x20]!
0x1936161e4 <+4>: stp x29, x30, [sp, #0x10]
0x1936161e8 <+8>: add x29, sp, #0x10 ; =0x10получите обратную трассировку:
(lldb) bt
malloc frame #1: 0x0000000100099648 backboardd_mh_execute_header + 71240
frame #2: 0x00000001945bf218 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56 frame #3: 0x00000001945be9cc CoreFoundation__CFRunLoopDoSource1 + 436
frame #4: 0x00000001945bc4b0 CoreFoundation__CFRunLoopRun + 1840 frame #5: 0x00000001944ea2b8 CoreFoundationCFRunLoopRunSpecific + 444
frame #6: 0x0000000194537b44 CoreFoundationCFRunLoopRun + 112 frame #7: 0x00000001000a5ba8 backboardd_mh_execute_header + 121768
frame #8: 0x00000001000a5bec backboardd_mh_execute_header + 121836 frame #9: 0x00000001936a5850 libsystem_pthread.dylib_pthread_body + 240
frame #10: 0x00000001936a5760 libsystem_pthread.dylib_pthread_start + 284 frame #11: 0x00000001936a2d94 libsystem_pthread.dylibthread_start + 4Устранение неполадок:
Установите последнюю версию Xcode (разработано и протестировано с 8.3.3). Если lldb не подключается, убедитесь, что у вас установлен SDK для целевой версии iOS.
Предупреждения:
Я надеюсь это исправить, но сейчас очень занят, извините!
Запуск других PoC:
Если вы поместите бинарник в папку pocs в этом проекте, вы сможете заставить эксплойт выполнить его, выбрав его в интерфейсе на устройстве и нажав «exec bundle binary».
Он всё равно будет работать в песочнице приложения, но если в приложении есть символ privileged_task_port, ему будет предоставлено право отправки на task port launchd. Папка triple_fetch_sdk содержит пример проекта, показывающий, как использовать это для создания PoC, например, для запуска поведения в интересующих процессах, которые затем можно отлаживать с помощью debugserver.
Она также содержит API удалённого вызова/портов/файлов/памяти, которые позволяют легко вызывать функции в других процессах и перемещать файловые дескрипторы, mach-порты и память.
(1) [https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html] (2) [https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html] (3) [http://newosxbook.com/articles/PST2.html] (4) [https://gist.github.com/thlorenz/a068c202f2487ec13809]
Этот проект содержит код (debugserver.diff) и бинарник (debugserver), основанные на lldb, который подпадает под следующую лицензию:
Университет Иллинойса/NCSA Лицензия с открытым исходным кодом
Copyright (c) 2010 Apple Inc. Все права защищены.
Разработчик:
LLDB Team
Настоящим предоставляется разрешение, бесплатно, любому лицу, получившему копию этого программного обеспечения и сопутствующих файлов документации («Программное обеспечение»), на использование Программного обеспечения без ограничений, включая, без ограничения, права на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного обеспечения, а также на разрешение лицам, которым предоставляется Программное обеспечение, делать то же самое, при соблюдении следующих условий:
Распространение исходного кода должно сохранять вышеупомянутое уведомление об авторских правах, этот список условий и следующий отказ от ответственности.
Распространение в двоичной форме должно воспроизводить вышеупомянутое уведомление об авторских правах, этот список условий и следующие отказы от ответственности в документации и/или других материалах, предоставляемых вместе с распространением.
Ни имена команды LLDB Team, владельцев авторских прав, ни имена её участников не могут использоваться для одобрения или продвижения продуктов, производных от этого Программного обеспечения, без предварительного специального письменного разрешения.
ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЯМИ КОММЕРЧЕСКОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ОПРЕДЕЛЁННОЙ ЦЕЛИ И ОТСУТСТВИЯ НАРУШЕНИЙ. НИ В КОЕМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЕТЕНЗИИ, УБЫТКИ ИЛИ ИНУЮ ОТВЕТСТВЕННОСТЬ, БУДЬ ТО В ДЕЙСТВИИ ДОГОВОРА, ГРАЖДАНСКОГО ПРАВОНАРУШЕНИЯ ИЛИ ИНЫМ ОБРАЗОМ, ВОЗНИКШИЕ ИЗ, В СВЯЗИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.