Tôi muốn biết thư viện nào được sử dụng bởi các tệp thực thi trên hệ thống của tôi. Cụ thể hơn, tôi muốn xếp hạng thư viện nào được sử dụng nhiều nhất, cùng với các tệp nhị phân sử dụng chúng. Tôi có thể làm cái này như thế nào?
Tôi muốn biết thư viện nào được sử dụng bởi các tệp thực thi trên hệ thống của tôi. Cụ thể hơn, tôi muốn xếp hạng thư viện nào được sử dụng nhiều nhất, cùng với các tệp nhị phân sử dụng chúng. Tôi có thể làm cái này như thế nào?
Câu trả lời:
ldd
để liệt kê các thư viện chia sẻ cho mỗi thực thi.Để tìm câu trả lời cho tất cả các tệp thực thi trong thư mục "/ 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
Thay đổi "/ bin" ở trên thành "/" để tìm kiếm tất cả các thư mục.
Đầu ra (chỉ cho thư mục / bin) sẽ trông giống như thế này:
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
Chỉnh sửa - Đã xóa "grep -P"
ldd -v
ldd
thực sự chạy tệp thực thi với một biến môi trường đặc biệt và trình liên kết động Linux nhận ra cờ này và chỉ xuất ra các thư viện thay vì chạy tệp thực thi. Nhìn vào nguồn để ldd
; trên hệ thống của tôi, đó là một tập lệnh bash. Nếu tệp thực thi được liên kết tĩnh và sử dụng các tòa nhà, và chỉ định một trình tải khác, nó có thể làm những việc xấu tùy ý. Vì vậy, không sử dụng ldd
trên một thực thi mà bạn không tin tưởng.
Tôi không có ldd trên chuỗi công cụ ARM của mình nên tôi đã sử dụng objdump:
$ (CROSS_COMPILE) objdump -p
Ví dụ:
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
nên sử dụng trên các tệp thực thi không đáng tin cậy.
obbjdump -p
hiển thị thông tin bổ sung như RPATH
, có thể hữu ích khi điều tra các vấn đề liên kết động với thực thi của bạn.
musl-gcc
thường xuyên tạo ra các nhị phân sao cho việc gọi ldd
nhị phân chỉ thực hiện nhị phân , vì vậy ngày nay tôi thường xuyên nhắc nhở về việc không an toàn như thế nào ldd
).
Trên Linux tôi sử dụng:
lsof -P -T -p Application_PID
Điều này hoạt động tốt hơn so với ldd
khi thực thi sử dụng trình tải không mặc định
Kiểm tra các phụ thuộc thư viện chia sẻ của một chương trình thực thi
Để tìm ra những thư viện mà một thực thi cụ thể phụ thuộc vào, bạn có thể sử dụng lệnh ldd. Lệnh này gọi trình liên kết động để tìm ra các phụ thuộc thư viện của một tệp thực thi.
> $ ldd / đường dẫn / đến / chương trình
Lưu ý rằng KHÔNG nên chạy ldd với bất kỳ bên thứ ba không đáng tin cậy nào vì một số phiên bản của ldd có thể trực tiếp gọi tệp thực thi để xác định các phụ thuộc thư viện của nó, có thể gây rủi ro bảo mật.
Thay vào đó, một cách an toàn hơn để hiển thị các phụ thuộc thư viện của tệp nhị phân ứng dụng không xác định là sử dụng lệnh sau.
$ objdump -p / đường dẫn / đến / chương trình | grep CẦN
readelf -d
đệ quy
redelf -d
tạo ra sản lượng tương tự objdump -p
được đề cập tại: https://stackoverflow.com/a/15520982/895245
Nhưng hãy cẩn thận rằng các thư viện động có thể phụ thuộc vào các thư viện động khác, để bạn phải kiểm tra lại.
Thí dụ:
readelf -d /bin/ls | grep 'NEEDED'
Mẫu ouptut:
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
0x0000000000000001 (NEEDED) Shared library: [libacl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
Sau đó:
$ 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
Chọn một và lặp lại:
readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'
Đầu ra mẫu:
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]
Và như thế.
/proc/<pid>/maps
để chạy các quy trình
Điều này rất hữu ích để tìm tất cả các thư viện hiện đang được sử dụng bằng cách chạy các tệp thực thi. Ví dụ:
sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u
hiển thị tất cả các phụ thuộc động hiện đang được tải của 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
Phương pháp này cũng cho thấy các thư viện được mở bằng dlopen
, được thử nghiệm với thiết lập tối thiểu này đã bị hack với sleep(1000)
Ubuntu 18.04.
Xem thêm: /superuser/310199/see-civersely-loaded- Shared -objects-in-linux / 12303089
Trên OS X theo mặc định không có ldd
, objdump
hoặc lsof
. Để thay thế, hãy thử 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)
Trong ví dụ này, sử dụng which openssl
điền vào đường dẫn đủ điều kiện cho môi trường người dùng hiện tại và thực thi nhất định.
Trên hệ thống UNIX, giả sử tên nhị phân (thực thi) là thử nghiệm. Sau đó, chúng tôi sử dụng lệnh sau để liệt kê các thư viện được sử dụng trong thử nghiệm là
ldd test
Với ldd
bạn có thể có được các thư viện mà các công cụ sử dụng. Để xếp hạng việc sử dụng các thư viện cho một bộ công cụ, bạn có thể sử dụng một cái gì đó như lệnh sau.
ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c
(Ở đây sed
loại bỏ tất cả các dòng không bắt đầu bằng một tab và chỉ lọc ra các thư viện thực tế. Với sort | uniq -c
bạn, mỗi thư viện sẽ có một số đếm cho biết số lần xảy ra.)
Bạn có thể muốn thêm sort -g
vào cuối để có được các thư viện theo thứ tự sử dụng.
Lưu ý rằng bạn có thể nhận được hai dòng không phải thư viện với lệnh trên. Một trong những thực thi tĩnh ("không phải là thực thi động") và một không có thư viện. Cái sau là kết quả của linux-gate.so.1
nó không phải là một thư viện trong hệ thống tệp của bạn mà là một "được cung cấp" bởi kernel.
Một tùy chọn khác có thể chỉ là đọc tệp nằm ở
/proc/<pid>/maps
Ví dụ: id quá trình là 2601 thì lệnh là
cat /proc/2601/maps
Và đầu ra là như thế
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
trên các gói in ubfox liên quan đến thực thi
ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F ":" '{print $1}'
Tôi thấy bài đăng này rất hữu ích vì tôi cần điều tra các phụ thuộc từ thư viện do bên thứ 3 cung cấp (đường dẫn thực thi 32 so với 64 bit).
Tôi kết hợp một tập lệnh bash đệ quy Q & D dựa trên đề xuất 'readelf -d' trên bản phân phối RHEL 6.
Nó rất cơ bản và sẽ kiểm tra mọi phụ thuộc mọi lúc ngay cả khi nó có thể đã được kiểm tra trước đó (tức là rất dài dòng). Đầu ra là rất cơ bản quá.
#! /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!!
chuyển hướng đầu ra đến một tệp và grep cho 'tìm thấy' hoặc 'không thành công'
Sử dụng và sửa đổi, có nguy cơ của riêng bạn, tất nhiên, như bạn muốn.
dlopen
.