Что такое трюк LD_PRELOAD?

342

Я недавно натолкнулся на упоминание о нем на proggit, и (на данный момент) это не объясняется.

Я подозреваю, что это может быть так, но я точно не знаю.

Хэнк Гей
источник
1
На самом деле это не ответ, поэтому я не буду публиковать его как один, но ... Стивен Келл использует LD_PRELOAD для своей библиотеки liballocs в этом видео, и если вы посмотрите предыдущие биты, вы сможете лучше понять, как и почему. Похоже, что liballocs используется, чтобы другие динамические языки могли общаться друг с другом. В этом разговоре объясняются некоторые глубокие внутренние аспекты. youtu.be/LwicN2u6Dro?t=24m10s
Элайджа Линн

Ответы:

415

Если вы укажете LD_PRELOADпуть к общему объекту, этот файл будет загружен до любой другой библиотеки (включая среду выполнения C libc.so). Итак, чтобы запустить lsвашу специальную malloc()реализацию, сделайте это:

$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls
JesperE
источник
12
Я понятия не имел, что это существует ... кажется, что это будет основным вектором для атак безопасности. Есть идеи, как это обеспечить?
rmeador
141
Это обеспечивается тем фактом, что загрузчик будет игнорировать LD_PRELOAD в случае ошибки! = Euid - Джошуа
Джошуа
18
@ Джошуа: что такое руид и эуид?
heinrich5991
20
@ heinrich5991 Реальные и эффективные идентификаторы пользователей: lst.de/~okir/blackhats/node23.html
gsingh2011
59
Помните одну важную вещь: обычно вы хотите указать абсолютный путь к LD_PRELOAD. Причина в том, что, будучи переменной среды, она наследуется дочерними процессами, которые могут иметь рабочий каталог, отличный от родительского процесса. Таким образом, любой относительный путь не сможет найти библиотеку для предварительной загрузки.
Фрерих Раабе
49

Вы можете переопределить символы в стандартных библиотеках, создав библиотеку с такими же символами и указав библиотеку в LD_PRELOAD.

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

Джошуа
источник
17
«Некоторые люди используют его для указания библиотек в нестандартных местах» ... Правда? Звучит как "Некоторые люди используют это неправильно"!
Том
6
LD_PRELOAD может в силу порядка загрузки перехватывать заданные приложением жестко заданные пути.
Джошуа
1
Было бы неправильным предварительно загружать другую версию библиотеки - предполагая, что они совместимы?
z0r
2
Я видел, что он использовался для загрузки отладочного или инструментального варианта или для загрузки библиотеки, которая делает что-то совершенно радикально отличающееся от базовой библиотеки, как будто для эмуляции какой-либо другой системы.
Джошуа
1
В случае, если библиотеки не скомпилированы правильно (используется, чтобы сталкиваться с этим с помощью mysql все время, когда он имел слабую связь с универсальным libmysql_client, который перезаписывал символическую ссылку более старой версии - в зависимости от того, какую версию perl вы использовали, вы должны были указать / Force это с помощью LD_PRELOAD .. полезный трюк. Если я правильно помню, valgrind использует эту технику для обеспечения возможности отладки для двоичных файлов без необходимости перекомпиляции ... это очень полезно.
synthesizerpatel
37

С LD_PRELOADпомощью библиотеки вы можете отдавать приоритет.

Например, вы можете написать библиотеку, которая реализует mallocи free. И, загрузив их с LD_PRELOADвашими mallocи freeбудут выполнены, а не стандартные.

Ронни Брендель
источник
а что если программа использует calloc? разве это не все испортит?
Янус Троелсен
7
@JanusTroelsen, если библиотека, которую вы пишете, не реализует определенную часть, эта часть будет загружена из исходной библиотеки.
Вудроу Барлоу
@JanusTroelsen, другими словами, LD_PRELOAD позволяет вам указать, какая реализация конкретного символа будет использоваться. Если предварительно загруженная библиотека не экспортирует символ, он будет найден в другом месте.
sherrellbc
1
@JanusTroelsen: Оказывается, что mallocи free специально спроектированы в glibc, чтобы позволить этому, и акции callocудается назвать ваши импортированные malloc. Не пытайтесь делать это с любыми другими функциями. Это не будет работать так хорошо.
Джошуа
30

Как уже упоминалось, многие используют LD_PRELOADпредварительную загрузку библиотеки. Кстати, вы можете проверить, если настройка доступна по lddкоманде.

Пример: предположим, вам нужно предварительно загрузить свой собственный libselinux.so.1.

> ldd /bin/ls
    ...
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3927b1d000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f3927914000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f392754f000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f3927311000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f392710c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3927d65000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f3926f07000)

Таким образом, установите вашу среду предзагрузки:

  export LD_PRELOAD=/home/patric/libselinux.so.1

Проверьте свою библиотеку еще раз:

>ldd /bin/ls
    ...
    libselinux.so.1 =>
    /home/patric/libselinux.so.1 (0x00007fb9245d8000)
    ...
Patric
источник
9

LD_PRELOADперечисляет общие библиотеки с функциями, которые переопределяют стандартный набор, так же как /etc/ld.so.preloadи. Они реализованы загрузчиком /lib/ld-linux.so. Если вы хотите переопределить только несколько выбранных функций, вы можете сделать это, создав переопределяющий объектный файл и настройки LD_PRELOAD; функции в этом объектном файле будут переопределять только те функции, которые оставят другие такими, какими они были.

Для получения дополнительной информации о посещении общих библиотек http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Раджеш
источник
3

Вот подробный пост в блоге о предварительной загрузке:

https://blog.cryptomilk.org/2014/07/21/what-is-preloading/

Asn
источник
13
Спасибо за публикацию вашего ответа! Обратите внимание, что вы должны опубликовать основные части ответа здесь, на этом сайте, иначе ваша публикация может быть удалена. См. Раздел часто задаваемых вопросов, где упоминаются ответы «едва ли больше, чем ссылка». Вы по-прежнему можете включить ссылку, если хотите, но только в качестве «ссылки». Ответ должен стоять самостоятельно, без необходимости ссылки.
Тарын
3

это легко экспортировать mylib.soв env:

$ export LD_PRELOAD=/path/mylib.so
$ ./mybin

отключить :

$ export LD_PRELOAD=
JulienGenoud
источник
7
илиunset LD_PRELOAD
Мортен
2

когда используется LD_PRELOAD, этот файл будет загружен до того, как будет загружена любая другая $export LD_PRELOAD=/path/libбиблиотека, даже это может быть использовано и в программах

Sumith Senarathne
источник
1

С помощью LD_PRELOAD путь, вы можете заставить загрузчик приложения загружать предоставленный общий объект сверх предоставленного по умолчанию.

Разработчики используют это для отладки своих приложений, предоставляя разные версии общих объектов.

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

dnahc araknayirp
источник