如何使Unix二进制自包含?

Yar*_*tov 10 unix linux ubuntu linker

我有一个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
Run Code Online (Sandbox Code Playgroud)

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

Nem*_*emo 5

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

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

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

#!/bin/sh
here=`dirname "$0"`
export LD_LIBRARY_PATH="$here"/lib
exec "$here"/bin/my_app "$@"
Run Code Online (Sandbox Code Playgroud)

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

(为了具有生产价值,请正确添加"$here"/libLD_LIBRARY_PATH是否非空等)

[编辑,以配合您的更新]

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

如果您确实需要不同的 ld-linux.so,则无需修补 ELF 标头,只需运行动态链接器本身即可:

/path/to/my-ld-linux.so my_program <args>
Run Code Online (Sandbox Code Playgroud)

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

修补可执行文件本身是邪恶的。请考虑一下那些在你继续前进后必须维护你的东西的可怜人...... 没有人会指望你亲手破解了 ELF 头。 任何人都可以阅读 shell 脚本正在做什么。

只是我的 0.02 美元。


Spu*_*d86 2

CDE是一种专门为满足您的需求而设计的软件。这是关于它的谷歌技术演讲 http://www.youtube.com/watch?v=6XdwHo1BWwY