Jaka jest sztuczka LD_PRELOAD?

342

Niedawno natknąłem się na to odniesienie w proggit i (jak na razie) nie zostało to wyjaśnione.

Podejrzewam, że to może być to, ale nie jestem pewien.

Hank Gay
źródło
1
Naprawdę nie jest to odpowiedź, więc nie opublikuję tego jako jednego, ale ... Stephen Kell używa LD_PRELOAD do swojej biblioteki liballocs w tym filmie i jeśli obejrzysz poprzednie fragmenty, możesz lepiej zrozumieć, w jaki sposób / dlaczego. Wydaje się, że liballocs są używane, aby inne dynamiczne języki mogły ze sobą rozmawiać. W tej rozmowie wyjaśniono niektóre głębokie elementy wewnętrzne. youtu.be/LwicN2u6Dro?t=24m10s
Elijah Lynn

Odpowiedzi:

415

Jeśli ustawisz LD_PRELOADścieżkę do obiektu współdzielonego, plik ten zostanie załadowany przed każdą inną biblioteką (w tym środowiskiem uruchomieniowym C libc.so). Aby uruchomić lsspecjalną malloc()implementację, wykonaj następujące czynności:

$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls
JesperE
źródło
12
Nie miałem pojęcia, że ​​to istnieje ... wydaje się, że byłby to główny wektor ataków bezpieczeństwa. Masz pomysł, jak to jest zabezpieczone?
rmeador
141
Jest to zabezpieczone przez fakt, że moduł ładujący zignoruje LD_PRELOAD, jeśli ruid! = Euid - Joshua
Joshua
18
@Joshua: czym są ruid i euid?
heinrich5991
20
@ heinrich5991 Rzeczywiste i skuteczne identyfikatory użytkowników: lst.de/~okir/blackhats/node23.html
gsingh2011
59
Należy pamiętać o jednej ważnej rzeczy: zazwyczaj chcesz określić bezwzględną ścieżkę do LD_PRELOAD. Powodem jest to, że jest to zmienna środowiskowa, dziedziczone przez procesy potomne - które mogą mieć inny katalog roboczy niż proces macierzysty. Dlatego żadna ścieżka względna nie zlokalizowałaby biblioteki do wstępnego załadowania.
Frerich Raabe,
49

Można zastąpić symbole w bibliotekach podstawowych, tworząc bibliotekę z tymi samymi symbolami i określając bibliotekę w LD_PRELOAD.

Niektóre osoby używają go do określania bibliotek w niestandardowych lokalizacjach, ale LD_LIBRARY_PATHjest to lepsze w tym celu.

