macOS Apps - Inspecting, debugging and Fuzzing

Підтримка HackTricks

Статичний аналіз

otool & objdump & nm

otool -L /bin/ls #List dynamically linked libraries
otool -tv /bin/ps #Decompile application
objdump -m --dylibs-used /bin/ls #List dynamically linked libraries
objdump -m -h /bin/ls # Get headers information
objdump -m --syms /bin/ls # Check if the symbol table exists to get function names
objdump -m --full-contents /bin/ls # Dump every section
objdump -d /bin/ls # Dissasemble the binary
objdump --disassemble-symbols=_hello --x86-asm-syntax=intel toolsdemo #Disassemble a function using intel flavour
nm -m ./tccd # List of symbols

jtool2 & Disarm

Ви можете завантажити disarm звідси.

ARCH=arm64e disarm -c -i -I --signature /path/bin # Get bin info and signature
ARCH=arm64e disarm -c -l /path/bin # Get binary sections
ARCH=arm64e disarm -c -L /path/bin # Get binary commands (dependencies included)
ARCH=arm64e disarm -c -S /path/bin # Get symbols (func names, strings...)
ARCH=arm64e disarm -c -d /path/bin # Get disasembled
jtool2 -d __DATA.__const myipc_server | grep MIG # Get MIG info

Ви можете завантажити jtool2 тут або встановити його за допомогою brew.

# Install
brew install --cask jtool2

jtool2 -l /bin/ls # Get commands (headers)
jtool2 -L /bin/ls # Get libraries
jtool2 -S /bin/ls # Get symbol info
jtool2 -d /bin/ls # Dump binary
jtool2 -D /bin/ls # Decompile binary

# Get signature information
ARCH=x86_64 jtool2 --sig /System/Applications/Automator.app/Contents/MacOS/Automator

# Get MIG information
jtool2 -d __DATA.__const myipc_server | grep MIG

jtool застарілий на користь disarm

Codesign / ldid

Codesign можна знайти в macOS, а ldid можна знайти в iOS

# Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"

# Check if the app’s contents have been modified
codesign --verify --verbose /Applications/Safari.app

# Get entitlements from the binary
codesign -d --entitlements :- /System/Applications/Automator.app # Check the TCC perms

# Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app

# Sign a binary
codesign -s <cert-name-keychain> toolsdemo

# Get signature info
ldid -h <binary>

# Get entitlements
ldid -e <binary>

# Change entilements
## /tmp/entl.xml is a XML file with the new entitlements to add
ldid -S/tmp/entl.xml <binary>

SuspiciousPackage

SuspiciousPackage - це інструмент, корисний для перевірки .pkg файлів (інсталяторів) та перегляду їх вмісту перед установкою. Ці інсталятори мають preinstall та postinstall bash скрипти, які автори шкідливого ПЗ зазвичай зловживають для постійності шкідливого ПЗ.

hdiutil

Цей інструмент дозволяє монтувати образи дисків Apple (.dmg) для їх перевірки перед запуском чого-небудь:

hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg

It will be mounted in /Volumes

Packed binaries

  • Перевірте на високу ентропію

  • Перевірте рядки (якщо майже немає зрозумілого рядка, упаковано)

  • Упаковщик UPX для MacOS генерує секцію під назвою "__XHDR"

Static Objective-C analysis

Metadata

Зверніть увагу, що програми, написані на Objective-C, зберігають свої оголошення класів під час компіляції в Mach-O binaries. Такі оголошення класів включають ім'я та тип:

  • Визначені інтерфейси

  • Методи інтерфейсу

  • Змінні екземпляра інтерфейсу

  • Визначені протоколи

Зверніть увагу, що ці імена можуть бути обфусцировані, щоб ускладнити реверсування бінарного файлу.

Function calling

Коли функція викликається в бінарному файлі, що використовує Objective-C, скомпільований код замість виклику цієї функції викликає objc_msgSend. Це викликатиме фінальну функцію:

Параметри, які очікує ця функція:

  • Перший параметр (self) - "вказівник, що вказує на екземпляр класу, який має отримати повідомлення". Іншими словами, це об'єкт, на якому викликається метод. Якщо метод є класовим, це буде екземпляр об'єкта класу (в цілому), тоді як для методів екземпляра self вказуватиме на створений екземпляр класу як об'єкт.

  • Другий параметр (op) - "селектор методу, який обробляє повідомлення". Знову ж таки, простіше кажучи, це просто ім'я методу.

  • Решта параметрів - це будь-які значення, які потрібні методу (op).

