- Как открыть и изучить Mach-O файл на macOS, как если бы ты работал с PE-файлом в Windows
- Что тебе нужно: инструменты, которые уже есть
- Шаг 1: Найди настоящий бинарник — не .app
- Шаг 2: Понимай структуру — как PE, но по-маковски
- Шаг 3: Импорты и экспорты — где они?
- Шаг 4: Динамический линковщик — твой новый друг
- Сравнение: PE vs Mach-O — что где искать
- Частые ошибки — и как их избежать
- Что выбрать в зависимости от ситуации
- Как лучше делать — практические рекомендации
- Итог: что делать прямо сейчас
Как открыть и изучить Mach-O файл на macOS, как если бы ты работал с PE-файлом в Windows
Ты — разработчик, который привык к IDA Pro, Ghidra или Binary Ninja на Windows, и тебе нужно разобраться с macOS-приложением. Ты знаешь, как читать PE-заголовки, искать секции .text и .data, находить импорты и анализировать вызовы API. А теперь — Mach-O. Ничего не похоже. Нет «PE заголовка», нет «Import Address Table». Ты чувствуешь, как будто перешёл в чужую вселенную. Не паникуй. Это не магия. Это просто другой формат. И если ты умеешь читать PE, ты уже умеешь читать Mach-O. Просто нужно перевести язык.
В этой статье я покажу, как открыть Mach-O файл так, как ты бы открыл PE. Без лишней теории. Только то, что нужно, чтобы начать анализировать бинарник на macOS прямо сейчас.
Что тебе нужно: инструменты, которые уже есть
Если ты работаешь с PE-файлами, ты, скорее всего, используешь:
- IDA Pro
- Ghidra
- Binary Ninja
- objdump / dumpbin / x64dbg
Хорошие новости: все эти инструменты работают с Mach-O без дополнительной настройки. Да, ты не ошибся. IDA Pro открывает .app/Contents/MacOS/YourApp без вопросов. Ghidra — тоже. Binary Ninja — отлично. Ты не должен учиться заново. Ты просто должен понять, как названия и структуры изменились.
Если ты не используешь ни один из них — установи Ghidra. Бесплатно, от NSA, поддерживает Mach-O на уровне PE. Или используй objdump из Xcode Command Line Tools — он есть на любом Mac с установленным Xcode.
Шаг 1: Найди настоящий бинарник — не .app
Ты скачал приложение. Открываешь папку — вижу MyApp.app. Пытаешься открыть его в IDA — не получается. Почему? Потому что .app — это не бинарник. Это пакет — директория с ресурсами, локализацией, Info.plist и, самое главное, бинарником внутри.
Путь к настоящему файлу:
/Applications/MyApp.app/Contents/MacOS/MyApp
Именно этот файл — Mach-O. Именно его нужно открывать. Это аналог myapp.exe в Windows. Не пытайся открыть Info.plist или Resources/ в Ghidra — они не бинарные. Если ты не знаешь, где бинарник — открой терминал и введи:
find /Applications/MyApp.app -type f -perm +111 -name "*"
Это найдёт все исполняемые файлы внутри пакета. Обычно их один — и он лежит в MacOS/.
Шаг 2: Понимай структуру — как PE, но по-маковски
PE-файл начинается с DOS-заголовка, потом — PE-заголовок, потом — секции (.text, .data, .rdata). Mach-O — другая логика. Но структура та же: заголовок → сегменты → секции.
В PE:
IMAGE_NT_HEADERS— заголовокIMAGE_SECTION_HEADER— описание секций- Секции — .text, .data, .rdata
В Mach-O:
mach_header_64— заголовок (вместоIMAGE_NT_HEADERS)load_command— команды загрузки (вместо таблицы секций)- Сегменты —
__TEXT,__DATA,__LINKEDIT - Секции внутри сегментов —
__text,__data,__bss
Ключевое отличие: в PE секции — это основа. В Mach-O — сегменты. Секции — это подразделы сегментов. Например:
__TEXT— содержит исполняемый код (аналог .text)__DATA— переменные, инициализированные данные (аналог .data)__LINKEDIT— метаданные для динамического линковщика (аналог .idata + .edata в PE, но в одном месте)
Чтобы увидеть это в Ghidra: открой файл → в окне «Symbol Tree» найди «Segments». Там ты увидишь __TEXT, __DATA и т.д. Кликни на __TEXT → увидишь секции внутри: __text, __stubs, __cstring.
Это как если бы в PE ты видел не только .text, но и .rdata, .idata, .pdata внутри одного сегмента. Mach-O объединяет логику. Не пугайся — просто запомни: сегмент = контейнер, секция = часть контейнера.
Шаг 3: Импорты и экспорты — где они?
В PE ты ищешь Import Address Table (IAT) — там перечислены все функции из DLL. В Mach-O нет IAT. Есть dyld — динамический линковщик. И он работает иначе.
Импорты в Mach-O — это символы, которые бинарник запрашивает у системных библиотек. Их можно найти в двух местах:
- Символы импорта — в секции
__stubsи__stub_helperвнутри__TEXT. Там лежат маленькие «переходники» — они вызываютdyld, чтобы найти реальную функцию. - Список библиотек — в команде
LC_LOAD_DYLIB. Ты можешь увидеть их в Ghidra: «Symbol Table» → «Imported Symbols». Там будут строки вроде_NSLog,_objc_msgSend,_pthread_create.
Чтобы посмотреть, какие библиотеки подключены — в терминале:
otool -L /Applications/MyApp.app/Contents/MacOS/MyApp
Вывод:
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 2113.20.115)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
Это твой аналог dumpbin /imports в Windows. Только здесь ты видишь не адреса, а имена библиотек.
Экспорты — это функции, которые сама библиотека предоставляет другим. В Mach-O они тоже в __LINKEDIT. В Ghidra: «Symbol Table» → «Exported Symbols». В терминале:
nm -g /Applications/MyApp.app/Contents/MacOS/MyApp
Вывод будет вида:
0000000100001234 T _main
0000000100002345 T _initializeApp
0000000100003456 T _handleClick
Буква T — значит, символ экспортируется (текстовая секция). U — неопределённый (импорт). Просто как в PE, но без таблиц.
Шаг 4: Динамический линковщик — твой новый друг
В Windows ты видишь, как kernel32.dll подгружается в память. В macOS всё делает dyld. Он загружает библиотеки, разрешает адреса, заполняет таблицы вызовов — всё автоматически.
Чтобы увидеть, как он работает — используй dyld в режиме отладки. В терминале:
export DYLD_PRINT_LIBRARIES=1
/Applications/MyApp.app/Contents/MacOS/MyApp
Ты увидишь, какие библиотеки загружаются, в каком порядке. Это как Process Monitor для загрузки DLL, но для macOS.
Если ты хочешь понять, как работает линковка на уровне байтов — открой секцию __LINKEDIT в Ghidra. Там лежит бинарный «словарь»: имена функций, адреса, таблицы хеширования. Это как IAT, но сжато и с хешами. Ты не будешь читать это вручную — Ghidra сделает это за тебя. Но если ты видишь, что в __LINKEDIT есть огромный блок данных — это нормально. Это не вирус, это метаданные линковщика.
Сравнение: PE vs Mach-O — что где искать
Вот таблица, которая поможет тебе быстро переключиться с Windows на macOS.
| Что ты ищешь в PE | Где искать в Mach-O | Команда в терминале |
|---|---|---|
| PE-заголовок | mach_header_64 в начале файла |
otool -h /path/to/binary |
| Секции (.text, .data) | Сегменты __TEXT, __DATA с секциями внутри |
otool -l /path/to/binary |
| Import Address Table (IAT) | Символы в __stubs и __stub_helper; список библиотек в LC_LOAD_DYLIB |
otool -I /path/to/binary |
| Экспорты | Символы с флагом T в __TEXT |
nm -g /path/to/binary |
| Ресурсы (ICO, DLL, строковые таблицы) | Внутри .app/Contents/Resources/ — это не бинарник |
ls /Applications/MyApp.app/Contents/Resources/ |
| Стек, куча, импорты в отладчике | То же самое — Ghidra/IDA показывают память одинаково | — |
Запомни: если ты ищешь импорты — смотри на otool -I и nm -u. Если ищешь экспорты — nm -g. Если хочешь увидеть структуру — otool -l. Все команды есть в macOS по умолчанию, если установлены Xcode Command Line Tools.
Частые ошибки — и как их избежать
- Открываешь .app как файл — не работает. Открывай только
Contents/MacOS/YourApp. - Ищешь .idata — её нет. Ищи
__stubsиLC_LOAD_DYLIB. - Думаешь, что __LINKEDIT — это вредоносный код — нет, это просто метаданные линковщика. Там нет исполняемого кода, только структуры.
- Не видишь функций в Ghidra — возможно, бинарник оптимизирован. Попробуй включить «Auto Analysis» с опцией «Create Functions». Иногда нужно вручную указать начало функции (клик правой кнопкой → «Create Function»).
- Используешь Windows-инструменты вроде x64dbg — они не работают с Mach-O. Используй только те, что поддерживают macOS (IDA, Ghidra, Binary Ninja).
Что выбрать в зависимости от ситуации
Ты не всегда хочешь глубокий анализ. Иногда нужно просто понять, что делает приложение.
- Ты просто хочешь посмотреть, какие библиотеки использует приложение? →
otool -L— 2 секунды, ничего не устанавливать. - Ты хочешь найти, где вызывается
NSAlertилиCFNetwork? → Открой Ghidra → ищи в «Symbol Table» по ключевому слову. Удобно, быстро, без реверсинга всего. - Ты разбираешь вредоносное ПО и ищешь вызовы
system()илиexecve()? → Используй IDA Pro или Binary Ninja. Они лучше показывают контроль потока и вызовы функций. Ghidra — тоже подойдёт, но медленнее. - Ты хочешь быстро посмотреть, есть ли в бинарнике строки вроде «https://» или «localhost»? →
strings /path/to/binary | grep -i "http"— это работает и на Mach-O, как и на PE. - Ты хочешь понять, как работает динамическая загрузка (dlopen)? → Открой Ghidra, найди вызовы
_dlopen,_dlsym— это означает, что приложение загружает библиотеки на лету. Это часто используется в плагинах или для обфускации.
Как лучше делать — практические рекомендации
- Всегда начинай с
otool -L— это твой первый шаг. Как если бы ты сначала смотрел, какие DLL подгружает PE-файл. - Используй Ghidra для первого анализа — он бесплатный, хорошо разбирает Mach-O, и не требует лицензии. IDA Pro — мощнее, но платный. Если ты не делаешь это профессионально — Ghidra хватит.
- Не пытайся читать __LINKEDIT вручную — он не для людей. Он для dyld. Ты можешь его «увидеть» в Ghidra, но не читай байты — он закодирован.
- Проверяй, не обфусцирован ли бинарник — если ты видишь только
__textи нет имён функций, а в__LINKEDITмного непонятных данных — возможно, приложение защищено (например, черезobfuscatorилиLLVMс оптимизацией). В этом случае используйstringsи ищи ключевые слова. - Если ты видишь много сегментов с именами вроде
__AUTH_или__RESTRICT— это не ошибка. Это современные механизмы защиты (SIP, Code Signing). Они не мешают анализу, но могут ограничивать модификацию.
Итог: что делать прямо сейчас
Ты получил бинарник на macOS. Что делать?
- Найди настоящий файл:
/Applications/MyApp.app/Contents/MacOS/MyApp - В терминале:
otool -L /path/to/binary— посмотри, какие библиотеки используются - Открой Ghidra → загрузи этот файл → дождись анализа
- В окне «Symbol Table» найди импорты (символы с «U») и экспорты (с «T»)
- Перейди в сегмент
__TEXT→ секция__text→ ищи функции по именам (например,_main) - Если нужно — используй
nm -gиstringsдля быстрого поиска
Ты не учишь новую систему. Ты просто переводишь привычные понятия с Windows на macOS. Импорты — это не IAT, а символы в __stubs. Секции — это не отдельные блоки, а части сегментов. Загрузка — это не LoadLibrary, а dyld. Но логика та же: ты ищешь, откуда берутся функции, куда они ведут, и что делает код.
Сделай это один раз — и ты будешь чувствовать себя как дома. Mach-O — не враг. Это просто другой язык. А ты уже знаешь, как читать по-английски. Теперь научишься читать по-маковски.
Информация в этой статье предназначена для образовательных и исследовательских целей. Анализ программного обеспечения без разрешения владельца может нарушать законы и условия использования. Всегда действуй в рамках законодательства и этических норм.