Jozuego
źródło
17
„Niektóre osoby używają go do określania bibliotek w niestandardowych lokalizacjach” ... Naprawdę? Brzmi jak „Niektórzy źle go używają”!
Tom
6
LD_PRELOAD może na podstawie kolejności ładowania przechwytywać określone przez aplikację ścieżki zakodowane na stałe.
Joshua
1
Czy niewłaściwe byłoby wstępne ładowanie innej wersji biblioteki - zakładając, że są one kompatybilne?
z0r
2
Widziałem, jak to było używane do ładowania debugowania lub oprzyrządowania, lub do ładowania biblioteki, która robi coś całkowicie radykalnie innego niż biblioteka podstawowa, tak jakby emulowała jakiś inny system.
Joshua
1
W przypadku, gdy biblioteki nie są poprawnie skompilowane (używane przez cały czas do uruchamiania z mysql, gdzie miał luźne sprzężenie z ogólnym libmysql_client, który nadpisał dowiązanie symboliczne starszej wersji - w zależności od używanej wersji perla trzeba było określić / force it LD_PRELOAD .. użyteczną sztuczką. Jeśli dobrze pamiętam, valgrind używa tej techniki, aby zapewnić możliwość debugowania plików binarnych bez konieczności ponownej kompilacji .. jest to całkiem przydatne.
synthesizerpatel
37

Dzięki LD_PRELOADniemu możesz dać bibliotekom pierwszeństwo.

Na przykład możesz napisać bibliotekę, która implementuje malloci free. I przez załadowanie ich ze LD_PRELOADswoim malloci freezostanie wykonany zamiast standardowych.

Ronny Brendel
źródło
ale co, jeśli program używa calloc? czy to by nie wszystko zepsuło?
Janus Troelsen
7
@JanusTroelsen, jeśli biblioteka, którą piszesz, nie implementuje określonej części, ta część zostanie załadowana z oryginalnej biblioteki.
Woodrow Barlow
@JanusTroelsen, Innymi słowy, LD_PRELOAD pozwala określić, która implementacja określonego symbolu ma być używana. Jeśli wstępnie załadowana biblioteka nie eksportuje symbolu, zostanie znaleziona w innym miejscu.
sherrellbc
1
@JanusTroelsen: Okazuje się, że malloci darmowe są specjalnie zaprojektowane w glibc, aby to umożliwić, a magazynie callocmożna zadzwonić do importowanego malloc. Nie próbuj tego z innymi funkcjami. To nie zadziała tak dobrze.
Joshua
30

Jak wiele osób wspomniało, używając LD_PRELOADdo wstępnego załadowania biblioteki. BTW, można SPRAWDŹ , czy ustawienie jest dostępne przez lddkomendę.

Przykład: załóżmy, że musisz wstępnie załadować własny 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)

Dlatego ustaw swoje środowisko ładowania wstępnego:

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

Sprawdź swoją bibliotekę jeszcze raz:

>ldd /bin/ls
    ...
    libselinux.so.1 =>
    /home/patric/libselinux.so.1 (0x00007fb9245d8000)
    ...
Patric
źródło
9

LD_PRELOADwyświetla listę bibliotek współdzielonych z funkcjami, które zastępują standardowy zestaw, podobnie jak /etc/ld.so.preloadrobi to. Są one realizowane przez moduł ładujący /lib/ld-linux.so. Jeśli chcesz zastąpić tylko kilka wybranych funkcji, możesz to zrobić, tworząc nadpisany plik obiektowy i ustawienie LD_PRELOAD; funkcje w tym pliku obiektowym zastąpią tylko te funkcje, pozostawiając inne takie, jakie były.

Więcej informacji na temat bibliotek współdzielonych można znaleźć na stronie http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Rajesz
źródło
3

Oto szczegółowy post na blogu na temat wstępnego ładowania:

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

asn
źródło
13
Dziękujemy za opublikowanie odpowiedzi! Należy pamiętać, że należy zamieścić zasadnicze części odpowiedzi tutaj, na tej stronie, w przeciwnym razie istnieje ryzyko, że post zostanie usunięty. Zobacz często zadawane pytania, w których wymieniono odpowiedzi „niewiele więcej niż link”. Możesz dodać link, jeśli chcesz, ale tylko jako „odniesienie”. Odpowiedź powinna stać sama z siebie, bez potrzeby linkowania.
Taryn
3

łatwo jest eksportować mylib.sodo env:

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

wyłączyć :

$ export LD_PRELOAD=
JulienGenoud
źródło
7
lubunset LD_PRELOAD
Morten
2

gdy używany jest LD_PRELOAD, plik ten zostanie załadowany przed jakąkolwiek inną $export LD_PRELOAD=/path/libbiblioteką lib, która ma zostać wstępnie załadowana, nawet tego można użyć w programach

Sumith Senarathne
źródło
1

Za pomocą LD_PRELOAD ścieżki można zmusić moduł ładujący aplikacje do ładowania udostępnionego obiektu współdzielonego, ponad domyślny.

Deweloperzy używają tego do debugowania swoich aplikacji, udostępniając różne wersje współdzielonych obiektów.

Używaliśmy go do hakowania niektórych aplikacji, zastępując istniejące funkcje za pomocą przygotowanych obiektów współdzielonych.

dnahc araknayirp
źródło