<
  • Главная
Статьи

Виконання довільного коду всередині завантажувача S-Boot в ОС Android. Частина 1

Завантажувач S-Boot від компанії Samsung для ОС Android є центральною ланкою в ланцюжку системи безпеки.

Автори: Nitay Artenstein (@nitayart) і Gilad Goldman (@ gnull00)

Завантажувач S-Boot від компанії Samsung для ОС Android є центральною ланкою в ланцюжку системи безпеки . Той, хто скомпрометував S-Boot, потенційно може завантажити інше ядро ​​і образ системи і, таким чином, обійти більшість механізмів захисту телефону.

Це добре відомий вектор атаки, часто використовуваний для отримання прав суперкористувача і модифікації ОС Android, що, за нашими припущеннями, користується особливим попитом у правоохоронних та урядових структурах.
Ще більш цікавим є той факт, що S-Boot містить декілька вразливостей, пов'язаних з порушенням цілісності пам'яті, одну з яких можна використовувати для виконання довільного коду всередині завантажувача.
На даний момент ми можемо підтвердити, що пролом присутній в чіпсетах Exynos. Уразливість універсальна для 90% ПЗУ в чіпсетах Exynos в пристроях Galaxy S5, S6 і S7. У самих останніх версіях ПЗУ для пристроїв S7 (станом на лютий 2017 року) ця проблема, здається, усунена. Більш точна інформація з'явиться в недалекому майбутньому.

Тема, яка буде викладатися, досить обширна, і ми вирішили розділити матеріал на дві частини. У першій частині буде розказано про внутрішній устрій S-Boot, схемах атаки і базові можливості налагодження. В кінці статті буде продемонстровано особливо цікавий напрямок атаки. У другій частині ми розглянемо конкретну уразливість, за допомогою який можна домогтися виконання довільного коду в S-Boot.

Ми не будемо торкатися азів реверс-інжинірингу, таких як завантаження в IDA або перебування базового адреси. На цю тему скоро вийде стаття від Фернана Лоуна Сана (Fernand Lone Sang; @_kamino_).

Як влаштований S-Boot
Як влаштований S-Boot   Малюнок 1: Стадії завантаження на телефонах компанії Samsung
Малюнок 1: Стадії завантаження на телефонах компанії Samsung

Процес завантаження ОС Android на пристроях, що випускаються Samsung, починається з запуску коду в завантажувальної частини ПЗУ (ROM), який перевіряє цілісність завантажувача для наступної стадії за допомогою публічного OEM-ключа, який відомий як SSBK (Samsung Secure Boot Key; Безпечний завантажувальний ключ для пристроїв від Samsung). Потім в пам'ять завантажуються два процеси: перший - S-Boot власною персоною, другий - TrustZone TEE (Trusted Execution Environment; Достовірна Виконавча), що запускаються в так званому «безпечному світі».

Далі два процеси починають працювати спільно. Операційною системою достовірної середовища виконання у випадку з чіпсетом Exynos є Trustonic (колишня MobiCore), яка викликається з S-Boot для перевірки правильної підписи образів перед завантаженням. Таким чином, злом або S-Boot, або TEE потенційно може привести до компрометації всієї системи.

Сам по собі S-Boot розділений на дві частини: BL1 - завантажувач, що викликається з завантажувальної частини ПЗУ, який ініціалізує низькорівневі об'єкти системи. BL2 - невелика операційна система, до якої відбувається перехід після перевірка сигнатури. Ця ОС містить драйвера для USB, екрану і I / O (операції введення / виводу).

Оскільки ми були зацікавлені в знаходженні уразливості, яка дозволить порушити процес завантаження, було вирішено почати дослідження процесу завантаження ядра. На цій стадії ми вже маємо ініціалізувала систему і можемо досить легко виконувати дискові операції введення / виводу, які знадобляться для завантаження іншого способу. Таким чином, ми вирішили відразу перейти до стадії BL2 (хоча в подальшому цілком можна зайнятися дослідженням стадії BL1).

На стадії BL2 у нас не було ніяких можливостей для налагодження, а тільки блоб sboot.bin разом зі стандартним чином для чіпсета Samsung Exynos. Ми відкрили блоб в IDA і перейшли до коду, які можуть застосовуватися до стадії BL2.

Малюнок 2: Типова функція в стадії BL 2 (зверніть увагу на кількість рядків)
Малюнок 2: Типова функція в стадії BL 2 (зверніть увагу на кількість рядків)

Знайти функції, пов'язані з стадії BL2, виявився досить просто. Знаючи, що стадія BL1 відповідає за ініціалізацію низькорівневих об'єктів, а на стадії BL2 з'являється практично повноцінна операційна система, ми зробили висновок, що функції, які використовуються в стадії BL2, повинні бути більше за обсягом, а також містити більше налагоджувальних рядків і посилань на інші функції . Після того як був знайдений перехід до стадії BL2, ми використовували деякі відомі трюки для знаходження базового адреси образу в пам'яті.

