Расширить раздел в файле Mach-O - PullRequest
1 голос
/ 18 апреля 2020

Я пытаюсь извлечь библиотеки из Dyld_shared_cache, и мне нужно исправить их во внешних ссылках.

Например, указатели в разделе __DATA.__objc_selrefs обычно указывают на данные вне файла mach-o, чтобы исправить то, что мне пришлось бы скопировать соответствующую c -строку из поля и добавить ее в раздел __TEXT.__objc_methname.

Хотя из моего понимания формата файла Mach-O это расширение __TEXT.__objc_methname сместит все разделы после него и заставит меня исправить все смещения и указатели, которые на них ссылаются. Есть ли способ добавить данные в раздел, не ломая много вещей?

Спасибо!

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Спасибо @ Kamil.S за идею добавления новой команды загрузки и раздела.

Одним из способов добавления дополнительных данных в раздел является создание дублирующего сегмента и раздела и вставка его перед __LINKEDIT сегмент.

  • Сдвиньте сегмент __LINKEDIT, чтобы у нас было место для добавления нового раздела.
    1. определяет количество слайдов, оно должно быть выровнено по странице, поэтому я выбираю 0x4000.
    2. добавьте количество слайдов к соответствующим командам загрузки, это включает, но не ограничивается:
      • __ Сегмент LINKEDIT (duh)
      • dyld_info_command
      • symtab_command
      • dysymtab_command
      • relatedit_data_commands
    3. физически перемещаться __LINKEDIT в файле.
  • продублируйте раздел и измените следующий размер 1
    • , должен быть длиной ваших новых данных.
    • addr, должно быть в свободном пространстве.
    • смещение, должно быть в свободном пространстве.
  • дублировать сегмент и изменить следующее 1
    • fileoff, должен быть началом свободного пространства.
    • vmaddr, должен быть началом свободного пространства.
    • размер файла, все что угодно так как он больше ваших данных.
    • vmsize, должен совпадать с размером файла.
    • nsects, измените, чтобы отразить, сколько разделов вы добавляете.
    • cmdsize, измените, чтобы отразить размер команды сегмента и команд его секций.
  • вставьте дублированный сегмент и разделы перед сегмент __LINKEDIT
  • обновляет заголовок mach_header
    • ncmds
    • sizeofcmds
  • физически записывать дополнительные данные в файл.

  1. вы можете при желании изменить поля имени и имени сегмента, хотя в этом нет необходимости. спасибо Kamil.S!
1 голос
/ 19 апреля 2020

ОБНОВЛЕНИЕ
После выяснения с помощью OP, что расширение __TEXT.__objc_methname произойдет во время последующей обработки Mach-O существующего исполняемого файла, у меня был свободный sh взгляд на проблему.

Другим вариантом будет создание новой команды загрузки LC_SEGMENT_64 с новой __TEXT_EXEC.__objc_methname записью сегмента / раздела (обычно __TEXT_EXEC используется для некоторых вещей ядра, но по сути это то же самое, что __TEXT ). Вот краткое ПО C, чтобы проиллюстрировать концепцию:

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        printf("%lx",[NSObject new]);
    }
    return 0;
}

Компилировать так:

gcc main.m -c -o main.o 
ld main.o -rename_section __TEXT __objc_methname __TEXT_EXEC __objc_methname -lobjc -lc 

Интересно, что только ld до Высокой Сьерры 10.14.6 генерирует __TEXT.__objc_methname, на Каталине нет никаких следов, все сделано по-другому.

UPDATE2 .
Играя с этим, я заметил права на выполнение для сегмента __TEXT ( и __TEXT_EXEC в этом отношении) не требуются для __objc_methname для работы. Более того, c имена сегментов и разделов не требуются:
Я мог бы выполнить:

__DATA.__objc_methname   
__DATA_CONST.__objc_methname 
__ARBITRARY.__arbitrary 

или, в моем случае, последний __DATA раздел
__DATA.__objc_classrefs, где оригинал данные объединяются по имени селектора. Все в порядке, пока есть правильная строка с нулевым символом C с именем селектора. Если я намеренно сломаю «new \ 0» в шестнадцатеричном редакторе или MachOView, я получу

"+[NSObject ne]: unrecognized selector sent to instance ..."

при запуске моего исполняемого файла PO C, так что значение будет использовано наверняка.

Таким образом, для суммирования __TEXT.__objc_methname самого раздела, скорее всего, есть подсказка отладчика, сделанная компоновщиком. Кажется, во время выполнения приложения нужны только имена селекторов в виде char* в любом месте памяти.

...