Jak wyświetlić wszystkie biblioteki współdzielone używane przez pliki wykonywalne w systemie Linux?

225

Chciałbym wiedzieć, które biblioteki są używane przez pliki wykonywalne w moim systemie. Mówiąc dokładniej, chciałbym ustalić, które biblioteki są najczęściej używane, wraz z binariami, które ich używają. W jaki sposób mogę to zrobić?

Alan Szlosek
źródło
Prawdopodobnie nie będziesz w stanie uzyskać dokładnej liczby, jeśli zostaną użyte pliki wykonywalne dlopen.
jxh

Odpowiedzi:

271
  1. Służy ldddo wyświetlania bibliotek współdzielonych dla każdego pliku wykonywalnego.
  2. Oczyść wyjście
  3. Sortuj, obliczaj liczby, sortuj według liczby

Aby znaleźć odpowiedź na wszystkie pliki wykonywalne w katalogu „/ bin”:

find /bin -type f -perm /a+x -exec ldd {} \; \
| grep so \
| sed -e '/^[^\t]/ d' \
| sed -e 's/\t//' \
| sed -e 's/.*=..//' \
| sed -e 's/ (0.*)//' \
| sort \
| uniq -c \
| sort -n

Zmień „/ bin” powyżej na „/”, aby przeszukać wszystkie katalogi.

Dane wyjściowe (tylko dla katalogu / bin) będą wyglądać mniej więcej tak:

  1 /lib64/libexpat.so.0
  1 /lib64/libgcc_s.so.1
  1 /lib64/libnsl.so.1
  1 /lib64/libpcre.so.0
  1 /lib64/libproc-3.2.7.so
  1 /usr/lib64/libbeecrypt.so.6
  1 /usr/lib64/libbz2.so.1
  1 /usr/lib64/libelf.so.1
  1 /usr/lib64/libpopt.so.0
  1 /usr/lib64/librpm-4.4.so
  1 /usr/lib64/librpmdb-4.4.so
  1 /usr/lib64/librpmio-4.4.so
  1 /usr/lib64/libsqlite3.so.0
  1 /usr/lib64/libstdc++.so.6
  1 /usr/lib64/libz.so.1
  2 /lib64/libasound.so.2
  2 /lib64/libblkid.so.1
  2 /lib64/libdevmapper.so.1.02
  2 /lib64/libpam_misc.so.0
  2 /lib64/libpam.so.0
  2 /lib64/libuuid.so.1
  3 /lib64/libaudit.so.0
  3 /lib64/libcrypt.so.1
  3 /lib64/libdbus-1.so.3
  4 /lib64/libresolv.so.2
  4 /lib64/libtermcap.so.2
  5 /lib64/libacl.so.1
  5 /lib64/libattr.so.1
  5 /lib64/libcap.so.1
  6 /lib64/librt.so.1
  7 /lib64/libm.so.6
  9 /lib64/libpthread.so.0
 13 /lib64/libselinux.so.1
 13 /lib64/libsepol.so.1
 22 /lib64/libdl.so.2
 83 /lib64/ld-linux-x86-64.so.2
 83 /lib64/libc.so.6

Edytuj - Usunięto „grep -P”

