LINUX.ORG.RU

Пропатчить бинарник (с помошью objcopy или ещё как)


0

2

Есть закрытый драйвер (ELF для Солярис/спарк, но это скорее всего, не принципиально), содержащий примерно такой код:

static struct type_a struct1 = {
        1,
        func1_from_other_module,
        static_func2,
};
static struct type_b struct2 = {
/* Тут тоже полно ссылок на локальные и внешние фукции */
};

Как посредством objcopy (или ещё чего) сделать что-нибудь из следующего:

  • поменять в struct1 ссылку static_func2 на func2_from_other_module ?
  • зарезервировать место между struct1 и struct2 ?
  • или перенести struct1 в конец файла (и обновить ссылки на неё)?

Второй-третий пункт опциональны. Просто, в новой версии соляры, type_a cущественно расширился, и теперь структуры наползают друг на друга. К счастью, пожертвовав некоторой функциональностью на это забить, но лучше сделать всё чисто.

★★★★★

1 - находишь смещение и меняешь (думаю, можно тупо искать 32-битовое слово с адресом func1_from_other_module); 2 и 3 - никак.

И cast XVilka

tailgunner ★★★★★
()
Ответ на: комментарий от alt-x

Думаю, что все.

Делается просто - пишешь обертку, использующую вызовы нового API. Она должна вызывать функции закрытого модуля. Их можно переименовать с помощью objcopy. В обертке уже заполняешь структуры как надо.

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

(это все можно сделать - я портировал закрытый модуль с Linux-2.4 на Linux-2.6)

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

Так и пытался делать сначала. Найти-то я его нашел. Вписал ожидаемое значение. Начал грузить - оба на, там совсем другое написано. Понял, что слишком мало знаю про ELF. Посмотрел бинарник objdump'ом. Задумался.

Проблема в том, что мне надо поменять локальную фукцию на глобальную. При этом, насколько я понимаю, можно (т.е. фактически даже нужно) вписать не адрес func2_from_other_module, а символ. Но как?

alt-x ★★★★★
() автор топика
Ответ на: комментарий от slapin

А, вон какую обёртку. Да, это вариант. Трудность в том, что практически все функции закрытого модуля - static, а наружу видны как раз таки через struct1 и struct2. Как сделать их видимыми для обёртки?

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

использовать указатели на функции, не? И да, для таких вещей удобен либо eresi (не развивается), либо radare (активно развивается)

XVilka ★★★★★
()
Ответ на: комментарий от alt-x

Собственно можно попробовать использовать ld. Пишем тупой файл:

static super_static_somthing = 123; // нужена инициализация если хотим в .data

super_global pointer = &super_static_something;

Компилируем и прилинковываем к тому что есть.
Как результат имеем глобальный символ который смотрит куда-то в .data (или .bss без инициализации) и relocation-запись для инициализации указателя. Аккуратно рихтуем оную запись дабы глядела куда положено (struct1 например). Далее пользуемся ей извне.

io ★★
()
Ответ на: комментарий от alt-x

Проблема в том, что мне надо поменять локальную фукцию на глобальную.

Думаю, нет - если в программе берется адрес статической функции, она уже мало отличается от глобальной.

Не знаю, как там в Солярисе, но в Linux у меня вполне срабатываает мой тупой подход - найти в .data адрес функции и заменить ее. Правда, это обычная userspace-программа.

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

И это существенно. Модуль же перемещаемый.

Поэтому абсолютный адрес ставить опасно - его же рихтуют на ходу (что и наблюдается). Самое правильное использовать скрипт ld для обеспечения доступа. Там же можно просто прописать, например, в .data-секции требуемое смещение для нового глобального символа, аналогично для функций и т.п. Линковать с -r - даже размер почти не поменяется.

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

Модуль же перемещаемый.

Значит, нужно вкрячить не абсолютный адрес, а смещение, и прописать relocation (хотя relocation уже должен быть).

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

func1_from_other_module встречается дважды в выводе objdump -x, a static_func2 - только один раз

SYMBOL TABLE:
[...]
0000000000000200 l     F .text  0000000000000018 static_func2
0000000000000000       F *UND*  0000000000000000 func1_from_other_module
[...]
RELOCATION RECORDS FOR [.data]:
OFFSET           TYPE              VALUE
00000000000000a0 R_SPARC_64        func1_from_other_module

Как добавить relocation? В доках на objcopy описано, как добавить секцию, но я не вижу как добавить что-то в существующую секцию...

И заодно, смещение 0xa0 - оно относительно чего?

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

Можно подумать, что объектный файл не elf. elf к elf-у вот и модуль, вот и разделяемая библиотека или программа. И все они тоже варианты elf-а, которые вполне можно использовать в следующей сборке. Особенно с использованием -r.

io ★★
()
Ответ на: комментарий от alt-x

Написано же RELOCATION RECORDS FOR [.data], значит от .data.

В большинстве процессоров есть команды для передачи управления по адресу с некоторым смещением относительно текущего. Это позволяет делать перемещаемый код и минимизировать количество relocation-записей.

Кроме того, если функция локальная, то как правило relocation-записи присутствуют часто не в форме имя_функции, a в виде .text+смещение,
надо проверить на что-то в стиле, .text+0x200.
Но таких может не быть (см. выше), если нужно подменить вызов, то сначала находится фрагмент, смотрим можно ли его просто поменять.
Если нельзя, то в конец .text можно подлинковать операции передачи управления (не call) к внешней процедуре (заодно появится relocation-запись),
затем в команде передачи управления по относительному адресу рихтуем смещение. Получаем было:
...
call local
...

будет:

....
call new_local
....

new_local:
jmp внешная_функция

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