macOS Apps - Inspecting, debugging and Fuzzing
Last updated
Last updated
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ви можете завантажити disarm звідси.
Ви можете завантажити jtool2 тут або встановити його за допомогою brew
.
jtool застарілий на користь disarm
Codesign
можна знайти в macOS, а ldid
можна знайти в iOS
SuspiciousPackage - це інструмент, корисний для перевірки .pkg файлів (інсталяторів) та перегляду їх вмісту перед установкою.
Ці інсталятори мають preinstall
та postinstall
bash скрипти, які автори шкідливого ПЗ зазвичай зловживають для постійності шкідливого ПЗ.
Цей інструмент дозволяє монтувати образи дисків Apple (.dmg) для їх перевірки перед запуском чого-небудь:
It will be mounted in /Volumes
Перевірте на високу ентропію
Перевірте рядки (якщо майже немає зрозумілого рядка, упаковано)
Упаковщик UPX для MacOS генерує секцію під назвою "__XHDR"
Зверніть увагу, що програми, написані на Objective-C, зберігають свої оголошення класів під час компіляції в Mach-O binaries. Такі оголошення класів включають ім'я та тип:
Визначені інтерфейси
Методи інтерфейсу
Змінні екземпляра інтерфейсу
Визначені протоколи
Зверніть увагу, що ці імена можуть бути обфусцировані, щоб ускладнити реверсування бінарного файлу.
Коли функція викликається в бінарному файлі, що використовує Objective-C, скомпільований код замість виклику цієї функції викликає objc_msgSend
. Це викликатиме фінальну функцію:
Параметри, які очікує ця функція:
Перший параметр (self) - "вказівник, що вказує на екземпляр класу, який має отримати повідомлення". Іншими словами, це об'єкт, на якому викликається метод. Якщо метод є класовим, це буде екземпляр об'єкта класу (в цілому), тоді як для методів екземпляра self вказуватиме на створений екземпляр класу як об'єкт.
Другий параметр (op) - "селектор методу, який обробляє повідомлення". Знову ж таки, простіше кажучи, це просто ім'я методу.
Решта параметрів - це будь-які значення, які потрібні методу (op).
Дивіться, як легко отримати цю інформацію за допомогою lldb
в ARM64 на цій сторінці:
x64:
Аргумент | Реєстр | (для) objc_msgSend |
1-й аргумент | rdi | self: об'єкт, на якому викликається метод |
2-й аргумент | rsi | op: ім'я методу |
3-й аргумент | rdx | 1-й аргумент для методу |
4-й аргумент | rcx | 2-й аргумент для методу |
5-й аргумент | r8 | 3-й аргумент для методу |
6-й аргумент | r9 | 4-й аргумент для методу |
7-й+ аргумент | rsp+ (в стеку) | 5-й+ аргумент для методу |
Dynadump - це інструмент для класового дампу Objective-C бінарних файлів. GitHub вказує на dylibs, але це також працює з виконуваними файлами.
На момент написання, це в даний час найкраще працює.
class-dump - це оригінальний інструмент для генерації декларацій для класів, категорій та протоколів у форматованому коді ObjectiveC.
Він старий і не підтримується, тому, ймовірно, не буде працювати належним чином.
iCDump - це сучасний крос-платформений дамп класів Objective-C. У порівнянні з існуючими інструментами, iCDump може працювати незалежно від екосистеми Apple і надає прив'язки до Python.
З бінарними файлами Swift, оскільки є сумісність з Objective-C, іноді ви можете витягти декларації за допомогою class-dump, але не завжди.
За допомогою команд jtool -l
або otool -l
можна знайти кілька секцій, які починаються з префікса __swift5
:
Ви можете знайти додаткову інформацію про інформацію, що зберігається в цих розділах, у цьому блозі.
Крім того, Swift бінарники можуть мати символи (наприклад, бібліотеки повинні зберігати символи, щоб їх функції можна було викликати). Символи зазвичай містять інформацію про назву функції та атрибути в неохайному вигляді, тому вони дуже корисні, і існують "деманглери", які можуть отримати оригінальну назву:
Зверніть увагу, що для налагодження бінарних файлів SIP потрібно вимкнути (csrutil disable
або csrutil enable --without debug
) або скопіювати бінарні файли в тимчасову папку та видалити підпис за допомогою codesign --remove-signature <binary-path>
або дозволити налагодження бінарного файлу (ви можете використовувати цей скрипт)
Зверніть увагу, що для інструментування системних бінарних файлів, (таких як cloudconfigurationd
) на macOS, SIP повинен бути вимкнений (просто видалення підпису не спрацює).
macOS надає деякі цікаві API, які надають інформацію про процеси:
proc_info
: Це основний API, який надає багато інформації про кожен процес. Вам потрібно бути root, щоб отримати інформацію про інші процеси, але спеціальні права або порти mach не потрібні.
libsysmon.dylib
: Дозволяє отримувати інформацію про процеси через функції, які надаються XPC, однак потрібно мати право com.apple.sysmond.client
.
Stackshotting - це техніка, що використовується для захоплення стану процесів, включаючи стек викликів усіх запущених потоків. Це особливо корисно для налагодження, аналізу продуктивності та розуміння поведінки системи в конкретний момент часу. На iOS та macOS stackshotting можна виконувати за допомогою кількох інструментів і методів, таких як інструменти sample
та spindump
.
Цей інструмент (/usr/bini/ysdiagnose
) в основному збирає багато інформації з вашого комп'ютера, виконуючи десятки різних команд, таких як ps
, zprint
...
Його потрібно запускати як root, а демон /usr/libexec/sysdiagnosed
має дуже цікаві права, такі як com.apple.system-task-ports
та get-task-allow
.
Його plist знаходиться в /System/Library/LaunchDaemons/com.apple.sysdiagnose.plist
, який оголошує 3 MachServices:
com.apple.sysdiagnose.CacheDelete
: Видаляє старі архіви в /var/rmp
com.apple.sysdiagnose.kernel.ipc
: Спеціальний порт 23 (ядро)
com.apple.sysdiagnose.service.xpc
: Інтерфейс режиму користувача через клас Libsysdiagnose
Obj-C. Три аргументи в словнику можуть бути передані (compress
, display
, run
)
MacOS генерує багато журналів, які можуть бути дуже корисними під час запуску програми, намагаючись зрозуміти що вона робить.
Більше того, є деякі журнали, які міститимуть тег <private>
, щоб сховати деяку інформацію, що ідентифікує користувача або комп'ютер. Однак можливо встановити сертифікат для розкриття цієї інформації. Слідуйте поясненням тут.
На лівій панелі Hopper можна побачити символи (Labels) бінарного файлу, список процедур і функцій (Proc) та рядки (Str). Це не всі рядки, а лише ті, що визначені в кількох частинах файлу Mac-O (як cstring або objc_methname
).
На середній панелі ви можете бачити дизасембльований код. І ви можете бачити його у сирому дизасемблюванні, як граф, як декодований і як бінарний, натискаючи на відповідну іконку:
Клацнувши правою кнопкою миші на об'єкті коду, ви можете побачити посилання на/з цього об'єкта або навіть змінити його назву (це не працює в декодованому псевдокоді):
Більше того, в нижній частині середньої панелі ви можете писати команди python.
На правій панелі ви можете побачити цікаву інформацію, таку як історія навігації (щоб ви знали, як ви потрапили в поточну ситуацію), граф викликів, де ви можете бачити всі функції, які викликають цю функцію, і всі функції, які викликає ця функція, а також інформацію про локальні змінні.
Цей інструмент дозволяє користувачам отримувати доступ до програм на надзвичайно низькому рівні і надає спосіб для користувачів відстежувати програми і навіть змінювати їхній потік виконання. Dtrace використовує пробники, які розміщені по всьому ядру і знаходяться в таких місцях, як початок і кінець системних викликів.
DTrace використовує функцію dtrace_probe_create
для створення пробника для кожного системного виклику. Ці пробники можуть бути активовані в точках входу та виходу кожного системного виклику. Взаємодія з DTrace відбувається через /dev/dtrace, який доступний лише для користувача root.
Щоб увімкнути Dtrace, не вимикаючи повністю захист SIP, ви можете виконати в режимі відновлення: csrutil enable --without dtrace
Ви також можете dtrace
або dtruss
бінарні файли, які ви скомпілювали.
Доступні пробники dtrace можна отримати за допомогою:
Назва зонда складається з чотирьох частин: постачальника, модуля, функції та назви (fbt:mach_kernel:ptrace:entry
). Якщо ви не вкажете якусь частину назви, Dtrace застосує цю частину як шаблон.
Щоб налаштувати DTrace для активації зондів і вказати, які дії виконувати, коли вони спрацьовують, нам потрібно буде використовувати мову D.
Більш детальне пояснення та більше прикладів можна знайти за посиланням https://illumos.org/books/dtrace/chp-intro.html
Запустіть man -k dtrace
, щоб перерахувати доступні скрипти DTrace. Приклад: sudo dtruss -n binary
скрипт
Це засіб трасування ядра. Документовані коди можна знайти в /usr/share/misc/trace.codes
.
Інструменти, такі як latency
, sc_usage
, fs_usage
та trace
, використовують його внутрішньо.
Для взаємодії з kdebug
використовується sysctl
через простір імен kern.kdebug
, а MIB, які можна використовувати, можна знайти в sys/sysctl.h
, де реалізовані функції в bsd/kern/kdebug.c
.
Щоб взаємодіяти з kdebug за допомогою власного клієнта, зазвичай виконуються такі кроки:
Видалити існуючі налаштування з KERN_KDSETREMOVE
Встановити трасування з KERN_KDSETBUF та KERN_KDSETUP
Використовувати KERN_KDGETBUF, щоб отримати кількість записів у буфері
Отримати власного клієнта з трасування за допомогою KERN_KDPINDEX
Увімкнути трасування з KERN_KDENABLE
Прочитати буфер, викликавши KERN_KDREADTR
Щоб зіставити кожен потік з його процесом, викликати KERN_KDTHRMAP.
Щоб отримати цю інформацію, можна використовувати інструмент Apple trace
або спеціальний інструмент kDebugView (kdv).
Зверніть увагу, що Kdebug доступний лише для 1 клієнта одночасно. Тобто лише один інструмент на базі k-debug може бути виконаний одночасно.
API ktrace_*
походять з libktrace.dylib
, які обгортують ті, що з Kdebug
. Тоді клієнт може просто викликати ktrace_session_create
та ktrace_events_[single/class]
, щоб встановити зворотні виклики для конкретних кодів, а потім запустити його з ktrace_start
.
Ви можете використовувати це навіть з активованим SIP
Ви можете використовувати утиліту ktrace
як клієнт:
Or tailspin
.
Це використовується для профілювання на рівні ядра і побудоване за допомогою викликів Kdebug
.
В основному, глобальна змінна kernel_debug_active
перевіряється, і якщо вона встановлена, викликається kperf_kdebug_handler
з кодом Kdebug
та адресою кадру ядра, що викликає. Якщо код Kdebug
відповідає одному з вибраних, отримуються "дії", налаштовані як бітова карта (перевірте osfmk/kperf/action.h
для варіантів).
Kperf також має таблицю MIB sysctl: (як root) sysctl kperf
. Ці коди можна знайти в osfmk/kperf/kperfbsd.c
.
Більше того, підмножина функціональності Kperf знаходиться в kpc
, який надає інформацію про лічильники продуктивності машини.
ProcessMonitor є дуже корисним інструментом для перевірки дій, пов'язаних з процесами, які виконує процес (наприклад, моніторинг нових процесів, які створює процес).
SpriteTree є інструментом для виведення відносин між процесами.
Вам потрібно моніторити ваш Mac за допомогою команди sudo eslogger fork exec rename create > cap.json
(термінал, що запускає це, вимагає FDA). А потім ви можете завантажити json в цей інструмент, щоб переглянути всі відносини:
FileMonitor дозволяє моніторити події файлів (такі як створення, модифікації та видалення), надаючи детальну інформацію про такі події.
Crescendo є GUI-інструментом з виглядом і відчуттям, які можуть бути знайомі користувачам Windows з Procmon від Microsoft Sysinternal. Цей інструмент дозволяє записувати різні типи подій, які можна почати і зупинити, дозволяє фільтрувати ці події за категоріями, такими як файл, процес, мережа тощо, і надає функціональність для збереження записаних подій у форматі json.
Apple Instruments є частиною інструментів розробника Xcode – використовуються для моніторингу продуктивності додатків, виявлення витоків пам'яті та відстеження активності файлової системи.
Дозволяє відстежувати дії, виконувані процесами:
Taskexplorer корисний для перегляду бібліотек, які використовуються бінарним файлом, файлів, які він використовує, та мережевих з'єднань. Він також перевіряє бінарні процеси на virustotal і показує інформацію про бінарний файл.
У цьому блозі ви можете знайти приклад того, як налагодити працюючий демон, який використовував PT_DENY_ATTACH
, щоб запобігти налагодженню, навіть якщо SIP був вимкнений.
lldb є де факто інструментом для налагодження бінарних файлів macOS.
Ви можете встановити смак intel, використовуючи lldb, створивши файл .lldbinit
у вашій домашній папці з наступним рядком:
Всередині lldb, збережіть процес за допомогою process save-core
(lldb) Команда | Опис |
run (r) | Початок виконання, яке триватиме безперервно, поки не буде досягнуто точку зупинки або процес не завершиться. |
process launch --stop-at-entry | Почати виконання, зупинившись на точці входу |
continue (c) | Продовжити виконання налагоджуваного процесу. |
nexti (n / ni) | Виконати наступну інструкцію. Ця команда пропустить виклики функцій. |
stepi (s / si) | Виконати наступну інструкцію. На відміну від команди nexti, ця команда зайде в виклики функцій. |
finish (f) | Виконати решту інструкцій у поточній функції (“рамці”), повернутися та зупинитися. |
control + c | Призупинити виконання. Якщо процес був запущений (r) або продовжений (c), це призведе до зупинки процесу ...де б він не виконувався в даний момент. |
breakpoint (b) |
breakpoint delete <num> |
help | help breakpoint #Отримати допомогу з команди точки зупинки help memory write #Отримати допомогу для запису в пам'ять |
reg | |
x/s <reg/memory address> | Відобразити пам'ять як рядок, закінчений нульовим символом. |
x/i <reg/memory address> | Відобразити пам'ять як інструкцію асемблера. |
x/b <reg/memory address> | Відобразити пам'ять як байт. |
print object (po) | Це надрукує об'єкт, на який посилається параметр po $raw
Зверніть увагу, що більшість API або методів Objective-C від Apple повертають об'єкти, і тому їх слід відображати за допомогою команди “друк об'єкта” (po). Якщо po не дає змістовного виходу, використовуйте |
memory | memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 #Записати AAAA за цією адресою memory write -f s $rip+0x11f+7 "AAAA" #Записати AAAA за адресою |
disassembly | dis #Дизасемблювати поточну функцію dis -n <funcname> #Дизасемблювати функцію dis -n <funcname> -b <basename> #Дизасемблювати функцію dis -c 6 #Дизасемблювати 6 рядків dis -c 0x100003764 -e 0x100003768 # Від однієї адреси до іншої dis -p -c 4 # Почати з поточної адреси дизасемблювання |
parray | parray 3 (char **)$x1 # Перевірити масив з 3 компонентів у регістрі x1 |
image dump sections | Друк карти пам'яті поточного процесу |
image dump symtab <library> |
|
При виклику функції objc_sendMsg
регістр rsi містить назву методу як рядок, закінчений нульовим символом (“C”). Щоб надрукувати назву через lldb, виконайте:
(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) print (char*)$rsi:
(char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
Команда sysctl hw.model
повертає "Mac", коли хост є MacOS, але щось інше, коли це VM.
Граючи з значеннями hw.logicalcpu
та hw.physicalcpu
, деякі шкідливі програми намагаються виявити, чи це VM.
Деякі шкідливі програми також можуть виявити, чи машина є VMware на основі MAC-адреси (00:50:56).
Також можливо дізнатися, чи процес налагоджується за допомогою простого коду, такого як:
if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //процес налагоджується }
Він також може викликати системний виклик ptrace
з прапором PT_DENY_ATTACH
. Це запобігає прикріпленню та трасуванню налагоджувача.
Ви можете перевірити, чи функція sysctl
або ptrace
імпортується (але шкідливе ПЗ може імпортувати її динамічно)
Як зазначено в цьому звіті, “Перемога над анти-дебаг техніками: варіанти macOS ptrace” : “Повідомлення Process # exited with status = 45 (0x0000002d) зазвичай є явною ознакою того, що ціль налагодження використовує PT_DENY_ATTACH”
Ядрові дампи створюються, якщо:
kern.coredump
sysctl встановлено на 1 (за замовчуванням)
Якщо процес не був suid/sgid або kern.sugid_coredump
дорівнює 1 (за замовчуванням 0)
Ліміт AS_CORE
дозволяє операцію. Можна подавити створення дампів коду, викликавши ulimit -c 0
і знову увімкнути їх за допомогою ulimit -c unlimited
.
У цих випадках ядрові дампи генеруються відповідно до sysctl kern.corefile
і зазвичай зберігаються в /cores/core/.%P
.
ReportCrash аналізує процеси, що зазнали краху, і зберігає звіт про крах на диск. Звіт про крах містить інформацію, яка може допомогти розробнику діагностувати причину краху.
Для додатків та інших процесів які працюють у контексті запуску для кожного користувача, ReportCrash працює як LaunchAgent і зберігає звіти про крах у ~/Library/Logs/DiagnosticReports/
користувача.
Для демонів, інших процесів які працюють у системному контексті запуску та інших привілейованих процесів, ReportCrash працює як LaunchDaemon і зберігає звіти про крах у системному /Library/Logs/DiagnosticReports
Якщо ви турбуєтеся про звіти про крах, які надсилаються Apple, ви можете їх вимкнути. Якщо ні, звіти про крах можуть бути корисними для з'ясування, як сервер зазнав краху.
Під час фуззингу в MacOS важливо не дозволяти Mac засинати:
systemsetup -setsleep Never
pmset, Системні налаштування
Якщо ви фуззите через SSH-з'єднання, важливо переконатися, що сесія не закриється. Тому змініть файл sshd_config на:
TCPKeepAlive Yes
ClientAliveInterval 0
ClientAliveCountMax 0
Перегляньте наступну сторінку, щоб дізнатися, яка програма відповідає за обробку вказаної схеми або протоколу:
macOS File Extension & URL scheme app handlersЦе цікаво, щоб знайти процеси, які керують мережевими даними:
Або використовуйте netstat
або lsof
Працює для CLI інструментів
Він "просто працює" з macOS GUI інструментами. Зверніть увагу, що деякі macOS додатки мають специфічні вимоги, такі як унікальні імена файлів, правильне розширення, необхідність читати файли з пісочниці (~/Library/Containers/com.apple.Safari/Data
)...
Деякі приклади:
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)