可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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!
回答1:
i never done something like this before ;)
this will compile some c source, create a b.bash
script containing the binary (and the original script for simple development)
(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
invoke with (a.bash generates b.bash):
bash a.bash ;bash b.bash
i don't know how to evade writing out the binary into a temporary file before execution...
回答2:
I tried this out and it works. Hex was generated with 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
回答3:
Don't reinvent the wheel like several other answers are suggesting, just use the venerable shar command which is precisely doing this by design.
Assuming the file you want to embed in your script is binaryfile
, simply run
$ shar binaryfile > binaryfile.shar
and you are set. You have a shell script named binaryfile.shar
which when executed will extract binaryfile
.
回答4:
You can convert your binary to text, and then back to binary using uuencode/uudecode.
http://linux.die.net/man/1/uuencode
So you can store your binary data as text in your script and output it to a binary file.
uuencode binaryFile > output.txt
And then put that data into your script and when creating the binary file use uudecode.
回答5:
So, if I got it right you want to include a binary in your script and execute it on script exit?
Here is a binarymaker
script(This does not only create a script that extracts a binary, but merges any your script with any binary):
#!/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
You should run it like this
./binarymaker myscript mybinary resultscript
If you run resultscript
then both myscript
and mybinary
are going to be executed. You can optionally add a command to rm
the binary afterwards.
Also, do not forget to exit at the end of your script because otherwise it will continue and try to parse binary data.
If you're working with another script and not a binary, then it can be executed from pipe like this:
tail -n +$lineCount \$0 | source /dev/stdin
But it is not going to work on real binaries. Also, it doesn't work if your bash version is under 4
回答6:
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"
回答7:
Sure it is!
You can for example dump any binary into a file with:
echo $binary > file
There are many installation scripts which do things like that.