ฉันต้องการทราบว่าไลบรารี่ใดที่ถูกใช้งานบนระบบของฉัน โดยเฉพาะอย่างยิ่งฉันต้องการจัดอันดับห้องสมุดที่มีการใช้งานมากที่สุดพร้อมกับไบนารีที่ใช้พวกเขา ฉันจะทำสิ่งนี้ได้อย่างไร
ฉันต้องการทราบว่าไลบรารี่ใดที่ถูกใช้งานบนระบบของฉัน โดยเฉพาะอย่างยิ่งฉันต้องการจัดอันดับห้องสมุดที่มีการใช้งานมากที่สุดพร้อมกับไบนารีที่ใช้พวกเขา ฉันจะทำสิ่งนี้ได้อย่างไร
คำตอบ:
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
; ในระบบของฉันมันเป็นสคริปต์ทุบตี หากปฏิบัติการเชื่อมโยงแบบคงที่และใช้ syscalls และระบุตัวโหลดที่แตกต่างกันมันสามารถทำสิ่งชั่วร้ายโดยพลการ ดังนั้นอย่าใช้ldd
กับไฟล์ที่คุณไม่เชื่อถือ
ฉันไม่มี ldd บน toolchain ของฉันดังนั้นฉันจึงใช้ 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 path/to/the/tool
คุณจะต้องเขียนเชลล์สคริปต์เล็กน้อยเพื่อไปยังรายละเอียดทั่วทั้งระบบของคุณ
ตรวจสอบการอ้างอิงไลบรารีที่แบ่งใช้ของโปรแกรมที่เรียกทำงานได้
หากต้องการทราบว่าไลบรารีใดที่สามารถปฏิบัติการได้ขึ้นอยู่กับไลบรารีคุณสามารถใช้คำสั่ง ldd คำสั่งนี้เรียกใช้ dynamic linker เพื่อค้นหาการขึ้นต่อกันของไลบรารีของ executable
> $ ldd / path / to / program
โปรดทราบว่าไม่แนะนำให้เรียกใช้ ldd ด้วยโปรแกรมปฏิบัติการของ บริษัท อื่นที่ไม่น่าเชื่อถือเนื่องจาก ldd บางรุ่นอาจเรียกใช้งานโดยตรงเพื่อระบุการขึ้นต่อกันของไลบรารีซึ่งอาจมีความเสี่ยงด้านความปลอดภัย
วิธีที่ปลอดภัยกว่าในการแสดงการพึ่งพาไลบรารีของไบนารีแอปพลิเคชันที่ไม่รู้จักคือการใช้คำสั่งต่อไปนี้
$ objdump -p / path / to / program | grep ต้องการ
readelf -d
เรียกซ้ำ
redelf -d
สร้างเอาต์พุตที่คล้ายกันobjdump -p
ซึ่งถูกกล่าวถึงที่: https://stackoverflow.com/a/15520982/895245
แต่ระวังว่าไลบรารีแบบไดนามิกสามารถขึ้นอยู่กับไลบรารีแบบไดนามิกอื่น ๆ เพื่อที่คุณจะต้องเรียกคืน
ตัวอย่าง:
readelf -d /bin/ls | grep 'NEEDED'
ตัวอย่าง ouptut:
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
เติมในพา ธ ที่ผ่านการรับรองโดยสมบูรณ์สำหรับสภาพแวดล้อมผู้ใช้ที่สามารถเรียกใช้งานได้และปัจจุบัน
บนระบบ UNIX สมมติว่าชื่อ binary (executable) คือการทดสอบ จากนั้นเราจะใช้คำสั่งต่อไปนี้เพื่อแสดงรายการไลบรารีที่ใช้ในการทดสอบคือ
ldd test
ด้วยldd
คุณสามารถรับไลบรารีที่เครื่องมือใช้ ในการจัดอันดับการใช้งานไลบรารี่สำหรับชุดเครื่องมือคุณสามารถใช้คำสั่งดังต่อไปนี้
ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c
(ที่นี่จะsed
ตัดบรรทัดทั้งหมดที่ไม่ได้ขึ้นต้นด้วยแท็บและตัวกรองจะออกเฉพาะไลบรารีจริง ๆ เท่านั้นเมื่อsort | uniq -c
คุณได้รับแต่ละไลบรารีด้วยการนับจำนวนจะแสดงจำนวนครั้งที่มันเกิดขึ้น)
คุณอาจต้องการเพิ่มsort -g
ในตอนท้ายเพื่อรับไลบรารีตามลำดับการใช้งาน
โปรดทราบว่าคุณอาจได้รับสองบรรทัดที่ไม่ใช่ห้องสมุดด้วยคำสั่งดังกล่าว หนึ่งใน executables แบบคงที่ ("ไม่ใช่แบบไดนามิกที่ปฏิบัติการได้") และหนึ่งในนั้นที่ไม่มีไลบรารี หลังคือผลลัพธ์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 vs 64 บิต)
ฉันรวบรวมสคริปต์ B&D แบบเรียกซ้ำอีกครั้งโดยอ้างอิงจากข้อเสนอแนะ 'readelf -d' ใน distro RHEL 6
มันเป็นพื้นฐานมากและจะทดสอบทุกการพึ่งพาทุกครั้งแม้ว่ามันอาจได้รับการทดสอบมาก่อน (เช่น verbose มาก) เอาต์พุตก็ธรรมดามากเช่นกัน
#! /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
ใช้