John Vasileff
źródło
2
To świetna odpowiedź (podniosłem głos), ale czy możesz wyjaśnić polecenie „grep -P” \ t. * So ”? Według man interpretuje to wzorzec jako perge regexp, ale moja wersja grep go nie obsługuje (man wskazuje, że jest to ogólny problem). Który fragment wyrażenia regularnego jest specyficzny dla perla?
Bobby Jack
2
Myślę, że możesz potrzebować użyćldd -v
MountainX
58
Pamiętaj, że lddfaktycznie uruchamia plik wykonywalny ze specjalną zmienną środowiskową, a linker dynamiczny Linux rozpoznaje tę flagę i po prostu wyświetla biblioteki zamiast uruchamiać plik wykonywalny. Spójrz na źródło ldd; w moim systemie jest to skrypt bash. Jeśli plik wykonywalny jest statycznie powiązany i używa wywołań systemowych i określa inny moduł ładujący, może on wykonywać dowolne złe działania. Więc nie używaj lddpliku wykonywalnego, któremu nie ufasz.
Barry Kelly,
„ldd” nie działa dla mnie na kompilowanych binarnie plikach binarnych. Pytanie dotyczy znalezienia bibliotek używanych przez programy w bieżącym systemie (byłyby to programy rodzime, jak wyrażono). To dobra odpowiedź na to pytanie. Jednak pomyślałem, że wspomnę, że musisz użyć czegoś innego, jeśli szukasz wspólnych bibliotek dla programów dla innego systemu ('readelf' wspomniany w innej odpowiedzi, działało dla mnie)
Tim Bird
68

Nie miałem ldd na moim zestawie narzędzi ARM, więc użyłem objdump:

$ (CROSS_COMPILE) objdump -p

Na przykład:

objdump -p /usr/bin/python:

Dynamic Section:
  NEEDED               libpthread.so.0
  NEEDED               libdl.so.2
  NEEDED               libutil.so.1
  NEEDED               libssl.so.1.0.0
  NEEDED               libcrypto.so.1.0.0
  NEEDED               libz.so.1
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  INIT                 0x0000000000416a98
  FINI                 0x000000000053c058
  GNU_HASH             0x0000000000400298
  STRTAB               0x000000000040c858
  SYMTAB               0x0000000000402aa8
  STRSZ                0x0000000000006cdb
  SYMENT               0x0000000000000018
  DEBUG                0x0000000000000000
  PLTGOT               0x0000000000832fe8
  PLTRELSZ             0x0000000000002688
  PLTREL               0x0000000000000007
  JMPREL               0x0000000000414410
  RELA                 0x0000000000414398
  RELASZ               0x0000000000000078
  RELAENT              0x0000000000000018
  VERNEED              0x0000000000414258
  VERNEEDNUM           0x0000000000000008
  VERSYM               0x0000000000413534
smichak
źródło
2
To również powinno być bezpieczne, w przeciwieństwie do tego, lddktórego nie należy używać w niezaufanych plikach wykonywalnych.
PSkocik
Ponadto, obbjdump -ppokazy dodatkowe informacje, takie jak RPATH, które mogą być pomocne podczas badania dynamiczne łączenie problemów z wykonywalny.
sitaktif
+1 za metodę, która jest faktycznie bezpieczna i niezawodna (w jakiś sposób mam system, w którym musl-gccregularnie produkuje pliki binarne, tak że wywoływanie pliku lddbinarnego po prostu wykonuje plik binarny , więc w dzisiejszych czasach regularnie przypominam sobie, jak niebezpieczny lddjest).
mtraceur
54

W systemie Linux używam:

lsof -P -T -p Application_PID

Działa to lepiej niż lddwtedy, gdy plik wykonywalny używa innego niż domyślny modułu ładującego

Fabiano Tarlao
źródło
Wykorzystano to, aby dowiedzieć się, czy mariadb faktycznie używa tc-malloc , który jest ładowany przez LD_PRELOAD. Działa świetnie.
cmc
2
Szukałem czegoś, co pokaże mi „.so” dla danego pid. Właśnie tego potrzebowałem. Dzięki!
Leo Ufimcew
48

aby dowiedzieć się, jakich bibliotek używa plik binarny, użyj ldd

ldd path/to/the/tool

Musisz napisać mały skrypt powłoki, aby dostać się do awarii całego systemu.

pilif
źródło
19

Sprawdź zależności biblioteki współdzielonej od pliku wykonywalnego programu

Aby dowiedzieć się, od jakich bibliotek zależy dany plik wykonywalny, możesz użyć polecenia ldd. To polecenie wywołuje dynamiczny linker, aby dowiedzieć się o zależnościach bibliotekowych plików wykonywalnych.

> $ ldd / ścieżka / do / program

