Bash script containing binary executable

2020-02-11 03:25发布

Is it possible to write a bash script, which would contain a binary executable program inside?

I mean a script, which would contain a dump of an executable in a textual form, which will be dumped back to an executable by this script when it is executed?

I would love to know a solution, which will work out of the box without a need of installing additional packages. Is it possible?

Thanks!

7条回答
贼婆χ
2楼-- · 2020-02-11 04:26

I had to make a installer script to deploy it on a machine that did not even have tar, and I ended embedding busybox (for tar and gunzip) and the tarball to deploy on a shell script. I did it the dd way:

#!/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"
查看更多
登录 后发表回答