실행 파일과 해당 라이브러리를 모두 결합하세요.

실행 파일과 해당 라이브러리를 모두 결합하세요.

/bin/cat다음 공유 라이브러리를 사용하는 실행 파일이 있다고 가정해 보겠습니다 .

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

이러한 것들을 어떻게든 함께 "결합"하는 것이 가능합니까(실행 가능한 아카이브 또는 이와 유사한 것)?

이 작업을 수행하려는 프로그램에 대한 코드가 없으므로 -static 플래그를 사용하여 컴파일할 수는 없습니다.

답변1

시스템 위치의 모든 라이브러리를 실행 파일이 있는 하위 디렉터리로 복사하고 사용할 수 있습니다.파헬프, 실행 파일이 시스템 lib 디렉터리가 아닌 해당 위치에서 lib종속성을 찾도록 합니다.

예를 들어:

상대화 라이브러리:

#!/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"

LD_LIBRARY_PATH( 해킹과 달리 이것은 setuid 실행 파일에서도 작동해야 한다고 생각합니다 .)

./lib그런 다음 실행 파일과 함께 디렉터리를 이동하기 만 하면 됩니다 .

답변2

"가입"의 의미에 따라 다릅니다. 가장 좋은 방법은 원본 소스 코드를 정적 바이너리로 다시 컴파일하는 것입니다.

그러나 응용 프로그램에서 제어하는 ​​하위 디렉터리( /usr/share/myapp예:)에 모든 라이브러리를 포함시킨 다음 해당 디렉터리를 라이브러리 검색 순서에 넣을 수 있습니다. 한 가지 방법은 (Linux에서) 다음을 사용하는 것입니다 LD_LIBRARY_PATH.

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

Linux에서는 /etc/ld.so.conf동일한 작업을 수행하도록 파일을 수정할 수 있습니다. Ubuntu는 *.conf파일을 디렉터리에 추가 할 수도 있습니다 /etc/ld.so.conf.d.

답변3

여러 공유 객체와 공유 라이브러리 ELF 실행 파일을 정적으로 링크된 blob으로 변환하는 것은 쉽지 않습니다.

이것실행 가능 파일말씀하신 내용은 가능할 수도 있습니다. "실행 가능한 아카이브"란 실행 시 시스템의 다른 파일에 의존하지 않고 자체적으로 압축을 풀고 프로그램을 실행하는 파일을 의미합니다.

이는 대부분의 Linux 배포판에 있는 쉘 스크립트와 유틸리티를 사용하여 매우 간단하게 수행할 수 있습니다(그러나 쉘과 유틸리티에 대한 종속성이 추가됩니다). 원칙은 동일하지만 ELF "실행 가능한 아카이브"를 만드는 것은 좀 더 복잡할 수 있습니다. 프로그램 버전이 자주 실행될 것으로 예상되는 경우 다음과 같이 사용자 시스템에 해당 버전을 "설치"하도록 스크립트를 수정해야 합니다.데이비드그리고자네브.

쉘 스크립트 기반 실행 가능한 아카이브 사용 예

실행에 필요한 파일을 수집합니다. cat프로그램을 사용하는 예제의 내용은 다음과 같습니다.

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

Base64로 인코딩하여 tgz 파일을 생성합니다 . 디렉터리를 설정한 후에 이 작업을 수행 cat.b64할 수 있습니다 .fachas_cat_files

tar -cz fachas_cat_files | base64 > cat.b64

이것은 스크립트에 포함될 수 있도록 인쇄 가능한 문자로 tar 파일을 나타냅니다.

압축 중인 파일의 md5sum을 기록해 두십시오. 이를 쉘 스크립트에서 사용하여 압축을 푼 파일이 자신의 파일인지 확인할 수 있습니다.

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

아래와 같이 쉘 스크립트를 작성하고 이름을 새 "아카이브" 프로그램으로 지정하십시오.

#!/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

답변4

실행 가능한 아카이브를 위해 수정된 "ld-linux"와 유사한 부트로더를 작성하려는 경우 이것이 가능해야 한다고 말하고 싶습니다. /proc/xxx/maps 파일 시스템에서 실행 중인 동적 실행 파일을 살펴보면 실행 중인 동적 실행 파일이 프로세스의 메모리 공간에 매핑된 파일 묶음에 지나지 않는다는 것을 알 수 있습니다. 이러한 매핑된 파일은 별도의 파일이 아닌 실행 가능한 아카이브의 영역일 수 있으며 여전히 프로세스에 표시되는 동일한 데이터를 갖습니다. 실행 가능한 아카이브의 영역을 PAGE_SIZE로 정렬해야 합니다. ld-linux에서 파일(실행 파일 및 라이브러리)을 찾고 매핑하는 것 외에도 대부분의 다른 기능은 변경되지 않은 상태로 유지될 수 있습니다.

실행 파일이 dlopen과 같은 API를 사용할 때 합병증이 발생합니다. 실행 가능한 아카이브에도 포함해야 하는 경우 libdl.so도 수정하여 시스템 libdl.so 대신 아카이브에 포함해야 합니다.

실행 가능한 아카이브는 부트스트랩이 해당 파일과 파일 자체를 찾을 수 있도록 파일 목록과 해당 오프셋을 포함하는 "부트스트랩 ld-linux 대체"(정적 바이너리)의 PAGE_SIZE 연결이어야 합니다.

누구든지 참여한다면 유용한 프로젝트가 될 것이라고 생각합니다. 도커 컨테이너보다 훨씬 가볍습니다.

관련 정보