З позиції високого рівня на стадії BL2 виявляється кілька цікавих функцій (список неповний):

  1. Завантаження ядра.
  2. Прошивка образу нового образу.
  3. Відображення базового користувальницького інтерфейсу під час оновлення прошивки.
  4. Налагодження (якщо нам буде супроводжувати удача).

В завантажувач механізм завантаження образу нової прошивки зазвичай є благодатним грунтом для атаки, оскільки тут зловмисникові доступний пряме введення, а сам механізм досить складний. Саме виходячи з цих міркувань, ми почали дослідження з цього місця.

Малюнок 3: Додаток Odin для роботи з прошивками в пристроях Samsung
Малюнок 3: Додаток Odin для роботи з прошивками в пристроях Samsung

додаток Odin

Той, хто займався дослідженням телефонів на базі ОС Android, що випускаються компанією Samsung, знайомий з додатком Odin. Ця стара, але в деякій мірі неідеальна, програма призначена для завантаження прошивок на пристрій.

На стороні пристрою при завантаженні нової прошивки спочатку потрібно переключити телефон в режим завантаження в S-Boot за допомогою натискання комбінації з трьох клавіш. Потім пристрій підключається через USB до комп'ютера, на якому запущено клієнт Odin. Потім клієнт Odin відсилає обраний образ прошивки на сервер Odin, запущений на телефоні. Ви не можете завантажити будь-який образ. На заблокованому пристрої завантажувач не прийме прошивку, що не підписаний компанією Samsung.

Малюнок 4: Режим завантаження. Заблокований завантажувач не приймає непідписані образи

На стороні завантажувача додаток Odin використовує досить універсальний протокол для отримання і передачі даних через USB. Саме з цього місця ми і почнемо наші дослідження.
Якщо ви хочете слідувати нашим експериментам, завантажте версію прошивки G930FXXU1APF2 (пристрій Galaxy S7).

Ключова функція в додатку Odin, яка практично повністю відповідає за обробку протоколу - process_packet (за адресою 0x8F00A0A4). При перегляді функції тут же стикаємося з помилкою:

Малюнок 5: Початок функції process_packet
Малюнок 5: Початок функції process_packet

Як видно з малюнка вище, в протоколі Odin відбувається зчитування ID і переходу до відповідній гілці коду. Ідентифікатор пакету 0x65 говорить про те, що передбачається виконання операції з PIT-файлом, що містить інформацію розділах (більш детальну інформацію можна отримати в цій гілці на форумі XDA ).

Коли код доходить до ідентифікатора 0x65, далі або відбувається запис в буфер вмісту поточного PIT-файлу, або запис нового файлу в спеціальний розділ, що містить PIT-дані. Якщо другий байт пакету - 1, Odin переходить далі і копіює поточний PIT-файл в буфер, який потім буде передано клієнту. Клієнтові потрібно визначити, чи підходить нова прошивка під поточну схему розділів.

Однак не дуже зрозуміло, коли инициализируется буфер, в який копіюється PIT-файл (xfer_data.pit_buf). Швидше за все, пам'ять виділяється тільки в цьому випадку:

Малюнок 6: Виділення пам'яті для буфера pit_buf
Малюнок 6: Виділення пам'яті для буфера pit_buf

З малюнка вище видно, що спочатку потрібно відіслати ініціалізації пакет (ID 0x64) перш, ніж буде виділена пам'ять під буфер. В іншому випадку буфер буде вказувати на 0. Якщо ви спробуєте скопіювати PIT-файл перш, ніж пам'ять буде виділена, код буде копіювати в 0. Виходить класичне розіменування порожнього покажчика.

Ця вразливість схожа на багато інших, знайдені нами в додатку Odin, що призводять до краху завантажувача. Мінус в тому, що, цілком ймовірно, ми не можемо використовувати ці проломи в своїх цілях. На архітектурі ARM64 адреса 0 не є проекцією куди-небудь, і будь-які спроби копіювання призводять до негайного краху. З архітектурою ARM32 справи йдуть трохи краще, оскільки адреса 0 може містити таблицю векторів винятків (Exception Vector Table; EVT), яка може бути переписана. Проблема полягає в тому, що ми все ще не управляємо тим, що записуємо, оскільки не управляємо PIT-даними.

Але знайдена пролом дає нам щось інше. На малюнку нижче показаний екран під час краху завантажувача.

Малюнок 7: Всередині режиму Upload
Малюнок 7: Всередині режиму Upload

вивантаження пам'яті