Дивіться, як легко отримати цю інформацію за допомогою lldb в ARM64 на цій сторінці:

x64:

Dump ObjectiveC metadata

Dynadump

Dynadump - це інструмент для класового дампу Objective-C бінарних файлів. GitHub вказує на dylibs, але це також працює з виконуваними файлами.

./dynadump dump /path/to/bin

На момент написання, це в даний час найкраще працює.

Звичайні інструменти

nm --dyldinfo-only /path/to/bin
otool -ov /path/to/bin
objdump --macho --objc-meta-data /path/to/bin

class-dump

class-dump - це оригінальний інструмент для генерації декларацій для класів, категорій та протоколів у форматованому коді ObjectiveC.

Він старий і не підтримується, тому, ймовірно, не буде працювати належним чином.

ICDump

iCDump - це сучасний крос-платформений дамп класів Objective-C. У порівнянні з існуючими інструментами, iCDump може працювати незалежно від екосистеми Apple і надає прив'язки до Python.

import icdump
metadata = icdump.objc.parse("/path/to/bin")

print(metadata.to_decl())

Статичний аналіз Swift

З бінарними файлами Swift, оскільки є сумісність з Objective-C, іноді ви можете витягти декларації за допомогою class-dump, але не завжди.

За допомогою команд jtool -l або otool -l можна знайти кілька секцій, які починаються з префікса __swift5:

jtool2 -l /Applications/Stocks.app/Contents/MacOS/Stocks
LC 00: LC_SEGMENT_64              Mem: 0x000000000-0x100000000    __PAGEZERO
LC 01: LC_SEGMENT_64              Mem: 0x100000000-0x100028000    __TEXT
[...]
Mem: 0x100026630-0x100026d54        __TEXT.__swift5_typeref
Mem: 0x100026d60-0x100027061        __TEXT.__swift5_reflstr
Mem: 0x100027064-0x1000274cc        __TEXT.__swift5_fieldmd
Mem: 0x1000274cc-0x100027608        __TEXT.__swift5_capture
[...]

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

Крім того, Swift бінарники можуть мати символи (наприклад, бібліотеки повинні зберігати символи, щоб їх функції можна було викликати). Символи зазвичай містять інформацію про назву функції та атрибути в неохайному вигляді, тому вони дуже корисні, і існують "деманглери", які можуть отримати оригінальну назву:

# Ghidra plugin
https://github.com/ghidraninja/ghidra_scripts/blob/master/swift_demangler.py

# Swift cli
swift demangle

Динамічний аналіз

Зверніть увагу, що для налагодження бінарних файлів SIP потрібно вимкнути (csrutil disable або csrutil enable --without debug) або скопіювати бінарні файли в тимчасову папку та видалити підпис за допомогою codesign --remove-signature <binary-path> або дозволити налагодження бінарного файлу (ви можете використовувати цей скрипт)

Зверніть увагу, що для інструментування системних бінарних файлів, (таких як cloudconfigurationd) на macOS, SIP повинен бути вимкнений (просто видалення підпису не спрацює).

API

macOS надає деякі цікаві API, які надають інформацію про процеси:

  • proc_info: Це основний API, який надає багато інформації про кожен процес. Вам потрібно бути root, щоб отримати інформацію про інші процеси, але спеціальні права або порти mach не потрібні.

  • libsysmon.dylib: Дозволяє отримувати інформацію про процеси через функції, які надаються XPC, однак потрібно мати право com.apple.sysmond.client.

Stackshot та мікростекшоти

Stackshotting - це техніка, що використовується для захоплення стану процесів, включаючи стек викликів усіх запущених потоків. Це особливо корисно для налагодження, аналізу продуктивності та розуміння поведінки системи в конкретний момент часу. На iOS та macOS stackshotting можна виконувати за допомогою кількох інструментів і методів, таких як інструменти sample та spindump.

Sysdiagnose

