Bash脚本包含二进制可执行文件

时间:2013-08-23 19:51:02

标签: bash unix binary dump

是否可以编写一个bash脚本,其中包含一个二进制可执行程序?

我的意思是一个脚本,它包含一个文本形式的可执行文件转储,在执行它时会被这个脚本转储回可执行文件?

我很想知道一个解决方案,它可以开箱即用,无需安装额外的软件包。有可能吗?

谢谢!

7 个答案:

答案 0 :(得分:6)

我之前从未做过这样的事情;) 这将编译一些c源代码,创建一个包含二进制文件的b.bash脚本(以及用于简单开发的原始脚本)

(a.bash)

#!/bin/bash

if [ "$0" == "b.bash" ];then
  tail -n +$[ `grep -n '^BINARY' $0|cut -d ':' -f 1` + 1 ] $0 | base64 -d > a2.out
  chmod +x a2.out
  ./a2.out
  echo $?
  exit
fi

cat "$0" > b.bash
echo "BINARY" >> b.bash
cat > a.c << EOF
int     main(){
        return 12;
}
EOF
gcc a.c 
base64 a.out >> b.bash

调用(a.bash生成b.bash):

bash a.bash ;bash b.bash

我不知道如何避免在执行之前将二进制文件写入临时文件...

答案 1 :(得分:4)

我尝试了这个并且它有效。十六进制是用xxd生成的。

#!/bin/bash

xxd -r >foo <<'EndHere'
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
0000010: 0200 3e00 0100 0000 e003 4000 0000 0000  ..>.......@.....
0000020: 4000 0000 0000 0000 000a 0000 0000 0000  @...............
0000030: 0000 0000 4000 3800 0800 4000 1e00 1b00  ....@.8...@.....
0000040: 0600 0000 0500 0000 4000 0000 0000 0000  ........@.......
0000050: 4000 4000 0000 0000 4000 4000 0000 0000  @.@.....@.@.....
...
0001960: 6400 5f65 6461 7461 006d 6169 6e00 5f69  d._edata.main._i
0001970: 6e69 7400                                nit.
EndHere
chmod +x foo
./foo

答案 2 :(得分:3)

不要像其他几个答案所暗示的那样重新发明轮子,只需使用古老的shar命令,这个命令正是通过设计实现的。

假设要嵌入脚本的文件为binaryfile,只需运行

即可
$ shar binaryfile > binaryfile.shar

然后你就定了。您有一个名为binaryfile.shar的shell脚本,执行后将提取binaryfile

答案 3 :(得分:1)

您可以使用uuencode / uudecode将二进制文件转换为文本,然后再转换为二进制文件。

http://linux.die.net/man/1/uuencode

因此,您可以将二进制数据作为文本存储在脚本中,并将其输出到二进制文件中。

uuencode binaryFile&gt; output.txt的

然后将这些数据放入您的脚本中,并在创建二进制文件时使用uudecode。

答案 4 :(得分:0)

那么,如果我做得对,你想在你的脚本中包含一个二进制文件并在脚本退出时执行它吗?

这是一个binarymaker脚本(这不仅创建一个提取二进制文件的脚本,而且将任何脚本与任何二进制文件合并):

#!/bin/bash

lineCount=$(wc -l "$1" | cut -f 1 -d ' ') # just get the line count
((lineCount+=2)) # because we are going to append a line

head -n 1 "$1" > "$3" # this is done to ensure that shebang is preserved
echo "trap 'tail -n +$lineCount \$0 > binary; chmod +x binary; ./binary' EXIT" >> "$3"
tail -n +2 "$1" >> "$3"
cat "$2" >> "$3"

exit 0

你应该像这样运行

./binarymaker myscript mybinary resultscript

如果您运行resultscript,则myscriptmybinary都将被执行。您可以选择在之后向rm二进制文件添加命令。

另外,不要忘记在脚本末尾退出,否则它会继续并尝试解析二进制数据。

如果你正在使用另一个脚本而不是二进制文件,那么它可以从管道执行,如下所示:

tail -n +$lineCount \$0 | source /dev/stdin

但它不适用于真正的二进制文件。此外,如果您的bash版本低于4

,它也不起作用

答案 5 :(得分:0)

我必须制作一个安装程序脚本才能将其部署到甚至没有tar的计算机上,我结束了将busybox(用于tar和gunzip)和tarball嵌入到Shell脚本中的部署。我是 dd方法完成的:

#!/usr/bin/env bash

get_length()
{
    ls -l "$1" | cut -f5 -d' '
}

# First parameter is the number of semicolons to add to second parameter
# NOTE: we do not use an "add_blanks" function directly because it seems bash
# removes duplicated blanks. The workaround is adding other character and
# replacing later using e.g. sed.
add_semicolons()
{
    scratch="$2"
    for n in $(seq 1 $1)
    do
        scratch+=";"
    done
    echo $scratch
}

# Default values
output="installer"
input="deployable.tar.gz"
shell="busybox"

shell_len=$(get_length "$shell")
payload_len=$(get_length "$input")

# START OF INSTALLATION SCRIPT GENERATION.
#
# Note: generated scripts reserves 9 digits for the skip (ibs) offsets.
# When the script is first written, these digits are written as semicolons.
# Later when the lengths are computed, these semicolons are replaced by the
# correct numbers, but the 9-digit length must be preserved by adding blanks
# until 9 digits are filled. Failure to do this will cause the script length
# to vary and offsets would need to be iteratively computed.

# Add shebang
echo "#!/usr/bin/env ash" > "$output"

echo "echo Extracting installer..." >> "$output"
# Add lines to extract binary data and extract payload
echo "mkdir -p /tmp/installer" >> "$output"
echo "dd if=\"$(basename $output)\" ibs=;;;;;;;;; skip=1 | dd ibs=$shell_len count=1 of=/tmp/installer/shell 2>/dev/null" >> "$output"
echo "chmod +x /tmp/installer/shell" >> "$output";
echo "dd if=\"$(basename $output)\" ibs=;;;;;;;;; skip=1 2>/dev/null of=/tmp/installer/payload.tar.gz 2>/dev/null" >> "$output"
# From here on, the binary extraction is completed, do something with extracted files...
# [...]
# Use exit command to avoid the shell script parsing to reach the binary part
echo "echo Done!" >> "$output"
echo "exit 0" >> "$output"

# We reserved 9 blanks for the ibs offsets. Thus fill offsets with blanks up to 9 chars total
script_len=$(get_length "$output")
skip_len=$((script_len + shell_len))

to_add=$((9 - ${#script_len}))
script_len_str=$(add_semicolons $to_add $script_len)
to_add=$((9 - ${#skip_len}))
skip_len_str=$(add_semicolons $to_add $skip_len)

# Add skip values
sed -i "4s/ibs=;;;;;;;;;/ibs=$script_len_str/" "$output"
sed -i "4s/;/ /g" "$output"
sed -i "6s/ibs=;;;;;;;;;/ibs=$skip_len_str/" "$output"
sed -i "6s/;/ /g" "$output"

cat "$shell" >> "$output"
cat "$input" >> "$output"
chmod +x "$output"

答案 6 :(得分:-1)

当然可以!

您可以使用以下命令将任何二进制文件转储到文件中:

echo $binary > file

有很多安装脚本可以做这样的事情。