Категория > Новости > Липосакция для fat binary. Ломаем программу для macOS с поддержкой нескольких архитектур - «Новости»

Липосакция для fat binary. Ломаем программу для macOS с поддержкой нескольких архитектур - «Новости»


9-10-2021, 00:02. Автор: Капитолина
Мы мно­го раз писали о взло­ме прог­рамм для Windows. Для нее соз­дано мно­жес­тво отладчи­ков, дизас­сем­бле­ров и дру­гих полез­ных инс­тру­мен­тов. Сегод­ня же мы обра­тим взор на муль­тип­роцес­сорную прог­рамму для macOS, вер­нее, на пла­гин для маков­ско­го Adobe Illustrator CC 2021, который (в целях обу­чения!) будет прев­ращен из проб­ной вер­сии в пол­ноцен­ную. При­чем понадо­бят­ся нам исклю­читель­но инс­тру­мен­ты для Windows: IDA вер­сии 7.2 и Hiew.

warning


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



 

Немного теории


Для начала корот­ко попыта­емся получить пред­став­ление, что имен­но нам пред­сто­ит ломать. Мы уже при­вык­ли, что все исполня­емые фай­лы и биб­лиоте­ки под акту­аль­ные вер­сии Windows име­нуют­ся EXE/DLL и име­ют струк­туру MZ-PE. Под macOS исполь­зует­ся фор­мат Mach-O (сок­ращение от Mach object), явля­ющий­ся потом­ком фор­мата a.out, который макось унас­ледова­ла от Unix.


Как извес­тно, Apple любит пери­оди­чес­ки перехо­дить с одно­го семей­ства про­цес­соров на дру­гое, из‑за чего меня­ется и архи­тек­тура при­ложе­ний. Начав с PowerPC, Apple в середи­не нулевых перемет­нулась в стан Intel, пос­ле чего в недав­нем прош­лом кор­порация решила перей­ти на плат­форму ARM. Дабы поль­зовате­ли помень­ше стра­дали от подоб­ных метаний, был взят на воору­жение муль­тип­роцес­сорный фор­мат Fat binary («жир­ный бинар­ник»), который может содер­жать код одновре­мен­но под нес­коль­ко про­цес­соров. Такой модуль может работать как под Intel, так и под ARM.


Что же такое модуль Mach-O? Обыч­но он сос­тоит из трех областей. Заголо­вок содер­жит общую информа­цию о дво­ичном фай­ле: порядок бай­тов (магичес­кое чис­ло), тип про­цес­сора, количес­тво команд заг­рузки и т. д. Затем сле­дуют коман­ды заг­рузки — это сво­его рода оглавле­ние, которое опи­сыва­ет положе­ние сег­ментов, динами­чес­кую таб­лицу сим­волов и про­чие полез­ные вещи. Каж­дая коман­да заг­рузки содер­жит метадан­ные, такие как тип коман­ды, ее имя, позиция в дво­ичном фай­ле. Наконец, третья область — это дан­ные, обыч­но самая боль­шая часть объ­ектно­го фай­ла. Она содер­жит код и раз­личную допол­нитель­ную информа­цию.


Муль­тип­роцес­сорный «жир­ный» модуль может вклю­чать в себя нес­коль­ко обыч­ных модулей Mach-O, заточен­ных под раз­ные про­цес­соры (обыч­но это i386 и x86_64, ARM или ARM64). Струк­тура его пре­дель­но прос­та — сра­зу за Fat header, в котором опи­сыва­ются вхо­дящие в модуль бло­ки Mach-O, сле­дует код этих бло­ков, рас­положен­ный под­ряд. Я не буду под­робно оста­нав­ливать­ся на опи­сании всех сек­ций и полей дан­ного фор­мата, жела­ющие могут лег­ко нагуг­лить спе­цифи­кацию. Оста­новим­ся лишь на фор­мате заголов­ков, пос­коль­ку они понадо­бят­ся нам в даль­нейших дей­стви­ях.


Струк­тура клас­сичес­кого заголов­ка Mach-O выг­лядит так.


struct mach_header {
// Сигнатура, обычно CF FA ED FE или CE FA ED FE, но для варианта с обратным порядком байтов, возможна и обратная сигнатура FE ED FA CF
uint32_t magic;
// Тип процессора, для intel это 7, для ARM С
cpu_type_t cputype;
// Подтип процессора, 1 означает 64-разрядность, например, 07000001h x86_64
cpu_subtype_t cpusubtype;
// Тип файла
uint32_t filetype;
// Количество команд, следующих за хидером
uint32_t ncmds;
// Размер команд, следующих за хидером
uint32_t sizeofcmds;
// Набор битовых флагов, которые указывают состояние некоторых дополнительных функций формата файла Mach-O
uint32_t flags;
};

«Жир­ный заголо­вок» пред­став­ляет собой типич­ный заголо­вок Universal binary и выг­лядит вот так.


struct fat_header {
uint32_t magic; // 0BEBAFECAh
// Количество последующих блоков fat_arch, соответствующих поддерживаемым процессорам
uint32_t nfat_arch;
};
struct fat_arch {
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
// Смещение до блока кода относительно начала файла
uint32_t offset;
// Длина соответствующего блока кода
uint32_t size;
// Выравнивание
uint32_t align;
};
struct fat_arch {
...
}
Липосакция для fat binary. Ломаем программу для macOS с поддержкой нескольких архитектур - «Новости»
Струк­тура заголов­ка Mach-O

Ну а теперь, ког­да мы в дос­таточ­ной сте­пени воору­жились теорией, рас­смот­рим прак­тичес­кий при­мер. У нас есть некий инстал­лирован­ный иллюс­тра­торов­ский пла­гин, который тре­бует­ся оту­чить от суици­да по про­шес­твии три­аль­ного пери­ода. Пред­положим так­же, что дос­тупа к маку, на котором он уста­нов­лен, у нас нет, как и дру­гого мака под рукой — толь­ко воз­можность перепи­сывать фай­лы. Ищем в пап­ке нуж­ного пла­гина под­папку ContentsMacOS, а в ней — исполня­емый модуль пла­гина. В дан­ном слу­чае это динами­чес­кая биб­лиоте­ка Fat Mach-O file, о чем нам говорит сиг­натура CA FE BA BE.



Перейти обратно к новости