LINUX.ORG.RU

Подключить свою библиотеку либо расширить секцию кода?

 , ,


0

2

Добрый день, подскажите пожалуйста , имеется библиотеки - shared library под ARM, с расширением so. В это библиотеке перезаписал несколько функций на свои, все работает отлично, теперь понадобилось добавить еще несколько функций, но места в секции .text не хватает(много не хватает). Я так понимаю что раз это готовая слинкованная либа, то уже мало что может помочь? Пробовал добавить свою секцию (objcopy), секцию добавил, но все остальное съехало (видимо можно только в объектный файл добавлять) Исходников естественно нет, пересобрать либу полностью не могу, вижу только один выход: написать свою «so» с нужными функциями, которые вызывать из уже существующей библиотеки. Но возможно ли в текущей либе руками прописать загрузку и вызов функций из новой, получится такое сделать без пересборки?

Код в текущей библиотеке правил с помощью IDA, сейчас все работает, но требуется переделка, а места не хватает, как можно решить такую задачу?


Можно вставить динамическую загрузку библиотеки в одну из существующих функций.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Как раз это и имею ввиду. Смотрю в текущей либе имеются и используюстя функции dlopen, dlsym, думаю это как раз то-что надо, только вот пока не писал никогда библиотеки, только небольшие программы под gcc (CodeBlock, Win, Ubuntu). В планах в свободное место текущей библиотеки, вставить код загрузки новой (пока не существ.), дальше вопрос - как использовать функции, аргументы и параметры из новой библиотеки. да и вообще много вопросов.

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 1)

если функция прописана в таблице символов, то ставишь размер и адрес 0 в ELF, и она будет искаться в других загруженных либах

SR_team ★★★★★
()
Последнее исправление: SR_team (всего исправлений: 1)

Пропатчить можно всё. Разберись как устроен формат .so, там вроде ничего сложного. Если секция кода в начале или в конце (по памяти) то её легко просто расширить (добавив байты в начало или в конец, чтобы смещения до данных не сбились), если в середине - думаю можно ещё одну исполняемую секцию с краю создать.

Если что, устройство .so ни разу не изучал, всё что выше - из общих соображений.

firkax ★★★★★
()
Ответ на: комментарий от Devill

Так же как и любые другие функции. Для большинства современных архитектур и соглашений о вызовах - посредством инструкции call или её аналога.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от firkax

Уже не первый день читаю, изучаю. Секция с кодом(. text) находится в середине, не получится ее расширить, я не смог по крайней мере, поэтому тут и спросил, кое какие данные добавил в секцию .rodara, пока работает, но больше не добавить туда. Пока изучаю как либы создавать на примерах

И кстати пытался добавить еще одну секцию с кодом, с помощью objcopy, она записалась и сдвинулось все остальное, видимо objcopy не умеет работать с такими данными, может я править не умею, но вариант со сторонней библиотекой вроде нравится.

Спасибо за отзывы

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 1)
Ответ на: комментарий от firkax

Он не то что сдвинул, после применения objcopy, он записал мою секцию кода поверх секций .symtab .strtab, попутно затер нулями такие как .data .bss что-то в этом роде.

Даже не стал проверять этот файл в работе, так как больше половины символов превратил в 00, на тот момент я и подумал что утилита работает только с объектными файлами, т.е. с кодом, могу ошибаться.

Добавлял таким методом: objcopy --add-section .sect=77.bin \ --set-section-flags .sect=code,contents,alloc,load,readonly \ lib.so newlib.so.

Плюс к этому выходной файл стал почти на 30Kb больше, хотя добавил всего 100 байт (для проверки)

Если подскажете как сделать правильно, буду благодарен, и не только на словах.

С Shared Library тоже пока не особо получается

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 6)
Ответ на: комментарий от Devill

Ну, я повторю, не изучал формат .so файлов, но скорее всего стал бы делать не через objcopy а вручную посмотрел его заголовки и подправил бы там нужные поля - тогда никаких непоняток с добавившимися 30кб или затёртыми данными не было бы. С виндовым PE такое вполне прокатывало давно.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Также как и вы стал сравнивать заголовки обеих файлов, хотел сравнить что изменилось. Думал в ручную добавить секцию.

Но изменения были только в трёх байтах, readelf показал что добавилась секция, вроде всё. Может конечно можно руками прописать, попробую еще почитать устройство elf.

Devill
() автор топика
Ответ на: комментарий от Devill

Три байта это явно мало для метаданных секции - у неё как минимум размер и смещение (а скорее два - в файле и в памяти), и какие-нить флаги, всё по 4 байта, итого 12-16 байт минимум. А скорее больше.

firkax ★★★★★
()
Ответ на: комментарий от pon4ik

Можно вставить динамическую загрузку библиотеки в одну из существующих функций.

Зачем динамическую? Элемент NEEDED в секцию .dynamic добавить куда проще. Есть даже command-line тулза.

