Verbinden Sie die ausführbare Datei und alle ihre Bibliotheken

8

Nehmen wir an, ich habe eine /bin/catausführbare Datei, die die folgenden gemeinsam genutzten Bibliotheken verwendet:

linux-vdso.so.1
libc.so.6
/lib64/ld-linux-x86-64.so.2

Ist es möglich, dieses Zeug irgendwie "zusammenzufügen" (ausführbares Archiv oder ähnliches)?

Ich habe nicht den Code des Programms, mit dem ich das machen möchte, also kann ich ihn nicht einfach mit dem Flag -static kompilieren.


quelle

Antworten:

6

Sie können alle Bibliotheken von ihren Systemspeicherorten in ein Unterverzeichnis kopieren , in dem sich Ihre ausführbare Datei befindet, und patchelf verwenden , damit die ausführbare Datei dort anstelle der Verzeichnisse der Systembibliothek nach ihren libdependenzen sucht.

Z.B:

relativize_libs:

#!/bin/bash -e
[ -n "$1" ] || set -- a.out
mkdir -p ./lib/ #<copy the libraries here
#use ldd to resolve the libs and use `patchelf --print-needed to filter out
# "magic" libs kernel-interfacing libs such as linux-vdso.so, ld-linux-x86-65.so or libpthread
# which you probably should not relativize anyway
join \
    <(ldd "$1" |awk '{if(substr($3,0,1)=="/") print $1,$3}' |sort) \
    <(patchelf --print-needed "$1" |sort) |cut -d\  -f2 |

#copy the lib selection to ./lib
xargs -d '\n' -I{} cp --copy-contents {} ./lib 
#make the relative lib paths override the system lib path
patchelf --set-rpath "\$ORIGIN/lib" "$1"

(Ich glaube, dass dies im Gegensatz zum LD_LIBRARY_PATHHacken auch mit ausführbaren Dateien von setuid funktionieren sollte).

Danach müssen Sie nur noch dieses ./libVerzeichnis zusammen mit der ausführbaren Datei verschieben.

PSkocik
quelle
1
Gute Arbeit! Die "Join" -Eingaben müssen sortiert sein, daher sollten Sie die ldd- und Patchelf-Ausgaben beide durch Sortieren leiten.
Bklyn
5

Kommt darauf an, was du mit "beitreten" meinst. Der beste Weg ist, die ursprüngliche Quelle als statische Binärdatei neu zu kompilieren.

Sie können jedoch alle Bibliotheken in ein Unterverzeichnis aufnehmen, das beispielsweise von der Anwendung gesteuert wird, /usr/share/myappund dieses Verzeichnis dann in die Reihenfolge der Bibliothekssuche einfügen. Eine Möglichkeit, dies zu tun, wäre (unter Linux) die Verwendung von LD_LIBRARY_PATH:

LD_LIBRARY_PATH=/usr/share/myapp/lib:/usr/local/lib:/usr/lib/i686-linux-gnu:/lib/i686-linux-gnu

Unter Linux können Sie die /etc/ld.so.confDatei so ändern , dass sie dasselbe tut - und Ubuntu fügt die *.confDateien auch im /etc/ld.so.conf.dVerzeichnis hinzu.

Mei
quelle
+1. Zur Verdeutlichung glaube ich, dass Sie die ursprüngliche Binärdatei als statische Binärdatei neu kompilieren müssen.
Kyle Smith
Nee. Richten Sie einfach den gewünschten Bibliothekssuchpfad ein und fertig.
Mei
4

Das Konvertieren einer Reihe von gemeinsam genutzten Objekten und einer gemeinsam genutzten ELF-Datei mit gemeinsam genutzten Bibliotheken in einen statisch verknüpften Blob ist nicht einfach.

Das von Ihnen erwähnte ausführbare Archiv ist möglicherweise möglich. Angenommen, mit "ausführbares Archiv" haben Sie eine Datei gemeint, die sich beim Ausführen selbst entpackt und ein Programm ohne Abhängigkeiten von anderen Dateien im System ausführt.

Dies kann ganz einfach mit einem Shell-Skript und einer Reihe von Dienstprogrammen erfolgen, die in den meisten Linux-Distributionen zu finden sind (es werden jedoch Abhängigkeiten von der Shell und den Dienstprogrammen hinzugefügt). Das Erstellen eines ausführbaren ELF-Archivs ist möglicherweise viel aufwändiger, obwohl die Prinzipien dieselben sind. Wenn Sie erwarten, dass Ihre Version des Programms häufig ausgeführt wird, sollten Sie das Skript so ändern, dass es auf dem Benutzersystem installiert wird, wie von David und janneb angegeben .

Ein Beispiel für die Verwendung eines auf Shell-Skripten basierenden ausführbaren Archivs

Sammeln Sie die Dateien, die Sie für die Ausführung benötigen. Ein Beispiel mit einem catProgramm hätte Folgendes:

fachas_cat_files/cat
fachas_cat_files/lib/libc.so.6

Base64 codiert die tgz-Datei und erstellt sie. cat.b64Dies kann nach dem Einrichten Ihres fachas_cat_filesVerzeichnisses folgendermaßen erfolgen.

tar -cz fachas_cat_files | base64 > cat.b64

Dadurch wird die TAR-Datei mit druckbaren Zeichen dargestellt, sodass sie in das Skript aufgenommen werden kann.

Notieren Sie sich die md5-Summen der Dateien, die Sie verpacken, und überprüfen Sie im Shell-Skript, ob die nicht geteerten Dateien Ihre eigenen sind oder nicht.

find fachas_cat_files/ -type f -exec md5sum {} \; > cat.md5

Erstellen Sie ein Shell-Skript wie das folgende und nennen Sie es Ihr neues "Archiv" -Programm.

#!/bin/bash

TEMP_DIR=/tmp

# Check Md5sum
md5sum -c --quiet >/dev/null 2>&1 <<EOF 
--- Paste contents of cat.md5 here. ---
EOF

# Untar from base64 encoded tarball.
test $? -eq 0 || base64 -d <<EOF | tar -xz -C ${TEMP_DIR}
--- Paste contents of cat.b64 here. ---
EOF

# Execute the binary.
LD_LIBRARY_PATH=${TEMP_DIR}/fachas_cat_files/lib/ ${TEMP_DIR}/fachas_cat_files/cat $*

# Optionally remove the temporary files, if you do, the whole md5sum set of steps is 
# not necessary.
# rm -fr ${TEMP_DIR}/fachas_cat_files
Anil
quelle
0

Nein, es ist nicht möglich. Sie können möglicherweise ein Archiv (.tar.gz oder was auch immer) erstellen, das Folgendes enthält

  • Die ursprüngliche ausführbare Datei wurde umbenannt, z. B. bin / cat.real
  • Ein privates Verzeichnis, z. B. lib / fachas-cat, das Kopien aller Bibliotheken enthält, die bin / cat.real benötigt
  • Ein Shellscript bin / cat, das LD_LIBRARY_PATH auf $ SOME_INSTALL_PREFIX / lib / fachas-cat / setzt und bin / cat.real ausführt
janneb
quelle