Цей інструмент (/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

Ліва панель

На лівій панелі Hopper можна побачити символи (Labels) бінарного файлу, список процедур і функцій (Proc) та рядки (Str). Це не всі рядки, а лише ті, що визначені в кількох частинах файлу Mac-O (як cstring або objc_methname).

Середня панель

На середній панелі ви можете бачити дизасембльований код. І ви можете бачити його у сирому дизасемблюванні, як граф, як декодований і як бінарний, натискаючи на відповідну іконку:

Клацнувши правою кнопкою миші на об'єкті коду, ви можете побачити посилання на/з цього об'єкта або навіть змінити його назву (це не працює в декодованому псевдокоді):

Більше того, в нижній частині середньої панелі ви можете писати команди python.

Права панель

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

dtrace

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

DTrace використовує функцію dtrace_probe_create для створення пробника для кожного системного виклику. Ці пробники можуть бути активовані в точках входу та виходу кожного системного виклику. Взаємодія з DTrace відбувається через /dev/dtrace, який доступний лише для користувача root.

Щоб увімкнути Dtrace, не вимикаючи повністю захист SIP, ви можете виконати в режимі відновлення: csrutil enable --without dtrace

Ви також можете dtrace або dtruss бінарні файли, які ви скомпілювали.

Доступні пробники dtrace можна отримати за допомогою:

dtrace -l | head
ID   PROVIDER            MODULE                          FUNCTION NAME
1     dtrace                                                     BEGIN
2     dtrace                                                     END
3     dtrace                                                     ERROR
43    profile                                                     profile-97
44    profile                                                     profile-199

Назва зонда складається з чотирьох частин: постачальника, модуля, функції та назви (fbt:mach_kernel:ptrace:entry). Якщо ви не вкажете якусь частину назви, Dtrace застосує цю частину як шаблон.

Щоб налаштувати DTrace для активації зондів і вказати, які дії виконувати, коли вони спрацьовують, нам потрібно буде використовувати мову D.

Більш детальне пояснення та більше прикладів можна знайти за посиланням https://illumos.org/books/dtrace/chp-intro.html

Приклади

Запустіть man -k dtrace, щоб перерахувати доступні скрипти DTrace. Приклад: sudo dtruss -n binary

#Count the number of syscalls of each running process
sudo dtrace -n 'syscall:::entry {@[execname] = count()}'
  • скрипт

syscall:::entry
/pid == $1/
{
}

#Log every syscall of a PID
sudo dtrace -s script.d 1234
syscall::open:entry
{
printf("%s(%s)", probefunc, copyinstr(arg0));
}
syscall::close:entry
{
printf("%s(%d)\n", probefunc, arg0);
}

#Log files opened and closed by a process
sudo dtrace -s b.d -c "cat /etc/hosts"
syscall:::entry
{
;
}
syscall:::return
{
printf("=%d\n", arg1);
}

#Log sys calls with values
sudo dtrace -s syscalls_info.d -c "cat /etc/hosts"

dtruss

dtruss -c ls #Get syscalls of ls
dtruss -c -p 1000 #get syscalls of PID 1000

kdebug

Це засіб трасування ядра. Документовані коди можна знайти в /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 може бути виконаний одночасно.

ktrace

API ktrace_* походять з libktrace.dylib, які обгортують ті, що з Kdebug. Тоді клієнт може просто викликати ktrace_session_create та ktrace_events_[single/class], щоб встановити зворотні виклики для конкретних кодів, а потім запустити його з ktrace_start.

Ви можете використовувати це навіть з активованим SIP

Ви можете використовувати утиліту ktrace як клієнт:

ktrace trace -s -S -t c -c ls | grep "ls("

Or tailspin.

kperf

Це використовується для профілювання на рівні ядра і побудоване за допомогою викликів 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

ProcessMonitor є дуже корисним інструментом для перевірки дій, пов'язаних з процесами, які виконує процес (наприклад, моніторинг нових процесів, які створює процес).

SpriteTree

SpriteTree є інструментом для виведення відносин між процесами. Вам потрібно моніторити ваш Mac за допомогою команди sudo eslogger fork exec rename create > cap.json (термінал, що запускає це, вимагає FDA). А потім ви можете завантажити json в цей інструмент, щоб переглянути всі відносини:

FileMonitor

FileMonitor дозволяє моніторити події файлів (такі як створення, модифікації та видалення), надаючи детальну інформацію про такі події.

Crescendo

Crescendo є GUI-інструментом з виглядом і відчуттям, які можуть бути знайомі користувачам Windows з Procmon від Microsoft Sysinternal. Цей інструмент дозволяє записувати різні типи подій, які можна почати і зупинити, дозволяє фільтрувати ці події за категоріями, такими як файл, процес, мережа тощо, і надає функціональність для збереження записаних подій у форматі json.

Apple Instruments

Apple Instruments є частиною інструментів розробника Xcode – використовуються для моніторингу продуктивності додатків, виявлення витоків пам'яті та відстеження активності файлової системи.

fs_usage

Дозволяє відстежувати дії, виконувані процесами:

fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names containing ls
fs_usage -w -f network curl #This tracks network actions

TaskExplorer

Taskexplorer корисний для перегляду бібліотек, які використовуються бінарним файлом, файлів, які він використовує, та мережевих з'єднань. Він також перевіряє бінарні процеси на virustotal і показує інформацію про бінарний файл.

PT_DENY_ATTACH

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

lldb

lldb є де факто інструментом для налагодження бінарних файлів macOS.

lldb ./malware.bin
lldb -p 1122
lldb -n malware.bin
lldb -n malware.bin --waitfor

Ви можете встановити смак intel, використовуючи lldb, створивши файл .lldbinit у вашій домашній папці з наступним рядком:

settings set target.x86-disassembly-flavor intel

Всередині lldb, збережіть процес за допомогою process save-core

При виклику функції 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:"

Анти-динамічний аналіз

Виявлення VM

  • Команда 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, ви можете їх вимкнути. Якщо ні, звіти про крах можуть бути корисними для з'ясування, як сервер зазнав краху.

#To disable crash reporting:
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist

#To re-enable crash reporting:
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist

Сон

Під час фуззингу в MacOS важливо не дозволяти Mac засинати:

  • systemsetup -setsleep Never

  • pmset, Системні налаштування

Відключення SSH

Якщо ви фуззите через SSH-з'єднання, важливо переконатися, що сесія не закриється. Тому змініть файл sshd_config на:

  • TCPKeepAlive Yes

  • ClientAliveInterval 0

  • ClientAliveCountMax 0

sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

Internal Handlers

Перегляньте наступну сторінку, щоб дізнатися, яка програма відповідає за обробку вказаної схеми або протоколу:

Enumerating Network Processes

Це цікаво, щоб знайти процеси, які керують мережевими даними:

dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >> recv.log
#wait some time
sort -u recv.log > procs.txt
cat procs.txt

Або використовуйте netstat або lsof

Libgmalloc

lldb -o "target create `which some-binary`" -o "settings set target.env-vars DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib" -o "run arg1 arg2" -o "bt" -o "reg read" -o "dis -s \$pc-32 -c 24 -m -F intel" -o "quit"

Fuzzers

Працює для CLI інструментів

Він "просто працює" з macOS GUI інструментами. Зверніть увагу, що деякі macOS додатки мають специфічні вимоги, такі як унікальні імена файлів, правильне розширення, необхідність читати файли з пісочниці (~/Library/Containers/com.apple.Safari/Data)...

Деякі приклади:

# iBooks
litefuzz -l -c "/System/Applications/Books.app/Contents/MacOS/Books FUZZ" -i files/epub -o crashes/ibooks -t /Users/test/Library/Containers/com.apple.iBooksX/Data/tmp -x 10 -n 100000 -ez

# -l : Local
# -c : cmdline with FUZZ word (if not stdin is used)
# -i : input directory or file
# -o : Dir to output crashes
# -t : Dir to output runtime fuzzing artifacts
# -x : Tmeout for the run (default is 1)
# -n : Num of fuzzing iterations (default is 1)
# -e : enable second round fuzzing where any crashes found are reused as inputs
# -z : enable malloc debug helpers

# Font Book
litefuzz -l -c "/System/Applications/Font Book.app/Contents/MacOS/Font Book FUZZ" -i input/fonts -o crashes/font-book -x 2 -n 500000 -ez

# smbutil (using pcap capture)
litefuzz -lk -c "smbutil view smb://localhost:4455" -a tcp://localhost:4455 -i input/mac-smb-resp -p -n 100000 -z

# screensharingd (using pcap capture)
litefuzz -s -a tcp://localhost:5900 -i input/screenshared-session --reportcrash screensharingd -p -n 100000

Більше інформації про Fuzzing MacOS

Посилання

Підтримати HackTricks

Last updated