dimgel ★★★★★
()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от firkax

Нашел как править и создавать свои секции. Создал секцию кода в конце библиотеки, занес туда некоторый код, сделал ссылку на него из оригинальной секции кода, в IDA все вроде нормально, запускаю отладчик и при переходе по ссылке -SegmentFault, и показывает что это секция BSS(Не иницилизированые данные), в общем убавил размер .BSS в таблице секций, снова в IDA все хорошо, а во время отладки Тоже-самое, видимо не только эта либа, но видимо и другие загружают свой .BSS сегмент по этому адресу, в общем пока не вижу выхода как «клепать» новую SO.

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 1)
Ответ на: комментарий от Devill

Добавь в начало. BSS не надо убавлять, это переменные.

В начало - всмысле сдвинь всё вперёд (на одинаковое количество байт в памяти) и на освободившееся место сделай новую секцию. В .so должен быть PIC-код, который от таких сдвигов не ломается. Не знаю бывают ли там relocations (динамические патчи для не-PIC кода) если бывают то их тоже придётся пропатчить.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от pon4ik

Спасибо всем, позже попробую эти варианты.

Подскажите, попробовал скомпилировать небольшой кусок кода в SO, получается не правильно видимо, так как IDA ругается:

This file contains non standart usage of relocations,

и почему-то нет разницы в выходном out.o файле, что так arm-none-eabi-gcc -fpic -c function.c, что без ключа -fPIC. По мануалам в сети - должна быть разница, пробую собирать так:

arm-none-eabi-gcc -fpic -c function.c

arm-none-eabi-gcc -shared -o function.so function.o

(откуда-то появляются «левые» функции: _start, bss_start, .init_proc, .term_proc )

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 2)
Ответ на: комментарий от firkax

Да как раз столкнулся с этим во время чтения манулов по компиляции коа для SHARED SO, используется ключ PIC (позиционно не зависимый) Попробую сегодня в начало вставить, посмотрю какие секции перед секцией . text

Devill
() автор топика
Ответ на: комментарий от Devill

В динамических ELF код не в секциях, а в сегментах. Если нет свободного места в Program Headers, можно попробовать завести свой исполняемый сегмент вместо GNU_STACK или другого пустого незагружаемого сегмента.

Но лучше не править бинарник, а попытаться управлять процессом динамической загрузки и связывания.

readelf -l /bin/sh
Elf file type is DYN (Shared object file)
Entry point 0x5cd0
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000004360 0x0000000000004360  R      0x1000
  LOAD           0x0000000000005000 0x0000000000005000 0x0000000000005000
                 0x00000000000127f5 0x00000000000127f5  R E    0x1000
  LOAD           0x0000000000018000 0x0000000000018000 0x0000000000018000
                 0x00000000000058f0 0x00000000000058f0  R      0x1000
  LOAD           0x000000000001df30 0x000000000001ef30 0x000000000001ef30
                 0x0000000000001310 0x0000000000003f40  RW     0x1000
  DYNAMIC        0x000000000001eb08 0x000000000001fb08 0x000000000001fb08
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  NOTE           0x0000000000000358 0x0000000000000358 0x0000000000000358
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_PROPERTY   0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  GNU_EH_FRAME   0x0000000000019f44 0x0000000000019f44 0x0000000000019f44
                 0x0000000000000804 0x0000000000000804  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
vM ★★
()
Последнее исправление: vM (всего исправлений: 1)
Ответ на: комментарий от Devill

Если через IDA правил, то она не применяет патчи ELF, только к коду/данным. Тоже с этим сталкивался, когда надо было завернуть внутрь либы функции, которых нет в libc - пришлось писать патчер.

SR_team ★★★★★
()
Ответ на: комментарий от SR_team

Правил с помощью IDA PRO, после применения правок(поменял пару функций на свои), файл хорошо работает по сей день.

Написал тестовую либу с одной функцией, пытаюсь ее загрузить в память при помощи текущей (рабочей) либы, выдает ошибку:

«has unexpected e_type»

Readelf показывает тип библиотеки: REL (Relocation), а надо такой тип: DYN (Shared object file)

Как собрать такой тип не могу понять. При компиляции использую ключи: -fPIC, shared

Скорее всего и ошибка открытия(загрузки), когда пытаюсь загрузить её из по андроид.

readelf -l - показывает НОЛЬ программных сегментов

readelf -S - показывает 10 секций (text, data, bss, symtab, strtab и т.д.)

Devill
() автор топика
Последнее исправление: Devill (всего исправлений: 1)
Ответ на: комментарий от anonymous

Все верно, нашёл у себя небольшой «косяк», компилировал с ключём ‘-c’, убрал его, теперь все хорошо, либа создаётся и загружается в память.

Увеличение основой библиотеки пока не стал проверять.

Devill
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.