Zauważ, że NIE jest zalecane uruchamianie ldd z dowolnym niezaufanym plikiem wykonywalnym innej firmy, ponieważ niektóre wersje ldd mogą bezpośrednio wywoływać plik wykonywalny w celu zidentyfikowania zależności biblioteki, co może stanowić zagrożenie bezpieczeństwa.

Zamiast tego bezpieczniejszym sposobem pokazania zależności biblioteki nieznanego pliku binarnego jest użycie następującego polecenia.

$ objdump -p / path / to / program | POTRZEBUJESZ grep

po więcej informacji

kayle
źródło
14

readelf -d rekurencja

redelf -dprodukuje podobne wyniki, o objdump -pktórych wspomniano na stronie : https://stackoverflow.com/a/15520982/895245

Ale uważaj, że biblioteki dynamiczne mogą zależeć od innych bibliotek dynamicznych, abyś musiał się powtarzać.

Przykład:

readelf -d /bin/ls | grep 'NEEDED'

Przykładowy ouptut:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Następnie:

$ locate libselinux.so.1
/lib/i386-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libselinux.so.1
/mnt/debootstrap/lib/x86_64-linux-gnu/libselinux.so.1

Wybierz jeden i powtórz:

readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'

Przykładowe dane wyjściowe:

0x0000000000000001 (NEEDED)             Shared library: [libpcre.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

I tak dalej.

/proc/<pid>/maps do uruchamiania procesów

Jest to przydatne, aby znaleźć wszystkie biblioteki aktualnie używane przez uruchamianie plików wykonywalnych. Na przykład:

sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u

pokazuje wszystkie aktualnie załadowane zależności dynamiczne init(PID 1):

/lib/x86_64-linux-gnu/ld-2.23.so
/lib/x86_64-linux-gnu/libapparmor.so.1.4.0
/lib/x86_64-linux-gnu/libaudit.so.1.0.0
/lib/x86_64-linux-gnu/libblkid.so.1.1.0
/lib/x86_64-linux-gnu/libc-2.23.so
/lib/x86_64-linux-gnu/libcap.so.2.24
/lib/x86_64-linux-gnu/libdl-2.23.so
/lib/x86_64-linux-gnu/libkmod.so.2.3.0
/lib/x86_64-linux-gnu/libmount.so.1.1.0
/lib/x86_64-linux-gnu/libpam.so.0.83.1
/lib/x86_64-linux-gnu/libpcre.so.3.13.2
/lib/x86_64-linux-gnu/libpthread-2.23.so
/lib/x86_64-linux-gnu/librt-2.23.so
/lib/x86_64-linux-gnu/libseccomp.so.2.2.3
/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libuuid.so.1.3.0

Ta metoda pokazuje również biblioteki otwarte przy użyciu dlopen, przetestowane przy użyciu tej minimalnej konfiguracji zhakowanej za pomocą sleep(1000)Ubuntu 18.04.

Zobacz także: /superuser/310199/see-currently-loaded-shared-objects-in-linux/1243089

Ciro Santilli
źródło
7

W OS X domyślnie nie ma ldd, objdumplub lsof. Alternatywnie spróbuj otool -L:

$ otool -L `which openssl`
/usr/bin/openssl:
    /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

W tym przykładzie użycie which opensslwypełnia pełną ścieżkę dla danego środowiska wykonywalnego i bieżącego użytkownika.

bluebadge
źródło
6

W systemie UNIX załóżmy, że nazwa binarna (wykonywalna) to test. Następnie używamy następującego polecenia, aby wyświetlić listę bibliotek używanych w teście

ldd test
Raghwendra
źródło
4

Dzięki lddniemu możesz uzyskać biblioteki, których używają narzędzia. Aby uporządkować wykorzystanie bibliotek dla zestawu narzędzi, możesz użyć czegoś takiego jak następujące polecenie.

ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c

(Tutaj sedusuwa wszystkie wiersze, które nie zaczynają się od tabulatora, i odfiltrowuje tylko rzeczywiste bibliotekisort | uniq -c Otrzymujesz każdą bibliotekę z liczbą wskazującą liczbę jej wystąpienia).

Możesz dodać sort -g na końcu, aby uporządkować biblioteki w kolejności użycia.

Zauważ, że prawdopodobnie otrzymujesz linie dwie linie niebiblijne z powyższym poleceniem. Jeden ze statycznych plików wykonywalnych („nie jest dynamicznym plikiem wykonywalnym”) i jeden bez żadnej biblioteki. Ta ostatnia jest wynikiem, że linux-gate.so.1nie jest to biblioteka w systemie plików, ale „dostarczana” przez jądro.

Mweerden
źródło
2

Jeszcze jedną opcją może być po prostu odczytanie pliku znajdującego się pod adresem

/proc/<pid>/maps

Na przykład, czy identyfikator procesu to 2601, a następnie polecenie to

cat /proc/2601/maps

A wynik jest jak

7fb37a8f2000-7fb37a8f4000 r-xp 00000000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37a8f4000-7fb37aaf3000 ---p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf3000-7fb37aaf4000 r--p 00001000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf4000-7fb37aaf5000 rw-p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf5000-7fb37aafe000 r-xp 00000000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37aafe000-7fb37acfd000 ---p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfd000-7fb37acfe000 r--p 00008000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfe000-7fb37acff000 rw-p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acff000-7fb37ad1d000 r-xp 00000000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37ad1d000-7fb37af1d000 ---p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1d000-7fb37af1e000 r--p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1e000-7fb37af1f000 rw-p 0001f000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1f000-7fb37af21000 r-xp 00000000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37af21000-7fb37b121000 ---p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b121000-7fb37b122000 r--p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b122000-7fb37b123000 rw-p 00003000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
SoSen
źródło
2

na pakietach drukowania ubuntu związanych z plikiem wykonywalnym

ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F  ":"  '{print $1}'
Shimon Doodkin
źródło
0

Uznałem ten post za bardzo pomocny, ponieważ potrzebowałem zbadać zależności z biblioteki dostarczonej przez inną firmę (ścieżki wykonania 32 lub 64-bitowe).

Złożyłem rekursywny skrypt bashowy Q&D oparty na sugestii „readelf-d” w dystrybucji RHEL 6.

Jest to bardzo podstawowe i za każdym razem będzie testować każdą zależność, nawet jeśli mogła być wcześniej przetestowana (tj. Bardzo gadatliwa). Wyjście jest również bardzo podstawowe.

#! /bin/bash

recurse ()
# Param 1 is the nuumber of spaces that the output will be prepended with
# Param 2 full path to library
{
#Use 'readelf -d' to find dependencies
dependencies=$(readelf -d ${2} | grep NEEDED | awk '{ print $5 }' | tr -d '[]')
for d in $dependencies; do
   echo "${1}${d}"
   nm=${d##*/}
   #libstdc++ hack for the '+'-s
   nm1=${nm//"+"/"\+"}
   # /lib /lib64 /usr/lib and /usr/lib are searched
   children=$(locate ${d} | grep -E "(^/(lib|lib64|usr/lib|usr/lib64)/${nm1})")
   rc=$?
   #at least locate... didn't fail
   if [ ${rc} == "0" ] ; then
      #we have at least one dependency
      if [ ${#children[@]} -gt 0 ]; then
         #check the dependeny's dependencies
         for c in $children; do
          recurse "  ${1}" ${c}
         done
      else
         echo "${1}no children found"
      fi
   else
      echo "${1}locate failed for ${d}"
   fi
done
}
# Q&D -- recurse needs 2 params could/should be supplied from cmdline
recurse "" !!full path to library you want to investigate!!

przekieruj wyjście do pliku i grep dla „znaleziono” lub „nie powiodło się”

Używaj i modyfikuj, na własne ryzyko, oczywiście, jak chcesz.

Anders Domeij
źródło