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ć?
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ć?
Odpowiedzi:
ldd
do wyświetlania bibliotek współdzielonych dla każdego pliku wykonywalnego.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”
ldd -v
ldd
faktycznie 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 ldd
pliku wykonywalnego, któremu nie ufasz.
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
ldd
którego nie należy używać w niezaufanych plikach wykonywalnych.
obbjdump -p
pokazy dodatkowe informacje, takie jak RPATH
, które mogą być pomocne podczas badania dynamiczne łączenie problemów z wykonywalny.
musl-gcc
regularnie produkuje pliki binarne, tak że wywoływanie pliku ldd
binarnego po prostu wykonuje plik binarny , więc w dzisiejszych czasach regularnie przypominam sobie, jak niebezpieczny ldd
jest).
W systemie Linux używam:
lsof -P -T -p Application_PID
Działa to lepiej niż ldd
wtedy, gdy plik wykonywalny używa innego niż domyślny modułu ładującego
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
readelf -d
rekurencja
redelf -d
produkuje podobne wyniki, o objdump -p
któ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
W OS X domyślnie nie ma ldd
, objdump
lub 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 openssl
wypełnia pełną ścieżkę dla danego środowiska wykonywalnego i bieżącego użytkownika.
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
Dzięki ldd
niemu 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 sed
usuwa 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.1
nie jest to biblioteka w systemie plików, ale „dostarczana” przez jądro.
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
na pakietach drukowania ubuntu związanych z plikiem wykonywalnym
ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F ":" '{print $1}'
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.
dlopen
.