gpt4 book ai didi

linux - 如何使 Unix 二进制文件自包含?

转载 作者:IT王子 更新时间:2023-10-29 00:07:02 27 4
gpt4 key购买 nike

我有一个 Linux 二进制文件,没有源代码,可以在一台机器上运行,我想制作一个独立的包,可以在同一架构的不同机器上运行。实现这一目标的方法是什么?

在我的例子中,两台机器都有相同的架构,相同的 Ubuntu 内核,但目标机器没有 make 并且在 /lib 下有错误的文件版本和/usr

我的一个想法是使用 chroot 并重新创建二进制文件使用的文件系统的子集,可能使用 strace 来确定它需要什么。是否已经有可以执行此操作的工具?

为了后代,下面是我如何确定一个进程打开了哪些文件

#!/usr/bin/python
# source of trace_fileopen.py
# Runs command and prints all files that have been successfully opened with mode O_RDONLY
# example: trace_fileopen.py ls -l
import re, sys, subprocess, os

if __name__=='__main__':
strace_fn = '/tmp/strace.out'
strace_re = re.compile(r'([^(]+?)\((.*)\)\s*=\s*(\S+?)\s+(.*)$')

cmd = sys.argv[1]
nowhere = open('/dev/null','w')#
p = subprocess.Popen(['strace','-o', strace_fn]+sys.argv[1:], stdout=nowhere, stderr=nowhere)
sts = os.waitpid(p.pid, 0)[1]

output = []
for line in open(strace_fn):
# ignore lines like --- SIGCHLD (Child exited) @ 0 (0) ---
if not strace_re.match(line):
continue
(function,args,returnval,msg) = strace_re.findall(line)[0]
if function=='open' and returnval!='-1':
(fname,mode)=args.split(',',1)
if mode.strip()=='O_RDONLY':
if fname.startswith('"') and fname.endswith('"') and len(fname)>=2:
fname = fname[1:-1]
output.append(fname)
prev_line = ""
for line in sorted(output):
if line==prev_line:
continue
print line
prev_line = line

更新LD_LIBRARY_PATH 解决方案的问题是 /lib 被硬编码到解释器中并优先于 LD_LIBRARY_PATH,因此 native 版本将首先加载。解释器被硬编码到二进制文件中。一种方法可能是修补解释器并将二进制文件作为 patched_interpreter mycommandline 问题是当 mycommandlinejava 开头时,这不会工作,因为 Java 设置 LD_LIBRARY_PATH 并重新启动自身,它求助于旧的解释器。对我有用的解决方案是在文本编辑器中打开二进制文件,找到解释器 (/lib/ld-linux-x86-64.so.2),并将其替换为相同长度补丁解释器的路径

最佳答案

正如其他人所提到的,静态链接是一种选择。除了与 glibc 的静态链接在每个版本中都会出现一些问题(抱歉,没有引用资料;只是我的经验)。

您的 chroot 想法可能有点矫枉过正。

据我所知,大多数商业产品使用的解决方案是让它们的“应用程序”成为一个设置 LD_LIBRARY_PATH 的 shell 脚本,然后运行实际的可执行文件。沿着这些线的东西:

#!/bin/sh
here=`dirname "$0"`
export LD_LIBRARY_PATH="$here"/lib
exec "$here"/bin/my_app "$@"

然后您只需将所有相关 .so 文件的副本转储到 lib/ 下,将您的可执行文件放在 bin/ 下,将脚本放在 中。,并运送整棵树。

(为了具有生产值(value),如果 LD_LIBRARY_PATH 不为空,请将 "$here"/lib 适本地放在前面,等等)

[编辑,配合你的更新]

我认为您可能对什么是硬编码什么不是硬编码感到困惑。 ld-linux-x86-64.so.2 是动态链接器本身;并且您是正确的,它的路径被硬编码到 ELF header 中。但是其他库不是硬编码的;它们由动态链接器搜索,动态链接器将遵循 LD_LIBRARY_PATH

如果你真的需要一个不同的 ld-linux.so,而不是修补 ELF 头,只需运行动态链接器本身:

/path/to/my-ld-linux.so my_program <args>

这将使用您的链接器而不是 ELF header 中列出的链接器。

修补可执行文件本身是邪恶的。请考虑在您继续前进后必须维护您的东西的可怜人......没有人会期望您手工破解 ELF header 。 任何人都可以阅读 shell 脚本在做什么。

只要我的 0.02 美元。

关于linux - 如何使 Unix 二进制文件自包含?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6701650/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com