На малюнку вище видно, що інформація виводиться оброблювачем винятків завантажувача, після чого здійснюється перехід в так званий режим Upload, який є напівсекретних і вже кілька років спантеличує користувачів спільноти XDA .

Деякі користувачі говорять, що перемикання в цей режим здійснюється після особливих провалів ядра; інші говорять, що перехід відбувається через проблеми з інтегральної мікросхемою, що управляє потужністю (Power management integrated circuit; PMIC). Тепер ми знаємо, що перемикання в цей режим відбувається під час винятків.

Досліджуючи код, ми бачимо, що режим Upload реалізований у вигляді вбудованої функції (inline function) всередині usbd3_rdx_process (за адресою 0x8F028C1C). Код, показаний нижче, трохи відредагований і спрощений з метою підвищення читабельності.

mode_switch = p_board_info-> mode_switch;
if (mode_switch & UPLOAD_MODE)
{
if (! transaction_data.response_buffer)
{
transaction_data.response_buffer = (char *) malloc (0x80000);
if (! transaction_data.response_buffer)
{
printf ( "% s: buffer allocation failed. \ n", "usbd3_rdx_process");
goto INFINITE_LOOP;
}
}
if (! strcmp (packet_buf, "PoWeRdOwN"))
{
goto POWERDOWN;
}
if (! strcmp (packet_buf, "PrEaMbLe"))
{
memcpy (transaction_data.response_buffer, "AcKnOwLeDgMeNt", 15);
goto SEND_RESPONSE;
}
if (! strcmp (packet_buf, "PrObE"))
{
memcpy (transaction_data.response_buffer, log_location_buf, log_location_buf_size);
goto SEND_RESPONSE;
}
...
dump_start_addr = strtol (packet_buf, NULL, 16);
dump_end_addr = strtol (packet_buf + 9, NULL, 16);
...
(Some length checks)
...
memcpy (transaction_data.response_buffer, dump_start_addr, dump_end_addr - dump_start_addr);
goto SEND_RESPONSE;
Це базовий протокол для вивантаження пам'яті з пристрою. Після відправки серії ініціалізацій пакетів, ви можете просто відіслати початковий і кінцевий адреса для вивантаження і у відповідь отримати шматок пам'яті через USB.
Цю надзвичайно корисну можливість можна використовувати для налагоджувальних та дослідних цілей, оскільки ми можемо вивантажити образ пам'яті після краху, переглянути вміст регістрів, стека і зрозуміти, яка ситуація в цілому. З метою більш всебічного дослідження ми також можемо вивантажити всю пам'ять, що і буде зроблено у другій частині.

Оскільки ми не змогли знайти загальнодоступний інструмент для вивантаження пам'яті в режимі Upload, то написали свою власну утиліту , Якій ви вільно можете користуватися в своїх цілях і експериментах.

Фаззінга додатки Odin

На цьому етапі досліджень ми повернулися до протоколу Odin в надії знайти вразливість, придатну до експлуатації. Зазвичай одним з перших кроків при вивченні нового методу атаки є написання простих фаззеров для швидкого пошуку проломів.

Це завдання вирішується трохи складніше у випадку з S-Boot, оскільки використовується спеціальний протокол на базі технології CDC ACM, яка може застосовуватися для емуляції послідовних портів через USB. Коректна робота з цим протоколом досить складна. Наприклад, необхідно відсилати порожній пакет після кожного стандартного пакета. Деякі пакети повинні бути розміром 1024 байт, навіть якщо містять 4 байта корисних даних. Всі ці та інші складності утруднювали написання з нуля фаззера пакетів.

І тут нам на допомогу приходить прекрасна утиліта Heimdall, написана Бенджаміном до білого (Benjamin Dobell). Heimdall - реалізація протоколу клієнта Odin з відкритим вихідним кодом, що бере на себе всю рутину взаємодії кодом Odin'а в засобі завантаження, яка була використана в якості бази для написання фаззера.

Ми додали параметр командного рядка з ім'ям «fuzz», які приймають на вході набір сирих пакетів, попередньо згенерованих за допомогою коду на Python, після чого отримана інформація відсилається в певній послідовності. У процесі пересилання враховуються низькорівневі нюанси. Доопрацьований фаззер можна скачати звідси .

В процесі тестування програми Odin було спровоковано кілька цікавих крахів, але, на перший погляд, в знайдених знахідки не було нічого корисного. Перед тим як зануритися глибше всередину Odin'а ми вирішили розширити інструментарій для налагодження. І тут нас чекала цікава знахідка.

UART консоль

У процесі пошуків всередині бінарного файлу за адресою 0x8F08BD78 ми знайшли набір строкових покажчиків, навідних на роздуми:

Малюнок 8: Передбачуваний список команд
Малюнок 8: Передбачуваний список команд

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

Припускаючи, що був знайдений в деякому роді послідовний інтерфейс, за допомогою якого можна підключитися до терміналу, ми виявили, що члени форуму XDA побували тут до нас .

З'ясовується, що розробники компанії Samsung залишили UART термінал, до якого можна отримати доступ через завантажувач і який використовується для виконання низькорівневих команд в службових і діагностичних цілях. Деякі команди дозволяють завантажувати ядро ​​зі спеціальними параметрами, записувати / читати інформацію зі сховища і активувати різні USB режими.

Однак з моменту первісної публікації в співтоваристві XDA в 2012 році, більше ніхто не ділився інформацією про використання цих терміналів, і багато припустили, що цей інтерфейс був відключений. Ми вирішили перевірити цю гіпотезу.

Після вивчення інших джерел і зокрема презентації Майкла Оссмана і Кайла Осборна на конференції Black Hat від 2013 року ми вирішили, що в телефонах Samsung і Nexus використовувалася мікросхема мультиплексора між USB коннектором і USB контролером. Детектуючи напруга між піном ID і земляним піном в USB коннекторе, мультиплексор перемикав різні схеми з'єднання на пристрої.

Дві схеми з'єднання офіційно задокументовані: звичайний USB і USB OTG. Ще один режим, який не згадано в загальнодоступній документації, - UART.

Малюнок 9: Пристрій Samsung Anyway
Малюнок 9: Пристрій Samsung Anyway

Потім ми спробували підключитися до Недокументовані UART терміналу. Наш перший пункт призначення - Samsung Anyway , Пристрій, який компанія Samsung тримає в секреті. Цей апарат, який використовується інженерами компанії Samsung, важко знайти у вільному продажу, але іноді можна купити на Ebay.

Пристрій Samsung Anyway робить не що інше як настройку розмірів опорів до піну ID і обрив ліній D + / D- до DSUB коннектор, який потім може бути приєднаний до комп'ютера через адаптер Serial-USB.

Отримавши старе пристрій Anyway з аукціону eBay, ми протестували різні комбінації перемикачів, щоб підключитися до UART терміналу. Ця методика працювала на старих телефонах. Однак все, чого нам вдалося досягти, - отримати логи завантажувача і ядра, але не отримати доступ до найбільш терміналу.

Було вирішено змайструвати власний кабель для інтерфейсу UART, схожий з тим, який Джошуа Дрейк зробив на базі UART кабелю для телефону Nexus 4 . Ми зібрали інформацію з спільноти XDA щодо відповідностей між опорами для Піна ID і режимами, які використовуються виробником. Крім того, деякі підказки були отримані з DTS-файлів ядра. В результаті була отримана наступна схема пристрою:
Було вирішено змайструвати власний кабель для інтерфейсу UART, схожий з тим, який Джошуа Дрейк зробив на базі   UART кабелю для телефону Nexus 4

Малюнок 10: Саморобний перехідник
Малюнок 10: Саморобний перехідник

Оскільки було необхідно управляти діапазоном опорів, ми використовували змінний резистор для установки бажаного значення (вимірюваного за допомогою мультиметра) і приєднання до пристрою S7.
Наш адаптер досить простий: перехідник RS232-USB має свої власні лінії прийому / передачі під'єднані до ліній D + / D- в USB коннекторе. Пін ID заземлений через змінний резистор.

З'ясувалося, що розмір коректного опору - 619 КОм. При такому значенні резистора були отримані деякі вихідні дані під час завантаження пристрою. Однак ми досі не домоглися бажаного, оскільки після отримання кількох рядків, все закінчується, і у нас немає доступу до терміналу.

Малюнок 11: Вихідні дані UART порту
Малюнок 11: Вихідні дані UART порту. Після появи рядка ifconn_com_to_open висновок інформації припиняється

Занурившись вглиб проблеми, ми знайшли функцію, яку позначили як get_initial_uart_str (адреса 0x8F006ECC). Мабуть, UART консоль запускалася тільки якщо ця функція повертала не порожнє значення:

Малюнок 12: Функція get_initial_uart_str
Малюнок 12: Функція get_initial_uart_str

З цього місця і, особливо, починаючи з мітки LABEL_9, видно, що завантажувач очікує послідовність повернень каретки перш, ніж перейти в режим консолі.

Тепер було зрозуміло, що робити далі: шляхом натискання клавіші «enter» на старті при підключеному переходнике і одночасному натисканні кнопок Гучність і Харчування, нам вдалося пройти перевірку і в функції ifconn_com_to_open і в терміналі.

Нарешті, нас чекав успіх:

Малюнок 13: UART консоль
Малюнок 13: UART консоль

Як видно з малюнка вище, в консолі вже виведені деякі цікаві команди, докладніше про які ми поговоримо в другій частині.



Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью