Mi piacerebbe sapere quali librerie sono utilizzate dagli eseguibili sul mio sistema. Più specificamente, vorrei classificare quali librerie sono maggiormente utilizzate, insieme ai binari che le usano. Come posso fare questo?
Mi piacerebbe sapere quali librerie sono utilizzate dagli eseguibili sul mio sistema. Più specificamente, vorrei classificare quali librerie sono maggiormente utilizzate, insieme ai binari che le usano. Come posso fare questo?
Risposte:
ldd
per elencare le librerie condivise per ciascun eseguibile.Per trovare la risposta per tutti gli eseguibili nella directory "/ 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
Cambia "/ bin" sopra in "/" per cercare in tutte le directory.
L'output (solo per la directory / bin) avrà un aspetto simile al seguente:
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
Modifica - Rimosso "grep -P"
ldd -v
ldd
fatto che esegue effettivamente l'eseguibile con una speciale variabile di ambiente e il linker dinamico Linux riconosce questo flag e genera solo le librerie anziché eseguire l'eseguibile. Guarda la fonte per ldd
; sul mio sistema, è uno script bash. Se l'eseguibile è staticamente collegato e usa syscalls e specifica un caricatore diverso, può fare cose malvagie arbitrarie. Quindi non usare ldd
su un eseguibile di cui non ti fidi.
Non avevo ldd sulla mia toolchain ARM, quindi ho usato objdump:
$ (CROSS_COMPILE) objdump -p
Per esempio:
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
quale non dovrebbe essere usato su eseguibili non attendibili.
obbjdump -p
mostra informazioni aggiuntive come RPATH
, che possono essere di aiuto quando si esaminano i problemi di collegamento dinamico con l'eseguibile.
musl-gcc
produce regolarmente binari in modo tale che la chiamata ldd
al binario esegua solo il binario , quindi oggigiorno mi viene regolarmente ricordato quanto non ldd
sia sicuro ).
Su Linux utilizzo:
lsof -P -T -p Application_PID
Funziona meglio di ldd
quando l'eseguibile utilizza un caricatore non predefinito
Controlla le dipendenze della libreria condivisa di un programma eseguibile
Per scoprire da quali librerie dipende un determinato eseguibile, puoi usare il comando ldd. Questo comando richiama il linker dinamico per scoprire le dipendenze della libreria di un eseguibile.
> $ ldd / path / to / program
Si noti che NON è consigliabile eseguire ldd con alcun eseguibile di terze parti non attendibile poiché alcune versioni di ldd possono richiamare direttamente l'eseguibile per identificare le dipendenze della libreria, il che può essere un rischio per la sicurezza.
Invece, un modo più sicuro per mostrare le dipendenze delle librerie di un binario di un'applicazione sconosciuta è usare il seguente comando.
$ objdump -p / path / to / program | grep NECESSARIO
readelf -d
ricorsione
redelf -d
produce un output simile al objdump -p
quale è stato menzionato su: https://stackoverflow.com/a/15520982/895245
Ma attenzione che le librerie dinamiche possono dipendere da altre librerie dinamiche, a cui devi fare affidamento.
Esempio:
readelf -d /bin/ls | grep 'NEEDED'
Uscita campione:
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
0x0000000000000001 (NEEDED) Shared library: [libacl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
Poi:
$ 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
Scegline uno e ripeti:
readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'
Uscita campione:
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]
E così via.
/proc/<pid>/maps
per i processi in esecuzione
Questo è utile per trovare tutte le librerie attualmente in uso eseguendo eseguibili. Per esempio:
sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u
mostra tutte le dipendenze dinamiche attualmente caricate di 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
Questo metodo mostra anche le librerie aperte con dlopen
, testate con questa configurazione minima hackerata con un sleep(1000)
su Ubuntu 18.04.
Vedi anche: /superuser/310199/see-currently-loaded-shared-objects-in-linux/1243089
Su OS X per impostazione predefinita non c'è ldd
, objdump
o lsof
. In alternativa, prova 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)
In questo esempio, l'utilizzo di which openssl
riempie il percorso completo per l'ambiente eseguibile e l'utente corrente specificato.
Sul sistema UNIX, supponiamo che il nome binario (eseguibile) sia test. Quindi utilizziamo il seguente comando per elencare le librerie utilizzate nel test
ldd test
Con ldd
te puoi ottenere le librerie utilizzate dagli strumenti. Per classificare l'utilizzo delle librerie per un set di strumenti puoi usare qualcosa come il seguente comando.
ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c
(Qui sed
elimina tutte le righe che non iniziano con una scheda e filtra solo le librerie effettive. Con sort | uniq -c
ogni libreria si ottiene un conteggio che indica il numero di volte che si è verificato.)
Potresti voler aggiungere sort -g
alla fine per ottenere le librerie in ordine di utilizzo.
Si noti che probabilmente si ottengono righe due righe non di libreria con il comando precedente. Uno di eseguibili statici ("non un eseguibile dinamico") e uno senza alcuna libreria. Quest'ultimo è il risultato linux-gate.so.1
che non è una libreria nel file system ma una "fornita" dal kernel.
Un'altra opzione può essere solo leggere il file che si trova in
/proc/<pid>/maps
Ad esempio, l'id di processo è 2601, quindi il comando è
cat /proc/2601/maps
E l'output è simile
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
sui pacchetti di stampa ubuntu relativi a un eseguibile
ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F ":" '{print $1}'
Ho trovato questo post molto utile in quanto avevo bisogno di indagare sulle dipendenze da una libreria fornita da terze parti (percorsi di esecuzione 32 vs 64 bit).
Ho messo insieme uno script bash ricorsivo di domande e risposte basato sul suggerimento "readelf -d" su una distro RHEL 6.
È molto semplice e verificherà ogni dipendenza ogni volta anche se avrebbe potuto essere testato prima (cioè molto dettagliato). Anche l'output è molto semplice.
#! /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!!
reindirizzare l'output su un file e grep per "trovato" o "non riuscito"
Utilizzare e modificare, a proprio rischio, ovviamente, come si desidera.
dlopen
.