Я хотів би знати, які бібліотеки використовуються виконуваними файлами в моїй системі. Більш конкретно, я хотів би оцінити, які бібліотеки використовуються найбільше, а також двійкові файли, які ними користуються. Як я можу це зробити?
Я хотів би знати, які бібліотеки використовуються виконуваними файлами в моїй системі. Більш конкретно, я хотів би оцінити, які бібліотеки використовуються найбільше, а також двійкові файли, які ними користуються. Як я можу це зробити?
Відповіді:
ldd
для переліку спільних бібліотек для кожного виконуваного файлу.Щоб знайти відповідь на всі виконувані файли в каталозі "/ 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
Змініть "/ bin" вище на "/", щоб шукати всі каталоги.
Вихід (лише для каталогу / bin) буде виглядати приблизно так:
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
Редагувати - Видалено "grep -P"
ldd -v
ldd
насправді працює виконуваний файл зі спеціальною змінною середовища, а динамічний лінкер Linux розпізнає цей прапор і просто виводить бібліотеки, а не працює виконуваним файлом. Подивіться на джерело ldd
; у моїй системі це сценарій bash. Якщо виконуваний файл є статично пов'язаним і використовує системні дзвінки та вказує інший завантажувач, він може робити довільні злі речі. Тому не використовуйте ldd
у виконаному файлі, якому ви не довіряєте.
У мене не було ldd на моєму ланцюжку інструментів ARM, тому я використовував objdump:
$ (CROSS_COMPILE) objdump -p
Наприклад:
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
що не слід використовувати у ненадійних виконуваних файлах.
obbjdump -p
відображається додаткова інформація на зразок RPATH
, яка може бути корисною при дослідженні динамічних зв'язків проблем із вашим виконуваним файлом.
musl-gcc
регулярно виробляє двійкові файли, так що виклик ldd
на бінарний файл просто виконує двійкові файли , тому сьогодні мені регулярно нагадують про те, наскільки це небезпечно ldd
).
У Linux я використовую:
lsof -P -T -p Application_PID
Це працює краще, ніж ldd
коли виконуваний файл використовує завантажувач за замовчуванням
Перевірте залежність спільної бібліотеки виконуваної програми
Щоб дізнатися, від яких бібліотек залежить певний виконуваний файл, ви можете скористатися командою ldd. Ця команда викликає динамічний лінкер, щоб з'ясувати залежність виконуваної бібліотеки.
> $ ldd / шлях / до / програми
Зауважте, що НЕ рекомендується запускати ldd з будь-яким не довіреним стороннім виконуваним файлом, оскільки деякі версії ldd можуть безпосередньо викликати виконуваний файл для виявлення його залежностей від бібліотеки, що може становити загрозу безпеці.
Натомість більш безпечним способом відображення залежностей бібліотеки від невідомої бінарної програми є використання наступної команди.
$ objdump -p / шлях / до / програми | grep ПОТРІБНА
readelf -d
рекурсія
redelf -d
створює аналогічний вихід, про objdump -p
який згадувалося на веб- сайті: https://stackoverflow.com/a/15520982/895245
Але майте на увазі, що динамічні бібліотеки можуть залежати від інших динамічних бібліотек, і вам доведеться повторювати.
Приклад:
readelf -d /bin/ls | grep 'NEEDED'
Вибірка зразка:
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
0x0000000000000001 (NEEDED) Shared library: [libacl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
Тоді:
$ 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
Виберіть один і повторіть:
readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'
Вибірка зразка:
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]
І так далі.
/proc/<pid>/maps
для запуску процесів
Це корисно для пошуку всіх бібліотек, які зараз використовуються для запуску виконуваних файлів. Наприклад:
sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u
показує всі завантажені в даний час динамічні залежності 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
Цей метод також показує бібліотеки, відкриті dlopen
, перевірені цією мінімальною установкою, підключеною до sleep(1000)
Ubuntu 18.04.
Дивіться також: /superuser/310199/see-currently-loaded-shared-objects-in-linux/1243089
У OS X за замовчуванням немає ldd
, objdump
або lsof
. В якості альтернативи спробуйте 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)
У цьому прикладі, використовуючи which openssl
заповнення повністю кваліфікованого шляху для даного виконуваного та поточного середовища користувача.
З ldd
вами можна отримати бібліотеки, якими користуються інструменти. Для ранжирування використання бібліотек для набору інструментів ви можете використовувати щось на зразок наступної команди.
ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c
(Тут sed
знімаються всі рядки, які не починаються з вкладки, і фільтруються лише фактичні бібліотеки. З sort | uniq -c
кожної бібліотеки ви отримуєте підрахунок, який вказує кількість разів, коли вона відбулася.)
Ви можете додати sort -g
в кінці, щоб отримати бібліотеки в порядку використання.
Зверніть увагу, що ви, ймовірно, отримуєте рядки двох небібліотечних рядків із вищевказаною командою. Один зі статичних виконуваних файлів ("не динамічний виконуваний файл") і один без бібліотеки. Останнє є результатом, linux-gate.so.1
який не є бібліотекою у вашій файловій системі, а такою, яку "постачає" ядро.
Ще одним варіантом може бути лише читання файлу, розміщеного на
/proc/<pid>/maps
Наприклад, id процесу 2601, тоді команда є
cat /proc/2601/maps
І вихід схожий
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
на пакунки друку ubuntu, пов'язані з виконуваним файлом
ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F ":" '{print $1}'
Мені ця публікація виявилася дуже корисною, оскільки мені потрібно було дослідити залежності від бібліотеки, що постачається сторонніми сторонами (32 проти 64 бітових шляхів виконання).
Я зібрав Q&D повторюваний скрипт bash на основі пропозиції 'readelf -d' для дистрибутива RHEL 6.
Це дуже просто і буде перевіряти кожну залежність кожен раз, навіть якщо вона могла бути випробувана раніше (тобто дуже багатослівна). Вихід також є дуже базовим.
#! /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!!
перенаправити вихід у файл та grep для 'знайдено' або 'не вдалося'
Використовуйте та змінюйте, на власний ризик, звичайно, як хочете.
dlopen
.